potree.js 4.9 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941399423994339944399453994639947399483994939950399513995239953399543995539956399573995839959399603996139962399633996439965399663996739968399693997039971399723997339974399753997639977399783997939980399813998239983399843998539986399873998839989399903999139992399933999439995399963999739998399994000040001400024000340004400054000640007400084000940010400114001240013400144001540016400174001840019400204002140022400234002440025400264002740028400294003040031400324003340034400354003640037400384003940040400414004240043400444004540046400474004840049400504005140052400534005440055400564005740058400594006040061400624006340064400654006640067400684006940070400714007240073400744007540076400774007840079400804008140082400834008440085400864008740088400894009040091400924009340094400954009640097400984009940100401014010240103401044010540106401074010840109401104011140112401134011440115401164011740118401194012040121401224012340124401254012640127401284012940130401314013240133401344013540136401374013840139401404014140142401434014440145401464014740148401494015040151401524015340154401554015640157401584015940160401614016240163401644016540166401674016840169401704017140172401734017440175401764017740178401794018040181401824018340184401854018640187401884018940190401914019240193401944019540196401974019840199402004020140202402034020440205402064020740208402094021040211402124021340214402154021640217402184021940220402214022240223402244022540226402274022840229402304023140232402334023440235402364023740238402394024040241402424024340244402454024640247402484024940250402514025240253402544025540256402574025840259402604026140262402634026440265402664026740268402694027040271402724027340274402754027640277402784027940280402814028240283402844028540286402874028840289402904029140292402934029440295402964029740298402994030040301403024030340304403054030640307403084030940310403114031240313403144031540316403174031840319403204032140322403234032440325403264032740328403294033040331403324033340334403354033640337403384033940340403414034240343403444034540346403474034840349403504035140352403534035440355403564035740358403594036040361403624036340364403654036640367403684036940370403714037240373403744037540376403774037840379403804038140382403834038440385403864038740388403894039040391403924039340394403954039640397403984039940400404014040240403404044040540406404074040840409404104041140412404134041440415404164041740418404194042040421404224042340424404254042640427404284042940430404314043240433404344043540436404374043840439404404044140442404434044440445404464044740448404494045040451404524045340454404554045640457404584045940460404614046240463404644046540466404674046840469404704047140472404734047440475404764047740478404794048040481404824048340484404854048640487404884048940490404914049240493404944049540496404974049840499405004050140502405034050440505405064050740508405094051040511405124051340514405154051640517405184051940520405214052240523405244052540526405274052840529405304053140532405334053440535405364053740538405394054040541405424054340544405454054640547405484054940550405514055240553405544055540556405574055840559405604056140562405634056440565405664056740568405694057040571405724057340574405754057640577405784057940580405814058240583405844058540586405874058840589405904059140592405934059440595405964059740598405994060040601406024060340604406054060640607406084060940610406114061240613406144061540616406174061840619406204062140622406234062440625406264062740628406294063040631406324063340634406354063640637406384063940640406414064240643406444064540646406474064840649406504065140652406534065440655406564065740658406594066040661406624066340664406654066640667406684066940670406714067240673406744067540676406774067840679406804068140682406834068440685406864068740688406894069040691406924069340694406954069640697406984069940700407014070240703407044070540706407074070840709407104071140712407134071440715407164071740718407194072040721407224072340724407254072640727407284072940730407314073240733407344073540736407374073840739407404074140742407434074440745407464074740748407494075040751407524075340754407554075640757407584075940760407614076240763407644076540766407674076840769407704077140772407734077440775407764077740778407794078040781407824078340784407854078640787407884078940790407914079240793407944079540796407974079840799408004080140802408034080440805408064080740808408094081040811408124081340814408154081640817408184081940820408214082240823408244082540826408274082840829408304083140832408334083440835408364083740838408394084040841408424084340844408454084640847408484084940850408514085240853408544085540856408574085840859408604086140862408634086440865408664086740868408694087040871408724087340874408754087640877408784087940880408814088240883408844088540886408874088840889408904089140892408934089440895408964089740898408994090040901409024090340904409054090640907409084090940910409114091240913409144091540916409174091840919409204092140922409234092440925409264092740928409294093040931409324093340934409354093640937409384093940940409414094240943409444094540946409474094840949409504095140952409534095440955409564095740958409594096040961409624096340964409654096640967409684096940970409714097240973409744097540976409774097840979409804098140982409834098440985409864098740988409894099040991409924099340994409954099640997409984099941000410014100241003410044100541006410074100841009410104101141012410134101441015410164101741018410194102041021410224102341024410254102641027410284102941030410314103241033410344103541036410374103841039410404104141042410434104441045410464104741048410494105041051410524105341054410554105641057410584105941060410614106241063410644106541066410674106841069410704107141072410734107441075410764107741078410794108041081410824108341084410854108641087410884108941090410914109241093410944109541096410974109841099411004110141102411034110441105411064110741108411094111041111411124111341114411154111641117411184111941120411214112241123411244112541126411274112841129411304113141132411334113441135411364113741138411394114041141411424114341144411454114641147411484114941150411514115241153411544115541156411574115841159411604116141162411634116441165411664116741168411694117041171411724117341174411754117641177411784117941180411814118241183411844118541186411874118841189411904119141192411934119441195411964119741198411994120041201412024120341204412054120641207412084120941210412114121241213412144121541216412174121841219412204122141222412234122441225412264122741228412294123041231412324123341234412354123641237412384123941240412414124241243412444124541246412474124841249412504125141252412534125441255412564125741258412594126041261412624126341264412654126641267412684126941270412714127241273412744127541276412774127841279412804128141282412834128441285412864128741288412894129041291412924129341294412954129641297412984129941300413014130241303413044130541306413074130841309413104131141312413134131441315413164131741318413194132041321413224132341324413254132641327413284132941330413314133241333413344133541336413374133841339413404134141342413434134441345413464134741348413494135041351413524135341354413554135641357413584135941360413614136241363413644136541366413674136841369413704137141372413734137441375413764137741378413794138041381413824138341384413854138641387413884138941390413914139241393413944139541396413974139841399414004140141402414034140441405414064140741408414094141041411414124141341414414154141641417414184141941420414214142241423414244142541426414274142841429414304143141432414334143441435414364143741438414394144041441414424144341444414454144641447414484144941450414514145241453414544145541456414574145841459414604146141462414634146441465414664146741468414694147041471414724147341474414754147641477414784147941480414814148241483414844148541486414874148841489414904149141492414934149441495414964149741498414994150041501415024150341504415054150641507415084150941510415114151241513415144151541516415174151841519415204152141522415234152441525415264152741528415294153041531415324153341534415354153641537415384153941540415414154241543415444154541546415474154841549415504155141552415534155441555415564155741558415594156041561415624156341564415654156641567415684156941570415714157241573415744157541576415774157841579415804158141582415834158441585415864158741588415894159041591415924159341594415954159641597415984159941600416014160241603416044160541606416074160841609416104161141612416134161441615416164161741618416194162041621416224162341624416254162641627416284162941630416314163241633416344163541636416374163841639416404164141642416434164441645416464164741648416494165041651416524165341654416554165641657416584165941660416614166241663416644166541666416674166841669416704167141672416734167441675416764167741678416794168041681416824168341684416854168641687416884168941690416914169241693416944169541696416974169841699417004170141702417034170441705417064170741708417094171041711417124171341714417154171641717417184171941720417214172241723417244172541726417274172841729417304173141732417334173441735417364173741738417394174041741417424174341744417454174641747417484174941750417514175241753417544175541756417574175841759417604176141762417634176441765417664176741768417694177041771417724177341774417754177641777417784177941780417814178241783417844178541786417874178841789417904179141792417934179441795417964179741798417994180041801418024180341804418054180641807418084180941810418114181241813418144181541816418174181841819418204182141822418234182441825418264182741828418294183041831418324183341834418354183641837418384183941840418414184241843418444184541846418474184841849418504185141852418534185441855418564185741858418594186041861418624186341864418654186641867418684186941870418714187241873418744187541876418774187841879418804188141882418834188441885418864188741888418894189041891418924189341894418954189641897418984189941900419014190241903419044190541906419074190841909419104191141912419134191441915419164191741918419194192041921419224192341924419254192641927419284192941930419314193241933419344193541936419374193841939419404194141942419434194441945419464194741948419494195041951419524195341954419554195641957419584195941960419614196241963419644196541966419674196841969419704197141972419734197441975419764197741978419794198041981419824198341984419854198641987419884198941990419914199241993419944199541996419974199841999420004200142002420034200442005420064200742008420094201042011420124201342014420154201642017420184201942020420214202242023420244202542026420274202842029420304203142032420334203442035420364203742038420394204042041420424204342044420454204642047420484204942050420514205242053420544205542056420574205842059420604206142062420634206442065420664206742068420694207042071420724207342074420754207642077420784207942080420814208242083420844208542086420874208842089420904209142092420934209442095420964209742098420994210042101421024210342104421054210642107421084210942110421114211242113421144211542116421174211842119421204212142122421234212442125421264212742128421294213042131421324213342134421354213642137421384213942140421414214242143421444214542146421474214842149421504215142152421534215442155421564215742158421594216042161421624216342164421654216642167421684216942170421714217242173421744217542176421774217842179421804218142182421834218442185421864218742188421894219042191421924219342194421954219642197421984219942200422014220242203422044220542206422074220842209422104221142212422134221442215422164221742218422194222042221422224222342224422254222642227422284222942230422314223242233422344223542236422374223842239422404224142242422434224442245422464224742248422494225042251422524225342254422554225642257422584225942260422614226242263422644226542266422674226842269422704227142272422734227442275422764227742278422794228042281422824228342284422854228642287422884228942290422914229242293422944229542296422974229842299423004230142302423034230442305423064230742308423094231042311423124231342314423154231642317423184231942320423214232242323423244232542326423274232842329423304233142332423334233442335423364233742338423394234042341423424234342344423454234642347423484234942350423514235242353423544235542356423574235842359423604236142362423634236442365423664236742368423694237042371423724237342374423754237642377423784237942380423814238242383423844238542386423874238842389423904239142392423934239442395423964239742398423994240042401424024240342404424054240642407424084240942410424114241242413424144241542416424174241842419424204242142422424234242442425424264242742428424294243042431424324243342434424354243642437424384243942440424414244242443424444244542446424474244842449424504245142452424534245442455424564245742458424594246042461424624246342464424654246642467424684246942470424714247242473424744247542476424774247842479424804248142482424834248442485424864248742488424894249042491424924249342494424954249642497424984249942500425014250242503425044250542506425074250842509425104251142512425134251442515425164251742518425194252042521425224252342524425254252642527425284252942530425314253242533425344253542536425374253842539425404254142542425434254442545425464254742548425494255042551425524255342554425554255642557425584255942560425614256242563425644256542566425674256842569425704257142572425734257442575425764257742578425794258042581425824258342584425854258642587425884258942590425914259242593425944259542596425974259842599426004260142602426034260442605426064260742608426094261042611426124261342614426154261642617426184261942620426214262242623426244262542626426274262842629426304263142632426334263442635426364263742638426394264042641426424264342644426454264642647426484264942650426514265242653426544265542656426574265842659426604266142662426634266442665426664266742668426694267042671426724267342674426754267642677426784267942680426814268242683426844268542686426874268842689426904269142692426934269442695426964269742698426994270042701427024270342704427054270642707427084270942710427114271242713427144271542716427174271842719427204272142722427234272442725427264272742728427294273042731427324273342734427354273642737427384273942740427414274242743427444274542746427474274842749427504275142752427534275442755427564275742758427594276042761427624276342764427654276642767427684276942770427714277242773427744277542776427774277842779427804278142782427834278442785427864278742788427894279042791427924279342794427954279642797427984279942800428014280242803428044280542806428074280842809428104281142812428134281442815428164281742818428194282042821428224282342824428254282642827428284282942830428314283242833428344283542836428374283842839428404284142842428434284442845428464284742848428494285042851428524285342854428554285642857428584285942860428614286242863428644286542866428674286842869428704287142872428734287442875428764287742878428794288042881428824288342884428854288642887428884288942890428914289242893428944289542896428974289842899429004290142902429034290442905429064290742908429094291042911429124291342914429154291642917429184291942920429214292242923429244292542926429274292842929429304293142932429334293442935429364293742938429394294042941429424294342944429454294642947429484294942950429514295242953429544295542956429574295842959429604296142962429634296442965429664296742968429694297042971429724297342974429754297642977429784297942980429814298242983429844298542986429874298842989429904299142992429934299442995429964299742998429994300043001430024300343004430054300643007430084300943010430114301243013430144301543016430174301843019430204302143022430234302443025430264302743028430294303043031430324303343034430354303643037430384303943040430414304243043430444304543046430474304843049430504305143052430534305443055430564305743058430594306043061430624306343064430654306643067430684306943070430714307243073430744307543076430774307843079430804308143082430834308443085430864308743088430894309043091430924309343094430954309643097430984309943100431014310243103431044310543106431074310843109431104311143112431134311443115431164311743118431194312043121431224312343124431254312643127431284312943130431314313243133431344313543136431374313843139431404314143142431434314443145431464314743148431494315043151431524315343154431554315643157431584315943160431614316243163431644316543166431674316843169431704317143172431734317443175431764317743178431794318043181431824318343184431854318643187431884318943190431914319243193431944319543196431974319843199432004320143202432034320443205432064320743208432094321043211432124321343214432154321643217432184321943220432214322243223432244322543226432274322843229432304323143232432334323443235432364323743238432394324043241432424324343244432454324643247432484324943250432514325243253432544325543256432574325843259432604326143262432634326443265432664326743268432694327043271432724327343274432754327643277432784327943280432814328243283432844328543286432874328843289432904329143292432934329443295432964329743298432994330043301433024330343304433054330643307433084330943310433114331243313433144331543316433174331843319433204332143322433234332443325433264332743328433294333043331433324333343334433354333643337433384333943340433414334243343433444334543346433474334843349433504335143352433534335443355433564335743358433594336043361433624336343364433654336643367433684336943370433714337243373433744337543376433774337843379433804338143382433834338443385433864338743388433894339043391433924339343394433954339643397433984339943400434014340243403434044340543406434074340843409434104341143412434134341443415434164341743418434194342043421434224342343424434254342643427434284342943430434314343243433434344343543436434374343843439434404344143442434434344443445434464344743448434494345043451434524345343454434554345643457434584345943460434614346243463434644346543466434674346843469434704347143472434734347443475434764347743478434794348043481434824348343484434854348643487434884348943490434914349243493434944349543496434974349843499435004350143502435034350443505435064350743508435094351043511435124351343514435154351643517435184351943520435214352243523435244352543526435274352843529435304353143532435334353443535435364353743538435394354043541435424354343544435454354643547435484354943550435514355243553435544355543556435574355843559435604356143562435634356443565435664356743568435694357043571435724357343574435754357643577435784357943580435814358243583435844358543586435874358843589435904359143592435934359443595435964359743598435994360043601436024360343604436054360643607436084360943610436114361243613436144361543616436174361843619436204362143622436234362443625436264362743628436294363043631436324363343634436354363643637436384363943640436414364243643436444364543646436474364843649436504365143652436534365443655436564365743658436594366043661436624366343664436654366643667436684366943670436714367243673436744367543676436774367843679436804368143682436834368443685436864368743688436894369043691436924369343694436954369643697436984369943700437014370243703437044370543706437074370843709437104371143712437134371443715437164371743718437194372043721437224372343724437254372643727437284372943730437314373243733437344373543736437374373843739437404374143742437434374443745437464374743748437494375043751437524375343754437554375643757437584375943760437614376243763437644376543766437674376843769437704377143772437734377443775437764377743778437794378043781437824378343784437854378643787437884378943790437914379243793437944379543796437974379843799438004380143802438034380443805438064380743808438094381043811438124381343814438154381643817438184381943820438214382243823438244382543826438274382843829438304383143832438334383443835438364383743838438394384043841438424384343844438454384643847438484384943850438514385243853438544385543856438574385843859438604386143862438634386443865438664386743868438694387043871438724387343874438754387643877438784387943880438814388243883438844388543886438874388843889438904389143892438934389443895438964389743898438994390043901439024390343904439054390643907439084390943910439114391243913439144391543916439174391843919439204392143922439234392443925439264392743928439294393043931439324393343934439354393643937439384393943940439414394243943439444394543946439474394843949439504395143952439534395443955439564395743958439594396043961439624396343964439654396643967439684396943970439714397243973439744397543976439774397843979439804398143982439834398443985439864398743988439894399043991439924399343994439954399643997439984399944000440014400244003440044400544006440074400844009440104401144012440134401444015440164401744018440194402044021440224402344024440254402644027440284402944030440314403244033440344403544036440374403844039440404404144042440434404444045440464404744048440494405044051440524405344054440554405644057440584405944060440614406244063440644406544066440674406844069440704407144072440734407444075440764407744078440794408044081440824408344084440854408644087440884408944090440914409244093440944409544096440974409844099441004410144102441034410444105441064410744108441094411044111441124411344114441154411644117441184411944120441214412244123441244412544126441274412844129441304413144132441334413444135441364413744138441394414044141441424414344144441454414644147441484414944150441514415244153441544415544156441574415844159441604416144162441634416444165441664416744168441694417044171441724417344174441754417644177441784417944180441814418244183441844418544186441874418844189441904419144192441934419444195441964419744198441994420044201442024420344204442054420644207442084420944210442114421244213442144421544216442174421844219442204422144222442234422444225442264422744228442294423044231442324423344234442354423644237442384423944240442414424244243442444424544246442474424844249442504425144252442534425444255442564425744258442594426044261442624426344264442654426644267442684426944270442714427244273442744427544276442774427844279442804428144282442834428444285442864428744288442894429044291442924429344294442954429644297442984429944300443014430244303443044430544306443074430844309443104431144312443134431444315443164431744318443194432044321443224432344324443254432644327443284432944330443314433244333443344433544336443374433844339443404434144342443434434444345443464434744348443494435044351443524435344354443554435644357443584435944360443614436244363443644436544366443674436844369443704437144372443734437444375443764437744378443794438044381443824438344384443854438644387443884438944390443914439244393443944439544396443974439844399444004440144402444034440444405444064440744408444094441044411444124441344414444154441644417444184441944420444214442244423444244442544426444274442844429444304443144432444334443444435444364443744438444394444044441444424444344444444454444644447444484444944450444514445244453444544445544456444574445844459444604446144462444634446444465444664446744468444694447044471444724447344474444754447644477444784447944480444814448244483444844448544486444874448844489444904449144492444934449444495444964449744498444994450044501445024450344504445054450644507445084450944510445114451244513445144451544516445174451844519445204452144522445234452444525445264452744528445294453044531445324453344534445354453644537445384453944540445414454244543445444454544546445474454844549445504455144552445534455444555445564455744558445594456044561445624456344564445654456644567445684456944570445714457244573445744457544576445774457844579445804458144582445834458444585445864458744588445894459044591445924459344594445954459644597445984459944600446014460244603446044460544606446074460844609446104461144612446134461444615446164461744618446194462044621446224462344624446254462644627446284462944630446314463244633446344463544636446374463844639446404464144642446434464444645446464464744648446494465044651446524465344654446554465644657446584465944660446614466244663446644466544666446674466844669446704467144672446734467444675446764467744678446794468044681446824468344684446854468644687446884468944690446914469244693446944469544696446974469844699447004470144702447034470444705447064470744708447094471044711447124471344714447154471644717447184471944720447214472244723447244472544726447274472844729447304473144732447334473444735447364473744738447394474044741447424474344744447454474644747447484474944750447514475244753447544475544756447574475844759447604476144762447634476444765447664476744768447694477044771447724477344774447754477644777447784477944780447814478244783447844478544786447874478844789447904479144792447934479444795447964479744798447994480044801448024480344804448054480644807448084480944810448114481244813448144481544816448174481844819448204482144822448234482444825448264482744828448294483044831448324483344834448354483644837448384483944840448414484244843448444484544846448474484844849448504485144852448534485444855448564485744858448594486044861448624486344864448654486644867448684486944870448714487244873448744487544876448774487844879448804488144882448834488444885448864488744888448894489044891448924489344894448954489644897448984489944900449014490244903449044490544906449074490844909449104491144912449134491444915449164491744918449194492044921449224492344924449254492644927449284492944930449314493244933449344493544936449374493844939449404494144942449434494444945449464494744948449494495044951449524495344954449554495644957449584495944960449614496244963449644496544966449674496844969449704497144972449734497444975449764497744978449794498044981449824498344984449854498644987449884498944990449914499244993449944499544996449974499844999450004500145002450034500445005450064500745008450094501045011450124501345014450154501645017450184501945020450214502245023450244502545026450274502845029450304503145032450334503445035450364503745038450394504045041450424504345044450454504645047450484504945050450514505245053450544505545056450574505845059450604506145062450634506445065450664506745068450694507045071450724507345074450754507645077450784507945080450814508245083450844508545086450874508845089450904509145092450934509445095450964509745098450994510045101451024510345104451054510645107451084510945110451114511245113451144511545116451174511845119451204512145122451234512445125451264512745128451294513045131451324513345134451354513645137451384513945140451414514245143451444514545146451474514845149451504515145152451534515445155451564515745158451594516045161451624516345164451654516645167451684516945170451714517245173451744517545176451774517845179451804518145182451834518445185451864518745188451894519045191451924519345194451954519645197451984519945200452014520245203452044520545206452074520845209452104521145212452134521445215452164521745218452194522045221452224522345224452254522645227452284522945230452314523245233452344523545236452374523845239452404524145242452434524445245452464524745248452494525045251452524525345254452554525645257452584525945260452614526245263452644526545266452674526845269452704527145272452734527445275452764527745278452794528045281452824528345284452854528645287452884528945290452914529245293452944529545296452974529845299453004530145302453034530445305453064530745308453094531045311453124531345314453154531645317453184531945320453214532245323453244532545326453274532845329453304533145332453334533445335453364533745338453394534045341453424534345344453454534645347453484534945350453514535245353453544535545356453574535845359453604536145362453634536445365453664536745368453694537045371453724537345374453754537645377453784537945380453814538245383453844538545386453874538845389453904539145392453934539445395453964539745398453994540045401454024540345404454054540645407454084540945410454114541245413454144541545416454174541845419454204542145422454234542445425454264542745428454294543045431454324543345434454354543645437454384543945440454414544245443454444544545446454474544845449454504545145452454534545445455454564545745458454594546045461454624546345464454654546645467454684546945470454714547245473454744547545476454774547845479454804548145482454834548445485454864548745488454894549045491454924549345494454954549645497454984549945500455014550245503455044550545506455074550845509455104551145512455134551445515455164551745518455194552045521455224552345524455254552645527455284552945530455314553245533455344553545536455374553845539455404554145542455434554445545455464554745548455494555045551455524555345554455554555645557455584555945560455614556245563455644556545566455674556845569455704557145572455734557445575455764557745578455794558045581455824558345584455854558645587455884558945590455914559245593455944559545596455974559845599456004560145602456034560445605456064560745608456094561045611456124561345614456154561645617456184561945620456214562245623456244562545626456274562845629456304563145632456334563445635456364563745638456394564045641456424564345644456454564645647456484564945650456514565245653456544565545656456574565845659456604566145662456634566445665456664566745668456694567045671456724567345674456754567645677456784567945680456814568245683456844568545686456874568845689456904569145692456934569445695456964569745698456994570045701457024570345704457054570645707457084570945710457114571245713457144571545716457174571845719457204572145722457234572445725457264572745728457294573045731457324573345734457354573645737457384573945740457414574245743457444574545746457474574845749457504575145752457534575445755457564575745758457594576045761457624576345764457654576645767457684576945770457714577245773457744577545776457774577845779457804578145782457834578445785457864578745788457894579045791457924579345794457954579645797457984579945800458014580245803458044580545806458074580845809458104581145812458134581445815458164581745818458194582045821458224582345824458254582645827458284582945830458314583245833458344583545836458374583845839458404584145842458434584445845458464584745848458494585045851458524585345854458554585645857458584585945860458614586245863458644586545866458674586845869458704587145872458734587445875458764587745878458794588045881458824588345884458854588645887458884588945890458914589245893458944589545896458974589845899459004590145902459034590445905459064590745908459094591045911459124591345914459154591645917459184591945920459214592245923459244592545926459274592845929459304593145932459334593445935459364593745938459394594045941459424594345944459454594645947459484594945950459514595245953459544595545956459574595845959459604596145962459634596445965459664596745968459694597045971459724597345974459754597645977459784597945980459814598245983459844598545986459874598845989459904599145992459934599445995459964599745998459994600046001460024600346004460054600646007460084600946010460114601246013460144601546016460174601846019460204602146022460234602446025460264602746028460294603046031460324603346034460354603646037460384603946040460414604246043460444604546046460474604846049460504605146052460534605446055460564605746058460594606046061460624606346064460654606646067460684606946070460714607246073460744607546076460774607846079460804608146082460834608446085460864608746088460894609046091460924609346094460954609646097460984609946100461014610246103461044610546106461074610846109461104611146112461134611446115461164611746118461194612046121461224612346124461254612646127461284612946130461314613246133461344613546136461374613846139461404614146142461434614446145461464614746148461494615046151461524615346154461554615646157461584615946160461614616246163461644616546166461674616846169461704617146172461734617446175461764617746178461794618046181461824618346184461854618646187461884618946190461914619246193461944619546196461974619846199462004620146202462034620446205462064620746208462094621046211462124621346214462154621646217462184621946220462214622246223462244622546226462274622846229462304623146232462334623446235462364623746238462394624046241462424624346244462454624646247462484624946250462514625246253462544625546256462574625846259462604626146262462634626446265462664626746268462694627046271462724627346274462754627646277462784627946280462814628246283462844628546286462874628846289462904629146292462934629446295462964629746298462994630046301463024630346304463054630646307463084630946310463114631246313463144631546316463174631846319463204632146322463234632446325463264632746328463294633046331463324633346334463354633646337463384633946340463414634246343463444634546346463474634846349463504635146352463534635446355463564635746358463594636046361463624636346364463654636646367463684636946370463714637246373463744637546376463774637846379463804638146382463834638446385463864638746388463894639046391463924639346394463954639646397463984639946400464014640246403464044640546406464074640846409464104641146412464134641446415464164641746418464194642046421464224642346424464254642646427464284642946430464314643246433464344643546436464374643846439464404644146442464434644446445464464644746448464494645046451464524645346454464554645646457464584645946460464614646246463464644646546466464674646846469464704647146472464734647446475464764647746478464794648046481464824648346484464854648646487464884648946490464914649246493464944649546496464974649846499465004650146502465034650446505465064650746508465094651046511465124651346514465154651646517465184651946520465214652246523465244652546526465274652846529465304653146532465334653446535465364653746538465394654046541465424654346544465454654646547465484654946550465514655246553465544655546556465574655846559465604656146562465634656446565465664656746568465694657046571465724657346574465754657646577465784657946580465814658246583465844658546586465874658846589465904659146592465934659446595465964659746598465994660046601466024660346604466054660646607466084660946610466114661246613466144661546616466174661846619466204662146622466234662446625466264662746628466294663046631466324663346634466354663646637466384663946640466414664246643466444664546646466474664846649466504665146652466534665446655466564665746658466594666046661466624666346664466654666646667466684666946670466714667246673466744667546676466774667846679466804668146682466834668446685466864668746688466894669046691466924669346694466954669646697466984669946700467014670246703467044670546706467074670846709467104671146712467134671446715467164671746718467194672046721467224672346724467254672646727467284672946730467314673246733467344673546736467374673846739467404674146742467434674446745467464674746748467494675046751467524675346754467554675646757467584675946760467614676246763467644676546766467674676846769467704677146772467734677446775467764677746778467794678046781467824678346784467854678646787467884678946790467914679246793467944679546796467974679846799468004680146802468034680446805468064680746808468094681046811468124681346814468154681646817468184681946820468214682246823468244682546826468274682846829468304683146832468334683446835468364683746838468394684046841468424684346844468454684646847468484684946850468514685246853468544685546856468574685846859468604686146862468634686446865468664686746868468694687046871468724687346874468754687646877468784687946880468814688246883468844688546886468874688846889468904689146892468934689446895468964689746898468994690046901469024690346904469054690646907469084690946910469114691246913469144691546916469174691846919469204692146922469234692446925469264692746928469294693046931469324693346934469354693646937469384693946940469414694246943469444694546946469474694846949469504695146952469534695446955469564695746958469594696046961469624696346964469654696646967469684696946970469714697246973469744697546976469774697846979469804698146982469834698446985469864698746988469894699046991469924699346994469954699646997469984699947000470014700247003470044700547006470074700847009470104701147012470134701447015470164701747018470194702047021470224702347024470254702647027470284702947030470314703247033470344703547036470374703847039470404704147042470434704447045470464704747048470494705047051470524705347054470554705647057470584705947060470614706247063470644706547066470674706847069470704707147072470734707447075470764707747078470794708047081470824708347084470854708647087470884708947090470914709247093470944709547096470974709847099471004710147102471034710447105471064710747108471094711047111471124711347114471154711647117471184711947120471214712247123471244712547126471274712847129471304713147132471334713447135471364713747138471394714047141471424714347144471454714647147471484714947150471514715247153471544715547156471574715847159471604716147162471634716447165471664716747168471694717047171471724717347174471754717647177471784717947180471814718247183471844718547186471874718847189471904719147192471934719447195471964719747198471994720047201472024720347204472054720647207472084720947210472114721247213472144721547216472174721847219472204722147222472234722447225472264722747228472294723047231472324723347234472354723647237472384723947240472414724247243472444724547246472474724847249472504725147252472534725447255472564725747258472594726047261472624726347264472654726647267472684726947270472714727247273472744727547276472774727847279472804728147282472834728447285472864728747288472894729047291472924729347294472954729647297472984729947300473014730247303473044730547306473074730847309473104731147312473134731447315473164731747318473194732047321473224732347324473254732647327473284732947330473314733247333473344733547336473374733847339473404734147342473434734447345473464734747348473494735047351473524735347354473554735647357473584735947360473614736247363473644736547366473674736847369473704737147372473734737447375473764737747378473794738047381473824738347384473854738647387473884738947390473914739247393473944739547396473974739847399474004740147402474034740447405474064740747408474094741047411474124741347414474154741647417474184741947420474214742247423474244742547426474274742847429474304743147432474334743447435474364743747438474394744047441474424744347444474454744647447474484744947450474514745247453474544745547456474574745847459474604746147462474634746447465474664746747468474694747047471474724747347474474754747647477474784747947480474814748247483474844748547486474874748847489474904749147492474934749447495474964749747498474994750047501475024750347504475054750647507475084750947510475114751247513475144751547516475174751847519475204752147522475234752447525475264752747528475294753047531475324753347534475354753647537475384753947540475414754247543475444754547546475474754847549475504755147552475534755447555475564755747558475594756047561475624756347564475654756647567475684756947570475714757247573475744757547576475774757847579475804758147582475834758447585475864758747588475894759047591475924759347594475954759647597475984759947600476014760247603476044760547606476074760847609476104761147612476134761447615476164761747618476194762047621476224762347624476254762647627476284762947630476314763247633476344763547636476374763847639476404764147642476434764447645476464764747648476494765047651476524765347654476554765647657476584765947660476614766247663476644766547666476674766847669476704767147672476734767447675476764767747678476794768047681476824768347684476854768647687476884768947690476914769247693476944769547696476974769847699477004770147702477034770447705477064770747708477094771047711477124771347714477154771647717477184771947720477214772247723477244772547726477274772847729477304773147732477334773447735477364773747738477394774047741477424774347744477454774647747477484774947750477514775247753477544775547756477574775847759477604776147762477634776447765477664776747768477694777047771477724777347774477754777647777477784777947780477814778247783477844778547786477874778847789477904779147792477934779447795477964779747798477994780047801478024780347804478054780647807478084780947810478114781247813478144781547816478174781847819478204782147822478234782447825478264782747828478294783047831478324783347834478354783647837478384783947840478414784247843478444784547846478474784847849478504785147852478534785447855478564785747858478594786047861478624786347864478654786647867478684786947870478714787247873478744787547876478774787847879478804788147882478834788447885478864788747888478894789047891478924789347894478954789647897478984789947900479014790247903479044790547906479074790847909479104791147912479134791447915479164791747918479194792047921479224792347924479254792647927479284792947930479314793247933479344793547936479374793847939479404794147942479434794447945479464794747948479494795047951479524795347954479554795647957479584795947960479614796247963479644796547966479674796847969479704797147972479734797447975479764797747978479794798047981479824798347984479854798647987479884798947990479914799247993479944799547996479974799847999480004800148002480034800448005480064800748008480094801048011480124801348014480154801648017480184801948020480214802248023480244802548026480274802848029480304803148032480334803448035480364803748038480394804048041480424804348044480454804648047480484804948050480514805248053480544805548056480574805848059480604806148062480634806448065480664806748068480694807048071480724807348074480754807648077480784807948080480814808248083480844808548086480874808848089480904809148092480934809448095480964809748098480994810048101481024810348104481054810648107481084810948110481114811248113481144811548116481174811848119481204812148122481234812448125481264812748128481294813048131481324813348134481354813648137481384813948140481414814248143481444814548146481474814848149481504815148152481534815448155481564815748158481594816048161481624816348164481654816648167481684816948170481714817248173481744817548176481774817848179481804818148182481834818448185481864818748188481894819048191481924819348194481954819648197481984819948200482014820248203482044820548206482074820848209482104821148212482134821448215482164821748218482194822048221482224822348224482254822648227482284822948230482314823248233482344823548236482374823848239482404824148242482434824448245482464824748248482494825048251482524825348254482554825648257482584825948260482614826248263482644826548266482674826848269482704827148272482734827448275482764827748278482794828048281482824828348284482854828648287482884828948290482914829248293482944829548296482974829848299483004830148302483034830448305483064830748308483094831048311483124831348314483154831648317483184831948320483214832248323483244832548326483274832848329483304833148332483334833448335483364833748338483394834048341483424834348344483454834648347483484834948350483514835248353483544835548356483574835848359483604836148362483634836448365483664836748368483694837048371483724837348374483754837648377483784837948380483814838248383483844838548386483874838848389483904839148392483934839448395483964839748398483994840048401484024840348404484054840648407484084840948410484114841248413484144841548416484174841848419484204842148422484234842448425484264842748428484294843048431484324843348434484354843648437484384843948440484414844248443484444844548446484474844848449484504845148452484534845448455484564845748458484594846048461484624846348464484654846648467484684846948470484714847248473484744847548476484774847848479484804848148482484834848448485484864848748488484894849048491484924849348494484954849648497484984849948500485014850248503485044850548506485074850848509485104851148512485134851448515485164851748518485194852048521485224852348524485254852648527485284852948530485314853248533485344853548536485374853848539485404854148542485434854448545485464854748548485494855048551485524855348554485554855648557485584855948560485614856248563485644856548566485674856848569485704857148572485734857448575485764857748578485794858048581485824858348584485854858648587485884858948590485914859248593485944859548596485974859848599486004860148602486034860448605486064860748608486094861048611486124861348614486154861648617486184861948620486214862248623486244862548626486274862848629486304863148632486334863448635486364863748638486394864048641486424864348644486454864648647486484864948650486514865248653486544865548656486574865848659486604866148662486634866448665486664866748668486694867048671486724867348674486754867648677486784867948680486814868248683486844868548686486874868848689486904869148692486934869448695486964869748698486994870048701487024870348704487054870648707487084870948710487114871248713487144871548716487174871848719487204872148722487234872448725487264872748728487294873048731487324873348734487354873648737487384873948740487414874248743487444874548746487474874848749487504875148752487534875448755487564875748758487594876048761487624876348764487654876648767487684876948770487714877248773487744877548776487774877848779487804878148782487834878448785487864878748788487894879048791487924879348794487954879648797487984879948800488014880248803488044880548806488074880848809488104881148812488134881448815488164881748818488194882048821488224882348824488254882648827488284882948830488314883248833488344883548836488374883848839488404884148842488434884448845488464884748848488494885048851488524885348854488554885648857488584885948860488614886248863488644886548866488674886848869488704887148872488734887448875488764887748878488794888048881488824888348884488854888648887488884888948890488914889248893488944889548896488974889848899489004890148902489034890448905489064890748908489094891048911489124891348914489154891648917489184891948920489214892248923489244892548926489274892848929489304893148932489334893448935489364893748938489394894048941489424894348944489454894648947489484894948950489514895248953489544895548956489574895848959489604896148962489634896448965489664896748968489694897048971489724897348974489754897648977489784897948980489814898248983489844898548986489874898848989489904899148992489934899448995489964899748998489994900049001490024900349004490054900649007490084900949010490114901249013490144901549016490174901849019490204902149022490234902449025490264902749028490294903049031490324903349034490354903649037490384903949040490414904249043490444904549046490474904849049490504905149052490534905449055490564905749058490594906049061490624906349064490654906649067490684906949070490714907249073490744907549076490774907849079490804908149082490834908449085490864908749088490894909049091490924909349094490954909649097490984909949100491014910249103491044910549106491074910849109491104911149112491134911449115491164911749118491194912049121491224912349124491254912649127491284912949130491314913249133491344913549136491374913849139491404914149142491434914449145491464914749148491494915049151491524915349154491554915649157491584915949160491614916249163491644916549166491674916849169491704917149172491734917449175491764917749178491794918049181491824918349184491854918649187491884918949190491914919249193491944919549196491974919849199492004920149202492034920449205492064920749208492094921049211492124921349214492154921649217492184921949220492214922249223492244922549226492274922849229492304923149232492334923449235492364923749238492394924049241492424924349244492454924649247492484924949250492514925249253492544925549256492574925849259492604926149262492634926449265492664926749268492694927049271492724927349274492754927649277492784927949280492814928249283492844928549286492874928849289492904929149292492934929449295492964929749298492994930049301493024930349304493054930649307493084930949310493114931249313493144931549316493174931849319493204932149322493234932449325493264932749328493294933049331493324933349334493354933649337493384933949340493414934249343493444934549346493474934849349493504935149352493534935449355493564935749358493594936049361493624936349364493654936649367493684936949370493714937249373493744937549376493774937849379493804938149382493834938449385493864938749388493894939049391493924939349394493954939649397493984939949400494014940249403494044940549406494074940849409494104941149412494134941449415494164941749418494194942049421494224942349424494254942649427494284942949430494314943249433494344943549436494374943849439494404944149442494434944449445494464944749448494494945049451494524945349454494554945649457494584945949460494614946249463494644946549466494674946849469494704947149472494734947449475494764947749478494794948049481494824948349484494854948649487494884948949490494914949249493494944949549496494974949849499495004950149502495034950449505495064950749508495094951049511495124951349514495154951649517495184951949520495214952249523495244952549526495274952849529495304953149532495334953449535495364953749538495394954049541495424954349544495454954649547495484954949550495514955249553495544955549556495574955849559495604956149562495634956449565495664956749568495694957049571495724957349574495754957649577495784957949580495814958249583495844958549586495874958849589495904959149592495934959449595495964959749598495994960049601496024960349604496054960649607496084960949610496114961249613496144961549616496174961849619496204962149622496234962449625496264962749628496294963049631496324963349634496354963649637496384963949640496414964249643496444964549646496474964849649496504965149652496534965449655496564965749658496594966049661496624966349664496654966649667496684966949670496714967249673496744967549676496774967849679496804968149682496834968449685496864968749688496894969049691496924969349694496954969649697496984969949700497014970249703497044970549706497074970849709497104971149712497134971449715497164971749718497194972049721497224972349724497254972649727497284972949730497314973249733497344973549736497374973849739497404974149742497434974449745497464974749748497494975049751497524975349754497554975649757497584975949760497614976249763497644976549766497674976849769497704977149772497734977449775497764977749778497794978049781497824978349784497854978649787497884978949790497914979249793497944979549796497974979849799498004980149802498034980449805498064980749808498094981049811498124981349814498154981649817498184981949820498214982249823498244982549826498274982849829498304983149832498334983449835498364983749838498394984049841498424984349844498454984649847498484984949850498514985249853498544985549856498574985849859498604986149862498634986449865498664986749868498694987049871498724987349874498754987649877498784987949880498814988249883498844988549886498874988849889498904989149892498934989449895498964989749898498994990049901499024990349904499054990649907499084990949910499114991249913499144991549916499174991849919499204992149922499234992449925499264992749928499294993049931499324993349934499354993649937499384993949940499414994249943499444994549946499474994849949499504995149952499534995449955499564995749958499594996049961499624996349964499654996649967499684996949970499714997249973499744997549976499774997849979499804998149982499834998449985499864998749988499894999049991499924999349994499954999649997499984999950000500015000250003500045000550006500075000850009500105001150012500135001450015500165001750018500195002050021500225002350024500255002650027500285002950030500315003250033500345003550036500375003850039500405004150042500435004450045500465004750048500495005050051500525005350054500555005650057500585005950060500615006250063500645006550066500675006850069500705007150072500735007450075500765007750078500795008050081500825008350084500855008650087500885008950090500915009250093500945009550096500975009850099501005010150102501035010450105501065010750108501095011050111501125011350114501155011650117501185011950120501215012250123501245012550126501275012850129501305013150132501335013450135501365013750138501395014050141501425014350144501455014650147501485014950150501515015250153501545015550156501575015850159501605016150162501635016450165501665016750168501695017050171501725017350174501755017650177501785017950180501815018250183501845018550186501875018850189501905019150192501935019450195501965019750198501995020050201502025020350204502055020650207502085020950210502115021250213502145021550216502175021850219502205022150222502235022450225502265022750228502295023050231502325023350234502355023650237502385023950240502415024250243502445024550246502475024850249502505025150252502535025450255502565025750258502595026050261502625026350264502655026650267502685026950270502715027250273502745027550276502775027850279502805028150282502835028450285502865028750288502895029050291502925029350294502955029650297502985029950300503015030250303503045030550306503075030850309503105031150312503135031450315503165031750318503195032050321503225032350324503255032650327503285032950330503315033250333503345033550336503375033850339503405034150342503435034450345503465034750348503495035050351503525035350354503555035650357503585035950360503615036250363503645036550366503675036850369503705037150372503735037450375503765037750378503795038050381503825038350384503855038650387503885038950390503915039250393503945039550396503975039850399504005040150402504035040450405504065040750408504095041050411504125041350414504155041650417504185041950420504215042250423504245042550426504275042850429504305043150432504335043450435504365043750438504395044050441504425044350444504455044650447504485044950450504515045250453504545045550456504575045850459504605046150462504635046450465504665046750468504695047050471504725047350474504755047650477504785047950480504815048250483504845048550486504875048850489504905049150492504935049450495504965049750498504995050050501505025050350504505055050650507505085050950510505115051250513505145051550516505175051850519505205052150522505235052450525505265052750528505295053050531505325053350534505355053650537505385053950540505415054250543505445054550546505475054850549505505055150552505535055450555505565055750558505595056050561505625056350564505655056650567505685056950570505715057250573505745057550576505775057850579505805058150582505835058450585505865058750588505895059050591505925059350594505955059650597505985059950600506015060250603506045060550606506075060850609506105061150612506135061450615506165061750618506195062050621506225062350624506255062650627506285062950630506315063250633506345063550636506375063850639506405064150642506435064450645506465064750648506495065050651506525065350654506555065650657506585065950660506615066250663506645066550666506675066850669506705067150672506735067450675506765067750678506795068050681506825068350684506855068650687506885068950690506915069250693506945069550696506975069850699507005070150702507035070450705507065070750708507095071050711507125071350714507155071650717507185071950720507215072250723507245072550726507275072850729507305073150732507335073450735507365073750738507395074050741507425074350744507455074650747507485074950750507515075250753507545075550756507575075850759507605076150762507635076450765507665076750768507695077050771507725077350774507755077650777507785077950780507815078250783507845078550786507875078850789507905079150792507935079450795507965079750798507995080050801508025080350804508055080650807508085080950810508115081250813508145081550816508175081850819508205082150822508235082450825508265082750828508295083050831508325083350834508355083650837508385083950840508415084250843508445084550846508475084850849508505085150852508535085450855508565085750858508595086050861508625086350864508655086650867508685086950870508715087250873508745087550876508775087850879508805088150882508835088450885508865088750888508895089050891508925089350894508955089650897508985089950900509015090250903509045090550906509075090850909509105091150912509135091450915509165091750918509195092050921509225092350924509255092650927509285092950930509315093250933509345093550936509375093850939509405094150942509435094450945509465094750948509495095050951509525095350954509555095650957509585095950960509615096250963509645096550966509675096850969509705097150972509735097450975509765097750978509795098050981509825098350984509855098650987509885098950990509915099250993509945099550996509975099850999510005100151002510035100451005510065100751008510095101051011510125101351014510155101651017510185101951020510215102251023510245102551026510275102851029510305103151032510335103451035510365103751038510395104051041510425104351044510455104651047510485104951050510515105251053510545105551056510575105851059510605106151062510635106451065510665106751068510695107051071510725107351074510755107651077510785107951080510815108251083510845108551086510875108851089510905109151092510935109451095510965109751098510995110051101511025110351104511055110651107511085110951110511115111251113511145111551116511175111851119511205112151122511235112451125511265112751128511295113051131511325113351134511355113651137511385113951140511415114251143511445114551146511475114851149511505115151152511535115451155511565115751158511595116051161511625116351164511655116651167511685116951170511715117251173511745117551176511775117851179511805118151182511835118451185511865118751188511895119051191511925119351194511955119651197511985119951200512015120251203512045120551206512075120851209512105121151212512135121451215512165121751218512195122051221512225122351224512255122651227512285122951230512315123251233512345123551236512375123851239512405124151242512435124451245512465124751248512495125051251512525125351254512555125651257512585125951260512615126251263512645126551266512675126851269512705127151272512735127451275512765127751278512795128051281512825128351284512855128651287512885128951290512915129251293512945129551296512975129851299513005130151302513035130451305513065130751308513095131051311513125131351314513155131651317513185131951320513215132251323513245132551326513275132851329513305133151332513335133451335513365133751338513395134051341513425134351344513455134651347513485134951350513515135251353513545135551356513575135851359513605136151362513635136451365513665136751368513695137051371513725137351374513755137651377513785137951380513815138251383513845138551386513875138851389513905139151392513935139451395513965139751398513995140051401514025140351404514055140651407514085140951410514115141251413514145141551416514175141851419514205142151422514235142451425514265142751428514295143051431514325143351434514355143651437514385143951440514415144251443514445144551446514475144851449514505145151452514535145451455514565145751458514595146051461514625146351464514655146651467514685146951470514715147251473514745147551476514775147851479514805148151482514835148451485514865148751488514895149051491514925149351494514955149651497514985149951500515015150251503515045150551506515075150851509515105151151512515135151451515515165151751518515195152051521515225152351524515255152651527515285152951530515315153251533515345153551536515375153851539515405154151542515435154451545515465154751548515495155051551515525155351554515555155651557515585155951560515615156251563515645156551566515675156851569515705157151572515735157451575515765157751578515795158051581515825158351584515855158651587515885158951590515915159251593515945159551596515975159851599516005160151602516035160451605516065160751608516095161051611516125161351614516155161651617516185161951620516215162251623516245162551626516275162851629516305163151632516335163451635516365163751638516395164051641516425164351644516455164651647516485164951650516515165251653516545165551656516575165851659516605166151662516635166451665516665166751668516695167051671516725167351674516755167651677516785167951680516815168251683516845168551686516875168851689516905169151692516935169451695516965169751698516995170051701517025170351704517055170651707517085170951710517115171251713517145171551716517175171851719517205172151722517235172451725517265172751728517295173051731517325173351734517355173651737517385173951740517415174251743517445174551746517475174851749517505175151752517535175451755517565175751758517595176051761517625176351764517655176651767517685176951770517715177251773517745177551776517775177851779517805178151782517835178451785517865178751788517895179051791517925179351794517955179651797517985179951800518015180251803518045180551806518075180851809518105181151812518135181451815518165181751818518195182051821518225182351824518255182651827518285182951830518315183251833518345183551836518375183851839518405184151842518435184451845518465184751848518495185051851518525185351854518555185651857518585185951860518615186251863518645186551866518675186851869518705187151872518735187451875518765187751878518795188051881518825188351884518855188651887518885188951890518915189251893518945189551896518975189851899519005190151902519035190451905519065190751908519095191051911519125191351914519155191651917519185191951920519215192251923519245192551926519275192851929519305193151932519335193451935519365193751938519395194051941519425194351944519455194651947519485194951950519515195251953519545195551956519575195851959519605196151962519635196451965519665196751968519695197051971519725197351974519755197651977519785197951980519815198251983519845198551986519875198851989519905199151992519935199451995519965199751998519995200052001520025200352004520055200652007520085200952010520115201252013520145201552016520175201852019520205202152022520235202452025520265202752028520295203052031520325203352034520355203652037520385203952040520415204252043520445204552046520475204852049520505205152052520535205452055520565205752058520595206052061520625206352064520655206652067520685206952070520715207252073520745207552076520775207852079520805208152082520835208452085520865208752088520895209052091520925209352094520955209652097520985209952100521015210252103521045210552106521075210852109521105211152112521135211452115521165211752118521195212052121521225212352124521255212652127521285212952130521315213252133521345213552136521375213852139521405214152142521435214452145521465214752148521495215052151521525215352154521555215652157521585215952160521615216252163521645216552166521675216852169521705217152172521735217452175521765217752178521795218052181521825218352184521855218652187521885218952190521915219252193521945219552196521975219852199522005220152202522035220452205522065220752208522095221052211522125221352214522155221652217522185221952220522215222252223522245222552226522275222852229522305223152232522335223452235522365223752238522395224052241522425224352244522455224652247522485224952250522515225252253522545225552256522575225852259522605226152262522635226452265522665226752268522695227052271522725227352274522755227652277522785227952280522815228252283522845228552286522875228852289522905229152292522935229452295522965229752298522995230052301523025230352304523055230652307523085230952310523115231252313523145231552316523175231852319523205232152322523235232452325523265232752328523295233052331523325233352334523355233652337523385233952340523415234252343523445234552346523475234852349523505235152352523535235452355523565235752358523595236052361523625236352364523655236652367523685236952370523715237252373523745237552376523775237852379523805238152382523835238452385523865238752388523895239052391523925239352394523955239652397523985239952400524015240252403524045240552406524075240852409524105241152412524135241452415524165241752418524195242052421524225242352424524255242652427524285242952430524315243252433524345243552436524375243852439524405244152442524435244452445524465244752448524495245052451524525245352454524555245652457524585245952460524615246252463524645246552466524675246852469524705247152472524735247452475524765247752478524795248052481524825248352484524855248652487524885248952490524915249252493524945249552496524975249852499525005250152502525035250452505525065250752508525095251052511525125251352514525155251652517525185251952520525215252252523525245252552526525275252852529525305253152532525335253452535525365253752538525395254052541525425254352544525455254652547525485254952550525515255252553525545255552556525575255852559525605256152562525635256452565525665256752568525695257052571525725257352574525755257652577525785257952580525815258252583525845258552586525875258852589525905259152592525935259452595525965259752598525995260052601526025260352604526055260652607526085260952610526115261252613526145261552616526175261852619526205262152622526235262452625526265262752628526295263052631526325263352634526355263652637526385263952640526415264252643526445264552646526475264852649526505265152652526535265452655526565265752658526595266052661526625266352664526655266652667526685266952670526715267252673526745267552676526775267852679526805268152682526835268452685526865268752688526895269052691526925269352694526955269652697526985269952700527015270252703527045270552706527075270852709527105271152712527135271452715527165271752718527195272052721527225272352724527255272652727527285272952730527315273252733527345273552736527375273852739527405274152742527435274452745527465274752748527495275052751527525275352754527555275652757527585275952760527615276252763527645276552766527675276852769527705277152772527735277452775527765277752778527795278052781527825278352784527855278652787527885278952790527915279252793527945279552796527975279852799528005280152802528035280452805528065280752808528095281052811528125281352814528155281652817528185281952820528215282252823528245282552826528275282852829528305283152832528335283452835528365283752838528395284052841528425284352844528455284652847528485284952850528515285252853528545285552856528575285852859528605286152862528635286452865528665286752868528695287052871528725287352874528755287652877528785287952880528815288252883528845288552886528875288852889528905289152892528935289452895528965289752898528995290052901529025290352904529055290652907529085290952910529115291252913529145291552916529175291852919529205292152922529235292452925529265292752928529295293052931529325293352934529355293652937529385293952940529415294252943529445294552946529475294852949529505295152952529535295452955529565295752958529595296052961529625296352964529655296652967529685296952970529715297252973529745297552976529775297852979529805298152982529835298452985529865298752988529895299052991529925299352994529955299652997529985299953000530015300253003530045300553006530075300853009530105301153012530135301453015530165301753018530195302053021530225302353024530255302653027530285302953030530315303253033530345303553036530375303853039530405304153042530435304453045530465304753048530495305053051530525305353054530555305653057530585305953060530615306253063530645306553066530675306853069530705307153072530735307453075530765307753078530795308053081530825308353084530855308653087530885308953090530915309253093530945309553096530975309853099531005310153102531035310453105531065310753108531095311053111531125311353114531155311653117531185311953120531215312253123531245312553126531275312853129531305313153132531335313453135531365313753138531395314053141531425314353144531455314653147531485314953150531515315253153531545315553156531575315853159531605316153162531635316453165531665316753168531695317053171531725317353174531755317653177531785317953180531815318253183531845318553186531875318853189531905319153192531935319453195531965319753198531995320053201532025320353204532055320653207532085320953210532115321253213532145321553216532175321853219532205322153222532235322453225532265322753228532295323053231532325323353234532355323653237532385323953240532415324253243532445324553246532475324853249532505325153252532535325453255532565325753258532595326053261532625326353264532655326653267532685326953270532715327253273532745327553276532775327853279532805328153282532835328453285532865328753288532895329053291532925329353294532955329653297532985329953300533015330253303533045330553306533075330853309533105331153312533135331453315533165331753318533195332053321533225332353324533255332653327533285332953330533315333253333533345333553336533375333853339533405334153342533435334453345533465334753348533495335053351533525335353354533555335653357533585335953360533615336253363533645336553366533675336853369533705337153372533735337453375533765337753378533795338053381533825338353384533855338653387533885338953390533915339253393533945339553396533975339853399534005340153402534035340453405534065340753408534095341053411534125341353414534155341653417534185341953420534215342253423534245342553426534275342853429534305343153432534335343453435534365343753438534395344053441534425344353444534455344653447534485344953450534515345253453534545345553456534575345853459534605346153462534635346453465534665346753468534695347053471534725347353474534755347653477534785347953480534815348253483534845348553486534875348853489534905349153492534935349453495534965349753498534995350053501535025350353504535055350653507535085350953510535115351253513535145351553516535175351853519535205352153522535235352453525535265352753528535295353053531535325353353534535355353653537535385353953540535415354253543535445354553546535475354853549535505355153552535535355453555535565355753558535595356053561535625356353564535655356653567535685356953570535715357253573535745357553576535775357853579535805358153582535835358453585535865358753588535895359053591535925359353594535955359653597535985359953600536015360253603536045360553606536075360853609536105361153612536135361453615536165361753618536195362053621536225362353624536255362653627536285362953630536315363253633536345363553636536375363853639536405364153642536435364453645536465364753648536495365053651536525365353654536555365653657536585365953660536615366253663536645366553666536675366853669536705367153672536735367453675536765367753678536795368053681536825368353684536855368653687536885368953690536915369253693536945369553696536975369853699537005370153702537035370453705537065370753708537095371053711537125371353714537155371653717537185371953720537215372253723537245372553726537275372853729537305373153732537335373453735537365373753738537395374053741537425374353744537455374653747537485374953750537515375253753537545375553756537575375853759537605376153762537635376453765537665376753768537695377053771537725377353774537755377653777537785377953780537815378253783537845378553786537875378853789537905379153792537935379453795537965379753798537995380053801538025380353804538055380653807538085380953810538115381253813538145381553816538175381853819538205382153822538235382453825538265382753828538295383053831538325383353834538355383653837538385383953840538415384253843538445384553846538475384853849538505385153852538535385453855538565385753858538595386053861538625386353864538655386653867538685386953870538715387253873538745387553876538775387853879538805388153882538835388453885538865388753888538895389053891538925389353894538955389653897538985389953900539015390253903539045390553906539075390853909539105391153912539135391453915539165391753918539195392053921539225392353924539255392653927539285392953930539315393253933539345393553936539375393853939539405394153942539435394453945539465394753948539495395053951539525395353954539555395653957539585395953960539615396253963539645396553966539675396853969539705397153972539735397453975539765397753978539795398053981539825398353984539855398653987539885398953990539915399253993539945399553996539975399853999540005400154002540035400454005540065400754008540095401054011540125401354014540155401654017540185401954020540215402254023540245402554026540275402854029540305403154032540335403454035540365403754038540395404054041540425404354044540455404654047540485404954050540515405254053540545405554056540575405854059540605406154062540635406454065540665406754068540695407054071540725407354074540755407654077540785407954080540815408254083540845408554086540875408854089540905409154092540935409454095540965409754098540995410054101541025410354104541055410654107541085410954110541115411254113541145411554116541175411854119541205412154122541235412454125541265412754128541295413054131541325413354134541355413654137541385413954140541415414254143541445414554146541475414854149541505415154152541535415454155541565415754158541595416054161541625416354164541655416654167541685416954170541715417254173541745417554176541775417854179541805418154182541835418454185541865418754188541895419054191541925419354194541955419654197541985419954200542015420254203542045420554206542075420854209542105421154212542135421454215542165421754218542195422054221542225422354224542255422654227542285422954230542315423254233542345423554236542375423854239542405424154242542435424454245542465424754248542495425054251542525425354254542555425654257542585425954260542615426254263542645426554266542675426854269542705427154272542735427454275542765427754278542795428054281542825428354284542855428654287542885428954290542915429254293542945429554296542975429854299543005430154302543035430454305543065430754308543095431054311543125431354314543155431654317543185431954320543215432254323543245432554326543275432854329543305433154332543335433454335543365433754338543395434054341543425434354344543455434654347543485434954350543515435254353543545435554356543575435854359543605436154362543635436454365543665436754368543695437054371543725437354374543755437654377543785437954380543815438254383543845438554386543875438854389543905439154392543935439454395543965439754398543995440054401544025440354404544055440654407544085440954410544115441254413544145441554416544175441854419544205442154422544235442454425544265442754428544295443054431544325443354434544355443654437544385443954440544415444254443544445444554446544475444854449544505445154452544535445454455544565445754458544595446054461544625446354464544655446654467544685446954470544715447254473544745447554476544775447854479544805448154482544835448454485544865448754488544895449054491544925449354494544955449654497544985449954500545015450254503545045450554506545075450854509545105451154512545135451454515545165451754518545195452054521545225452354524545255452654527545285452954530545315453254533545345453554536545375453854539545405454154542545435454454545545465454754548545495455054551545525455354554545555455654557545585455954560545615456254563545645456554566545675456854569545705457154572545735457454575545765457754578545795458054581545825458354584545855458654587545885458954590545915459254593545945459554596545975459854599546005460154602546035460454605546065460754608546095461054611546125461354614546155461654617546185461954620546215462254623546245462554626546275462854629546305463154632546335463454635546365463754638546395464054641546425464354644546455464654647546485464954650546515465254653546545465554656546575465854659546605466154662546635466454665546665466754668546695467054671546725467354674546755467654677546785467954680546815468254683546845468554686546875468854689546905469154692546935469454695546965469754698546995470054701547025470354704547055470654707547085470954710547115471254713547145471554716547175471854719547205472154722547235472454725547265472754728547295473054731547325473354734547355473654737547385473954740547415474254743547445474554746547475474854749547505475154752547535475454755547565475754758547595476054761547625476354764547655476654767547685476954770547715477254773547745477554776547775477854779547805478154782547835478454785547865478754788547895479054791547925479354794547955479654797547985479954800548015480254803548045480554806548075480854809548105481154812548135481454815548165481754818548195482054821548225482354824548255482654827548285482954830548315483254833548345483554836548375483854839548405484154842548435484454845548465484754848548495485054851548525485354854548555485654857548585485954860548615486254863548645486554866548675486854869548705487154872548735487454875548765487754878548795488054881548825488354884548855488654887548885488954890548915489254893548945489554896548975489854899549005490154902549035490454905549065490754908549095491054911549125491354914549155491654917549185491954920549215492254923549245492554926549275492854929549305493154932549335493454935549365493754938549395494054941549425494354944549455494654947549485494954950549515495254953549545495554956549575495854959549605496154962549635496454965549665496754968549695497054971549725497354974549755497654977549785497954980549815498254983549845498554986549875498854989549905499154992549935499454995549965499754998549995500055001550025500355004550055500655007550085500955010550115501255013550145501555016550175501855019550205502155022550235502455025550265502755028550295503055031550325503355034550355503655037550385503955040550415504255043550445504555046550475504855049550505505155052550535505455055550565505755058550595506055061550625506355064550655506655067550685506955070550715507255073550745507555076550775507855079550805508155082550835508455085550865508755088550895509055091550925509355094550955509655097550985509955100551015510255103551045510555106551075510855109551105511155112551135511455115551165511755118551195512055121551225512355124551255512655127551285512955130551315513255133551345513555136551375513855139551405514155142551435514455145551465514755148551495515055151551525515355154551555515655157551585515955160551615516255163551645516555166551675516855169551705517155172551735517455175551765517755178551795518055181551825518355184551855518655187551885518955190551915519255193551945519555196551975519855199552005520155202552035520455205552065520755208552095521055211552125521355214552155521655217552185521955220552215522255223552245522555226552275522855229552305523155232552335523455235552365523755238552395524055241552425524355244552455524655247552485524955250552515525255253552545525555256552575525855259552605526155262552635526455265552665526755268552695527055271552725527355274552755527655277552785527955280552815528255283552845528555286552875528855289552905529155292552935529455295552965529755298552995530055301553025530355304553055530655307553085530955310553115531255313553145531555316553175531855319553205532155322553235532455325553265532755328553295533055331553325533355334553355533655337553385533955340553415534255343553445534555346553475534855349553505535155352553535535455355553565535755358553595536055361553625536355364553655536655367553685536955370553715537255373553745537555376553775537855379553805538155382553835538455385553865538755388553895539055391553925539355394553955539655397553985539955400554015540255403554045540555406554075540855409554105541155412554135541455415554165541755418554195542055421554225542355424554255542655427554285542955430554315543255433554345543555436554375543855439554405544155442554435544455445554465544755448554495545055451554525545355454554555545655457554585545955460554615546255463554645546555466554675546855469554705547155472554735547455475554765547755478554795548055481554825548355484554855548655487554885548955490554915549255493554945549555496554975549855499555005550155502555035550455505555065550755508555095551055511555125551355514555155551655517555185551955520555215552255523555245552555526555275552855529555305553155532555335553455535555365553755538555395554055541555425554355544555455554655547555485554955550555515555255553555545555555556555575555855559555605556155562555635556455565555665556755568555695557055571555725557355574555755557655577555785557955580555815558255583555845558555586555875558855589555905559155592555935559455595555965559755598555995560055601556025560355604556055560655607556085560955610556115561255613556145561555616556175561855619556205562155622556235562455625556265562755628556295563055631556325563355634556355563655637556385563955640556415564255643556445564555646556475564855649556505565155652556535565455655556565565755658556595566055661556625566355664556655566655667556685566955670556715567255673556745567555676556775567855679556805568155682556835568455685556865568755688556895569055691556925569355694556955569655697556985569955700557015570255703557045570555706557075570855709557105571155712557135571455715557165571755718557195572055721557225572355724557255572655727557285572955730557315573255733557345573555736557375573855739557405574155742557435574455745557465574755748557495575055751557525575355754557555575655757557585575955760557615576255763557645576555766557675576855769557705577155772557735577455775557765577755778557795578055781557825578355784557855578655787557885578955790557915579255793557945579555796557975579855799558005580155802558035580455805558065580755808558095581055811558125581355814558155581655817558185581955820558215582255823558245582555826558275582855829558305583155832558335583455835558365583755838558395584055841558425584355844558455584655847558485584955850558515585255853558545585555856558575585855859558605586155862558635586455865558665586755868558695587055871558725587355874558755587655877558785587955880558815588255883558845588555886558875588855889558905589155892558935589455895558965589755898558995590055901559025590355904559055590655907559085590955910559115591255913559145591555916559175591855919559205592155922559235592455925559265592755928559295593055931559325593355934559355593655937559385593955940559415594255943559445594555946559475594855949559505595155952559535595455955559565595755958559595596055961559625596355964559655596655967559685596955970559715597255973559745597555976559775597855979559805598155982559835598455985559865598755988559895599055991559925599355994559955599655997559985599956000560015600256003560045600556006560075600856009560105601156012560135601456015560165601756018560195602056021560225602356024560255602656027560285602956030560315603256033560345603556036560375603856039560405604156042560435604456045560465604756048560495605056051560525605356054560555605656057560585605956060560615606256063560645606556066560675606856069560705607156072560735607456075560765607756078560795608056081560825608356084560855608656087560885608956090560915609256093560945609556096560975609856099561005610156102561035610456105561065610756108561095611056111561125611356114561155611656117561185611956120561215612256123561245612556126561275612856129561305613156132561335613456135561365613756138561395614056141561425614356144561455614656147561485614956150561515615256153561545615556156561575615856159561605616156162561635616456165561665616756168561695617056171561725617356174561755617656177561785617956180561815618256183561845618556186561875618856189561905619156192561935619456195561965619756198561995620056201562025620356204562055620656207562085620956210562115621256213562145621556216562175621856219562205622156222562235622456225562265622756228562295623056231562325623356234562355623656237562385623956240562415624256243562445624556246562475624856249562505625156252562535625456255562565625756258562595626056261562625626356264562655626656267562685626956270562715627256273562745627556276562775627856279562805628156282562835628456285562865628756288562895629056291562925629356294562955629656297562985629956300563015630256303563045630556306563075630856309563105631156312563135631456315563165631756318563195632056321563225632356324563255632656327563285632956330563315633256333563345633556336563375633856339563405634156342563435634456345563465634756348563495635056351563525635356354563555635656357563585635956360563615636256363563645636556366563675636856369563705637156372563735637456375563765637756378563795638056381563825638356384563855638656387563885638956390563915639256393563945639556396563975639856399564005640156402564035640456405564065640756408564095641056411564125641356414564155641656417564185641956420564215642256423564245642556426564275642856429564305643156432564335643456435564365643756438564395644056441564425644356444564455644656447564485644956450564515645256453564545645556456564575645856459564605646156462564635646456465564665646756468564695647056471564725647356474564755647656477564785647956480564815648256483564845648556486564875648856489564905649156492564935649456495564965649756498564995650056501565025650356504565055650656507565085650956510565115651256513565145651556516565175651856519565205652156522565235652456525565265652756528565295653056531565325653356534565355653656537565385653956540565415654256543565445654556546565475654856549565505655156552565535655456555565565655756558565595656056561565625656356564565655656656567565685656956570565715657256573565745657556576565775657856579565805658156582565835658456585565865658756588565895659056591565925659356594565955659656597565985659956600566015660256603566045660556606566075660856609566105661156612566135661456615566165661756618566195662056621566225662356624566255662656627566285662956630566315663256633566345663556636566375663856639566405664156642566435664456645566465664756648566495665056651566525665356654566555665656657566585665956660566615666256663566645666556666566675666856669566705667156672566735667456675566765667756678566795668056681566825668356684566855668656687566885668956690566915669256693566945669556696566975669856699567005670156702567035670456705567065670756708567095671056711567125671356714567155671656717567185671956720567215672256723567245672556726567275672856729567305673156732567335673456735567365673756738567395674056741567425674356744567455674656747567485674956750567515675256753567545675556756567575675856759567605676156762567635676456765567665676756768567695677056771567725677356774567755677656777567785677956780567815678256783567845678556786567875678856789567905679156792567935679456795567965679756798567995680056801568025680356804568055680656807568085680956810568115681256813568145681556816568175681856819568205682156822568235682456825568265682756828568295683056831568325683356834568355683656837568385683956840568415684256843568445684556846568475684856849568505685156852568535685456855568565685756858568595686056861568625686356864568655686656867568685686956870568715687256873568745687556876568775687856879568805688156882568835688456885568865688756888568895689056891568925689356894568955689656897568985689956900569015690256903569045690556906569075690856909569105691156912569135691456915569165691756918569195692056921569225692356924569255692656927569285692956930569315693256933569345693556936569375693856939569405694156942569435694456945569465694756948569495695056951569525695356954569555695656957569585695956960569615696256963569645696556966569675696856969569705697156972569735697456975569765697756978569795698056981569825698356984569855698656987569885698956990569915699256993569945699556996569975699856999570005700157002570035700457005570065700757008570095701057011570125701357014570155701657017570185701957020570215702257023570245702557026570275702857029570305703157032570335703457035570365703757038570395704057041570425704357044570455704657047570485704957050570515705257053570545705557056570575705857059570605706157062570635706457065570665706757068570695707057071570725707357074570755707657077570785707957080570815708257083570845708557086570875708857089570905709157092570935709457095570965709757098570995710057101571025710357104571055710657107571085710957110571115711257113571145711557116571175711857119571205712157122571235712457125571265712757128571295713057131571325713357134571355713657137571385713957140571415714257143571445714557146571475714857149571505715157152571535715457155571565715757158571595716057161571625716357164571655716657167571685716957170571715717257173571745717557176571775717857179571805718157182571835718457185571865718757188571895719057191571925719357194571955719657197571985719957200572015720257203572045720557206572075720857209572105721157212572135721457215572165721757218572195722057221572225722357224572255722657227572285722957230572315723257233572345723557236572375723857239572405724157242572435724457245572465724757248572495725057251572525725357254572555725657257572585725957260572615726257263572645726557266572675726857269572705727157272572735727457275572765727757278572795728057281572825728357284572855728657287572885728957290572915729257293572945729557296572975729857299573005730157302573035730457305573065730757308573095731057311573125731357314573155731657317573185731957320573215732257323573245732557326573275732857329573305733157332573335733457335573365733757338573395734057341573425734357344573455734657347573485734957350573515735257353573545735557356573575735857359573605736157362573635736457365573665736757368573695737057371573725737357374573755737657377573785737957380573815738257383573845738557386573875738857389573905739157392573935739457395573965739757398573995740057401574025740357404574055740657407574085740957410574115741257413574145741557416574175741857419574205742157422574235742457425574265742757428574295743057431574325743357434574355743657437574385743957440574415744257443574445744557446574475744857449574505745157452574535745457455574565745757458574595746057461574625746357464574655746657467574685746957470574715747257473574745747557476574775747857479574805748157482574835748457485574865748757488574895749057491574925749357494574955749657497574985749957500575015750257503575045750557506575075750857509575105751157512575135751457515575165751757518575195752057521575225752357524575255752657527575285752957530575315753257533575345753557536575375753857539575405754157542575435754457545575465754757548575495755057551575525755357554575555755657557575585755957560575615756257563575645756557566575675756857569575705757157572575735757457575575765757757578575795758057581575825758357584575855758657587575885758957590575915759257593575945759557596575975759857599576005760157602576035760457605576065760757608576095761057611576125761357614576155761657617576185761957620576215762257623576245762557626576275762857629576305763157632576335763457635576365763757638576395764057641576425764357644576455764657647576485764957650576515765257653576545765557656576575765857659576605766157662576635766457665576665766757668576695767057671576725767357674576755767657677576785767957680576815768257683576845768557686576875768857689576905769157692576935769457695576965769757698576995770057701577025770357704577055770657707577085770957710577115771257713577145771557716577175771857719577205772157722577235772457725577265772757728577295773057731577325773357734577355773657737577385773957740577415774257743577445774557746577475774857749577505775157752577535775457755577565775757758577595776057761577625776357764577655776657767577685776957770577715777257773577745777557776577775777857779577805778157782577835778457785577865778757788577895779057791577925779357794577955779657797577985779957800578015780257803578045780557806578075780857809578105781157812578135781457815578165781757818578195782057821578225782357824578255782657827578285782957830578315783257833578345783557836578375783857839578405784157842578435784457845578465784757848578495785057851578525785357854578555785657857578585785957860578615786257863578645786557866578675786857869578705787157872578735787457875578765787757878578795788057881578825788357884578855788657887578885788957890578915789257893578945789557896578975789857899579005790157902579035790457905579065790757908579095791057911579125791357914579155791657917579185791957920579215792257923579245792557926579275792857929579305793157932579335793457935579365793757938579395794057941579425794357944579455794657947579485794957950579515795257953579545795557956579575795857959579605796157962579635796457965579665796757968579695797057971579725797357974579755797657977579785797957980579815798257983579845798557986579875798857989579905799157992579935799457995579965799757998579995800058001580025800358004580055800658007580085800958010580115801258013580145801558016580175801858019580205802158022580235802458025580265802758028580295803058031580325803358034580355803658037580385803958040580415804258043580445804558046580475804858049580505805158052580535805458055580565805758058580595806058061580625806358064580655806658067580685806958070580715807258073580745807558076580775807858079580805808158082580835808458085580865808758088580895809058091580925809358094580955809658097580985809958100581015810258103581045810558106581075810858109581105811158112581135811458115581165811758118581195812058121581225812358124581255812658127581285812958130581315813258133581345813558136581375813858139581405814158142581435814458145581465814758148581495815058151581525815358154581555815658157581585815958160581615816258163581645816558166581675816858169581705817158172581735817458175581765817758178581795818058181581825818358184581855818658187581885818958190581915819258193581945819558196581975819858199582005820158202582035820458205582065820758208582095821058211582125821358214582155821658217582185821958220582215822258223582245822558226582275822858229582305823158232582335823458235582365823758238582395824058241582425824358244582455824658247582485824958250582515825258253582545825558256582575825858259582605826158262582635826458265582665826758268582695827058271582725827358274582755827658277582785827958280582815828258283582845828558286582875828858289582905829158292582935829458295582965829758298582995830058301583025830358304583055830658307583085830958310583115831258313583145831558316583175831858319583205832158322583235832458325583265832758328583295833058331583325833358334583355833658337583385833958340583415834258343583445834558346583475834858349583505835158352583535835458355583565835758358583595836058361583625836358364583655836658367583685836958370583715837258373583745837558376583775837858379583805838158382583835838458385583865838758388583895839058391583925839358394583955839658397583985839958400584015840258403584045840558406584075840858409584105841158412584135841458415584165841758418584195842058421584225842358424584255842658427584285842958430584315843258433584345843558436584375843858439584405844158442584435844458445584465844758448584495845058451584525845358454584555845658457584585845958460584615846258463584645846558466584675846858469584705847158472584735847458475584765847758478584795848058481584825848358484584855848658487584885848958490584915849258493584945849558496584975849858499585005850158502585035850458505585065850758508585095851058511585125851358514585155851658517585185851958520585215852258523585245852558526585275852858529585305853158532585335853458535585365853758538585395854058541585425854358544585455854658547585485854958550585515855258553585545855558556585575855858559585605856158562585635856458565585665856758568585695857058571585725857358574585755857658577585785857958580585815858258583585845858558586585875858858589585905859158592585935859458595585965859758598585995860058601586025860358604586055860658607586085860958610586115861258613586145861558616586175861858619586205862158622586235862458625586265862758628586295863058631586325863358634586355863658637586385863958640586415864258643586445864558646586475864858649586505865158652586535865458655586565865758658586595866058661586625866358664586655866658667586685866958670586715867258673586745867558676586775867858679586805868158682586835868458685586865868758688586895869058691586925869358694586955869658697586985869958700587015870258703587045870558706587075870858709587105871158712587135871458715587165871758718587195872058721587225872358724587255872658727587285872958730587315873258733587345873558736587375873858739587405874158742587435874458745587465874758748587495875058751587525875358754587555875658757587585875958760587615876258763587645876558766587675876858769587705877158772587735877458775587765877758778587795878058781587825878358784587855878658787587885878958790587915879258793587945879558796587975879858799588005880158802588035880458805588065880758808588095881058811588125881358814588155881658817588185881958820588215882258823588245882558826588275882858829588305883158832588335883458835588365883758838588395884058841588425884358844588455884658847588485884958850588515885258853588545885558856588575885858859588605886158862588635886458865588665886758868588695887058871588725887358874588755887658877588785887958880588815888258883588845888558886588875888858889588905889158892588935889458895588965889758898588995890058901589025890358904589055890658907589085890958910589115891258913589145891558916589175891858919589205892158922589235892458925589265892758928589295893058931589325893358934589355893658937589385893958940589415894258943589445894558946589475894858949589505895158952589535895458955589565895758958589595896058961589625896358964589655896658967589685896958970589715897258973589745897558976589775897858979589805898158982589835898458985589865898758988589895899058991589925899358994589955899658997589985899959000590015900259003590045900559006590075900859009590105901159012590135901459015590165901759018590195902059021590225902359024590255902659027590285902959030590315903259033590345903559036590375903859039590405904159042590435904459045590465904759048590495905059051590525905359054590555905659057590585905959060590615906259063590645906559066590675906859069590705907159072590735907459075590765907759078590795908059081590825908359084590855908659087590885908959090590915909259093590945909559096590975909859099591005910159102591035910459105591065910759108591095911059111591125911359114591155911659117591185911959120591215912259123591245912559126591275912859129591305913159132591335913459135591365913759138591395914059141591425914359144591455914659147591485914959150591515915259153591545915559156591575915859159591605916159162591635916459165591665916759168591695917059171591725917359174591755917659177591785917959180591815918259183591845918559186591875918859189591905919159192591935919459195591965919759198591995920059201592025920359204592055920659207592085920959210592115921259213592145921559216592175921859219592205922159222592235922459225592265922759228592295923059231592325923359234592355923659237592385923959240592415924259243592445924559246592475924859249592505925159252592535925459255592565925759258592595926059261592625926359264592655926659267592685926959270592715927259273592745927559276592775927859279592805928159282592835928459285592865928759288592895929059291592925929359294592955929659297592985929959300593015930259303593045930559306593075930859309593105931159312593135931459315593165931759318593195932059321593225932359324593255932659327593285932959330593315933259333593345933559336593375933859339593405934159342593435934459345593465934759348593495935059351593525935359354593555935659357593585935959360593615936259363593645936559366593675936859369593705937159372593735937459375593765937759378593795938059381593825938359384593855938659387593885938959390593915939259393593945939559396593975939859399594005940159402594035940459405594065940759408594095941059411594125941359414594155941659417594185941959420594215942259423594245942559426594275942859429594305943159432594335943459435594365943759438594395944059441594425944359444594455944659447594485944959450594515945259453594545945559456594575945859459594605946159462594635946459465594665946759468594695947059471594725947359474594755947659477594785947959480594815948259483594845948559486594875948859489594905949159492594935949459495594965949759498594995950059501595025950359504595055950659507595085950959510595115951259513595145951559516595175951859519595205952159522595235952459525595265952759528595295953059531595325953359534595355953659537595385953959540595415954259543595445954559546595475954859549595505955159552595535955459555595565955759558595595956059561595625956359564595655956659567595685956959570595715957259573595745957559576595775957859579595805958159582595835958459585595865958759588595895959059591595925959359594595955959659597595985959959600596015960259603596045960559606596075960859609596105961159612596135961459615596165961759618596195962059621596225962359624596255962659627596285962959630596315963259633596345963559636596375963859639596405964159642596435964459645596465964759648596495965059651596525965359654596555965659657596585965959660596615966259663596645966559666596675966859669596705967159672596735967459675596765967759678596795968059681596825968359684596855968659687596885968959690596915969259693596945969559696596975969859699597005970159702597035970459705597065970759708597095971059711597125971359714597155971659717597185971959720597215972259723597245972559726597275972859729597305973159732597335973459735597365973759738597395974059741597425974359744597455974659747597485974959750597515975259753597545975559756597575975859759597605976159762597635976459765597665976759768597695977059771597725977359774597755977659777597785977959780597815978259783597845978559786597875978859789597905979159792597935979459795597965979759798597995980059801598025980359804598055980659807598085980959810598115981259813598145981559816598175981859819598205982159822598235982459825598265982759828598295983059831598325983359834598355983659837598385983959840598415984259843598445984559846598475984859849598505985159852598535985459855598565985759858598595986059861598625986359864598655986659867598685986959870598715987259873598745987559876598775987859879598805988159882598835988459885598865988759888598895989059891598925989359894598955989659897598985989959900599015990259903599045990559906599075990859909599105991159912599135991459915599165991759918599195992059921599225992359924599255992659927599285992959930599315993259933599345993559936599375993859939599405994159942599435994459945599465994759948599495995059951599525995359954599555995659957599585995959960599615996259963599645996559966599675996859969599705997159972599735997459975599765997759978599795998059981599825998359984599855998659987599885998959990599915999259993599945999559996599975999859999600006000160002600036000460005600066000760008600096001060011600126001360014600156001660017600186001960020600216002260023600246002560026600276002860029600306003160032600336003460035600366003760038600396004060041600426004360044600456004660047600486004960050600516005260053600546005560056600576005860059600606006160062600636006460065600666006760068600696007060071600726007360074600756007660077600786007960080600816008260083600846008560086600876008860089600906009160092600936009460095600966009760098600996010060101601026010360104601056010660107601086010960110601116011260113601146011560116601176011860119601206012160122601236012460125601266012760128601296013060131601326013360134601356013660137601386013960140601416014260143601446014560146601476014860149601506015160152601536015460155601566015760158601596016060161601626016360164601656016660167601686016960170601716017260173601746017560176601776017860179601806018160182601836018460185601866018760188601896019060191601926019360194601956019660197601986019960200602016020260203602046020560206602076020860209602106021160212602136021460215602166021760218602196022060221602226022360224602256022660227602286022960230602316023260233602346023560236602376023860239602406024160242602436024460245602466024760248602496025060251602526025360254602556025660257602586025960260602616026260263602646026560266602676026860269602706027160272602736027460275602766027760278602796028060281602826028360284602856028660287602886028960290602916029260293602946029560296602976029860299603006030160302603036030460305603066030760308603096031060311603126031360314603156031660317603186031960320603216032260323603246032560326603276032860329603306033160332603336033460335603366033760338603396034060341603426034360344603456034660347603486034960350603516035260353603546035560356603576035860359603606036160362603636036460365603666036760368603696037060371603726037360374603756037660377603786037960380603816038260383603846038560386603876038860389603906039160392603936039460395603966039760398603996040060401604026040360404604056040660407604086040960410604116041260413604146041560416604176041860419604206042160422604236042460425604266042760428604296043060431604326043360434604356043660437604386043960440604416044260443604446044560446604476044860449604506045160452604536045460455604566045760458604596046060461604626046360464604656046660467604686046960470604716047260473604746047560476604776047860479604806048160482604836048460485604866048760488604896049060491604926049360494604956049660497604986049960500605016050260503605046050560506605076050860509605106051160512605136051460515605166051760518605196052060521605226052360524605256052660527605286052960530605316053260533605346053560536605376053860539605406054160542605436054460545605466054760548605496055060551605526055360554605556055660557605586055960560605616056260563605646056560566605676056860569605706057160572605736057460575605766057760578605796058060581605826058360584605856058660587605886058960590605916059260593605946059560596605976059860599606006060160602606036060460605606066060760608606096061060611606126061360614606156061660617606186061960620606216062260623606246062560626606276062860629606306063160632606336063460635606366063760638606396064060641606426064360644606456064660647606486064960650606516065260653606546065560656606576065860659606606066160662606636066460665606666066760668606696067060671606726067360674606756067660677606786067960680606816068260683606846068560686606876068860689606906069160692606936069460695606966069760698606996070060701607026070360704607056070660707607086070960710607116071260713607146071560716607176071860719607206072160722607236072460725607266072760728607296073060731607326073360734607356073660737607386073960740607416074260743607446074560746607476074860749607506075160752607536075460755607566075760758607596076060761607626076360764607656076660767607686076960770607716077260773607746077560776607776077860779607806078160782607836078460785607866078760788607896079060791607926079360794607956079660797607986079960800608016080260803608046080560806608076080860809608106081160812608136081460815608166081760818608196082060821608226082360824608256082660827608286082960830608316083260833608346083560836608376083860839608406084160842608436084460845608466084760848608496085060851608526085360854608556085660857608586085960860608616086260863608646086560866608676086860869608706087160872608736087460875608766087760878608796088060881608826088360884608856088660887608886088960890608916089260893608946089560896608976089860899609006090160902609036090460905609066090760908609096091060911609126091360914609156091660917609186091960920609216092260923609246092560926609276092860929609306093160932609336093460935609366093760938609396094060941609426094360944609456094660947609486094960950609516095260953609546095560956609576095860959609606096160962609636096460965609666096760968609696097060971609726097360974609756097660977609786097960980609816098260983609846098560986609876098860989609906099160992609936099460995609966099760998609996100061001610026100361004610056100661007610086100961010610116101261013610146101561016610176101861019610206102161022610236102461025610266102761028610296103061031610326103361034610356103661037610386103961040610416104261043610446104561046610476104861049610506105161052610536105461055610566105761058610596106061061610626106361064610656106661067610686106961070610716107261073610746107561076610776107861079610806108161082610836108461085610866108761088610896109061091610926109361094610956109661097610986109961100611016110261103611046110561106611076110861109611106111161112611136111461115611166111761118611196112061121611226112361124611256112661127611286112961130611316113261133611346113561136611376113861139611406114161142611436114461145611466114761148611496115061151611526115361154611556115661157611586115961160611616116261163611646116561166611676116861169611706117161172611736117461175611766117761178611796118061181611826118361184611856118661187611886118961190611916119261193611946119561196611976119861199612006120161202612036120461205612066120761208612096121061211612126121361214612156121661217612186121961220612216122261223612246122561226612276122861229612306123161232612336123461235612366123761238612396124061241612426124361244612456124661247612486124961250612516125261253612546125561256612576125861259612606126161262612636126461265612666126761268612696127061271612726127361274612756127661277612786127961280612816128261283612846128561286612876128861289612906129161292612936129461295612966129761298612996130061301613026130361304613056130661307613086130961310613116131261313613146131561316613176131861319613206132161322613236132461325613266132761328613296133061331613326133361334613356133661337613386133961340613416134261343613446134561346613476134861349613506135161352613536135461355613566135761358613596136061361613626136361364613656136661367613686136961370613716137261373613746137561376613776137861379613806138161382613836138461385613866138761388613896139061391613926139361394613956139661397613986139961400614016140261403614046140561406614076140861409614106141161412614136141461415614166141761418614196142061421614226142361424614256142661427614286142961430614316143261433614346143561436614376143861439614406144161442614436144461445614466144761448614496145061451614526145361454614556145661457614586145961460614616146261463614646146561466614676146861469614706147161472614736147461475614766147761478614796148061481614826148361484614856148661487614886148961490614916149261493614946149561496614976149861499615006150161502615036150461505615066150761508615096151061511615126151361514615156151661517615186151961520615216152261523615246152561526615276152861529615306153161532615336153461535615366153761538615396154061541615426154361544615456154661547615486154961550615516155261553615546155561556615576155861559615606156161562615636156461565615666156761568615696157061571615726157361574615756157661577615786157961580615816158261583615846158561586615876158861589615906159161592615936159461595615966159761598615996160061601616026160361604616056160661607616086160961610616116161261613616146161561616616176161861619616206162161622616236162461625616266162761628616296163061631616326163361634616356163661637616386163961640616416164261643616446164561646616476164861649616506165161652616536165461655616566165761658616596166061661616626166361664616656166661667616686166961670616716167261673616746167561676616776167861679616806168161682616836168461685616866168761688616896169061691616926169361694616956169661697616986169961700617016170261703617046170561706617076170861709617106171161712617136171461715617166171761718617196172061721617226172361724617256172661727617286172961730617316173261733617346173561736617376173861739617406174161742617436174461745617466174761748617496175061751617526175361754617556175661757617586175961760617616176261763617646176561766617676176861769617706177161772617736177461775617766177761778617796178061781617826178361784617856178661787617886178961790617916179261793617946179561796617976179861799618006180161802618036180461805618066180761808618096181061811618126181361814618156181661817618186181961820618216182261823618246182561826618276182861829618306183161832618336183461835618366183761838618396184061841618426184361844618456184661847618486184961850618516185261853618546185561856618576185861859618606186161862618636186461865618666186761868618696187061871618726187361874618756187661877618786187961880618816188261883618846188561886618876188861889618906189161892618936189461895618966189761898618996190061901619026190361904619056190661907619086190961910619116191261913619146191561916619176191861919619206192161922619236192461925619266192761928619296193061931619326193361934619356193661937619386193961940619416194261943619446194561946619476194861949619506195161952619536195461955619566195761958619596196061961619626196361964619656196661967619686196961970619716197261973619746197561976619776197861979619806198161982619836198461985619866198761988619896199061991619926199361994619956199661997619986199962000620016200262003620046200562006620076200862009620106201162012620136201462015620166201762018620196202062021620226202362024620256202662027620286202962030620316203262033620346203562036620376203862039620406204162042620436204462045620466204762048620496205062051620526205362054620556205662057620586205962060620616206262063620646206562066620676206862069620706207162072620736207462075620766207762078620796208062081620826208362084620856208662087620886208962090620916209262093620946209562096620976209862099621006210162102621036210462105621066210762108621096211062111621126211362114621156211662117621186211962120621216212262123621246212562126621276212862129621306213162132621336213462135621366213762138621396214062141621426214362144621456214662147621486214962150621516215262153621546215562156621576215862159621606216162162621636216462165621666216762168621696217062171621726217362174621756217662177621786217962180621816218262183621846218562186621876218862189621906219162192621936219462195621966219762198621996220062201622026220362204622056220662207622086220962210622116221262213622146221562216622176221862219622206222162222622236222462225622266222762228622296223062231622326223362234622356223662237622386223962240622416224262243622446224562246622476224862249622506225162252622536225462255622566225762258622596226062261622626226362264622656226662267622686226962270622716227262273622746227562276622776227862279622806228162282622836228462285622866228762288622896229062291622926229362294622956229662297622986229962300623016230262303623046230562306623076230862309623106231162312623136231462315623166231762318623196232062321623226232362324623256232662327623286232962330623316233262333623346233562336623376233862339623406234162342623436234462345623466234762348623496235062351623526235362354623556235662357623586235962360623616236262363623646236562366623676236862369623706237162372623736237462375623766237762378623796238062381623826238362384623856238662387623886238962390623916239262393623946239562396623976239862399624006240162402624036240462405624066240762408624096241062411624126241362414624156241662417624186241962420624216242262423624246242562426624276242862429624306243162432624336243462435624366243762438624396244062441624426244362444624456244662447624486244962450624516245262453624546245562456624576245862459624606246162462624636246462465624666246762468624696247062471624726247362474624756247662477624786247962480624816248262483624846248562486624876248862489624906249162492624936249462495624966249762498624996250062501625026250362504625056250662507625086250962510625116251262513625146251562516625176251862519625206252162522625236252462525625266252762528625296253062531625326253362534625356253662537625386253962540625416254262543625446254562546625476254862549625506255162552625536255462555625566255762558625596256062561625626256362564625656256662567625686256962570625716257262573625746257562576625776257862579625806258162582625836258462585625866258762588625896259062591625926259362594625956259662597625986259962600626016260262603626046260562606626076260862609626106261162612626136261462615626166261762618626196262062621626226262362624626256262662627626286262962630626316263262633626346263562636626376263862639626406264162642626436264462645626466264762648626496265062651626526265362654626556265662657626586265962660626616266262663626646266562666626676266862669626706267162672626736267462675626766267762678626796268062681626826268362684626856268662687626886268962690626916269262693626946269562696626976269862699627006270162702627036270462705627066270762708627096271062711627126271362714627156271662717627186271962720627216272262723627246272562726627276272862729627306273162732627336273462735627366273762738627396274062741627426274362744627456274662747627486274962750627516275262753627546275562756627576275862759627606276162762627636276462765627666276762768627696277062771627726277362774627756277662777627786277962780627816278262783627846278562786627876278862789627906279162792627936279462795627966279762798627996280062801628026280362804628056280662807628086280962810628116281262813628146281562816628176281862819628206282162822628236282462825628266282762828628296283062831628326283362834628356283662837628386283962840628416284262843628446284562846628476284862849628506285162852628536285462855628566285762858628596286062861628626286362864628656286662867628686286962870628716287262873628746287562876628776287862879628806288162882628836288462885628866288762888628896289062891628926289362894628956289662897628986289962900629016290262903629046290562906629076290862909629106291162912629136291462915629166291762918629196292062921629226292362924629256292662927629286292962930629316293262933629346293562936629376293862939629406294162942629436294462945629466294762948629496295062951629526295362954629556295662957629586295962960629616296262963629646296562966629676296862969629706297162972629736297462975629766297762978629796298062981629826298362984629856298662987629886298962990629916299262993629946299562996629976299862999630006300163002630036300463005630066300763008630096301063011630126301363014630156301663017630186301963020630216302263023630246302563026630276302863029630306303163032630336303463035630366303763038630396304063041630426304363044630456304663047630486304963050630516305263053630546305563056630576305863059630606306163062630636306463065630666306763068630696307063071630726307363074630756307663077630786307963080630816308263083630846308563086630876308863089630906309163092630936309463095630966309763098630996310063101631026310363104631056310663107631086310963110631116311263113631146311563116631176311863119631206312163122631236312463125631266312763128631296313063131631326313363134631356313663137631386313963140631416314263143631446314563146631476314863149631506315163152631536315463155631566315763158631596316063161631626316363164631656316663167631686316963170631716317263173631746317563176631776317863179631806318163182631836318463185631866318763188631896319063191631926319363194631956319663197631986319963200632016320263203632046320563206632076320863209632106321163212632136321463215632166321763218632196322063221632226322363224632256322663227632286322963230632316323263233632346323563236632376323863239632406324163242632436324463245632466324763248632496325063251632526325363254632556325663257632586325963260632616326263263632646326563266632676326863269632706327163272632736327463275632766327763278632796328063281632826328363284632856328663287632886328963290632916329263293632946329563296632976329863299633006330163302633036330463305633066330763308633096331063311633126331363314633156331663317633186331963320633216332263323633246332563326633276332863329633306333163332633336333463335633366333763338633396334063341633426334363344633456334663347633486334963350633516335263353633546335563356633576335863359633606336163362633636336463365633666336763368633696337063371633726337363374633756337663377633786337963380633816338263383633846338563386633876338863389633906339163392633936339463395633966339763398633996340063401634026340363404634056340663407634086340963410634116341263413634146341563416634176341863419634206342163422634236342463425634266342763428634296343063431634326343363434634356343663437634386343963440634416344263443634446344563446634476344863449634506345163452634536345463455634566345763458634596346063461634626346363464634656346663467634686346963470634716347263473634746347563476634776347863479634806348163482634836348463485634866348763488634896349063491634926349363494634956349663497634986349963500635016350263503635046350563506635076350863509635106351163512635136351463515635166351763518635196352063521635226352363524635256352663527635286352963530635316353263533635346353563536635376353863539635406354163542635436354463545635466354763548635496355063551635526355363554635556355663557635586355963560635616356263563635646356563566635676356863569635706357163572635736357463575635766357763578635796358063581635826358363584635856358663587635886358963590635916359263593635946359563596635976359863599636006360163602636036360463605636066360763608636096361063611636126361363614636156361663617636186361963620636216362263623636246362563626636276362863629636306363163632636336363463635636366363763638636396364063641636426364363644636456364663647636486364963650636516365263653636546365563656636576365863659636606366163662636636366463665636666366763668636696367063671636726367363674636756367663677636786367963680636816368263683636846368563686636876368863689636906369163692636936369463695636966369763698636996370063701637026370363704637056370663707637086370963710637116371263713637146371563716637176371863719637206372163722637236372463725637266372763728637296373063731637326373363734637356373663737637386373963740637416374263743637446374563746637476374863749637506375163752637536375463755637566375763758637596376063761637626376363764637656376663767637686376963770637716377263773637746377563776637776377863779637806378163782637836378463785637866378763788637896379063791637926379363794637956379663797637986379963800638016380263803638046380563806638076380863809638106381163812638136381463815638166381763818638196382063821638226382363824638256382663827638286382963830638316383263833638346383563836638376383863839638406384163842638436384463845638466384763848638496385063851638526385363854638556385663857638586385963860638616386263863638646386563866638676386863869638706387163872638736387463875638766387763878638796388063881638826388363884638856388663887638886388963890638916389263893638946389563896638976389863899639006390163902639036390463905639066390763908639096391063911639126391363914639156391663917639186391963920639216392263923639246392563926639276392863929639306393163932639336393463935639366393763938639396394063941639426394363944639456394663947639486394963950639516395263953639546395563956639576395863959639606396163962639636396463965639666396763968639696397063971639726397363974639756397663977639786397963980639816398263983639846398563986639876398863989639906399163992639936399463995639966399763998639996400064001640026400364004640056400664007640086400964010640116401264013640146401564016640176401864019640206402164022640236402464025640266402764028640296403064031640326403364034640356403664037640386403964040640416404264043640446404564046640476404864049640506405164052640536405464055640566405764058640596406064061640626406364064640656406664067640686406964070640716407264073640746407564076640776407864079640806408164082640836408464085640866408764088640896409064091640926409364094640956409664097640986409964100641016410264103641046410564106641076410864109641106411164112641136411464115641166411764118641196412064121641226412364124641256412664127641286412964130641316413264133641346413564136641376413864139641406414164142641436414464145641466414764148641496415064151641526415364154641556415664157641586415964160641616416264163641646416564166641676416864169641706417164172641736417464175641766417764178641796418064181641826418364184641856418664187641886418964190641916419264193641946419564196641976419864199642006420164202642036420464205642066420764208642096421064211642126421364214642156421664217642186421964220642216422264223642246422564226642276422864229642306423164232642336423464235642366423764238642396424064241642426424364244642456424664247642486424964250642516425264253642546425564256642576425864259642606426164262642636426464265642666426764268642696427064271642726427364274642756427664277642786427964280642816428264283642846428564286642876428864289642906429164292642936429464295642966429764298642996430064301643026430364304643056430664307643086430964310643116431264313643146431564316643176431864319643206432164322643236432464325643266432764328643296433064331643326433364334643356433664337643386433964340643416434264343643446434564346643476434864349643506435164352643536435464355643566435764358643596436064361643626436364364643656436664367643686436964370643716437264373643746437564376643776437864379643806438164382643836438464385643866438764388643896439064391643926439364394643956439664397643986439964400644016440264403644046440564406644076440864409644106441164412644136441464415644166441764418644196442064421644226442364424644256442664427644286442964430644316443264433644346443564436644376443864439644406444164442644436444464445644466444764448644496445064451644526445364454644556445664457644586445964460644616446264463644646446564466644676446864469644706447164472644736447464475644766447764478644796448064481644826448364484644856448664487644886448964490644916449264493644946449564496644976449864499645006450164502645036450464505645066450764508645096451064511645126451364514645156451664517645186451964520645216452264523645246452564526645276452864529645306453164532645336453464535645366453764538645396454064541645426454364544645456454664547645486454964550645516455264553645546455564556645576455864559645606456164562645636456464565645666456764568645696457064571645726457364574645756457664577645786457964580645816458264583645846458564586645876458864589645906459164592645936459464595645966459764598645996460064601646026460364604646056460664607646086460964610646116461264613646146461564616646176461864619646206462164622646236462464625646266462764628646296463064631646326463364634646356463664637646386463964640646416464264643646446464564646646476464864649646506465164652646536465464655646566465764658646596466064661646626466364664646656466664667646686466964670646716467264673646746467564676646776467864679646806468164682646836468464685646866468764688646896469064691646926469364694646956469664697646986469964700647016470264703647046470564706647076470864709647106471164712647136471464715647166471764718647196472064721647226472364724647256472664727647286472964730647316473264733647346473564736647376473864739647406474164742647436474464745647466474764748647496475064751647526475364754647556475664757647586475964760647616476264763647646476564766647676476864769647706477164772647736477464775647766477764778647796478064781647826478364784647856478664787647886478964790647916479264793647946479564796647976479864799648006480164802648036480464805648066480764808648096481064811648126481364814648156481664817648186481964820648216482264823648246482564826648276482864829648306483164832648336483464835648366483764838648396484064841648426484364844648456484664847648486484964850648516485264853648546485564856648576485864859648606486164862648636486464865648666486764868648696487064871648726487364874648756487664877648786487964880648816488264883648846488564886648876488864889648906489164892648936489464895648966489764898648996490064901649026490364904649056490664907649086490964910649116491264913649146491564916649176491864919649206492164922649236492464925649266492764928649296493064931649326493364934649356493664937649386493964940649416494264943649446494564946649476494864949649506495164952649536495464955649566495764958649596496064961649626496364964649656496664967649686496964970649716497264973649746497564976649776497864979649806498164982649836498464985649866498764988649896499064991649926499364994649956499664997649986499965000650016500265003650046500565006650076500865009650106501165012650136501465015650166501765018650196502065021650226502365024650256502665027650286502965030650316503265033650346503565036650376503865039650406504165042650436504465045650466504765048650496505065051650526505365054650556505665057650586505965060650616506265063650646506565066650676506865069650706507165072650736507465075650766507765078650796508065081650826508365084650856508665087650886508965090650916509265093650946509565096650976509865099651006510165102651036510465105651066510765108651096511065111651126511365114651156511665117651186511965120651216512265123651246512565126651276512865129651306513165132651336513465135651366513765138651396514065141651426514365144651456514665147651486514965150651516515265153651546515565156651576515865159651606516165162651636516465165651666516765168651696517065171651726517365174651756517665177651786517965180651816518265183651846518565186651876518865189651906519165192651936519465195651966519765198651996520065201652026520365204652056520665207652086520965210652116521265213652146521565216652176521865219652206522165222652236522465225652266522765228652296523065231652326523365234652356523665237652386523965240652416524265243652446524565246652476524865249652506525165252652536525465255652566525765258652596526065261652626526365264652656526665267652686526965270652716527265273652746527565276652776527865279652806528165282652836528465285652866528765288652896529065291652926529365294652956529665297652986529965300653016530265303653046530565306653076530865309653106531165312653136531465315653166531765318653196532065321653226532365324653256532665327653286532965330653316533265333653346533565336653376533865339653406534165342653436534465345653466534765348653496535065351653526535365354653556535665357653586535965360653616536265363653646536565366653676536865369653706537165372653736537465375653766537765378653796538065381653826538365384653856538665387653886538965390653916539265393653946539565396653976539865399654006540165402654036540465405654066540765408654096541065411654126541365414654156541665417654186541965420654216542265423654246542565426654276542865429654306543165432654336543465435654366543765438654396544065441654426544365444654456544665447654486544965450654516545265453654546545565456654576545865459654606546165462654636546465465654666546765468654696547065471654726547365474654756547665477654786547965480654816548265483654846548565486654876548865489654906549165492654936549465495654966549765498654996550065501655026550365504655056550665507655086550965510655116551265513655146551565516655176551865519655206552165522655236552465525655266552765528655296553065531655326553365534655356553665537655386553965540655416554265543655446554565546655476554865549655506555165552655536555465555655566555765558655596556065561655626556365564655656556665567655686556965570655716557265573655746557565576655776557865579655806558165582655836558465585655866558765588655896559065591655926559365594655956559665597655986559965600656016560265603656046560565606656076560865609656106561165612656136561465615656166561765618656196562065621656226562365624656256562665627656286562965630656316563265633656346563565636656376563865639656406564165642656436564465645656466564765648656496565065651656526565365654656556565665657656586565965660656616566265663656646566565666656676566865669656706567165672656736567465675656766567765678656796568065681656826568365684656856568665687656886568965690656916569265693656946569565696656976569865699657006570165702657036570465705657066570765708657096571065711657126571365714657156571665717657186571965720657216572265723657246572565726657276572865729657306573165732657336573465735657366573765738657396574065741657426574365744657456574665747657486574965750657516575265753657546575565756657576575865759657606576165762657636576465765657666576765768657696577065771657726577365774657756577665777657786577965780657816578265783657846578565786657876578865789657906579165792657936579465795657966579765798657996580065801658026580365804658056580665807658086580965810658116581265813658146581565816658176581865819658206582165822658236582465825658266582765828658296583065831658326583365834658356583665837658386583965840658416584265843658446584565846658476584865849658506585165852658536585465855658566585765858658596586065861658626586365864658656586665867658686586965870658716587265873658746587565876658776587865879658806588165882658836588465885658866588765888658896589065891658926589365894658956589665897658986589965900659016590265903659046590565906659076590865909659106591165912659136591465915659166591765918659196592065921659226592365924659256592665927659286592965930659316593265933659346593565936659376593865939659406594165942659436594465945659466594765948659496595065951659526595365954659556595665957659586595965960659616596265963659646596565966659676596865969659706597165972659736597465975659766597765978659796598065981659826598365984659856598665987659886598965990659916599265993659946599565996659976599865999660006600166002660036600466005660066600766008660096601066011660126601366014660156601666017660186601966020660216602266023660246602566026660276602866029660306603166032660336603466035660366603766038660396604066041660426604366044660456604666047660486604966050660516605266053660546605566056660576605866059660606606166062660636606466065660666606766068660696607066071660726607366074660756607666077660786607966080660816608266083660846608566086660876608866089660906609166092660936609466095660966609766098660996610066101661026610366104661056610666107661086610966110661116611266113661146611566116661176611866119661206612166122661236612466125661266612766128661296613066131661326613366134661356613666137661386613966140661416614266143661446614566146661476614866149661506615166152661536615466155661566615766158661596616066161661626616366164661656616666167661686616966170661716617266173661746617566176661776617866179661806618166182661836618466185661866618766188661896619066191661926619366194661956619666197661986619966200662016620266203662046620566206662076620866209662106621166212662136621466215662166621766218662196622066221662226622366224662256622666227662286622966230662316623266233662346623566236662376623866239662406624166242662436624466245662466624766248662496625066251662526625366254662556625666257662586625966260662616626266263662646626566266662676626866269662706627166272662736627466275662766627766278662796628066281662826628366284662856628666287662886628966290662916629266293662946629566296662976629866299663006630166302663036630466305663066630766308663096631066311663126631366314663156631666317663186631966320663216632266323663246632566326663276632866329663306633166332663336633466335663366633766338663396634066341663426634366344663456634666347663486634966350663516635266353663546635566356663576635866359663606636166362663636636466365663666636766368663696637066371663726637366374663756637666377663786637966380663816638266383663846638566386663876638866389663906639166392663936639466395663966639766398663996640066401664026640366404664056640666407664086640966410664116641266413664146641566416664176641866419664206642166422664236642466425664266642766428664296643066431664326643366434664356643666437664386643966440664416644266443664446644566446664476644866449664506645166452664536645466455664566645766458664596646066461664626646366464664656646666467664686646966470664716647266473664746647566476664776647866479664806648166482664836648466485664866648766488664896649066491664926649366494664956649666497664986649966500665016650266503665046650566506665076650866509665106651166512665136651466515665166651766518665196652066521665226652366524665256652666527665286652966530665316653266533665346653566536665376653866539665406654166542665436654466545665466654766548665496655066551665526655366554665556655666557665586655966560665616656266563665646656566566665676656866569665706657166572665736657466575665766657766578665796658066581665826658366584665856658666587665886658966590665916659266593665946659566596665976659866599666006660166602666036660466605666066660766608666096661066611666126661366614666156661666617666186661966620666216662266623666246662566626666276662866629666306663166632666336663466635666366663766638666396664066641666426664366644666456664666647666486664966650666516665266653666546665566656666576665866659666606666166662666636666466665666666666766668666696667066671666726667366674666756667666677666786667966680666816668266683666846668566686666876668866689666906669166692666936669466695666966669766698666996670066701667026670366704667056670666707667086670966710667116671266713667146671566716667176671866719667206672166722667236672466725667266672766728667296673066731667326673366734667356673666737667386673966740667416674266743667446674566746667476674866749667506675166752667536675466755667566675766758667596676066761667626676366764667656676666767667686676966770667716677266773667746677566776667776677866779667806678166782667836678466785667866678766788667896679066791667926679366794667956679666797667986679966800668016680266803668046680566806668076680866809668106681166812668136681466815668166681766818668196682066821668226682366824668256682666827668286682966830668316683266833668346683566836668376683866839668406684166842668436684466845668466684766848668496685066851668526685366854668556685666857668586685966860668616686266863668646686566866668676686866869668706687166872668736687466875668766687766878668796688066881668826688366884668856688666887668886688966890668916689266893668946689566896668976689866899669006690166902669036690466905669066690766908669096691066911669126691366914669156691666917669186691966920669216692266923669246692566926669276692866929669306693166932669336693466935669366693766938669396694066941669426694366944669456694666947669486694966950669516695266953669546695566956669576695866959669606696166962669636696466965669666696766968669696697066971669726697366974669756697666977669786697966980669816698266983669846698566986669876698866989669906699166992669936699466995669966699766998669996700067001670026700367004670056700667007670086700967010670116701267013670146701567016670176701867019670206702167022670236702467025670266702767028670296703067031670326703367034670356703667037670386703967040670416704267043670446704567046670476704867049670506705167052670536705467055670566705767058670596706067061670626706367064670656706667067670686706967070670716707267073670746707567076670776707867079670806708167082670836708467085670866708767088670896709067091670926709367094670956709667097670986709967100671016710267103671046710567106671076710867109671106711167112671136711467115671166711767118671196712067121671226712367124671256712667127671286712967130671316713267133671346713567136671376713867139671406714167142671436714467145671466714767148671496715067151671526715367154671556715667157671586715967160671616716267163671646716567166671676716867169671706717167172671736717467175671766717767178671796718067181671826718367184671856718667187671886718967190671916719267193671946719567196671976719867199672006720167202672036720467205672066720767208672096721067211672126721367214672156721667217672186721967220672216722267223672246722567226672276722867229672306723167232672336723467235672366723767238672396724067241672426724367244672456724667247672486724967250672516725267253672546725567256672576725867259672606726167262672636726467265672666726767268672696727067271672726727367274672756727667277672786727967280672816728267283672846728567286672876728867289672906729167292672936729467295672966729767298672996730067301673026730367304673056730667307673086730967310673116731267313673146731567316673176731867319673206732167322673236732467325673266732767328673296733067331673326733367334673356733667337673386733967340673416734267343673446734567346673476734867349673506735167352673536735467355673566735767358673596736067361673626736367364673656736667367673686736967370673716737267373673746737567376673776737867379673806738167382673836738467385673866738767388673896739067391673926739367394673956739667397673986739967400674016740267403674046740567406674076740867409674106741167412674136741467415674166741767418674196742067421674226742367424674256742667427674286742967430674316743267433674346743567436674376743867439674406744167442674436744467445674466744767448674496745067451674526745367454674556745667457674586745967460674616746267463674646746567466674676746867469674706747167472674736747467475674766747767478674796748067481674826748367484674856748667487674886748967490674916749267493674946749567496674976749867499675006750167502675036750467505675066750767508675096751067511675126751367514675156751667517675186751967520675216752267523675246752567526675276752867529675306753167532675336753467535675366753767538675396754067541675426754367544675456754667547675486754967550675516755267553675546755567556675576755867559675606756167562675636756467565675666756767568675696757067571675726757367574675756757667577675786757967580675816758267583675846758567586675876758867589675906759167592675936759467595675966759767598675996760067601676026760367604676056760667607676086760967610676116761267613676146761567616676176761867619676206762167622676236762467625676266762767628676296763067631676326763367634676356763667637676386763967640676416764267643676446764567646676476764867649676506765167652676536765467655676566765767658676596766067661676626766367664676656766667667676686766967670676716767267673676746767567676676776767867679676806768167682676836768467685676866768767688676896769067691676926769367694676956769667697676986769967700677016770267703677046770567706677076770867709677106771167712677136771467715677166771767718677196772067721677226772367724677256772667727677286772967730677316773267733677346773567736677376773867739677406774167742677436774467745677466774767748677496775067751677526775367754677556775667757677586775967760677616776267763677646776567766677676776867769677706777167772677736777467775677766777767778677796778067781677826778367784677856778667787677886778967790677916779267793677946779567796677976779867799678006780167802678036780467805678066780767808678096781067811678126781367814678156781667817678186781967820678216782267823678246782567826678276782867829678306783167832678336783467835678366783767838678396784067841678426784367844678456784667847678486784967850678516785267853678546785567856678576785867859678606786167862678636786467865678666786767868678696787067871678726787367874678756787667877678786787967880678816788267883678846788567886678876788867889678906789167892678936789467895678966789767898678996790067901679026790367904679056790667907679086790967910679116791267913679146791567916679176791867919679206792167922679236792467925679266792767928679296793067931679326793367934679356793667937679386793967940679416794267943679446794567946679476794867949679506795167952679536795467955679566795767958679596796067961679626796367964679656796667967679686796967970679716797267973679746797567976679776797867979679806798167982679836798467985679866798767988679896799067991679926799367994679956799667997679986799968000680016800268003680046800568006680076800868009680106801168012680136801468015680166801768018680196802068021680226802368024680256802668027680286802968030680316803268033680346803568036680376803868039680406804168042680436804468045680466804768048680496805068051680526805368054680556805668057680586805968060680616806268063680646806568066680676806868069680706807168072680736807468075680766807768078680796808068081680826808368084680856808668087680886808968090680916809268093680946809568096680976809868099681006810168102681036810468105681066810768108681096811068111681126811368114681156811668117681186811968120681216812268123681246812568126681276812868129681306813168132681336813468135681366813768138681396814068141681426814368144681456814668147681486814968150681516815268153681546815568156681576815868159681606816168162681636816468165681666816768168681696817068171681726817368174681756817668177681786817968180681816818268183681846818568186681876818868189681906819168192681936819468195681966819768198681996820068201682026820368204682056820668207682086820968210682116821268213682146821568216682176821868219682206822168222682236822468225682266822768228682296823068231682326823368234682356823668237682386823968240682416824268243682446824568246682476824868249682506825168252682536825468255682566825768258682596826068261682626826368264682656826668267682686826968270682716827268273682746827568276682776827868279682806828168282682836828468285682866828768288682896829068291682926829368294682956829668297682986829968300683016830268303683046830568306683076830868309683106831168312683136831468315683166831768318683196832068321683226832368324683256832668327683286832968330683316833268333683346833568336683376833868339683406834168342683436834468345683466834768348683496835068351683526835368354683556835668357683586835968360683616836268363683646836568366683676836868369683706837168372683736837468375683766837768378683796838068381683826838368384683856838668387683886838968390683916839268393683946839568396683976839868399684006840168402684036840468405684066840768408684096841068411684126841368414684156841668417684186841968420684216842268423684246842568426684276842868429684306843168432684336843468435684366843768438684396844068441684426844368444684456844668447684486844968450684516845268453684546845568456684576845868459684606846168462684636846468465684666846768468684696847068471684726847368474684756847668477684786847968480684816848268483684846848568486684876848868489684906849168492684936849468495684966849768498684996850068501685026850368504685056850668507685086850968510685116851268513685146851568516685176851868519685206852168522685236852468525685266852768528685296853068531685326853368534685356853668537685386853968540685416854268543685446854568546685476854868549685506855168552685536855468555685566855768558685596856068561685626856368564685656856668567685686856968570685716857268573685746857568576685776857868579685806858168582685836858468585685866858768588685896859068591685926859368594685956859668597685986859968600686016860268603686046860568606686076860868609686106861168612686136861468615686166861768618686196862068621686226862368624686256862668627686286862968630686316863268633686346863568636686376863868639686406864168642686436864468645686466864768648686496865068651686526865368654686556865668657686586865968660686616866268663686646866568666686676866868669686706867168672686736867468675686766867768678686796868068681686826868368684686856868668687686886868968690686916869268693686946869568696686976869868699687006870168702687036870468705687066870768708687096871068711687126871368714687156871668717687186871968720687216872268723687246872568726687276872868729687306873168732687336873468735687366873768738687396874068741687426874368744687456874668747687486874968750687516875268753687546875568756687576875868759687606876168762687636876468765687666876768768687696877068771687726877368774687756877668777687786877968780687816878268783687846878568786687876878868789687906879168792687936879468795687966879768798687996880068801688026880368804688056880668807688086880968810688116881268813688146881568816688176881868819688206882168822688236882468825688266882768828688296883068831688326883368834688356883668837688386883968840688416884268843688446884568846688476884868849688506885168852688536885468855688566885768858688596886068861688626886368864688656886668867688686886968870688716887268873688746887568876688776887868879688806888168882688836888468885688866888768888688896889068891688926889368894688956889668897688986889968900689016890268903689046890568906689076890868909689106891168912689136891468915689166891768918689196892068921689226892368924689256892668927689286892968930689316893268933689346893568936689376893868939689406894168942689436894468945689466894768948689496895068951689526895368954689556895668957689586895968960689616896268963689646896568966689676896868969689706897168972689736897468975689766897768978689796898068981689826898368984689856898668987689886898968990689916899268993689946899568996689976899868999690006900169002690036900469005690066900769008690096901069011690126901369014690156901669017690186901969020690216902269023690246902569026690276902869029690306903169032690336903469035690366903769038690396904069041690426904369044690456904669047690486904969050690516905269053690546905569056690576905869059690606906169062690636906469065690666906769068690696907069071690726907369074690756907669077690786907969080690816908269083690846908569086690876908869089690906909169092690936909469095690966909769098690996910069101691026910369104691056910669107691086910969110691116911269113691146911569116691176911869119691206912169122691236912469125691266912769128691296913069131691326913369134691356913669137691386913969140691416914269143691446914569146691476914869149691506915169152691536915469155691566915769158691596916069161691626916369164691656916669167691686916969170691716917269173691746917569176691776917869179691806918169182691836918469185691866918769188691896919069191691926919369194691956919669197691986919969200692016920269203692046920569206692076920869209692106921169212692136921469215692166921769218692196922069221692226922369224692256922669227692286922969230692316923269233692346923569236692376923869239692406924169242692436924469245692466924769248692496925069251692526925369254692556925669257692586925969260692616926269263692646926569266692676926869269692706927169272692736927469275692766927769278692796928069281692826928369284692856928669287692886928969290692916929269293692946929569296692976929869299693006930169302693036930469305693066930769308693096931069311693126931369314693156931669317693186931969320693216932269323693246932569326693276932869329693306933169332693336933469335693366933769338693396934069341693426934369344693456934669347693486934969350693516935269353693546935569356693576935869359693606936169362693636936469365693666936769368693696937069371693726937369374693756937669377693786937969380693816938269383693846938569386693876938869389693906939169392693936939469395693966939769398693996940069401694026940369404694056940669407694086940969410694116941269413694146941569416694176941869419694206942169422694236942469425694266942769428694296943069431694326943369434694356943669437694386943969440694416944269443694446944569446694476944869449694506945169452694536945469455694566945769458694596946069461694626946369464694656946669467694686946969470694716947269473694746947569476694776947869479694806948169482694836948469485694866948769488694896949069491694926949369494694956949669497694986949969500695016950269503695046950569506695076950869509695106951169512695136951469515695166951769518695196952069521695226952369524695256952669527695286952969530695316953269533695346953569536695376953869539695406954169542695436954469545695466954769548695496955069551695526955369554695556955669557695586955969560695616956269563695646956569566695676956869569695706957169572695736957469575695766957769578695796958069581695826958369584695856958669587695886958969590695916959269593695946959569596695976959869599696006960169602696036960469605696066960769608696096961069611696126961369614696156961669617696186961969620696216962269623696246962569626696276962869629696306963169632696336963469635696366963769638696396964069641696426964369644696456964669647696486964969650696516965269653696546965569656696576965869659696606966169662696636966469665696666966769668696696967069671696726967369674696756967669677696786967969680696816968269683696846968569686696876968869689696906969169692696936969469695696966969769698696996970069701697026970369704697056970669707697086970969710697116971269713697146971569716697176971869719697206972169722697236972469725697266972769728697296973069731697326973369734697356973669737697386973969740697416974269743697446974569746697476974869749697506975169752697536975469755697566975769758697596976069761697626976369764697656976669767697686976969770697716977269773697746977569776697776977869779697806978169782697836978469785697866978769788697896979069791697926979369794697956979669797697986979969800698016980269803698046980569806698076980869809698106981169812698136981469815698166981769818698196982069821698226982369824698256982669827698286982969830698316983269833698346983569836698376983869839698406984169842698436984469845698466984769848698496985069851698526985369854698556985669857698586985969860698616986269863698646986569866698676986869869698706987169872698736987469875698766987769878698796988069881698826988369884698856988669887698886988969890698916989269893698946989569896698976989869899699006990169902699036990469905699066990769908699096991069911699126991369914699156991669917699186991969920699216992269923699246992569926699276992869929699306993169932699336993469935699366993769938699396994069941699426994369944699456994669947699486994969950699516995269953699546995569956699576995869959699606996169962699636996469965699666996769968699696997069971699726997369974699756997669977699786997969980699816998269983699846998569986699876998869989699906999169992699936999469995699966999769998699997000070001700027000370004700057000670007700087000970010700117001270013700147001570016700177001870019700207002170022700237002470025700267002770028700297003070031700327003370034700357003670037700387003970040700417004270043700447004570046700477004870049700507005170052700537005470055700567005770058700597006070061700627006370064700657006670067700687006970070700717007270073700747007570076700777007870079700807008170082700837008470085700867008770088700897009070091700927009370094700957009670097700987009970100701017010270103701047010570106701077010870109701107011170112701137011470115701167011770118701197012070121701227012370124701257012670127701287012970130701317013270133701347013570136701377013870139701407014170142701437014470145701467014770148701497015070151701527015370154701557015670157701587015970160701617016270163701647016570166701677016870169701707017170172701737017470175701767017770178701797018070181701827018370184701857018670187701887018970190701917019270193701947019570196701977019870199702007020170202702037020470205702067020770208702097021070211702127021370214702157021670217702187021970220702217022270223702247022570226702277022870229702307023170232702337023470235702367023770238702397024070241702427024370244702457024670247702487024970250702517025270253702547025570256702577025870259702607026170262702637026470265702667026770268702697027070271702727027370274702757027670277702787027970280702817028270283702847028570286702877028870289702907029170292702937029470295702967029770298702997030070301703027030370304703057030670307703087030970310703117031270313703147031570316703177031870319703207032170322703237032470325703267032770328703297033070331703327033370334703357033670337703387033970340703417034270343703447034570346703477034870349703507035170352703537035470355703567035770358703597036070361703627036370364703657036670367703687036970370703717037270373703747037570376703777037870379703807038170382703837038470385703867038770388703897039070391703927039370394703957039670397703987039970400704017040270403704047040570406704077040870409704107041170412704137041470415704167041770418704197042070421704227042370424704257042670427704287042970430704317043270433704347043570436704377043870439704407044170442704437044470445704467044770448704497045070451704527045370454704557045670457704587045970460704617046270463704647046570466704677046870469704707047170472704737047470475704767047770478704797048070481704827048370484704857048670487704887048970490704917049270493704947049570496704977049870499705007050170502705037050470505705067050770508705097051070511705127051370514705157051670517705187051970520705217052270523705247052570526705277052870529705307053170532705337053470535705367053770538705397054070541705427054370544705457054670547705487054970550705517055270553705547055570556705577055870559705607056170562705637056470565705667056770568705697057070571705727057370574705757057670577705787057970580705817058270583705847058570586705877058870589705907059170592705937059470595705967059770598705997060070601706027060370604706057060670607706087060970610706117061270613706147061570616706177061870619706207062170622706237062470625706267062770628706297063070631706327063370634706357063670637706387063970640706417064270643706447064570646706477064870649706507065170652706537065470655706567065770658706597066070661706627066370664706657066670667706687066970670706717067270673706747067570676706777067870679706807068170682706837068470685706867068770688706897069070691706927069370694706957069670697706987069970700707017070270703707047070570706707077070870709707107071170712707137071470715707167071770718707197072070721707227072370724707257072670727707287072970730707317073270733707347073570736707377073870739707407074170742707437074470745707467074770748707497075070751707527075370754707557075670757707587075970760707617076270763707647076570766707677076870769707707077170772707737077470775707767077770778707797078070781707827078370784707857078670787707887078970790707917079270793707947079570796707977079870799708007080170802708037080470805708067080770808708097081070811708127081370814708157081670817708187081970820708217082270823708247082570826708277082870829708307083170832708337083470835708367083770838708397084070841708427084370844708457084670847708487084970850708517085270853708547085570856708577085870859708607086170862708637086470865708667086770868708697087070871708727087370874708757087670877708787087970880708817088270883708847088570886708877088870889708907089170892708937089470895708967089770898708997090070901709027090370904709057090670907709087090970910709117091270913709147091570916709177091870919709207092170922709237092470925709267092770928709297093070931709327093370934709357093670937709387093970940709417094270943709447094570946709477094870949709507095170952709537095470955709567095770958709597096070961709627096370964709657096670967709687096970970709717097270973709747097570976709777097870979709807098170982709837098470985709867098770988709897099070991709927099370994709957099670997709987099971000710017100271003710047100571006710077100871009710107101171012710137101471015710167101771018710197102071021710227102371024710257102671027710287102971030710317103271033710347103571036710377103871039710407104171042710437104471045710467104771048710497105071051710527105371054710557105671057710587105971060710617106271063710647106571066710677106871069710707107171072710737107471075710767107771078710797108071081710827108371084710857108671087710887108971090710917109271093710947109571096710977109871099711007110171102711037110471105711067110771108711097111071111711127111371114711157111671117711187111971120711217112271123711247112571126711277112871129711307113171132711337113471135711367113771138711397114071141711427114371144711457114671147711487114971150711517115271153711547115571156711577115871159711607116171162711637116471165711667116771168711697117071171711727117371174711757117671177711787117971180711817118271183711847118571186711877118871189711907119171192711937119471195711967119771198711997120071201712027120371204712057120671207712087120971210712117121271213712147121571216712177121871219712207122171222712237122471225712267122771228712297123071231712327123371234712357123671237712387123971240712417124271243712447124571246712477124871249712507125171252712537125471255712567125771258712597126071261712627126371264712657126671267712687126971270712717127271273712747127571276712777127871279712807128171282712837128471285712867128771288712897129071291712927129371294712957129671297712987129971300713017130271303713047130571306713077130871309713107131171312713137131471315713167131771318713197132071321713227132371324713257132671327713287132971330713317133271333713347133571336713377133871339713407134171342713437134471345713467134771348713497135071351713527135371354713557135671357713587135971360713617136271363713647136571366713677136871369713707137171372713737137471375713767137771378713797138071381713827138371384713857138671387713887138971390713917139271393713947139571396713977139871399714007140171402714037140471405714067140771408714097141071411714127141371414714157141671417714187141971420714217142271423714247142571426714277142871429714307143171432714337143471435714367143771438714397144071441714427144371444714457144671447714487144971450714517145271453714547145571456714577145871459714607146171462714637146471465714667146771468714697147071471714727147371474714757147671477714787147971480714817148271483714847148571486714877148871489714907149171492714937149471495714967149771498714997150071501715027150371504715057150671507715087150971510715117151271513715147151571516715177151871519715207152171522715237152471525715267152771528715297153071531715327153371534715357153671537715387153971540715417154271543715447154571546715477154871549715507155171552715537155471555715567155771558715597156071561715627156371564715657156671567715687156971570715717157271573715747157571576715777157871579715807158171582715837158471585715867158771588715897159071591715927159371594715957159671597715987159971600716017160271603716047160571606716077160871609716107161171612716137161471615716167161771618716197162071621716227162371624716257162671627716287162971630716317163271633716347163571636716377163871639716407164171642716437164471645716467164771648716497165071651716527165371654716557165671657716587165971660716617166271663716647166571666716677166871669716707167171672716737167471675716767167771678716797168071681716827168371684716857168671687716887168971690716917169271693716947169571696716977169871699717007170171702717037170471705717067170771708717097171071711717127171371714717157171671717717187171971720717217172271723717247172571726717277172871729717307173171732717337173471735717367173771738717397174071741717427174371744717457174671747717487174971750717517175271753717547175571756717577175871759717607176171762717637176471765717667176771768717697177071771717727177371774717757177671777717787177971780717817178271783717847178571786717877178871789717907179171792717937179471795717967179771798717997180071801718027180371804718057180671807718087180971810718117181271813718147181571816718177181871819718207182171822718237182471825718267182771828718297183071831718327183371834718357183671837718387183971840718417184271843718447184571846718477184871849718507185171852718537185471855718567185771858718597186071861718627186371864718657186671867718687186971870718717187271873718747187571876718777187871879718807188171882718837188471885718867188771888718897189071891718927189371894718957189671897718987189971900719017190271903719047190571906719077190871909719107191171912719137191471915719167191771918719197192071921719227192371924719257192671927719287192971930719317193271933719347193571936719377193871939719407194171942719437194471945719467194771948719497195071951719527195371954719557195671957719587195971960719617196271963719647196571966719677196871969719707197171972719737197471975719767197771978719797198071981719827198371984719857198671987719887198971990719917199271993719947199571996719977199871999720007200172002720037200472005720067200772008720097201072011720127201372014720157201672017720187201972020720217202272023720247202572026720277202872029720307203172032720337203472035720367203772038720397204072041720427204372044720457204672047720487204972050720517205272053720547205572056720577205872059720607206172062720637206472065720667206772068720697207072071720727207372074720757207672077720787207972080720817208272083720847208572086720877208872089720907209172092720937209472095720967209772098720997210072101721027210372104721057210672107721087210972110721117211272113721147211572116721177211872119721207212172122721237212472125721267212772128721297213072131721327213372134721357213672137721387213972140721417214272143721447214572146721477214872149721507215172152721537215472155721567215772158721597216072161721627216372164721657216672167721687216972170721717217272173721747217572176721777217872179721807218172182721837218472185721867218772188721897219072191721927219372194721957219672197721987219972200722017220272203722047220572206722077220872209722107221172212722137221472215722167221772218722197222072221722227222372224722257222672227722287222972230722317223272233722347223572236722377223872239722407224172242722437224472245722467224772248722497225072251722527225372254722557225672257722587225972260722617226272263722647226572266722677226872269722707227172272722737227472275722767227772278722797228072281722827228372284722857228672287722887228972290722917229272293722947229572296722977229872299723007230172302723037230472305723067230772308723097231072311723127231372314723157231672317723187231972320723217232272323723247232572326723277232872329723307233172332723337233472335723367233772338723397234072341723427234372344723457234672347723487234972350723517235272353723547235572356723577235872359723607236172362723637236472365723667236772368723697237072371723727237372374723757237672377723787237972380723817238272383723847238572386723877238872389723907239172392723937239472395723967239772398723997240072401724027240372404724057240672407724087240972410724117241272413724147241572416724177241872419724207242172422724237242472425724267242772428724297243072431724327243372434724357243672437724387243972440724417244272443724447244572446724477244872449724507245172452724537245472455724567245772458724597246072461724627246372464724657246672467724687246972470724717247272473724747247572476724777247872479724807248172482724837248472485724867248772488724897249072491724927249372494724957249672497724987249972500725017250272503725047250572506725077250872509725107251172512725137251472515725167251772518725197252072521725227252372524725257252672527725287252972530725317253272533725347253572536725377253872539725407254172542725437254472545725467254772548725497255072551725527255372554725557255672557725587255972560725617256272563725647256572566725677256872569725707257172572725737257472575725767257772578725797258072581725827258372584725857258672587725887258972590725917259272593725947259572596725977259872599726007260172602726037260472605726067260772608726097261072611726127261372614726157261672617726187261972620726217262272623726247262572626726277262872629726307263172632726337263472635726367263772638726397264072641726427264372644726457264672647726487264972650726517265272653726547265572656726577265872659726607266172662726637266472665726667266772668726697267072671726727267372674726757267672677726787267972680726817268272683726847268572686726877268872689726907269172692726937269472695726967269772698726997270072701727027270372704727057270672707727087270972710727117271272713727147271572716727177271872719727207272172722727237272472725727267272772728727297273072731727327273372734727357273672737727387273972740727417274272743727447274572746727477274872749727507275172752727537275472755727567275772758727597276072761727627276372764727657276672767727687276972770727717277272773727747277572776727777277872779727807278172782727837278472785727867278772788727897279072791727927279372794727957279672797727987279972800728017280272803728047280572806728077280872809728107281172812728137281472815728167281772818728197282072821728227282372824728257282672827728287282972830728317283272833728347283572836728377283872839728407284172842728437284472845728467284772848728497285072851728527285372854728557285672857728587285972860728617286272863728647286572866728677286872869728707287172872728737287472875728767287772878728797288072881728827288372884728857288672887728887288972890728917289272893728947289572896728977289872899729007290172902729037290472905729067290772908729097291072911729127291372914729157291672917729187291972920729217292272923729247292572926729277292872929729307293172932729337293472935729367293772938729397294072941729427294372944729457294672947729487294972950729517295272953729547295572956729577295872959729607296172962729637296472965729667296772968729697297072971729727297372974729757297672977729787297972980729817298272983729847298572986729877298872989729907299172992729937299472995729967299772998729997300073001730027300373004730057300673007730087300973010730117301273013730147301573016730177301873019730207302173022730237302473025730267302773028730297303073031730327303373034730357303673037730387303973040730417304273043730447304573046730477304873049730507305173052730537305473055730567305773058730597306073061730627306373064730657306673067730687306973070730717307273073730747307573076730777307873079730807308173082730837308473085730867308773088730897309073091730927309373094730957309673097730987309973100731017310273103731047310573106731077310873109731107311173112731137311473115731167311773118731197312073121731227312373124731257312673127731287312973130731317313273133731347313573136731377313873139731407314173142731437314473145731467314773148731497315073151731527315373154731557315673157731587315973160731617316273163731647316573166731677316873169731707317173172731737317473175731767317773178731797318073181731827318373184731857318673187731887318973190731917319273193731947319573196731977319873199732007320173202732037320473205732067320773208732097321073211732127321373214732157321673217732187321973220732217322273223732247322573226732277322873229732307323173232732337323473235732367323773238732397324073241732427324373244732457324673247732487324973250732517325273253732547325573256732577325873259732607326173262732637326473265732667326773268732697327073271732727327373274732757327673277732787327973280732817328273283732847328573286732877328873289732907329173292732937329473295732967329773298732997330073301733027330373304733057330673307733087330973310733117331273313733147331573316733177331873319733207332173322733237332473325733267332773328733297333073331733327333373334733357333673337733387333973340733417334273343733447334573346733477334873349733507335173352733537335473355733567335773358733597336073361733627336373364733657336673367733687336973370733717337273373733747337573376733777337873379733807338173382733837338473385733867338773388733897339073391733927339373394733957339673397733987339973400734017340273403734047340573406734077340873409734107341173412734137341473415734167341773418734197342073421734227342373424734257342673427734287342973430734317343273433734347343573436734377343873439734407344173442734437344473445734467344773448734497345073451734527345373454734557345673457734587345973460734617346273463734647346573466734677346873469734707347173472734737347473475734767347773478734797348073481734827348373484734857348673487734887348973490734917349273493734947349573496734977349873499735007350173502735037350473505735067350773508735097351073511735127351373514735157351673517735187351973520735217352273523735247352573526735277352873529735307353173532735337353473535735367353773538735397354073541735427354373544735457354673547735487354973550735517355273553735547355573556735577355873559735607356173562735637356473565735667356773568735697357073571735727357373574735757357673577735787357973580735817358273583735847358573586735877358873589735907359173592735937359473595735967359773598735997360073601736027360373604736057360673607736087360973610736117361273613736147361573616736177361873619736207362173622736237362473625736267362773628736297363073631736327363373634736357363673637736387363973640736417364273643736447364573646736477364873649736507365173652736537365473655736567365773658736597366073661736627366373664736657366673667736687366973670736717367273673736747367573676736777367873679736807368173682736837368473685736867368773688736897369073691736927369373694736957369673697736987369973700737017370273703737047370573706737077370873709737107371173712737137371473715737167371773718737197372073721737227372373724737257372673727737287372973730737317373273733737347373573736737377373873739737407374173742737437374473745737467374773748737497375073751737527375373754737557375673757737587375973760737617376273763737647376573766737677376873769737707377173772737737377473775737767377773778737797378073781737827378373784737857378673787737887378973790737917379273793737947379573796737977379873799738007380173802738037380473805738067380773808738097381073811738127381373814738157381673817738187381973820738217382273823738247382573826738277382873829738307383173832738337383473835738367383773838738397384073841738427384373844738457384673847738487384973850738517385273853738547385573856738577385873859738607386173862738637386473865738667386773868738697387073871738727387373874738757387673877738787387973880738817388273883738847388573886738877388873889738907389173892738937389473895738967389773898738997390073901739027390373904739057390673907739087390973910739117391273913739147391573916739177391873919739207392173922739237392473925739267392773928739297393073931739327393373934739357393673937739387393973940739417394273943739447394573946739477394873949739507395173952739537395473955739567395773958739597396073961739627396373964739657396673967739687396973970739717397273973739747397573976739777397873979739807398173982739837398473985739867398773988739897399073991739927399373994739957399673997739987399974000740017400274003740047400574006740077400874009740107401174012740137401474015740167401774018740197402074021740227402374024740257402674027740287402974030740317403274033740347403574036740377403874039740407404174042740437404474045740467404774048740497405074051740527405374054740557405674057740587405974060740617406274063740647406574066740677406874069740707407174072740737407474075740767407774078740797408074081740827408374084740857408674087740887408974090740917409274093740947409574096740977409874099741007410174102741037410474105741067410774108741097411074111741127411374114741157411674117741187411974120741217412274123741247412574126741277412874129741307413174132741337413474135741367413774138741397414074141741427414374144741457414674147741487414974150741517415274153741547415574156741577415874159741607416174162741637416474165741667416774168741697417074171741727417374174741757417674177741787417974180741817418274183741847418574186741877418874189741907419174192741937419474195741967419774198741997420074201742027420374204742057420674207742087420974210742117421274213742147421574216742177421874219742207422174222742237422474225742267422774228742297423074231742327423374234742357423674237742387423974240742417424274243742447424574246742477424874249742507425174252742537425474255742567425774258742597426074261742627426374264742657426674267742687426974270742717427274273742747427574276742777427874279742807428174282742837428474285742867428774288742897429074291742927429374294742957429674297742987429974300743017430274303743047430574306743077430874309743107431174312743137431474315743167431774318743197432074321743227432374324743257432674327743287432974330743317433274333743347433574336743377433874339743407434174342743437434474345743467434774348743497435074351743527435374354743557435674357743587435974360743617436274363743647436574366743677436874369743707437174372743737437474375743767437774378743797438074381743827438374384743857438674387743887438974390743917439274393743947439574396743977439874399744007440174402744037440474405744067440774408744097441074411744127441374414744157441674417744187441974420744217442274423744247442574426744277442874429744307443174432744337443474435744367443774438744397444074441744427444374444744457444674447744487444974450744517445274453744547445574456744577445874459744607446174462744637446474465744667446774468744697447074471744727447374474744757447674477744787447974480744817448274483744847448574486744877448874489744907449174492744937449474495744967449774498744997450074501745027450374504745057450674507745087450974510745117451274513745147451574516745177451874519745207452174522745237452474525745267452774528745297453074531745327453374534745357453674537745387453974540745417454274543745447454574546745477454874549745507455174552745537455474555745567455774558745597456074561745627456374564745657456674567745687456974570745717457274573745747457574576745777457874579745807458174582745837458474585745867458774588745897459074591745927459374594745957459674597745987459974600746017460274603746047460574606746077460874609746107461174612746137461474615746167461774618746197462074621746227462374624746257462674627746287462974630746317463274633746347463574636746377463874639746407464174642746437464474645746467464774648746497465074651746527465374654746557465674657746587465974660746617466274663746647466574666746677466874669746707467174672746737467474675746767467774678746797468074681746827468374684746857468674687746887468974690746917469274693746947469574696746977469874699747007470174702747037470474705747067470774708747097471074711747127471374714747157471674717747187471974720747217472274723747247472574726747277472874729747307473174732747337473474735747367473774738747397474074741747427474374744747457474674747747487474974750747517475274753747547475574756747577475874759747607476174762747637476474765747667476774768747697477074771747727477374774747757477674777747787477974780747817478274783747847478574786747877478874789747907479174792747937479474795747967479774798747997480074801748027480374804748057480674807748087480974810748117481274813748147481574816748177481874819748207482174822748237482474825748267482774828748297483074831748327483374834748357483674837748387483974840748417484274843748447484574846748477484874849748507485174852748537485474855748567485774858748597486074861748627486374864748657486674867748687486974870748717487274873748747487574876748777487874879748807488174882748837488474885748867488774888748897489074891748927489374894748957489674897748987489974900749017490274903749047490574906749077490874909749107491174912749137491474915749167491774918749197492074921749227492374924749257492674927749287492974930749317493274933749347493574936749377493874939749407494174942749437494474945749467494774948749497495074951749527495374954749557495674957749587495974960749617496274963749647496574966749677496874969749707497174972749737497474975749767497774978749797498074981749827498374984749857498674987749887498974990749917499274993749947499574996749977499874999750007500175002750037500475005750067500775008750097501075011750127501375014750157501675017750187501975020750217502275023750247502575026750277502875029750307503175032750337503475035750367503775038750397504075041750427504375044750457504675047750487504975050750517505275053750547505575056750577505875059750607506175062750637506475065750667506775068750697507075071750727507375074750757507675077750787507975080750817508275083750847508575086750877508875089750907509175092750937509475095750967509775098750997510075101751027510375104751057510675107751087510975110751117511275113751147511575116751177511875119751207512175122751237512475125751267512775128751297513075131751327513375134751357513675137751387513975140751417514275143751447514575146751477514875149751507515175152751537515475155751567515775158751597516075161751627516375164751657516675167751687516975170751717517275173751747517575176751777517875179751807518175182751837518475185751867518775188751897519075191751927519375194751957519675197751987519975200752017520275203752047520575206752077520875209752107521175212752137521475215752167521775218752197522075221752227522375224752257522675227752287522975230752317523275233752347523575236752377523875239752407524175242752437524475245752467524775248752497525075251752527525375254752557525675257752587525975260752617526275263752647526575266752677526875269752707527175272752737527475275752767527775278752797528075281752827528375284752857528675287752887528975290752917529275293752947529575296752977529875299753007530175302753037530475305753067530775308753097531075311753127531375314753157531675317753187531975320753217532275323753247532575326753277532875329753307533175332753337533475335753367533775338753397534075341753427534375344753457534675347753487534975350753517535275353753547535575356753577535875359753607536175362753637536475365753667536775368753697537075371753727537375374753757537675377753787537975380753817538275383753847538575386753877538875389753907539175392753937539475395753967539775398753997540075401754027540375404754057540675407754087540975410754117541275413754147541575416754177541875419754207542175422754237542475425754267542775428754297543075431754327543375434754357543675437754387543975440754417544275443754447544575446754477544875449754507545175452754537545475455754567545775458754597546075461754627546375464754657546675467754687546975470754717547275473754747547575476754777547875479754807548175482754837548475485754867548775488754897549075491754927549375494754957549675497754987549975500755017550275503755047550575506755077550875509755107551175512755137551475515755167551775518755197552075521755227552375524755257552675527755287552975530755317553275533755347553575536755377553875539755407554175542755437554475545755467554775548755497555075551755527555375554755557555675557755587555975560755617556275563755647556575566755677556875569755707557175572755737557475575755767557775578755797558075581755827558375584755857558675587755887558975590755917559275593755947559575596755977559875599756007560175602756037560475605756067560775608756097561075611756127561375614756157561675617756187561975620756217562275623756247562575626756277562875629756307563175632756337563475635756367563775638756397564075641756427564375644756457564675647756487564975650756517565275653756547565575656756577565875659756607566175662756637566475665756667566775668756697567075671756727567375674756757567675677756787567975680756817568275683756847568575686756877568875689756907569175692756937569475695756967569775698756997570075701757027570375704757057570675707757087570975710757117571275713757147571575716757177571875719757207572175722757237572475725757267572775728757297573075731757327573375734757357573675737757387573975740757417574275743757447574575746757477574875749757507575175752757537575475755757567575775758757597576075761757627576375764757657576675767757687576975770757717577275773757747577575776757777577875779757807578175782757837578475785757867578775788757897579075791757927579375794757957579675797757987579975800758017580275803758047580575806758077580875809758107581175812758137581475815758167581775818758197582075821758227582375824758257582675827758287582975830758317583275833758347583575836758377583875839758407584175842758437584475845758467584775848758497585075851758527585375854758557585675857758587585975860758617586275863758647586575866758677586875869758707587175872758737587475875758767587775878758797588075881758827588375884758857588675887758887588975890758917589275893758947589575896758977589875899759007590175902759037590475905759067590775908759097591075911759127591375914759157591675917759187591975920759217592275923759247592575926759277592875929759307593175932759337593475935759367593775938759397594075941759427594375944759457594675947759487594975950759517595275953759547595575956759577595875959759607596175962759637596475965759667596775968759697597075971759727597375974759757597675977759787597975980759817598275983759847598575986759877598875989759907599175992759937599475995759967599775998759997600076001760027600376004760057600676007760087600976010760117601276013760147601576016760177601876019760207602176022760237602476025760267602776028760297603076031760327603376034760357603676037760387603976040760417604276043760447604576046760477604876049760507605176052760537605476055760567605776058760597606076061760627606376064760657606676067760687606976070760717607276073760747607576076760777607876079760807608176082760837608476085760867608776088760897609076091760927609376094760957609676097760987609976100761017610276103761047610576106761077610876109761107611176112761137611476115761167611776118761197612076121761227612376124761257612676127761287612976130761317613276133761347613576136761377613876139761407614176142761437614476145761467614776148761497615076151761527615376154761557615676157761587615976160761617616276163761647616576166761677616876169761707617176172761737617476175761767617776178761797618076181761827618376184761857618676187761887618976190761917619276193761947619576196761977619876199762007620176202762037620476205762067620776208762097621076211762127621376214762157621676217762187621976220762217622276223762247622576226762277622876229762307623176232762337623476235762367623776238762397624076241762427624376244762457624676247762487624976250762517625276253762547625576256762577625876259762607626176262762637626476265762667626776268762697627076271762727627376274762757627676277762787627976280762817628276283762847628576286762877628876289762907629176292762937629476295762967629776298762997630076301763027630376304763057630676307763087630976310763117631276313763147631576316763177631876319763207632176322763237632476325763267632776328763297633076331763327633376334763357633676337763387633976340763417634276343763447634576346763477634876349763507635176352763537635476355763567635776358763597636076361763627636376364763657636676367763687636976370763717637276373763747637576376763777637876379763807638176382763837638476385763867638776388763897639076391763927639376394763957639676397763987639976400764017640276403764047640576406764077640876409764107641176412764137641476415764167641776418764197642076421764227642376424764257642676427764287642976430764317643276433764347643576436764377643876439764407644176442764437644476445764467644776448764497645076451764527645376454764557645676457764587645976460764617646276463764647646576466764677646876469764707647176472764737647476475764767647776478764797648076481764827648376484764857648676487764887648976490764917649276493764947649576496764977649876499765007650176502765037650476505765067650776508765097651076511765127651376514765157651676517765187651976520765217652276523765247652576526765277652876529765307653176532765337653476535765367653776538765397654076541765427654376544765457654676547765487654976550765517655276553765547655576556765577655876559765607656176562765637656476565765667656776568765697657076571765727657376574765757657676577765787657976580765817658276583765847658576586765877658876589765907659176592765937659476595765967659776598765997660076601766027660376604766057660676607766087660976610766117661276613766147661576616766177661876619766207662176622766237662476625766267662776628766297663076631766327663376634766357663676637766387663976640766417664276643766447664576646766477664876649766507665176652766537665476655766567665776658766597666076661766627666376664766657666676667766687666976670766717667276673766747667576676766777667876679766807668176682766837668476685766867668776688766897669076691766927669376694766957669676697766987669976700767017670276703767047670576706767077670876709767107671176712767137671476715767167671776718767197672076721767227672376724767257672676727767287672976730767317673276733767347673576736767377673876739767407674176742767437674476745767467674776748767497675076751767527675376754767557675676757767587675976760767617676276763767647676576766767677676876769767707677176772767737677476775767767677776778767797678076781767827678376784767857678676787767887678976790767917679276793767947679576796767977679876799768007680176802768037680476805768067680776808768097681076811768127681376814768157681676817768187681976820768217682276823768247682576826768277682876829768307683176832768337683476835768367683776838768397684076841768427684376844768457684676847768487684976850768517685276853768547685576856768577685876859768607686176862768637686476865768667686776868768697687076871768727687376874768757687676877768787687976880768817688276883768847688576886768877688876889768907689176892768937689476895768967689776898768997690076901769027690376904769057690676907769087690976910769117691276913769147691576916769177691876919769207692176922769237692476925769267692776928769297693076931769327693376934769357693676937769387693976940769417694276943769447694576946769477694876949769507695176952769537695476955769567695776958769597696076961769627696376964769657696676967769687696976970769717697276973769747697576976769777697876979769807698176982769837698476985769867698776988769897699076991769927699376994769957699676997769987699977000770017700277003770047700577006770077700877009770107701177012770137701477015770167701777018770197702077021770227702377024770257702677027770287702977030770317703277033770347703577036770377703877039770407704177042770437704477045770467704777048770497705077051770527705377054770557705677057770587705977060770617706277063770647706577066770677706877069770707707177072770737707477075770767707777078770797708077081770827708377084770857708677087770887708977090770917709277093770947709577096770977709877099771007710177102771037710477105771067710777108771097711077111771127711377114771157711677117771187711977120771217712277123771247712577126771277712877129771307713177132771337713477135771367713777138771397714077141771427714377144771457714677147771487714977150771517715277153771547715577156771577715877159771607716177162771637716477165771667716777168771697717077171771727717377174771757717677177771787717977180771817718277183771847718577186771877718877189771907719177192771937719477195771967719777198771997720077201772027720377204772057720677207772087720977210772117721277213772147721577216772177721877219772207722177222772237722477225772267722777228772297723077231772327723377234772357723677237772387723977240772417724277243772447724577246772477724877249772507725177252772537725477255772567725777258772597726077261772627726377264772657726677267772687726977270772717727277273772747727577276772777727877279772807728177282772837728477285772867728777288772897729077291772927729377294772957729677297772987729977300773017730277303773047730577306773077730877309773107731177312773137731477315773167731777318773197732077321773227732377324773257732677327773287732977330773317733277333773347733577336773377733877339773407734177342773437734477345773467734777348773497735077351773527735377354773557735677357773587735977360773617736277363773647736577366773677736877369773707737177372773737737477375773767737777378773797738077381773827738377384773857738677387773887738977390773917739277393773947739577396773977739877399774007740177402774037740477405774067740777408774097741077411774127741377414774157741677417774187741977420774217742277423774247742577426774277742877429774307743177432774337743477435774367743777438774397744077441774427744377444774457744677447774487744977450774517745277453774547745577456774577745877459774607746177462774637746477465774667746777468774697747077471774727747377474774757747677477774787747977480774817748277483774847748577486774877748877489774907749177492774937749477495774967749777498774997750077501775027750377504775057750677507775087750977510775117751277513775147751577516775177751877519775207752177522775237752477525775267752777528775297753077531775327753377534775357753677537775387753977540775417754277543775447754577546775477754877549775507755177552775537755477555775567755777558775597756077561775627756377564775657756677567775687756977570775717757277573775747757577576775777757877579775807758177582775837758477585775867758777588775897759077591775927759377594775957759677597775987759977600776017760277603776047760577606776077760877609776107761177612776137761477615776167761777618776197762077621776227762377624776257762677627776287762977630776317763277633776347763577636776377763877639776407764177642776437764477645776467764777648776497765077651776527765377654776557765677657776587765977660776617766277663776647766577666776677766877669776707767177672776737767477675776767767777678776797768077681776827768377684776857768677687776887768977690776917769277693776947769577696776977769877699777007770177702777037770477705777067770777708777097771077711777127771377714777157771677717777187771977720777217772277723777247772577726777277772877729777307773177732777337773477735777367773777738777397774077741777427774377744777457774677747777487774977750777517775277753777547775577756777577775877759777607776177762777637776477765777667776777768777697777077771777727777377774777757777677777777787777977780777817778277783777847778577786777877778877789777907779177792777937779477795777967779777798777997780077801778027780377804778057780677807778087780977810778117781277813778147781577816778177781877819778207782177822778237782477825778267782777828778297783077831778327783377834778357783677837778387783977840778417784277843778447784577846778477784877849778507785177852778537785477855778567785777858778597786077861778627786377864778657786677867778687786977870778717787277873778747787577876778777787877879778807788177882778837788477885778867788777888778897789077891778927789377894778957789677897778987789977900779017790277903779047790577906779077790877909779107791177912779137791477915779167791777918779197792077921779227792377924779257792677927779287792977930779317793277933779347793577936779377793877939779407794177942779437794477945779467794777948779497795077951779527795377954779557795677957779587795977960779617796277963779647796577966779677796877969779707797177972779737797477975779767797777978779797798077981779827798377984779857798677987779887798977990779917799277993779947799577996779977799877999780007800178002780037800478005780067800778008780097801078011780127801378014780157801678017780187801978020780217802278023780247802578026780277802878029780307803178032780337803478035780367803778038780397804078041780427804378044780457804678047780487804978050780517805278053780547805578056780577805878059780607806178062780637806478065780667806778068780697807078071780727807378074780757807678077780787807978080780817808278083780847808578086780877808878089780907809178092780937809478095780967809778098780997810078101781027810378104781057810678107781087810978110781117811278113781147811578116781177811878119781207812178122781237812478125781267812778128781297813078131781327813378134781357813678137781387813978140781417814278143781447814578146781477814878149781507815178152781537815478155781567815778158781597816078161781627816378164781657816678167781687816978170781717817278173781747817578176781777817878179781807818178182781837818478185781867818778188781897819078191781927819378194781957819678197781987819978200782017820278203782047820578206782077820878209782107821178212782137821478215782167821778218782197822078221782227822378224782257822678227782287822978230782317823278233782347823578236782377823878239782407824178242782437824478245782467824778248782497825078251782527825378254782557825678257782587825978260782617826278263782647826578266782677826878269782707827178272782737827478275782767827778278782797828078281782827828378284782857828678287782887828978290782917829278293782947829578296782977829878299783007830178302783037830478305783067830778308783097831078311783127831378314783157831678317783187831978320783217832278323783247832578326783277832878329783307833178332783337833478335783367833778338783397834078341783427834378344783457834678347783487834978350783517835278353783547835578356783577835878359783607836178362783637836478365783667836778368783697837078371783727837378374783757837678377783787837978380783817838278383783847838578386783877838878389783907839178392783937839478395783967839778398783997840078401784027840378404784057840678407784087840978410784117841278413784147841578416784177841878419784207842178422784237842478425784267842778428784297843078431784327843378434784357843678437784387843978440784417844278443784447844578446784477844878449784507845178452784537845478455784567845778458784597846078461784627846378464784657846678467784687846978470784717847278473784747847578476784777847878479784807848178482784837848478485784867848778488784897849078491784927849378494784957849678497784987849978500785017850278503785047850578506785077850878509785107851178512785137851478515785167851778518785197852078521785227852378524785257852678527785287852978530785317853278533785347853578536785377853878539785407854178542785437854478545785467854778548785497855078551785527855378554785557855678557785587855978560785617856278563785647856578566785677856878569785707857178572785737857478575785767857778578785797858078581785827858378584785857858678587785887858978590785917859278593785947859578596785977859878599786007860178602786037860478605786067860778608786097861078611786127861378614786157861678617786187861978620786217862278623786247862578626786277862878629786307863178632786337863478635786367863778638786397864078641786427864378644786457864678647786487864978650786517865278653786547865578656786577865878659786607866178662786637866478665786667866778668786697867078671786727867378674786757867678677786787867978680786817868278683786847868578686786877868878689786907869178692786937869478695786967869778698786997870078701787027870378704787057870678707787087870978710787117871278713787147871578716787177871878719787207872178722787237872478725787267872778728787297873078731787327873378734787357873678737787387873978740787417874278743787447874578746787477874878749787507875178752787537875478755787567875778758787597876078761787627876378764787657876678767787687876978770787717877278773787747877578776787777877878779787807878178782787837878478785787867878778788787897879078791787927879378794787957879678797787987879978800788017880278803788047880578806788077880878809788107881178812788137881478815788167881778818788197882078821788227882378824788257882678827788287882978830788317883278833788347883578836788377883878839788407884178842788437884478845788467884778848788497885078851788527885378854788557885678857788587885978860788617886278863788647886578866788677886878869788707887178872788737887478875788767887778878788797888078881788827888378884788857888678887788887888978890788917889278893788947889578896788977889878899789007890178902789037890478905789067890778908789097891078911789127891378914789157891678917789187891978920789217892278923789247892578926789277892878929789307893178932789337893478935789367893778938789397894078941789427894378944789457894678947789487894978950789517895278953789547895578956789577895878959789607896178962789637896478965789667896778968789697897078971789727897378974789757897678977789787897978980789817898278983789847898578986789877898878989789907899178992789937899478995789967899778998789997900079001790027900379004790057900679007790087900979010790117901279013790147901579016790177901879019790207902179022790237902479025790267902779028790297903079031790327903379034790357903679037790387903979040790417904279043790447904579046790477904879049790507905179052790537905479055790567905779058790597906079061790627906379064790657906679067790687906979070790717907279073790747907579076790777907879079790807908179082790837908479085790867908779088790897909079091790927909379094790957909679097790987909979100791017910279103791047910579106791077910879109791107911179112791137911479115791167911779118791197912079121791227912379124791257912679127791287912979130791317913279133791347913579136791377913879139791407914179142791437914479145791467914779148791497915079151791527915379154791557915679157791587915979160791617916279163791647916579166791677916879169791707917179172791737917479175791767917779178791797918079181791827918379184791857918679187791887918979190791917919279193791947919579196791977919879199792007920179202792037920479205792067920779208792097921079211792127921379214792157921679217792187921979220792217922279223792247922579226792277922879229792307923179232792337923479235792367923779238792397924079241792427924379244792457924679247792487924979250792517925279253792547925579256792577925879259792607926179262792637926479265792667926779268792697927079271792727927379274792757927679277792787927979280792817928279283792847928579286792877928879289792907929179292792937929479295792967929779298792997930079301793027930379304793057930679307793087930979310793117931279313793147931579316793177931879319793207932179322793237932479325793267932779328793297933079331793327933379334793357933679337793387933979340793417934279343793447934579346793477934879349793507935179352793537935479355793567935779358793597936079361793627936379364793657936679367793687936979370793717937279373793747937579376793777937879379793807938179382793837938479385793867938779388793897939079391793927939379394793957939679397793987939979400794017940279403794047940579406794077940879409794107941179412794137941479415794167941779418794197942079421794227942379424794257942679427794287942979430794317943279433794347943579436794377943879439794407944179442794437944479445794467944779448794497945079451794527945379454794557945679457794587945979460794617946279463794647946579466794677946879469794707947179472794737947479475794767947779478794797948079481794827948379484794857948679487794887948979490794917949279493794947949579496794977949879499795007950179502795037950479505795067950779508795097951079511795127951379514795157951679517795187951979520795217952279523795247952579526795277952879529795307953179532795337953479535795367953779538795397954079541795427954379544795457954679547795487954979550795517955279553795547955579556795577955879559795607956179562795637956479565795667956779568795697957079571795727957379574795757957679577795787957979580795817958279583795847958579586795877958879589795907959179592795937959479595795967959779598795997960079601796027960379604796057960679607796087960979610796117961279613796147961579616796177961879619796207962179622796237962479625796267962779628796297963079631796327963379634796357963679637796387963979640796417964279643796447964579646796477964879649796507965179652796537965479655796567965779658796597966079661796627966379664796657966679667796687966979670796717967279673796747967579676796777967879679796807968179682796837968479685796867968779688796897969079691796927969379694796957969679697796987969979700797017970279703797047970579706797077970879709797107971179712797137971479715797167971779718797197972079721797227972379724797257972679727797287972979730797317973279733797347973579736797377973879739797407974179742797437974479745797467974779748797497975079751797527975379754797557975679757797587975979760797617976279763797647976579766797677976879769797707977179772797737977479775797767977779778797797978079781797827978379784797857978679787797887978979790797917979279793797947979579796797977979879799798007980179802798037980479805798067980779808798097981079811798127981379814798157981679817798187981979820798217982279823798247982579826798277982879829798307983179832798337983479835798367983779838798397984079841798427984379844798457984679847798487984979850798517985279853798547985579856798577985879859798607986179862798637986479865798667986779868798697987079871798727987379874798757987679877798787987979880798817988279883798847988579886798877988879889798907989179892798937989479895798967989779898798997990079901799027990379904799057990679907799087990979910799117991279913799147991579916799177991879919799207992179922799237992479925799267992779928799297993079931799327993379934799357993679937799387993979940799417994279943799447994579946799477994879949799507995179952799537995479955799567995779958799597996079961799627996379964799657996679967799687996979970799717997279973799747997579976799777997879979799807998179982799837998479985799867998779988799897999079991799927999379994799957999679997799987999980000800018000280003800048000580006800078000880009800108001180012800138001480015800168001780018800198002080021800228002380024800258002680027800288002980030800318003280033800348003580036800378003880039800408004180042800438004480045800468004780048800498005080051800528005380054800558005680057800588005980060800618006280063800648006580066800678006880069800708007180072800738007480075800768007780078800798008080081800828008380084800858008680087800888008980090800918009280093800948009580096800978009880099801008010180102801038010480105801068010780108801098011080111801128011380114801158011680117801188011980120801218012280123801248012580126801278012880129801308013180132801338013480135801368013780138801398014080141801428014380144801458014680147801488014980150801518015280153801548015580156801578015880159801608016180162801638016480165801668016780168801698017080171801728017380174801758017680177801788017980180801818018280183801848018580186801878018880189801908019180192801938019480195801968019780198801998020080201802028020380204802058020680207802088020980210802118021280213802148021580216802178021880219802208022180222802238022480225802268022780228802298023080231802328023380234802358023680237802388023980240802418024280243802448024580246802478024880249802508025180252802538025480255802568025780258802598026080261802628026380264802658026680267802688026980270802718027280273802748027580276802778027880279802808028180282802838028480285802868028780288802898029080291802928029380294802958029680297802988029980300803018030280303803048030580306803078030880309803108031180312803138031480315803168031780318803198032080321803228032380324803258032680327803288032980330803318033280333803348033580336803378033880339803408034180342803438034480345803468034780348803498035080351803528035380354803558035680357803588035980360803618036280363803648036580366803678036880369803708037180372803738037480375803768037780378803798038080381803828038380384803858038680387803888038980390803918039280393803948039580396803978039880399804008040180402804038040480405804068040780408804098041080411804128041380414804158041680417804188041980420804218042280423804248042580426804278042880429804308043180432804338043480435804368043780438804398044080441804428044380444804458044680447804488044980450804518045280453804548045580456804578045880459804608046180462804638046480465804668046780468804698047080471804728047380474804758047680477804788047980480804818048280483804848048580486804878048880489804908049180492804938049480495804968049780498804998050080501805028050380504805058050680507805088050980510805118051280513805148051580516805178051880519805208052180522805238052480525805268052780528805298053080531805328053380534805358053680537805388053980540805418054280543805448054580546805478054880549805508055180552805538055480555805568055780558805598056080561805628056380564805658056680567805688056980570805718057280573805748057580576805778057880579805808058180582805838058480585805868058780588805898059080591805928059380594805958059680597805988059980600806018060280603806048060580606806078060880609806108061180612806138061480615806168061780618806198062080621806228062380624806258062680627806288062980630806318063280633806348063580636806378063880639806408064180642806438064480645806468064780648806498065080651806528065380654806558065680657806588065980660806618066280663806648066580666806678066880669806708067180672806738067480675806768067780678806798068080681806828068380684806858068680687806888068980690806918069280693806948069580696806978069880699807008070180702807038070480705807068070780708807098071080711807128071380714807158071680717807188071980720807218072280723807248072580726807278072880729807308073180732807338073480735807368073780738807398074080741807428074380744807458074680747807488074980750807518075280753807548075580756807578075880759807608076180762807638076480765807668076780768807698077080771807728077380774807758077680777807788077980780807818078280783807848078580786807878078880789807908079180792807938079480795807968079780798807998080080801808028080380804808058080680807808088080980810808118081280813808148081580816808178081880819808208082180822808238082480825808268082780828808298083080831808328083380834808358083680837808388083980840808418084280843808448084580846808478084880849808508085180852808538085480855808568085780858808598086080861808628086380864808658086680867808688086980870808718087280873808748087580876808778087880879808808088180882808838088480885808868088780888808898089080891808928089380894808958089680897808988089980900809018090280903809048090580906809078090880909809108091180912809138091480915809168091780918809198092080921809228092380924809258092680927809288092980930809318093280933809348093580936809378093880939809408094180942809438094480945809468094780948809498095080951809528095380954809558095680957809588095980960809618096280963809648096580966809678096880969809708097180972809738097480975809768097780978809798098080981809828098380984809858098680987809888098980990809918099280993809948099580996809978099880999810008100181002810038100481005810068100781008810098101081011810128101381014810158101681017810188101981020810218102281023810248102581026810278102881029810308103181032810338103481035810368103781038810398104081041810428104381044810458104681047810488104981050810518105281053810548105581056810578105881059810608106181062810638106481065810668106781068810698107081071810728107381074810758107681077810788107981080810818108281083810848108581086810878108881089810908109181092810938109481095810968109781098810998110081101811028110381104811058110681107811088110981110811118111281113811148111581116811178111881119811208112181122811238112481125811268112781128811298113081131811328113381134811358113681137811388113981140811418114281143811448114581146811478114881149811508115181152811538115481155811568115781158811598116081161811628116381164811658116681167811688116981170811718117281173811748117581176811778117881179811808118181182811838118481185811868118781188811898119081191811928119381194811958119681197811988119981200812018120281203812048120581206812078120881209812108121181212812138121481215812168121781218812198122081221812228122381224812258122681227812288122981230812318123281233812348123581236812378123881239812408124181242812438124481245812468124781248812498125081251812528125381254812558125681257812588125981260812618126281263812648126581266812678126881269812708127181272812738127481275812768127781278812798128081281812828128381284812858128681287812888128981290812918129281293812948129581296812978129881299813008130181302813038130481305813068130781308813098131081311813128131381314813158131681317813188131981320813218132281323813248132581326813278132881329813308133181332813338133481335813368133781338813398134081341813428134381344813458134681347813488134981350813518135281353813548135581356813578135881359813608136181362813638136481365813668136781368813698137081371813728137381374813758137681377813788137981380813818138281383813848138581386813878138881389813908139181392813938139481395813968139781398813998140081401814028140381404814058140681407814088140981410814118141281413814148141581416814178141881419814208142181422814238142481425814268142781428814298143081431814328143381434814358143681437814388143981440814418144281443814448144581446814478144881449814508145181452814538145481455814568145781458814598146081461814628146381464814658146681467814688146981470814718147281473814748147581476814778147881479814808148181482814838148481485814868148781488814898149081491814928149381494814958149681497814988149981500815018150281503815048150581506815078150881509815108151181512815138151481515815168151781518815198152081521815228152381524815258152681527815288152981530815318153281533815348153581536815378153881539815408154181542815438154481545815468154781548815498155081551815528155381554815558155681557815588155981560815618156281563815648156581566815678156881569815708157181572815738157481575815768157781578815798158081581815828158381584815858158681587815888158981590815918159281593815948159581596815978159881599816008160181602816038160481605816068160781608816098161081611816128161381614816158161681617816188161981620816218162281623816248162581626816278162881629816308163181632816338163481635816368163781638816398164081641816428164381644816458164681647816488164981650816518165281653816548165581656816578165881659816608166181662816638166481665816668166781668816698167081671816728167381674816758167681677816788167981680816818168281683816848168581686816878168881689816908169181692816938169481695816968169781698816998170081701817028170381704817058170681707817088170981710817118171281713817148171581716817178171881719817208172181722817238172481725817268172781728817298173081731817328173381734817358173681737817388173981740817418174281743817448174581746817478174881749817508175181752817538175481755817568175781758817598176081761817628176381764817658176681767817688176981770817718177281773817748177581776817778177881779817808178181782817838178481785817868178781788817898179081791817928179381794817958179681797817988179981800818018180281803818048180581806818078180881809818108181181812818138181481815818168181781818818198182081821818228182381824818258182681827818288182981830818318183281833818348183581836818378183881839818408184181842818438184481845818468184781848818498185081851818528185381854818558185681857818588185981860818618186281863818648186581866818678186881869818708187181872818738187481875818768187781878818798188081881818828188381884818858188681887818888188981890818918189281893818948189581896818978189881899819008190181902819038190481905819068190781908819098191081911819128191381914819158191681917819188191981920819218192281923819248192581926819278192881929819308193181932819338193481935819368193781938819398194081941819428194381944819458194681947819488194981950819518195281953819548195581956819578195881959819608196181962819638196481965819668196781968819698197081971819728197381974819758197681977819788197981980819818198281983819848198581986819878198881989819908199181992819938199481995819968199781998819998200082001820028200382004820058200682007820088200982010820118201282013820148201582016820178201882019820208202182022820238202482025820268202782028820298203082031820328203382034820358203682037820388203982040820418204282043820448204582046820478204882049820508205182052820538205482055820568205782058820598206082061820628206382064820658206682067820688206982070820718207282073820748207582076820778207882079820808208182082820838208482085820868208782088820898209082091820928209382094820958209682097820988209982100821018210282103821048210582106821078210882109821108211182112821138211482115821168211782118821198212082121821228212382124821258212682127821288212982130821318213282133821348213582136821378213882139821408214182142821438214482145821468214782148821498215082151821528215382154821558215682157821588215982160821618216282163821648216582166821678216882169821708217182172821738217482175821768217782178821798218082181821828218382184821858218682187821888218982190821918219282193821948219582196821978219882199822008220182202822038220482205822068220782208822098221082211822128221382214822158221682217822188221982220822218222282223822248222582226822278222882229822308223182232822338223482235822368223782238822398224082241822428224382244822458224682247822488224982250822518225282253822548225582256822578225882259822608226182262822638226482265822668226782268822698227082271822728227382274822758227682277822788227982280822818228282283822848228582286822878228882289822908229182292822938229482295822968229782298822998230082301823028230382304823058230682307823088230982310823118231282313823148231582316823178231882319823208232182322823238232482325823268232782328823298233082331823328233382334823358233682337823388233982340823418234282343823448234582346823478234882349823508235182352823538235482355823568235782358823598236082361823628236382364823658236682367823688236982370823718237282373823748237582376823778237882379823808238182382823838238482385823868238782388823898239082391823928239382394823958239682397823988239982400824018240282403824048240582406824078240882409824108241182412824138241482415824168241782418824198242082421824228242382424824258242682427824288242982430824318243282433824348243582436824378243882439824408244182442824438244482445824468244782448824498245082451824528245382454824558245682457824588245982460824618246282463824648246582466824678246882469824708247182472824738247482475824768247782478824798248082481824828248382484824858248682487824888248982490824918249282493824948249582496824978249882499825008250182502825038250482505825068250782508825098251082511825128251382514825158251682517825188251982520825218252282523825248252582526825278252882529825308253182532825338253482535825368253782538825398254082541825428254382544825458254682547825488254982550825518255282553825548255582556825578255882559825608256182562825638256482565825668256782568825698257082571825728257382574825758257682577825788257982580825818258282583825848258582586825878258882589825908259182592825938259482595825968259782598825998260082601826028260382604826058260682607826088260982610826118261282613826148261582616826178261882619826208262182622826238262482625826268262782628826298263082631826328263382634826358263682637826388263982640826418264282643826448264582646826478264882649826508265182652826538265482655826568265782658826598266082661826628266382664826658266682667826688266982670826718267282673826748267582676826778267882679826808268182682826838268482685826868268782688826898269082691826928269382694826958269682697826988269982700827018270282703827048270582706827078270882709827108271182712827138271482715827168271782718827198272082721827228272382724827258272682727827288272982730827318273282733827348273582736827378273882739827408274182742827438274482745827468274782748827498275082751827528275382754827558275682757827588275982760827618276282763827648276582766827678276882769827708277182772827738277482775827768277782778827798278082781827828278382784827858278682787827888278982790827918279282793827948279582796827978279882799828008280182802828038280482805828068280782808828098281082811828128281382814828158281682817828188281982820828218282282823828248282582826828278282882829828308283182832828338283482835828368283782838828398284082841828428284382844828458284682847828488284982850828518285282853828548285582856828578285882859828608286182862828638286482865828668286782868828698287082871828728287382874828758287682877828788287982880828818288282883828848288582886828878288882889828908289182892828938289482895828968289782898828998290082901829028290382904829058290682907829088290982910829118291282913829148291582916829178291882919829208292182922829238292482925829268292782928829298293082931829328293382934829358293682937829388293982940829418294282943829448294582946829478294882949829508295182952829538295482955829568295782958829598296082961829628296382964829658296682967829688296982970829718297282973829748297582976829778297882979829808298182982829838298482985829868298782988829898299082991829928299382994829958299682997829988299983000830018300283003830048300583006830078300883009830108301183012830138301483015830168301783018830198302083021830228302383024830258302683027830288302983030830318303283033830348303583036830378303883039830408304183042830438304483045830468304783048830498305083051830528305383054830558305683057830588305983060830618306283063830648306583066830678306883069830708307183072830738307483075830768307783078830798308083081830828308383084830858308683087830888308983090830918309283093830948309583096830978309883099831008310183102831038310483105831068310783108831098311083111831128311383114831158311683117831188311983120831218312283123831248312583126831278312883129831308313183132831338313483135831368313783138831398314083141831428314383144831458314683147831488314983150831518315283153831548315583156831578315883159831608316183162831638316483165831668316783168831698317083171831728317383174831758317683177831788317983180831818318283183831848318583186831878318883189831908319183192831938319483195831968319783198831998320083201832028320383204832058320683207832088320983210832118321283213832148321583216832178321883219832208322183222832238322483225832268322783228832298323083231832328323383234832358323683237832388323983240832418324283243832448324583246832478324883249832508325183252832538325483255832568325783258832598326083261832628326383264832658326683267832688326983270832718327283273832748327583276832778327883279832808328183282832838328483285832868328783288832898329083291832928329383294832958329683297832988329983300833018330283303833048330583306833078330883309833108331183312833138331483315833168331783318833198332083321833228332383324833258332683327833288332983330833318333283333833348333583336833378333883339833408334183342833438334483345833468334783348833498335083351833528335383354833558335683357833588335983360833618336283363833648336583366833678336883369833708337183372833738337483375833768337783378833798338083381833828338383384833858338683387833888338983390833918339283393833948339583396833978339883399834008340183402834038340483405834068340783408834098341083411834128341383414834158341683417834188341983420834218342283423834248342583426834278342883429834308343183432834338343483435834368343783438834398344083441834428344383444834458344683447834488344983450834518345283453834548345583456834578345883459834608346183462834638346483465834668346783468834698347083471834728347383474834758347683477834788347983480834818348283483834848348583486834878348883489834908349183492834938349483495834968349783498834998350083501835028350383504835058350683507835088350983510835118351283513835148351583516835178351883519835208352183522835238352483525835268352783528835298353083531835328353383534835358353683537835388353983540835418354283543835448354583546835478354883549835508355183552835538355483555835568355783558835598356083561835628356383564835658356683567835688356983570835718357283573835748357583576835778357883579835808358183582835838358483585835868358783588835898359083591835928359383594835958359683597835988359983600836018360283603836048360583606836078360883609836108361183612836138361483615836168361783618836198362083621836228362383624836258362683627836288362983630836318363283633836348363583636836378363883639836408364183642836438364483645836468364783648836498365083651836528365383654836558365683657836588365983660836618366283663836648366583666836678366883669836708367183672836738367483675836768367783678836798368083681836828368383684836858368683687836888368983690836918369283693836948369583696836978369883699837008370183702837038370483705837068370783708837098371083711837128371383714837158371683717837188371983720837218372283723837248372583726837278372883729837308373183732837338373483735837368373783738837398374083741837428374383744837458374683747837488374983750837518375283753837548375583756837578375883759837608376183762837638376483765837668376783768837698377083771837728377383774837758377683777837788377983780837818378283783837848378583786837878378883789837908379183792837938379483795837968379783798837998380083801838028380383804838058380683807838088380983810838118381283813838148381583816838178381883819838208382183822838238382483825838268382783828838298383083831838328383383834838358383683837838388383983840838418384283843838448384583846838478384883849838508385183852838538385483855838568385783858838598386083861838628386383864838658386683867838688386983870838718387283873838748387583876838778387883879838808388183882838838388483885838868388783888838898389083891838928389383894838958389683897838988389983900839018390283903839048390583906839078390883909839108391183912839138391483915839168391783918839198392083921839228392383924839258392683927839288392983930839318393283933839348393583936839378393883939839408394183942839438394483945839468394783948839498395083951839528395383954839558395683957839588395983960839618396283963839648396583966839678396883969839708397183972839738397483975839768397783978839798398083981839828398383984839858398683987839888398983990839918399283993839948399583996839978399883999840008400184002840038400484005840068400784008840098401084011840128401384014840158401684017840188401984020840218402284023840248402584026840278402884029840308403184032840338403484035840368403784038840398404084041840428404384044840458404684047840488404984050840518405284053840548405584056840578405884059840608406184062840638406484065840668406784068840698407084071840728407384074840758407684077840788407984080840818408284083840848408584086840878408884089840908409184092840938409484095840968409784098840998410084101841028410384104841058410684107841088410984110841118411284113841148411584116841178411884119841208412184122841238412484125841268412784128841298413084131841328413384134841358413684137841388413984140841418414284143841448414584146841478414884149841508415184152841538415484155841568415784158841598416084161841628416384164841658416684167841688416984170841718417284173841748417584176841778417884179841808418184182841838418484185841868418784188841898419084191841928419384194841958419684197841988419984200842018420284203842048420584206842078420884209842108421184212842138421484215842168421784218842198422084221842228422384224842258422684227842288422984230842318423284233842348423584236842378423884239842408424184242842438424484245842468424784248842498425084251842528425384254842558425684257842588425984260842618426284263842648426584266842678426884269842708427184272842738427484275842768427784278842798428084281842828428384284842858428684287842888428984290842918429284293842948429584296842978429884299843008430184302843038430484305843068430784308843098431084311843128431384314843158431684317843188431984320843218432284323843248432584326843278432884329843308433184332843338433484335843368433784338843398434084341843428434384344843458434684347843488434984350843518435284353843548435584356843578435884359843608436184362843638436484365843668436784368843698437084371843728437384374843758437684377843788437984380843818438284383843848438584386843878438884389843908439184392843938439484395843968439784398843998440084401844028440384404844058440684407844088440984410844118441284413844148441584416844178441884419844208442184422844238442484425844268442784428844298443084431844328443384434844358443684437844388443984440844418444284443844448444584446844478444884449844508445184452844538445484455844568445784458844598446084461844628446384464844658446684467844688446984470844718447284473844748447584476844778447884479844808448184482844838448484485844868448784488844898449084491844928449384494844958449684497844988449984500845018450284503845048450584506845078450884509845108451184512845138451484515845168451784518845198452084521845228452384524845258452684527845288452984530845318453284533845348453584536845378453884539845408454184542845438454484545845468454784548845498455084551845528455384554845558455684557845588455984560845618456284563845648456584566845678456884569845708457184572845738457484575845768457784578845798458084581845828458384584845858458684587845888458984590845918459284593845948459584596845978459884599846008460184602846038460484605846068460784608846098461084611846128461384614846158461684617846188461984620846218462284623846248462584626846278462884629846308463184632846338463484635846368463784638846398464084641846428464384644846458464684647846488464984650846518465284653846548465584656846578465884659846608466184662846638466484665846668466784668846698467084671846728467384674846758467684677846788467984680846818468284683846848468584686846878468884689846908469184692846938469484695846968469784698846998470084701847028470384704847058470684707847088470984710847118471284713847148471584716847178471884719847208472184722847238472484725847268472784728847298473084731847328473384734847358473684737847388473984740847418474284743847448474584746847478474884749847508475184752847538475484755847568475784758847598476084761847628476384764847658476684767847688476984770847718477284773847748477584776847778477884779847808478184782847838478484785847868478784788847898479084791847928479384794847958479684797847988479984800848018480284803848048480584806848078480884809848108481184812848138481484815848168481784818848198482084821848228482384824848258482684827848288482984830848318483284833848348483584836848378483884839848408484184842848438484484845848468484784848848498485084851848528485384854848558485684857848588485984860848618486284863848648486584866848678486884869848708487184872848738487484875848768487784878848798488084881848828488384884848858488684887848888488984890848918489284893848948489584896848978489884899849008490184902849038490484905849068490784908849098491084911849128491384914849158491684917849188491984920849218492284923849248492584926849278492884929849308493184932849338493484935849368493784938849398494084941849428494384944849458494684947849488494984950849518495284953849548495584956849578495884959849608496184962849638496484965849668496784968849698497084971849728497384974849758497684977849788497984980849818498284983849848498584986849878498884989849908499184992849938499484995849968499784998849998500085001850028500385004850058500685007850088500985010850118501285013850148501585016850178501885019850208502185022850238502485025850268502785028850298503085031850328503385034850358503685037850388503985040850418504285043850448504585046850478504885049850508505185052850538505485055850568505785058850598506085061850628506385064850658506685067850688506985070850718507285073850748507585076850778507885079850808508185082850838508485085850868508785088850898509085091850928509385094850958509685097850988509985100851018510285103851048510585106851078510885109851108511185112851138511485115851168511785118851198512085121851228512385124851258512685127851288512985130851318513285133851348513585136851378513885139851408514185142851438514485145851468514785148851498515085151851528515385154851558515685157851588515985160851618516285163851648516585166851678516885169851708517185172851738517485175851768517785178851798518085181851828518385184851858518685187851888518985190851918519285193851948519585196851978519885199852008520185202852038520485205852068520785208852098521085211852128521385214852158521685217852188521985220852218522285223852248522585226852278522885229852308523185232852338523485235852368523785238852398524085241852428524385244852458524685247852488524985250852518525285253852548525585256852578525885259852608526185262852638526485265852668526785268852698527085271852728527385274852758527685277852788527985280852818528285283852848528585286852878528885289852908529185292852938529485295852968529785298852998530085301853028530385304853058530685307853088530985310853118531285313853148531585316853178531885319853208532185322853238532485325853268532785328853298533085331853328533385334853358533685337853388533985340853418534285343853448534585346853478534885349853508535185352853538535485355853568535785358853598536085361853628536385364853658536685367853688536985370853718537285373853748537585376853778537885379853808538185382853838538485385853868538785388853898539085391853928539385394853958539685397853988539985400854018540285403854048540585406854078540885409854108541185412854138541485415854168541785418854198542085421854228542385424854258542685427854288542985430854318543285433854348543585436854378543885439854408544185442854438544485445854468544785448854498545085451854528545385454854558545685457854588545985460854618546285463854648546585466854678546885469854708547185472854738547485475854768547785478854798548085481854828548385484854858548685487854888548985490854918549285493854948549585496854978549885499855008550185502855038550485505855068550785508855098551085511855128551385514855158551685517855188551985520855218552285523855248552585526855278552885529855308553185532855338553485535855368553785538855398554085541855428554385544855458554685547855488554985550855518555285553855548555585556855578555885559855608556185562855638556485565855668556785568855698557085571855728557385574855758557685577855788557985580855818558285583855848558585586855878558885589855908559185592855938559485595855968559785598855998560085601856028560385604856058560685607856088560985610856118561285613856148561585616856178561885619856208562185622856238562485625856268562785628856298563085631856328563385634856358563685637856388563985640856418564285643856448564585646856478564885649856508565185652856538565485655856568565785658856598566085661856628566385664856658566685667856688566985670856718567285673856748567585676856778567885679856808568185682856838568485685856868568785688856898569085691856928569385694856958569685697856988569985700857018570285703857048570585706857078570885709857108571185712857138571485715857168571785718857198572085721857228572385724857258572685727857288572985730857318573285733857348573585736857378573885739857408574185742857438574485745857468574785748857498575085751857528575385754857558575685757857588575985760857618576285763857648576585766857678576885769857708577185772857738577485775857768577785778857798578085781857828578385784857858578685787857888578985790857918579285793857948579585796857978579885799858008580185802858038580485805858068580785808858098581085811858128581385814858158581685817858188581985820858218582285823858248582585826858278582885829858308583185832858338583485835858368583785838858398584085841858428584385844858458584685847858488584985850858518585285853858548585585856858578585885859858608586185862858638586485865858668586785868858698587085871858728587385874858758587685877858788587985880858818588285883858848588585886858878588885889858908589185892858938589485895858968589785898858998590085901859028590385904859058590685907859088590985910859118591285913859148591585916859178591885919859208592185922859238592485925859268592785928859298593085931859328593385934859358593685937859388593985940859418594285943859448594585946859478594885949859508595185952859538595485955859568595785958859598596085961859628596385964859658596685967859688596985970859718597285973859748597585976859778597885979859808598185982859838598485985859868598785988859898599085991859928599385994859958599685997859988599986000860018600286003860048600586006860078600886009860108601186012860138601486015860168601786018860198602086021860228602386024860258602686027860288602986030860318603286033860348603586036860378603886039860408604186042860438604486045860468604786048860498605086051860528605386054860558605686057860588605986060860618606286063860648606586066860678606886069860708607186072860738607486075860768607786078860798608086081860828608386084860858608686087860888608986090860918609286093860948609586096860978609886099861008610186102861038610486105861068610786108861098611086111861128611386114861158611686117861188611986120861218612286123861248612586126861278612886129861308613186132861338613486135861368613786138861398614086141861428614386144861458614686147861488614986150861518615286153861548615586156861578615886159861608616186162861638616486165861668616786168861698617086171861728617386174861758617686177861788617986180861818618286183861848618586186861878618886189861908619186192861938619486195861968619786198861998620086201862028620386204862058620686207862088620986210862118621286213862148621586216862178621886219862208622186222862238622486225862268622786228862298623086231862328623386234862358623686237862388623986240862418624286243862448624586246862478624886249862508625186252862538625486255862568625786258862598626086261862628626386264862658626686267862688626986270862718627286273862748627586276862778627886279862808628186282862838628486285862868628786288862898629086291862928629386294862958629686297862988629986300863018630286303863048630586306863078630886309863108631186312863138631486315863168631786318863198632086321863228632386324863258632686327863288632986330863318633286333863348633586336863378633886339863408634186342863438634486345863468634786348863498635086351863528635386354863558635686357863588635986360863618636286363863648636586366863678636886369863708637186372863738637486375863768637786378863798638086381863828638386384863858638686387863888638986390863918639286393863948639586396863978639886399864008640186402864038640486405864068640786408864098641086411864128641386414864158641686417864188641986420864218642286423864248642586426864278642886429864308643186432864338643486435864368643786438864398644086441864428644386444864458644686447864488644986450864518645286453864548645586456864578645886459864608646186462864638646486465864668646786468864698647086471864728647386474864758647686477864788647986480864818648286483864848648586486864878648886489864908649186492864938649486495864968649786498864998650086501865028650386504865058650686507865088650986510865118651286513865148651586516865178651886519865208652186522865238652486525865268652786528865298653086531865328653386534865358653686537865388653986540865418654286543865448654586546865478654886549865508655186552865538655486555865568655786558865598656086561865628656386564865658656686567865688656986570865718657286573865748657586576865778657886579865808658186582865838658486585865868658786588865898659086591865928659386594865958659686597865988659986600866018660286603866048660586606866078660886609866108661186612866138661486615866168661786618866198662086621866228662386624866258662686627866288662986630866318663286633866348663586636866378663886639866408664186642866438664486645866468664786648866498665086651866528665386654866558665686657866588665986660866618666286663866648666586666866678666886669866708667186672866738667486675866768667786678866798668086681866828668386684866858668686687866888668986690866918669286693866948669586696866978669886699867008670186702867038670486705867068670786708867098671086711867128671386714867158671686717867188671986720867218672286723867248672586726867278672886729867308673186732867338673486735867368673786738867398674086741867428674386744867458674686747867488674986750867518675286753867548675586756867578675886759867608676186762867638676486765867668676786768867698677086771867728677386774867758677686777867788677986780867818678286783867848678586786867878678886789867908679186792867938679486795867968679786798867998680086801868028680386804868058680686807868088680986810868118681286813868148681586816868178681886819868208682186822868238682486825868268682786828868298683086831868328683386834868358683686837868388683986840868418684286843868448684586846868478684886849868508685186852868538685486855868568685786858868598686086861868628686386864868658686686867868688686986870868718687286873868748687586876868778687886879868808688186882868838688486885868868688786888868898689086891868928689386894868958689686897868988689986900869018690286903869048690586906869078690886909869108691186912869138691486915869168691786918869198692086921869228692386924869258692686927869288692986930869318693286933869348693586936869378693886939869408694186942869438694486945869468694786948869498695086951869528695386954869558695686957869588695986960869618696286963869648696586966869678696886969869708697186972869738697486975869768697786978869798698086981869828698386984869858698686987869888698986990869918699286993869948699586996869978699886999870008700187002870038700487005870068700787008870098701087011870128701387014870158701687017870188701987020870218702287023870248702587026870278702887029870308703187032870338703487035870368703787038870398704087041870428704387044870458704687047870488704987050870518705287053870548705587056870578705887059870608706187062870638706487065870668706787068870698707087071870728707387074870758707687077870788707987080870818708287083870848708587086870878708887089870908709187092870938709487095870968709787098870998710087101871028710387104871058710687107871088710987110871118711287113871148711587116871178711887119871208712187122871238712487125871268712787128871298713087131871328713387134871358713687137871388713987140871418714287143871448714587146871478714887149871508715187152871538715487155871568715787158871598716087161871628716387164871658716687167871688716987170871718717287173871748717587176871778717887179871808718187182871838718487185871868718787188871898719087191871928719387194871958719687197871988719987200872018720287203872048720587206872078720887209872108721187212872138721487215872168721787218872198722087221872228722387224872258722687227872288722987230872318723287233872348723587236872378723887239872408724187242872438724487245872468724787248872498725087251872528725387254872558725687257872588725987260872618726287263872648726587266872678726887269872708727187272872738727487275872768727787278872798728087281872828728387284872858728687287872888728987290872918729287293872948729587296872978729887299873008730187302873038730487305873068730787308873098731087311873128731387314873158731687317873188731987320873218732287323873248732587326873278732887329873308733187332873338733487335873368733787338873398734087341873428734387344873458734687347873488734987350873518735287353873548735587356873578735887359873608736187362873638736487365873668736787368873698737087371873728737387374873758737687377873788737987380873818738287383873848738587386873878738887389873908739187392873938739487395873968739787398873998740087401874028740387404874058740687407874088740987410874118741287413874148741587416874178741887419874208742187422874238742487425874268742787428874298743087431874328743387434874358743687437874388743987440874418744287443874448744587446874478744887449874508745187452874538745487455874568745787458874598746087461874628746387464874658746687467874688746987470874718747287473874748747587476874778747887479874808748187482874838748487485874868748787488874898749087491874928749387494874958749687497874988749987500875018750287503875048750587506875078750887509875108751187512875138751487515875168751787518875198752087521875228752387524875258752687527875288752987530875318753287533875348753587536875378753887539875408754187542875438754487545875468754787548875498755087551875528755387554875558755687557875588755987560875618756287563875648756587566875678756887569875708757187572875738757487575875768757787578875798758087581875828758387584875858758687587875888758987590875918759287593875948759587596875978759887599876008760187602876038760487605876068760787608876098761087611876128761387614876158761687617876188761987620876218762287623876248762587626876278762887629876308763187632876338763487635876368763787638876398764087641876428764387644876458764687647876488764987650876518765287653876548765587656876578765887659876608766187662876638766487665876668766787668876698767087671876728767387674876758767687677876788767987680876818768287683876848768587686876878768887689876908769187692876938769487695876968769787698876998770087701877028770387704877058770687707877088770987710877118771287713877148771587716877178771887719877208772187722877238772487725877268772787728877298773087731877328773387734877358773687737877388773987740877418774287743877448774587746877478774887749877508775187752877538775487755877568775787758877598776087761877628776387764877658776687767877688776987770877718777287773877748777587776877778777887779877808778187782877838778487785877868778787788877898779087791877928779387794877958779687797877988779987800878018780287803878048780587806878078780887809878108781187812878138781487815878168781787818878198782087821878228782387824878258782687827878288782987830878318783287833878348783587836878378783887839878408784187842878438784487845878468784787848878498785087851878528785387854878558785687857878588785987860878618786287863878648786587866878678786887869878708787187872878738787487875878768787787878878798788087881878828788387884878858788687887878888788987890878918789287893878948789587896878978789887899879008790187902879038790487905879068790787908879098791087911879128791387914879158791687917879188791987920879218792287923879248792587926879278792887929879308793187932879338793487935879368793787938879398794087941879428794387944879458794687947879488794987950879518795287953879548795587956879578795887959879608796187962879638796487965879668796787968879698797087971879728797387974879758797687977879788797987980879818798287983879848798587986879878798887989879908799187992879938799487995879968799787998879998800088001880028800388004880058800688007880088800988010880118801288013880148801588016880178801888019880208802188022880238802488025880268802788028880298803088031880328803388034880358803688037880388803988040880418804288043880448804588046880478804888049880508805188052880538805488055880568805788058880598806088061880628806388064880658806688067880688806988070880718807288073880748807588076880778807888079880808808188082880838808488085880868808788088880898809088091880928809388094880958809688097880988809988100881018810288103881048810588106881078810888109881108811188112881138811488115881168811788118881198812088121881228812388124881258812688127881288812988130881318813288133881348813588136881378813888139881408814188142881438814488145881468814788148881498815088151881528815388154881558815688157881588815988160881618816288163881648816588166881678816888169881708817188172881738817488175881768817788178881798818088181881828818388184881858818688187881888818988190881918819288193881948819588196881978819888199882008820188202882038820488205882068820788208882098821088211882128821388214882158821688217882188821988220882218822288223882248822588226882278822888229882308823188232882338823488235882368823788238882398824088241882428824388244882458824688247882488824988250882518825288253882548825588256882578825888259882608826188262882638826488265882668826788268882698827088271882728827388274882758827688277882788827988280882818828288283882848828588286882878828888289882908829188292882938829488295882968829788298882998830088301883028830388304883058830688307883088830988310883118831288313883148831588316883178831888319883208832188322883238832488325883268832788328883298833088331883328833388334883358833688337883388833988340883418834288343883448834588346883478834888349883508835188352883538835488355883568835788358883598836088361883628836388364883658836688367883688836988370883718837288373883748837588376883778837888379883808838188382883838838488385883868838788388883898839088391883928839388394883958839688397883988839988400884018840288403884048840588406884078840888409884108841188412884138841488415884168841788418884198842088421884228842388424884258842688427884288842988430884318843288433884348843588436884378843888439884408844188442884438844488445884468844788448884498845088451884528845388454884558845688457884588845988460884618846288463884648846588466884678846888469884708847188472884738847488475884768847788478884798848088481884828848388484884858848688487884888848988490884918849288493884948849588496884978849888499885008850188502885038850488505885068850788508885098851088511885128851388514885158851688517885188851988520885218852288523885248852588526885278852888529885308853188532885338853488535885368853788538885398854088541885428854388544885458854688547885488854988550885518855288553885548855588556885578855888559885608856188562885638856488565885668856788568885698857088571885728857388574885758857688577885788857988580885818858288583885848858588586885878858888589885908859188592885938859488595885968859788598885998860088601886028860388604886058860688607886088860988610886118861288613886148861588616886178861888619886208862188622886238862488625886268862788628886298863088631886328863388634886358863688637886388863988640886418864288643886448864588646886478864888649886508865188652886538865488655886568865788658886598866088661886628866388664886658866688667886688866988670886718867288673886748867588676886778867888679886808868188682886838868488685886868868788688886898869088691886928869388694886958869688697886988869988700887018870288703887048870588706887078870888709887108871188712887138871488715887168871788718887198872088721887228872388724887258872688727887288872988730887318873288733887348873588736887378873888739887408874188742887438874488745887468874788748887498875088751887528875388754887558875688757887588875988760887618876288763887648876588766887678876888769887708877188772887738877488775887768877788778887798878088781887828878388784887858878688787887888878988790887918879288793887948879588796887978879888799888008880188802888038880488805888068880788808888098881088811888128881388814888158881688817888188881988820888218882288823888248882588826888278882888829888308883188832888338883488835888368883788838888398884088841888428884388844888458884688847888488884988850888518885288853888548885588856888578885888859888608886188862888638886488865888668886788868888698887088871888728887388874888758887688877888788887988880888818888288883888848888588886888878888888889888908889188892888938889488895888968889788898888998890088901889028890388904889058890688907889088890988910889118891288913889148891588916889178891888919889208892188922889238892488925889268892788928889298893088931889328893388934889358893688937889388893988940889418894288943889448894588946889478894888949889508895188952889538895488955889568895788958889598896088961889628896388964889658896688967889688896988970889718897288973889748897588976889778897888979889808898188982889838898488985889868898788988889898899088991889928899388994889958899688997889988899989000890018900289003890048900589006890078900889009890108901189012890138901489015890168901789018890198902089021890228902389024890258902689027890288902989030890318903289033890348903589036890378903889039890408904189042890438904489045890468904789048890498905089051890528905389054890558905689057890588905989060890618906289063890648906589066890678906889069890708907189072890738907489075890768907789078890798908089081890828908389084890858908689087890888908989090890918909289093890948909589096890978909889099891008910189102891038910489105891068910789108891098911089111891128911389114891158911689117891188911989120891218912289123891248912589126891278912889129891308913189132891338913489135891368913789138891398914089141891428914389144891458914689147891488914989150891518915289153891548915589156891578915889159891608916189162891638916489165891668916789168891698917089171891728917389174891758917689177891788917989180891818918289183891848918589186891878918889189891908919189192891938919489195891968919789198891998920089201892028920389204892058920689207892088920989210892118921289213892148921589216892178921889219892208922189222892238922489225892268922789228892298923089231892328923389234892358923689237892388923989240892418924289243892448924589246892478924889249892508925189252892538925489255892568925789258892598926089261892628926389264892658926689267892688926989270892718927289273892748927589276892778927889279892808928189282892838928489285892868928789288892898929089291892928929389294892958929689297892988929989300893018930289303893048930589306893078930889309893108931189312893138931489315893168931789318893198932089321893228932389324893258932689327893288932989330893318933289333893348933589336893378933889339893408934189342893438934489345893468934789348893498935089351893528935389354893558935689357893588935989360893618936289363893648936589366893678936889369893708937189372893738937489375893768937789378893798938089381893828938389384893858938689387893888938989390893918939289393893948939589396893978939889399894008940189402894038940489405894068940789408894098941089411894128941389414894158941689417894188941989420894218942289423894248942589426894278942889429894308943189432894338943489435894368943789438894398944089441894428944389444894458944689447894488944989450894518945289453894548945589456894578945889459894608946189462894638946489465894668946789468894698947089471894728947389474894758947689477894788947989480894818948289483894848948589486894878948889489894908949189492894938949489495894968949789498894998950089501895028950389504895058950689507895088950989510895118951289513895148951589516895178951889519895208952189522895238952489525895268952789528895298953089531895328953389534895358953689537895388953989540895418954289543895448954589546895478954889549895508955189552895538955489555895568955789558895598956089561895628956389564895658956689567895688956989570895718957289573895748957589576895778957889579895808958189582895838958489585895868958789588895898959089591895928959389594895958959689597895988959989600896018960289603896048960589606896078960889609896108961189612896138961489615896168961789618896198962089621896228962389624896258962689627896288962989630896318963289633896348963589636896378963889639896408964189642896438964489645896468964789648896498965089651896528965389654896558965689657896588965989660896618966289663896648966589666896678966889669896708967189672896738967489675896768967789678896798968089681896828968389684896858968689687896888968989690896918969289693896948969589696896978969889699897008970189702897038970489705897068970789708897098971089711897128971389714897158971689717897188971989720897218972289723897248972589726897278972889729897308973189732897338973489735897368973789738897398974089741897428974389744897458974689747897488974989750897518975289753897548975589756897578975889759897608976189762897638976489765897668976789768897698977089771897728977389774897758977689777897788977989780897818978289783897848978589786897878978889789897908979189792897938979489795897968979789798897998980089801898028980389804898058980689807898088980989810898118981289813898148981589816898178981889819898208982189822898238982489825898268982789828898298983089831898328983389834898358983689837898388983989840898418984289843898448984589846898478984889849898508985189852898538985489855898568985789858898598986089861898628986389864898658986689867898688986989870898718987289873898748987589876898778987889879898808988189882898838988489885898868988789888898898989089891898928989389894898958989689897898988989989900899018990289903899048990589906899078990889909899108991189912899138991489915899168991789918899198992089921899228992389924899258992689927899288992989930899318993289933899348993589936899378993889939899408994189942899438994489945899468994789948899498995089951899528995389954899558995689957899588995989960899618996289963899648996589966899678996889969899708997189972899738997489975899768997789978899798998089981899828998389984899858998689987899888998989990899918999289993899948999589996899978999889999900009000190002900039000490005900069000790008900099001090011900129001390014900159001690017900189001990020900219002290023900249002590026900279002890029900309003190032900339003490035900369003790038900399004090041900429004390044900459004690047900489004990050900519005290053900549005590056900579005890059900609006190062900639006490065900669006790068900699007090071900729007390074900759007690077900789007990080900819008290083900849008590086900879008890089900909009190092900939009490095900969009790098900999010090101901029010390104901059010690107901089010990110901119011290113901149011590116901179011890119901209012190122901239012490125901269012790128901299013090131901329013390134901359013690137901389013990140901419014290143901449014590146901479014890149901509015190152901539015490155901569015790158901599016090161901629016390164901659016690167901689016990170901719017290173901749017590176901779017890179901809018190182901839018490185901869018790188901899019090191901929019390194901959019690197901989019990200902019020290203902049020590206902079020890209902109021190212902139021490215902169021790218902199022090221902229022390224902259022690227902289022990230902319023290233902349023590236902379023890239902409024190242902439024490245902469024790248902499025090251902529025390254902559025690257902589025990260902619026290263902649026590266902679026890269902709027190272902739027490275902769027790278902799028090281902829028390284902859028690287902889028990290902919029290293902949029590296902979029890299903009030190302903039030490305903069030790308903099031090311903129031390314903159031690317903189031990320903219032290323903249032590326903279032890329903309033190332903339033490335903369033790338903399034090341903429034390344903459034690347903489034990350903519035290353903549035590356903579035890359903609036190362903639036490365903669036790368903699037090371903729037390374903759037690377903789037990380903819038290383903849038590386903879038890389903909039190392903939039490395903969039790398903999040090401904029040390404904059040690407904089040990410904119041290413904149041590416904179041890419904209042190422904239042490425904269042790428904299043090431904329043390434904359043690437904389043990440904419044290443904449044590446904479044890449904509045190452904539045490455904569045790458904599046090461904629046390464904659046690467904689046990470904719047290473904749047590476904779047890479904809048190482904839048490485904869048790488904899049090491904929049390494904959049690497904989049990500905019050290503905049050590506905079050890509905109051190512905139051490515905169051790518905199052090521905229052390524905259052690527905289052990530905319053290533905349053590536905379053890539905409054190542905439054490545905469054790548905499055090551905529055390554905559055690557905589055990560905619056290563905649056590566905679056890569905709057190572905739057490575905769057790578905799058090581905829058390584905859058690587905889058990590905919059290593905949059590596905979059890599906009060190602906039060490605906069060790608906099061090611906129061390614906159061690617906189061990620906219062290623906249062590626906279062890629906309063190632906339063490635906369063790638906399064090641906429064390644906459064690647906489064990650906519065290653906549065590656906579065890659906609066190662906639066490665906669066790668906699067090671906729067390674906759067690677906789067990680906819068290683906849068590686906879068890689906909069190692906939069490695906969069790698906999070090701907029070390704907059070690707907089070990710907119071290713907149071590716907179071890719907209072190722907239072490725907269072790728907299073090731907329073390734907359073690737907389073990740907419074290743907449074590746907479074890749907509075190752907539075490755907569075790758907599076090761907629076390764907659076690767907689076990770907719077290773907749077590776907779077890779907809078190782907839078490785907869078790788907899079090791907929079390794907959079690797907989079990800908019080290803908049080590806908079080890809908109081190812908139081490815908169081790818908199082090821908229082390824908259082690827908289082990830908319083290833908349083590836908379083890839908409084190842908439084490845908469084790848908499085090851908529085390854908559085690857908589085990860908619086290863908649086590866908679086890869908709087190872908739087490875908769087790878908799088090881908829088390884908859088690887908889088990890908919089290893908949089590896908979089890899909009090190902909039090490905909069090790908909099091090911909129091390914909159091690917909189091990920909219092290923909249092590926909279092890929909309093190932909339093490935909369093790938909399094090941909429094390944909459094690947909489094990950909519095290953909549095590956909579095890959909609096190962909639096490965909669096790968909699097090971909729097390974909759097690977909789097990980909819098290983909849098590986909879098890989909909099190992909939099490995909969099790998909999100091001910029100391004910059100691007910089100991010910119101291013910149101591016910179101891019910209102191022910239102491025910269102791028910299103091031910329103391034910359103691037910389103991040910419104291043910449104591046910479104891049910509105191052910539105491055910569105791058910599106091061910629106391064910659106691067910689106991070910719107291073910749107591076910779107891079910809108191082910839108491085910869108791088910899109091091910929109391094910959109691097910989109991100911019110291103911049110591106911079110891109911109111191112911139111491115911169111791118911199112091121911229112391124911259112691127911289112991130911319113291133911349113591136911379113891139911409114191142911439114491145911469114791148911499115091151911529115391154911559115691157911589115991160911619116291163911649116591166911679116891169911709117191172911739117491175911769117791178911799118091181911829118391184911859118691187911889118991190911919119291193911949119591196911979119891199912009120191202912039120491205912069120791208912099121091211912129121391214912159121691217912189121991220912219122291223912249122591226912279122891229912309123191232912339123491235912369123791238912399124091241912429124391244912459124691247912489124991250912519125291253912549125591256912579125891259912609126191262912639126491265912669126791268912699127091271912729127391274912759127691277912789127991280912819128291283912849128591286912879128891289912909129191292912939129491295912969129791298912999130091301913029130391304913059130691307913089130991310913119131291313913149131591316913179131891319913209132191322913239132491325913269132791328913299133091331913329133391334913359133691337913389133991340913419134291343913449134591346913479134891349913509135191352913539135491355913569135791358913599136091361913629136391364913659136691367913689136991370913719137291373913749137591376913779137891379913809138191382913839138491385913869138791388913899139091391913929139391394913959139691397913989139991400914019140291403914049140591406914079140891409914109141191412914139141491415914169141791418914199142091421914229142391424914259142691427914289142991430914319143291433914349143591436914379143891439914409144191442914439144491445914469144791448914499145091451914529145391454914559145691457914589145991460914619146291463914649146591466914679146891469914709147191472914739147491475914769147791478914799148091481914829148391484914859148691487914889148991490914919149291493914949149591496914979149891499915009150191502915039150491505915069150791508915099151091511915129151391514915159151691517915189151991520915219152291523915249152591526915279152891529915309153191532915339153491535915369153791538915399154091541915429154391544915459154691547915489154991550915519155291553915549155591556915579155891559915609156191562915639156491565915669156791568915699157091571915729157391574915759157691577915789157991580915819158291583915849158591586915879158891589915909159191592915939159491595915969159791598915999160091601916029160391604916059160691607916089160991610916119161291613916149161591616916179161891619916209162191622916239162491625916269162791628916299163091631916329163391634916359163691637916389163991640916419164291643916449164591646916479164891649916509165191652916539165491655916569165791658916599166091661916629166391664916659166691667916689166991670916719167291673916749167591676916779167891679916809168191682916839168491685916869168791688916899169091691916929169391694916959169691697916989169991700917019170291703917049170591706917079170891709917109171191712917139171491715917169171791718917199172091721917229172391724917259172691727917289172991730917319173291733917349173591736917379173891739917409174191742917439174491745917469174791748917499175091751917529175391754917559175691757917589175991760917619176291763917649176591766917679176891769917709177191772917739177491775917769177791778917799178091781917829178391784917859178691787917889178991790917919179291793917949179591796917979179891799918009180191802918039180491805918069180791808918099181091811918129181391814918159181691817918189181991820918219182291823918249182591826918279182891829918309183191832918339183491835918369183791838918399184091841918429184391844918459184691847918489184991850918519185291853918549185591856918579185891859918609186191862918639186491865918669186791868918699187091871918729187391874918759187691877918789187991880918819188291883918849188591886918879188891889918909189191892918939189491895918969189791898918999190091901919029190391904919059190691907919089190991910919119191291913919149191591916919179191891919919209192191922919239192491925919269192791928919299193091931919329193391934919359193691937919389193991940919419194291943919449194591946919479194891949919509195191952919539195491955919569195791958919599196091961919629196391964919659196691967919689196991970919719197291973919749197591976919779197891979919809198191982919839198491985919869198791988919899199091991919929199391994919959199691997919989199992000920019200292003920049200592006920079200892009920109201192012920139201492015920169201792018920199202092021920229202392024920259202692027920289202992030920319203292033920349203592036920379203892039920409204192042920439204492045920469204792048920499205092051920529205392054920559205692057920589205992060920619206292063920649206592066920679206892069920709207192072920739207492075920769207792078920799208092081920829208392084920859208692087920889208992090920919209292093920949209592096920979209892099921009210192102921039210492105921069210792108921099211092111921129211392114921159211692117921189211992120921219212292123921249212592126921279212892129921309213192132921339213492135921369213792138921399214092141921429214392144921459214692147921489214992150921519215292153921549215592156921579215892159921609216192162921639216492165921669216792168921699217092171921729217392174921759217692177921789217992180921819218292183921849218592186921879218892189921909219192192921939219492195921969219792198921999220092201922029220392204922059220692207922089220992210922119221292213922149221592216922179221892219922209222192222922239222492225922269222792228922299223092231922329223392234922359223692237922389223992240922419224292243922449224592246922479224892249922509225192252922539225492255922569225792258922599226092261922629226392264922659226692267922689226992270922719227292273922749227592276922779227892279922809228192282922839228492285922869228792288922899229092291922929229392294922959229692297922989229992300923019230292303923049230592306923079230892309923109231192312923139231492315923169231792318923199232092321923229232392324923259232692327923289232992330923319233292333923349233592336923379233892339923409234192342923439234492345923469234792348923499235092351923529235392354923559235692357923589235992360923619236292363923649236592366923679236892369923709237192372923739237492375923769237792378923799238092381923829238392384923859238692387923889238992390923919239292393923949239592396923979239892399924009240192402924039240492405924069240792408924099241092411924129241392414924159241692417924189241992420924219242292423924249242592426924279242892429924309243192432924339243492435924369243792438924399244092441924429244392444924459244692447924489244992450924519245292453924549245592456924579245892459924609246192462924639246492465924669246792468924699247092471924729247392474924759247692477924789247992480924819248292483924849248592486924879248892489924909249192492924939249492495924969249792498924999250092501925029250392504925059250692507925089250992510925119251292513925149251592516925179251892519925209252192522925239252492525925269252792528925299253092531925329253392534925359253692537925389253992540925419254292543925449254592546925479254892549925509255192552925539255492555925569255792558925599256092561925629256392564925659256692567925689256992570925719257292573925749257592576925779257892579925809258192582925839258492585925869258792588925899259092591925929259392594925959259692597925989259992600926019260292603926049260592606926079260892609926109261192612926139261492615926169261792618926199262092621926229262392624926259262692627926289262992630926319263292633926349263592636926379263892639926409264192642926439264492645926469264792648926499265092651926529265392654926559265692657926589265992660926619266292663926649266592666926679266892669926709267192672926739267492675926769267792678926799268092681926829268392684926859268692687926889268992690926919269292693926949269592696926979269892699927009270192702927039270492705927069270792708927099271092711927129271392714927159271692717927189271992720927219272292723927249272592726927279272892729927309273192732927339273492735927369273792738927399274092741927429274392744927459274692747927489274992750927519275292753927549275592756927579275892759927609276192762927639276492765927669276792768927699277092771927729277392774927759277692777927789277992780927819278292783927849278592786927879278892789927909279192792927939279492795927969279792798927999280092801928029280392804928059280692807928089280992810928119281292813928149281592816928179281892819928209282192822928239282492825928269282792828928299283092831928329283392834928359283692837928389283992840928419284292843928449284592846928479284892849928509285192852928539285492855928569285792858928599286092861928629286392864928659286692867928689286992870928719287292873928749287592876928779287892879928809288192882928839288492885928869288792888928899289092891928929289392894928959289692897928989289992900929019290292903929049290592906929079290892909929109291192912929139291492915929169291792918929199292092921929229292392924929259292692927929289292992930929319293292933929349293592936929379293892939929409294192942929439294492945929469294792948929499295092951929529295392954929559295692957929589295992960929619296292963929649296592966929679296892969929709297192972929739297492975929769297792978929799298092981929829298392984929859298692987929889298992990929919299292993929949299592996929979299892999930009300193002930039300493005930069300793008930099301093011930129301393014930159301693017930189301993020930219302293023930249302593026930279302893029930309303193032930339303493035930369303793038930399304093041930429304393044930459304693047930489304993050930519305293053930549305593056930579305893059930609306193062930639306493065930669306793068930699307093071930729307393074930759307693077930789307993080930819308293083930849308593086930879308893089930909309193092930939309493095930969309793098930999310093101931029310393104931059310693107931089310993110931119311293113931149311593116931179311893119931209312193122931239312493125931269312793128931299313093131931329313393134931359313693137931389313993140931419314293143931449314593146931479314893149931509315193152931539315493155931569315793158931599316093161931629316393164931659316693167931689316993170931719317293173931749317593176931779317893179931809318193182931839318493185931869318793188931899319093191931929319393194931959319693197931989319993200932019320293203932049320593206932079320893209932109321193212932139321493215932169321793218932199322093221932229322393224932259322693227932289322993230932319323293233932349323593236932379323893239932409324193242932439324493245932469324793248932499325093251932529325393254932559325693257932589325993260932619326293263932649326593266932679326893269932709327193272932739327493275932769327793278932799328093281932829328393284932859328693287932889328993290932919329293293932949329593296932979329893299933009330193302933039330493305933069330793308933099331093311933129331393314933159331693317933189331993320933219332293323933249332593326933279332893329933309333193332933339333493335933369333793338933399334093341933429334393344933459334693347933489334993350933519335293353933549335593356933579335893359933609336193362933639336493365933669336793368933699337093371933729337393374933759337693377933789337993380933819338293383933849338593386933879338893389933909339193392933939339493395933969339793398933999340093401934029340393404934059340693407934089340993410934119341293413934149341593416934179341893419934209342193422934239342493425934269342793428934299343093431934329343393434934359343693437934389343993440934419344293443934449344593446934479344893449934509345193452934539345493455934569345793458934599346093461934629346393464934659346693467934689346993470934719347293473934749347593476934779347893479934809348193482934839348493485934869348793488934899349093491934929349393494934959349693497934989349993500935019350293503935049350593506935079350893509935109351193512935139351493515935169351793518935199352093521935229352393524935259352693527935289352993530935319353293533935349353593536935379353893539935409354193542935439354493545935469354793548935499355093551935529355393554935559355693557935589355993560935619356293563935649356593566935679356893569935709357193572935739357493575935769357793578935799358093581935829358393584935859358693587935889358993590935919359293593935949359593596935979359893599936009360193602936039360493605936069360793608936099361093611936129361393614936159361693617936189361993620936219362293623936249362593626936279362893629936309363193632936339363493635936369363793638936399364093641936429364393644936459364693647936489364993650936519365293653936549365593656936579365893659936609366193662936639366493665936669366793668936699367093671936729367393674936759367693677936789367993680936819368293683936849368593686936879368893689936909369193692936939369493695936969369793698936999370093701937029370393704937059370693707937089370993710937119371293713937149371593716937179371893719937209372193722937239372493725937269372793728937299373093731937329373393734937359373693737937389373993740937419374293743937449374593746937479374893749937509375193752937539375493755937569375793758937599376093761937629376393764937659376693767937689376993770937719377293773937749377593776937779377893779937809378193782937839378493785937869378793788937899379093791937929379393794937959379693797937989379993800938019380293803938049380593806938079380893809938109381193812938139381493815938169381793818938199382093821938229382393824938259382693827938289382993830938319383293833938349383593836938379383893839938409384193842938439384493845938469384793848938499385093851938529385393854938559385693857938589385993860938619386293863938649386593866938679386893869938709387193872938739387493875938769387793878938799388093881938829388393884938859388693887938889388993890938919389293893938949389593896938979389893899939009390193902939039390493905939069390793908939099391093911939129391393914939159391693917939189391993920939219392293923939249392593926939279392893929939309393193932939339393493935939369393793938939399394093941939429394393944939459394693947939489394993950939519395293953939549395593956939579395893959939609396193962939639396493965939669396793968939699397093971939729397393974939759397693977939789397993980939819398293983939849398593986939879398893989939909399193992939939399493995939969399793998939999400094001940029400394004940059400694007940089400994010940119401294013940149401594016940179401894019940209402194022940239402494025940269402794028940299403094031940329403394034940359403694037940389403994040940419404294043940449404594046940479404894049940509405194052940539405494055940569405794058940599406094061940629406394064940659406694067940689406994070940719407294073940749407594076940779407894079940809408194082940839408494085940869408794088940899409094091940929409394094940959409694097940989409994100941019410294103941049410594106941079410894109941109411194112941139411494115941169411794118941199412094121941229412394124941259412694127941289412994130941319413294133941349413594136941379413894139941409414194142941439414494145941469414794148941499415094151941529415394154941559415694157941589415994160941619416294163941649416594166941679416894169941709417194172941739417494175941769417794178941799418094181941829418394184941859418694187941889418994190941919419294193941949419594196941979419894199942009420194202942039420494205942069420794208942099421094211942129421394214942159421694217942189421994220942219422294223942249422594226942279422894229942309423194232942339423494235942369423794238942399424094241942429424394244942459424694247942489424994250942519425294253942549425594256942579425894259942609426194262942639426494265942669426794268942699427094271942729427394274942759427694277942789427994280942819428294283942849428594286942879428894289942909429194292942939429494295942969429794298942999430094301943029430394304943059430694307943089430994310943119431294313943149431594316943179431894319943209432194322943239432494325943269432794328943299433094331943329433394334943359433694337943389433994340943419434294343943449434594346943479434894349943509435194352943539435494355943569435794358943599436094361943629436394364943659436694367943689436994370943719437294373943749437594376943779437894379943809438194382943839438494385943869438794388943899439094391943929439394394943959439694397943989439994400944019440294403944049440594406944079440894409944109441194412944139441494415944169441794418944199442094421944229442394424944259442694427944289442994430944319443294433944349443594436944379443894439944409444194442944439444494445944469444794448944499445094451944529445394454944559445694457944589445994460944619446294463944649446594466944679446894469944709447194472944739447494475944769447794478944799448094481944829448394484944859448694487944889448994490944919449294493944949449594496944979449894499945009450194502945039450494505945069450794508945099451094511945129451394514945159451694517945189451994520945219452294523945249452594526945279452894529945309453194532945339453494535945369453794538945399454094541945429454394544945459454694547945489454994550945519455294553945549455594556945579455894559945609456194562945639456494565945669456794568945699457094571945729457394574945759457694577945789457994580945819458294583945849458594586945879458894589945909459194592945939459494595945969459794598945999460094601946029460394604946059460694607946089460994610946119461294613946149461594616946179461894619946209462194622946239462494625946269462794628946299463094631946329463394634946359463694637946389463994640946419464294643946449464594646946479464894649946509465194652946539465494655946569465794658946599466094661946629466394664946659466694667946689466994670946719467294673946749467594676946779467894679946809468194682946839468494685946869468794688946899469094691946929469394694946959469694697946989469994700947019470294703947049470594706947079470894709947109471194712947139471494715947169471794718947199472094721947229472394724947259472694727947289472994730947319473294733947349473594736947379473894739947409474194742947439474494745947469474794748947499475094751947529475394754947559475694757947589475994760947619476294763947649476594766947679476894769947709477194772947739477494775947769477794778947799478094781947829478394784947859478694787947889478994790947919479294793947949479594796947979479894799948009480194802948039480494805948069480794808948099481094811948129481394814948159481694817948189481994820948219482294823948249482594826948279482894829948309483194832948339483494835948369483794838948399484094841948429484394844948459484694847948489484994850948519485294853948549485594856948579485894859948609486194862948639486494865948669486794868948699487094871948729487394874948759487694877948789487994880948819488294883948849488594886948879488894889948909489194892948939489494895948969489794898948999490094901949029490394904949059490694907949089490994910949119491294913949149491594916949179491894919949209492194922949239492494925949269492794928949299493094931949329493394934949359493694937949389493994940949419494294943949449494594946949479494894949949509495194952949539495494955949569495794958949599496094961949629496394964949659496694967949689496994970949719497294973949749497594976949779497894979949809498194982949839498494985949869498794988
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@sdk/utils/math')) :
  3. typeof define === 'function' && define.amd ? define(['exports', '@sdk/utils/math'], factory) :
  4. (global = global || self, factory(global.Potree = {}, global.math$1));
  5. }(this, (function (exports, math$1) { 'use strict';
  6. math$1 = math$1 && Object.prototype.hasOwnProperty.call(math$1, 'default') ? math$1['default'] : math$1;
  7. // threejs.org/license
  8. var REVISION='124';var MOUSE={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2};var TOUCH={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3};var CullFaceNone=0;var CullFaceBack=1;var CullFaceFront=2;var CullFaceFrontBack=3;var BasicShadowMap=0;var PCFShadowMap=1;var PCFSoftShadowMap=2;var VSMShadowMap=3;var FrontSide=0;var BackSide=1;var DoubleSide=2;var FlatShading$1=1;var SmoothShading=2;var NoBlending=0;var NormalBlending=1;var AdditiveBlending=2;var SubtractiveBlending=3;var MultiplyBlending=4;var CustomBlending=5;var AddEquation=100;var SubtractEquation=101;var ReverseSubtractEquation=102;var MinEquation=103;var MaxEquation=104;var ZeroFactor=200;var OneFactor=201;var SrcColorFactor=202;var OneMinusSrcColorFactor=203;var SrcAlphaFactor=204;var OneMinusSrcAlphaFactor=205;var DstAlphaFactor=206;var OneMinusDstAlphaFactor=207;var DstColorFactor=208;var OneMinusDstColorFactor=209;var SrcAlphaSaturateFactor=210;var NeverDepth=0;var AlwaysDepth=1;var LessDepth=2;var LessEqualDepth=3;var EqualDepth=4;var GreaterEqualDepth=5;var GreaterDepth=6;var NotEqualDepth=7;var MultiplyOperation=0;var MixOperation=1;var AddOperation=2;var NoToneMapping=0;var LinearToneMapping=1;var ReinhardToneMapping=2;var CineonToneMapping=3;var ACESFilmicToneMapping=4;var CustomToneMapping=5;var UVMapping=300;var CubeReflectionMapping=301;var CubeRefractionMapping=302;var EquirectangularReflectionMapping=303;var EquirectangularRefractionMapping=304;var CubeUVReflectionMapping=306;var CubeUVRefractionMapping=307;var RepeatWrapping=1000;var ClampToEdgeWrapping=1001;var MirroredRepeatWrapping=1002;var NearestFilter=1003;var NearestMipmapNearestFilter=1004;var NearestMipMapNearestFilter=1004;var NearestMipmapLinearFilter=1005;var NearestMipMapLinearFilter=1005;var LinearFilter=1006;var LinearMipmapNearestFilter=1007;var LinearMipMapNearestFilter=1007;var LinearMipmapLinearFilter=1008;var LinearMipMapLinearFilter=1008;var UnsignedByteType=1009;var ByteType=1010;var ShortType=1011;var UnsignedShortType=1012;var IntType=1013;var UnsignedIntType=1014;var FloatType=1015;var HalfFloatType=1016;var UnsignedShort4444Type=1017;var UnsignedShort5551Type=1018;var UnsignedShort565Type=1019;var UnsignedInt248Type$1=1020;var AlphaFormat=1021;var RGBFormat=1022;var RGBAFormat=1023;var LuminanceFormat=1024;var LuminanceAlphaFormat=1025;var RGBEFormat=RGBAFormat;var DepthFormat=1026;var DepthStencilFormat=1027;var RedFormat=1028;var RedIntegerFormat=1029;var RGFormat=1030;var RGIntegerFormat=1031;var RGBIntegerFormat=1032;var RGBAIntegerFormat=1033;var RGB_S3TC_DXT1_Format=33776;var RGBA_S3TC_DXT1_Format$1=33777;var RGBA_S3TC_DXT3_Format=33778;var RGBA_S3TC_DXT5_Format$1=33779;var RGB_PVRTC_4BPPV1_Format=35840;var RGB_PVRTC_2BPPV1_Format=35841;var RGBA_PVRTC_4BPPV1_Format=35842;var RGBA_PVRTC_2BPPV1_Format=35843;var RGB_ETC1_Format=36196;var RGB_ETC2_Format=37492;var RGBA_ETC2_EAC_Format=37496;var RGBA_ASTC_4x4_Format=37808;var RGBA_ASTC_5x4_Format=37809;var RGBA_ASTC_5x5_Format=37810;var RGBA_ASTC_6x5_Format=37811;var RGBA_ASTC_6x6_Format=37812;var RGBA_ASTC_8x5_Format=37813;var RGBA_ASTC_8x6_Format=37814;var RGBA_ASTC_8x8_Format=37815;var RGBA_ASTC_10x5_Format=37816;var RGBA_ASTC_10x6_Format=37817;var RGBA_ASTC_10x8_Format=37818;var RGBA_ASTC_10x10_Format=37819;var RGBA_ASTC_12x10_Format=37820;var RGBA_ASTC_12x12_Format=37821;var RGBA_BPTC_Format=36492;var SRGB8_ALPHA8_ASTC_4x4_Format=37840;var SRGB8_ALPHA8_ASTC_5x4_Format=37841;var SRGB8_ALPHA8_ASTC_5x5_Format=37842;var SRGB8_ALPHA8_ASTC_6x5_Format=37843;var SRGB8_ALPHA8_ASTC_6x6_Format=37844;var SRGB8_ALPHA8_ASTC_8x5_Format=37845;var SRGB8_ALPHA8_ASTC_8x6_Format=37846;var SRGB8_ALPHA8_ASTC_8x8_Format=37847;var SRGB8_ALPHA8_ASTC_10x5_Format=37848;var SRGB8_ALPHA8_ASTC_10x6_Format=37849;var SRGB8_ALPHA8_ASTC_10x8_Format=37850;var SRGB8_ALPHA8_ASTC_10x10_Format=37851;var SRGB8_ALPHA8_ASTC_12x10_Format=37852;var SRGB8_ALPHA8_ASTC_12x12_Format=37853;var LoopOnce=2200;var LoopRepeat=2201;var LoopPingPong=2202;var InterpolateDiscrete=2300;var InterpolateLinear=2301;var InterpolateSmooth=2302;var ZeroCurvatureEnding=2400;var ZeroSlopeEnding=2401;var WrapAroundEnding=2402;var NormalAnimationBlendMode=2500;var AdditiveAnimationBlendMode=2501;var TrianglesDrawMode=0;var TriangleStripDrawMode=1;var TriangleFanDrawMode=2;var LinearEncoding=3000;var sRGBEncoding=3001;var GammaEncoding=3007;var RGBEEncoding=3002;var LogLuvEncoding=3003;var RGBM7Encoding=3004;var RGBM16Encoding=3005;var RGBDEncoding=3006;var BasicDepthPacking=3200;var RGBADepthPacking=3201;var TangentSpaceNormalMap=0;var ObjectSpaceNormalMap=1;var ZeroStencilOp=0;var KeepStencilOp=7680;var ReplaceStencilOp=7681;var IncrementStencilOp=7682;var DecrementStencilOp=7683;var IncrementWrapStencilOp=34055;var DecrementWrapStencilOp=34056;var InvertStencilOp=5386;var NeverStencilFunc=512;var LessStencilFunc=513;var EqualStencilFunc=514;var LessEqualStencilFunc=515;var GreaterStencilFunc=516;var NotEqualStencilFunc=517;var GreaterEqualStencilFunc=518;var AlwaysStencilFunc=519;var StaticDrawUsage=35044;var DynamicDrawUsage=35048;var StreamDrawUsage=35040;var StaticReadUsage=35045;var DynamicReadUsage=35049;var StreamReadUsage=35041;var StaticCopyUsage=35046;var DynamicCopyUsage=35050;var StreamCopyUsage=35042;var GLSL1='100';var GLSL3='300 es';/**
  9. * https://github.com/mrdoob/eventdispatcher.js/
  10. */function EventDispatcher(){}Object.assign(EventDispatcher.prototype,{addEventListener:function addEventListener(type,listener){if(this._listeners===undefined)this._listeners={};var listeners=this._listeners;if(listeners[type]===undefined){listeners[type]=[];}if(listeners[type].indexOf(listener)===-1){listeners[type].push(listener);}},hasEventListener:function hasEventListener(type,listener){if(this._listeners===undefined)return false;var listeners=this._listeners;return listeners[type]!==undefined&&listeners[type].indexOf(listener)!==-1;},dispatchEvent:function dispatchEvent(event){if(this._listeners===undefined)return;var listeners=this._listeners;var listenerArray=listeners[event.type];if(listenerArray!==undefined){event.target=this;// Make a copy, in case listeners are removed while iterating.
  11. var array=listenerArray.slice(0);for(var i=0,l=array.length;i<l;i++){array[i].call(this,event);}}}});var _lut=[];for(var i=0;i<256;i++){_lut[i]=(i<16?'0':'')+i.toString(16);}var _seed=1234567;var MathUtils={DEG2RAD:Math.PI/180,RAD2DEG:180/Math.PI,generateUUID:function generateUUID(){// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
  12. var d0=Math.random()*0xffffffff|0;var d1=Math.random()*0xffffffff|0;var d2=Math.random()*0xffffffff|0;var d3=Math.random()*0xffffffff|0;var uuid=_lut[d0&0xff]+_lut[d0>>8&0xff]+_lut[d0>>16&0xff]+_lut[d0>>24&0xff]+'-'+_lut[d1&0xff]+_lut[d1>>8&0xff]+'-'+_lut[d1>>16&0x0f|0x40]+_lut[d1>>24&0xff]+'-'+_lut[d2&0x3f|0x80]+_lut[d2>>8&0xff]+'-'+_lut[d2>>16&0xff]+_lut[d2>>24&0xff]+_lut[d3&0xff]+_lut[d3>>8&0xff]+_lut[d3>>16&0xff]+_lut[d3>>24&0xff];// .toUpperCase() here flattens concatenated strings to save heap memory space.
  13. return uuid.toUpperCase();},clamp:function clamp(value,min,max){return Math.max(min,Math.min(max,value));},// compute euclidian modulo of m % n
  14. // https://en.wikipedia.org/wiki/Modulo_operation
  15. euclideanModulo:function euclideanModulo(n,m){return (n%m+m)%m;},// Linear mapping from range <a1, a2> to range <b1, b2>
  16. mapLinear:function mapLinear(x,a1,a2,b1,b2){return b1+(x-a1)*(b2-b1)/(a2-a1);},// https://en.wikipedia.org/wiki/Linear_interpolation
  17. lerp:function lerp(x,y,t){return (1-t)*x+t*y;},// http://en.wikipedia.org/wiki/Smoothstep
  18. smoothstep:function smoothstep(x,min,max){if(x<=min)return 0;if(x>=max)return 1;x=(x-min)/(max-min);return x*x*(3-2*x);},smootherstep:function smootherstep(x,min,max){if(x<=min)return 0;if(x>=max)return 1;x=(x-min)/(max-min);return x*x*x*(x*(x*6-15)+10);},// Random integer from <low, high> interval
  19. randInt:function randInt(low,high){return low+Math.floor(Math.random()*(high-low+1));},// Random float from <low, high> interval
  20. randFloat:function randFloat(low,high){return low+Math.random()*(high-low);},// Random float from <-range/2, range/2> interval
  21. randFloatSpread:function randFloatSpread(range){return range*(0.5-Math.random());},// Deterministic pseudo-random float in the interval [ 0, 1 ]
  22. seededRandom:function seededRandom(s){if(s!==undefined)_seed=s%2147483647;// Park-Miller algorithm
  23. _seed=_seed*16807%2147483647;return (_seed-1)/2147483646;},degToRad:function degToRad(degrees){return degrees*MathUtils.DEG2RAD;},radToDeg:function radToDeg(radians){return radians*MathUtils.RAD2DEG;},isPowerOfTwo:function isPowerOfTwo(value){return (value&value-1)===0&&value!==0;},ceilPowerOfTwo:function ceilPowerOfTwo(value){return Math.pow(2,Math.ceil(Math.log(value)/Math.LN2));},floorPowerOfTwo:function floorPowerOfTwo(value){return Math.pow(2,Math.floor(Math.log(value)/Math.LN2));},setQuaternionFromProperEuler:function setQuaternionFromProperEuler(q,a,b,c,order){// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
  24. // rotations are applied to the axes in the order specified by 'order'
  25. // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
  26. // angles are in radians
  27. var cos=Math.cos;var sin=Math.sin;var c2=cos(b/2);var s2=sin(b/2);var c13=cos((a+c)/2);var s13=sin((a+c)/2);var c1_3=cos((a-c)/2);var s1_3=sin((a-c)/2);var c3_1=cos((c-a)/2);var s3_1=sin((c-a)/2);switch(order){case'XYX':q.set(c2*s13,s2*c1_3,s2*s1_3,c2*c13);break;case'YZY':q.set(s2*s1_3,c2*s13,s2*c1_3,c2*c13);break;case'ZXZ':q.set(s2*c1_3,s2*s1_3,c2*s13,c2*c13);break;case'XZX':q.set(c2*s13,s2*s3_1,s2*c3_1,c2*c13);break;case'YXY':q.set(s2*c3_1,c2*s13,s2*s3_1,c2*c13);break;case'ZYZ':q.set(s2*s3_1,s2*c3_1,c2*s13,c2*c13);break;default:console.warn('THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: '+order);}}};class Vector2{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;Object.defineProperty(this,'isVector2',{value:true});this.x=x;this.y=y;}get width(){return this.x;}set width(value){this.x=value;}get height(){return this.y;}set height(value){this.y=value;}set(x,y){this.x=x;this.y=y;return this;}setScalar(scalar){this.x=scalar;this.y=scalar;return this;}setX(x){this.x=x;return this;}setY(y){this.y=y;return this;}setComponent(index,value){switch(index){case 0:this.x=value;break;case 1:this.y=value;break;default:throw new Error('index is out of range: '+index);}return this;}getComponent(index){switch(index){case 0:return this.x;case 1:return this.y;default:throw new Error('index is out of range: '+index);}}clone(){return new this.constructor(this.x,this.y);}copy(v){this.x=v.x;this.y=v.y;return this;}add(v,w){if(w!==undefined){console.warn('THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');return this.addVectors(v,w);}this.x+=v.x;this.y+=v.y;return this;}addScalar(s){this.x+=s;this.y+=s;return this;}addVectors(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this;}addScaledVector(v,s){this.x+=v.x*s;this.y+=v.y*s;return this;}sub(v,w){if(w!==undefined){console.warn('THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');return this.subVectors(v,w);}this.x-=v.x;this.y-=v.y;return this;}subScalar(s){this.x-=s;this.y-=s;return this;}subVectors(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this;}multiply(v){this.x*=v.x;this.y*=v.y;return this;}multiplyScalar(scalar){this.x*=scalar;this.y*=scalar;return this;}divide(v){this.x/=v.x;this.y/=v.y;return this;}divideScalar(scalar){return this.multiplyScalar(1/scalar);}applyMatrix3(m){var x=this.x,y=this.y;var e=m.elements;this.x=e[0]*x+e[3]*y+e[6];this.y=e[1]*x+e[4]*y+e[7];return this;}min(v){this.x=Math.min(this.x,v.x);this.y=Math.min(this.y,v.y);return this;}max(v){this.x=Math.max(this.x,v.x);this.y=Math.max(this.y,v.y);return this;}clamp(min,max){// assumes min < max, componentwise
  28. this.x=Math.max(min.x,Math.min(max.x,this.x));this.y=Math.max(min.y,Math.min(max.y,this.y));return this;}clampScalar(minVal,maxVal){this.x=Math.max(minVal,Math.min(maxVal,this.x));this.y=Math.max(minVal,Math.min(maxVal,this.y));return this;}clampLength(min,max){var length=this.length();return this.divideScalar(length||1).multiplyScalar(Math.max(min,Math.min(max,length)));}floor(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this;}ceil(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this;}round(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this;}roundToZero(){this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x);this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y);return this;}negate(){this.x=-this.x;this.y=-this.y;return this;}dot(v){return this.x*v.x+this.y*v.y;}cross(v){return this.x*v.y-this.y*v.x;}lengthSq(){return this.x*this.x+this.y*this.y;}length(){return Math.sqrt(this.x*this.x+this.y*this.y);}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y);}normalize(){return this.divideScalar(this.length()||1);}angle(){// computes the angle in radians with respect to the positive x-axis
  29. var angle=Math.atan2(-this.y,-this.x)+Math.PI;return angle;}distanceTo(v){return Math.sqrt(this.distanceToSquared(v));}distanceToSquared(v){var dx=this.x-v.x,dy=this.y-v.y;return dx*dx+dy*dy;}manhattanDistanceTo(v){return Math.abs(this.x-v.x)+Math.abs(this.y-v.y);}setLength(length){return this.normalize().multiplyScalar(length);}lerp(v,alpha){this.x+=(v.x-this.x)*alpha;this.y+=(v.y-this.y)*alpha;return this;}lerpVectors(v1,v2,alpha){this.x=v1.x+(v2.x-v1.x)*alpha;this.y=v1.y+(v2.y-v1.y)*alpha;return this;}equals(v){return v.x===this.x&&v.y===this.y;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.x=array[offset];this.y=array[offset+1];return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this.x;array[offset+1]=this.y;return array;}fromBufferAttribute(attribute,index,offset){if(offset!==undefined){console.warn('THREE.Vector2: offset has been removed from .fromBufferAttribute().');}this.x=attribute.getX(index);this.y=attribute.getY(index);return this;}rotateAround(center,angle){var c=Math.cos(angle),s=Math.sin(angle);var x=this.x-center.x;var y=this.y-center.y;this.x=x*c-y*s+center.x;this.y=x*s+y*c+center.y;return this;}random(){this.x=Math.random();this.y=Math.random();return this;}}class Matrix3{constructor(){Object.defineProperty(this,'isMatrix3',{value:true});this.elements=[1,0,0,0,1,0,0,0,1];if(arguments.length>0){console.error('THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.');}}set(n11,n12,n13,n21,n22,n23,n31,n32,n33){var te=this.elements;te[0]=n11;te[1]=n21;te[2]=n31;te[3]=n12;te[4]=n22;te[5]=n32;te[6]=n13;te[7]=n23;te[8]=n33;return this;}identity(){this.set(1,0,0,0,1,0,0,0,1);return this;}clone(){return new this.constructor().fromArray(this.elements);}copy(m){var te=this.elements;var me=m.elements;te[0]=me[0];te[1]=me[1];te[2]=me[2];te[3]=me[3];te[4]=me[4];te[5]=me[5];te[6]=me[6];te[7]=me[7];te[8]=me[8];return this;}extractBasis(xAxis,yAxis,zAxis){xAxis.setFromMatrix3Column(this,0);yAxis.setFromMatrix3Column(this,1);zAxis.setFromMatrix3Column(this,2);return this;}setFromMatrix4(m){var me=m.elements;this.set(me[0],me[4],me[8],me[1],me[5],me[9],me[2],me[6],me[10]);return this;}multiply(m){return this.multiplyMatrices(this,m);}premultiply(m){return this.multiplyMatrices(m,this);}multiplyMatrices(a,b){var ae=a.elements;var be=b.elements;var te=this.elements;var a11=ae[0],a12=ae[3],a13=ae[6];var a21=ae[1],a22=ae[4],a23=ae[7];var a31=ae[2],a32=ae[5],a33=ae[8];var b11=be[0],b12=be[3],b13=be[6];var b21=be[1],b22=be[4],b23=be[7];var b31=be[2],b32=be[5],b33=be[8];te[0]=a11*b11+a12*b21+a13*b31;te[3]=a11*b12+a12*b22+a13*b32;te[6]=a11*b13+a12*b23+a13*b33;te[1]=a21*b11+a22*b21+a23*b31;te[4]=a21*b12+a22*b22+a23*b32;te[7]=a21*b13+a22*b23+a23*b33;te[2]=a31*b11+a32*b21+a33*b31;te[5]=a31*b12+a32*b22+a33*b32;te[8]=a31*b13+a32*b23+a33*b33;return this;}multiplyScalar(s){var te=this.elements;te[0]*=s;te[3]*=s;te[6]*=s;te[1]*=s;te[4]*=s;te[7]*=s;te[2]*=s;te[5]*=s;te[8]*=s;return this;}determinant(){var te=this.elements;var a=te[0],b=te[1],c=te[2],d=te[3],e=te[4],f=te[5],g=te[6],h=te[7],i=te[8];return a*e*i-a*f*h-b*d*i+b*f*g+c*d*h-c*e*g;}invert(){var te=this.elements,n11=te[0],n21=te[1],n31=te[2],n12=te[3],n22=te[4],n32=te[5],n13=te[6],n23=te[7],n33=te[8],t11=n33*n22-n32*n23,t12=n32*n13-n33*n12,t13=n23*n12-n22*n13,det=n11*t11+n21*t12+n31*t13;if(det===0)return this.set(0,0,0,0,0,0,0,0,0);var detInv=1/det;te[0]=t11*detInv;te[1]=(n31*n23-n33*n21)*detInv;te[2]=(n32*n21-n31*n22)*detInv;te[3]=t12*detInv;te[4]=(n33*n11-n31*n13)*detInv;te[5]=(n31*n12-n32*n11)*detInv;te[6]=t13*detInv;te[7]=(n21*n13-n23*n11)*detInv;te[8]=(n22*n11-n21*n12)*detInv;return this;}transpose(){var tmp;var m=this.elements;tmp=m[1];m[1]=m[3];m[3]=tmp;tmp=m[2];m[2]=m[6];m[6]=tmp;tmp=m[5];m[5]=m[7];m[7]=tmp;return this;}getNormalMatrix(matrix4){return this.setFromMatrix4(matrix4).copy(this).invert().transpose();}transposeIntoArray(r){var m=this.elements;r[0]=m[0];r[1]=m[3];r[2]=m[6];r[3]=m[1];r[4]=m[4];r[5]=m[7];r[6]=m[2];r[7]=m[5];r[8]=m[8];return this;}setUvTransform(tx,ty,sx,sy,rotation,cx,cy){var c=Math.cos(rotation);var s=Math.sin(rotation);this.set(sx*c,sx*s,-sx*(c*cx+s*cy)+cx+tx,-sy*s,sy*c,-sy*(-s*cx+c*cy)+cy+ty,0,0,1);return this;}scale(sx,sy){var te=this.elements;te[0]*=sx;te[3]*=sx;te[6]*=sx;te[1]*=sy;te[4]*=sy;te[7]*=sy;return this;}rotate(theta){var c=Math.cos(theta);var s=Math.sin(theta);var te=this.elements;var a11=te[0],a12=te[3],a13=te[6];var a21=te[1],a22=te[4],a23=te[7];te[0]=c*a11+s*a21;te[3]=c*a12+s*a22;te[6]=c*a13+s*a23;te[1]=-s*a11+c*a21;te[4]=-s*a12+c*a22;te[7]=-s*a13+c*a23;return this;}translate(tx,ty){var te=this.elements;te[0]+=tx*te[2];te[3]+=tx*te[5];te[6]+=tx*te[8];te[1]+=ty*te[2];te[4]+=ty*te[5];te[7]+=ty*te[8];return this;}equals(matrix){var te=this.elements;var me=matrix.elements;for(var _i=0;_i<9;_i++){if(te[_i]!==me[_i])return false;}return true;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;for(var _i2=0;_i2<9;_i2++){this.elements[_i2]=array[_i2+offset];}return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var te=this.elements;array[offset]=te[0];array[offset+1]=te[1];array[offset+2]=te[2];array[offset+3]=te[3];array[offset+4]=te[4];array[offset+5]=te[5];array[offset+6]=te[6];array[offset+7]=te[7];array[offset+8]=te[8];return array;}}var _canvas;var ImageUtils={getDataURL:function getDataURL(image){if(/^data:/i.test(image.src)){return image.src;}if(typeof HTMLCanvasElement=='undefined'){return image.src;}var canvas;if(image instanceof HTMLCanvasElement){canvas=image;}else {if(_canvas===undefined)_canvas=document.createElementNS('http://www.w3.org/1999/xhtml','canvas');_canvas.width=image.width;_canvas.height=image.height;var context=_canvas.getContext('2d');if(image instanceof ImageData){context.putImageData(image,0,0);}else {context.drawImage(image,0,0,image.width,image.height);}canvas=_canvas;}if(canvas.width>2048||canvas.height>2048){return canvas.toDataURL('image/jpeg',0.6);}else {return canvas.toDataURL('image/png');}}};var textureId=0;function Texture(){var image=arguments.length>0&&arguments[0]!==undefined?arguments[0]:Texture.DEFAULT_IMAGE;var mapping=arguments.length>1&&arguments[1]!==undefined?arguments[1]:Texture.DEFAULT_MAPPING;var wrapS=arguments.length>2&&arguments[2]!==undefined?arguments[2]:ClampToEdgeWrapping;var wrapT=arguments.length>3&&arguments[3]!==undefined?arguments[3]:ClampToEdgeWrapping;var magFilter=arguments.length>4&&arguments[4]!==undefined?arguments[4]:LinearFilter;var minFilter=arguments.length>5&&arguments[5]!==undefined?arguments[5]:LinearMipmapLinearFilter;var format=arguments.length>6&&arguments[6]!==undefined?arguments[6]:RGBAFormat;var type=arguments.length>7&&arguments[7]!==undefined?arguments[7]:UnsignedByteType;var anisotropy=arguments.length>8&&arguments[8]!==undefined?arguments[8]:1;var encoding=arguments.length>9&&arguments[9]!==undefined?arguments[9]:LinearEncoding;Object.defineProperty(this,'id',{value:textureId++});this.uuid=MathUtils.generateUUID();this.name='';this.image=image;this.mipmaps=[];this.mapping=mapping;this.wrapS=wrapS;this.wrapT=wrapT;this.magFilter=magFilter;this.minFilter=minFilter;this.anisotropy=anisotropy;this.format=format;this.internalFormat=null;this.type=type;this.offset=new Vector2(0,0);this.repeat=new Vector2(1,1);this.center=new Vector2(0,0);this.rotation=0;this.matrixAutoUpdate=true;this.matrix=new Matrix3();this.generateMipmaps=true;this.premultiplyAlpha=false;this.flipY=true;this.unpackAlignment=4;// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
  30. // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
  31. //
  32. // Also changing the encoding after already used by a Material will not automatically make the Material
  33. // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
  34. this.encoding=encoding;this.version=0;this.onUpdate=null;}Texture.DEFAULT_IMAGE=undefined;Texture.DEFAULT_MAPPING=UVMapping;Texture.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:Texture,isTexture:true,updateMatrix:function updateMatrix(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y);},clone:function clone(){return new this.constructor().copy(this);},copy:function copy(source){this.name=source.name;this.image=source.image;this.mipmaps=source.mipmaps.slice(0);this.mapping=source.mapping;this.wrapS=source.wrapS;this.wrapT=source.wrapT;this.magFilter=source.magFilter;this.minFilter=source.minFilter;this.anisotropy=source.anisotropy;this.format=source.format;this.internalFormat=source.internalFormat;this.type=source.type;this.offset.copy(source.offset);this.repeat.copy(source.repeat);this.center.copy(source.center);this.rotation=source.rotation;this.matrixAutoUpdate=source.matrixAutoUpdate;this.matrix.copy(source.matrix);this.generateMipmaps=source.generateMipmaps;this.premultiplyAlpha=source.premultiplyAlpha;this.flipY=source.flipY;this.unpackAlignment=source.unpackAlignment;this.encoding=source.encoding;return this;},toJSON:function toJSON(meta){var isRootObject=meta===undefined||typeof meta==='string';if(!isRootObject&&meta.textures[this.uuid]!==undefined){return meta.textures[this.uuid];}var output={metadata:{version:4.5,type:'Texture',generator:'Texture.toJSON'},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(this.image!==undefined){// TODO: Move to THREE.Image
  35. var image=this.image;if(image.uuid===undefined){image.uuid=MathUtils.generateUUID();// UGH
  36. }if(!isRootObject&&meta.images[image.uuid]===undefined){var url;if(Array.isArray(image)){// process array of images e.g. CubeTexture
  37. url=[];for(var _i3=0,l=image.length;_i3<l;_i3++){// check cube texture with data textures
  38. if(image[_i3].isDataTexture){url.push(serializeImage(image[_i3].image));}else {url.push(serializeImage(image[_i3]));}}}else {// process single image
  39. url=serializeImage(image);}meta.images[image.uuid]={uuid:image.uuid,url:url};}output.image=image.uuid;}if(!isRootObject){meta.textures[this.uuid]=output;}return output;},dispose:function dispose(){this.dispatchEvent({type:'dispose'});},transformUv:function transformUv(uv){if(this.mapping!==UVMapping)return uv;uv.applyMatrix3(this.matrix);if(uv.x<0||uv.x>1){switch(this.wrapS){case RepeatWrapping:uv.x=uv.x-Math.floor(uv.x);break;case ClampToEdgeWrapping:uv.x=uv.x<0?0:1;break;case MirroredRepeatWrapping:if(Math.abs(Math.floor(uv.x)%2)===1){uv.x=Math.ceil(uv.x)-uv.x;}else {uv.x=uv.x-Math.floor(uv.x);}break;}}if(uv.y<0||uv.y>1){switch(this.wrapT){case RepeatWrapping:uv.y=uv.y-Math.floor(uv.y);break;case ClampToEdgeWrapping:uv.y=uv.y<0?0:1;break;case MirroredRepeatWrapping:if(Math.abs(Math.floor(uv.y)%2)===1){uv.y=Math.ceil(uv.y)-uv.y;}else {uv.y=uv.y-Math.floor(uv.y);}break;}}if(this.flipY){uv.y=1-uv.y;}return uv;}});Object.defineProperty(Texture.prototype,'needsUpdate',{set:function set(value){if(value===true)this.version++;}});function serializeImage(image){if(typeof HTMLImageElement!=='undefined'&&image instanceof HTMLImageElement||typeof HTMLCanvasElement!=='undefined'&&image instanceof HTMLCanvasElement||typeof ImageBitmap!=='undefined'&&image instanceof ImageBitmap){// default images
  40. return ImageUtils.getDataURL(image);}else {if(image.data){// images of DataTexture
  41. return {data:Array.prototype.slice.call(image.data),width:image.width,height:image.height,type:image.data.constructor.name};}else {console.warn('THREE.Texture: Unable to serialize Texture.');return {};}}}class Vector4{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var w=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;Object.defineProperty(this,'isVector4',{value:true});this.x=x;this.y=y;this.z=z;this.w=w;}get width(){return this.z;}set width(value){this.z=value;}get height(){return this.w;}set height(value){this.w=value;}set(x,y,z,w){this.x=x;this.y=y;this.z=z;this.w=w;return this;}setScalar(scalar){this.x=scalar;this.y=scalar;this.z=scalar;this.w=scalar;return this;}setX(x){this.x=x;return this;}setY(y){this.y=y;return this;}setZ(z){this.z=z;return this;}setW(w){this.w=w;return this;}setComponent(index,value){switch(index){case 0:this.x=value;break;case 1:this.y=value;break;case 2:this.z=value;break;case 3:this.w=value;break;default:throw new Error('index is out of range: '+index);}return this;}getComponent(index){switch(index){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error('index is out of range: '+index);}}clone(){return new this.constructor(this.x,this.y,this.z,this.w);}copy(v){this.x=v.x;this.y=v.y;this.z=v.z;this.w=v.w!==undefined?v.w:1;return this;}add(v,w){if(w!==undefined){console.warn('THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');return this.addVectors(v,w);}this.x+=v.x;this.y+=v.y;this.z+=v.z;this.w+=v.w;return this;}addScalar(s){this.x+=s;this.y+=s;this.z+=s;this.w+=s;return this;}addVectors(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this;}addScaledVector(v,s){this.x+=v.x*s;this.y+=v.y*s;this.z+=v.z*s;this.w+=v.w*s;return this;}sub(v,w){if(w!==undefined){console.warn('THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');return this.subVectors(v,w);}this.x-=v.x;this.y-=v.y;this.z-=v.z;this.w-=v.w;return this;}subScalar(s){this.x-=s;this.y-=s;this.z-=s;this.w-=s;return this;}subVectors(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this;}multiplyScalar(scalar){this.x*=scalar;this.y*=scalar;this.z*=scalar;this.w*=scalar;return this;}applyMatrix4(m){var x=this.x,y=this.y,z=this.z,w=this.w;var e=m.elements;this.x=e[0]*x+e[4]*y+e[8]*z+e[12]*w;this.y=e[1]*x+e[5]*y+e[9]*z+e[13]*w;this.z=e[2]*x+e[6]*y+e[10]*z+e[14]*w;this.w=e[3]*x+e[7]*y+e[11]*z+e[15]*w;return this;}divideScalar(scalar){return this.multiplyScalar(1/scalar);}setAxisAngleFromQuaternion(q){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
  42. // q is assumed to be normalized
  43. this.w=2*Math.acos(q.w);var s=Math.sqrt(1-q.w*q.w);if(s<0.0001){this.x=1;this.y=0;this.z=0;}else {this.x=q.x/s;this.y=q.y/s;this.z=q.z/s;}return this;}setAxisAngleFromRotationMatrix(m){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
  44. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  45. var angle,x,y,z;// variables for result
  46. var epsilon=0.01,// margin to allow for rounding errors
  47. epsilon2=0.1,// margin to distinguish between 0 and 180 degrees
  48. te=m.elements,m11=te[0],m12=te[4],m13=te[8],m21=te[1],m22=te[5],m23=te[9],m31=te[2],m32=te[6],m33=te[10];if(Math.abs(m12-m21)<epsilon&&Math.abs(m13-m31)<epsilon&&Math.abs(m23-m32)<epsilon){// singularity found
  49. // first check for identity matrix which must have +1 for all terms
  50. // in leading diagonal and zero in other terms
  51. if(Math.abs(m12+m21)<epsilon2&&Math.abs(m13+m31)<epsilon2&&Math.abs(m23+m32)<epsilon2&&Math.abs(m11+m22+m33-3)<epsilon2){// this singularity is identity matrix so angle = 0
  52. this.set(1,0,0,0);return this;// zero angle, arbitrary axis
  53. }// otherwise this singularity is angle = 180
  54. angle=Math.PI;var xx=(m11+1)/2;var yy=(m22+1)/2;var zz=(m33+1)/2;var xy=(m12+m21)/4;var xz=(m13+m31)/4;var yz=(m23+m32)/4;if(xx>yy&&xx>zz){// m11 is the largest diagonal term
  55. if(xx<epsilon){x=0;y=0.707106781;z=0.707106781;}else {x=Math.sqrt(xx);y=xy/x;z=xz/x;}}else if(yy>zz){// m22 is the largest diagonal term
  56. if(yy<epsilon){x=0.707106781;y=0;z=0.707106781;}else {y=Math.sqrt(yy);x=xy/y;z=yz/y;}}else {// m33 is the largest diagonal term so base result on this
  57. if(zz<epsilon){x=0.707106781;y=0.707106781;z=0;}else {z=Math.sqrt(zz);x=xz/z;y=yz/z;}}this.set(x,y,z,angle);return this;// return 180 deg rotation
  58. }// as we have reached here there are no singularities so we can handle normally
  59. var s=Math.sqrt((m32-m23)*(m32-m23)+(m13-m31)*(m13-m31)+(m21-m12)*(m21-m12));// used to normalize
  60. if(Math.abs(s)<0.001)s=1;// prevent divide by zero, should not happen if matrix is orthogonal and should be
  61. // caught by singularity test above, but I've left it in just in case
  62. this.x=(m32-m23)/s;this.y=(m13-m31)/s;this.z=(m21-m12)/s;this.w=Math.acos((m11+m22+m33-1)/2);return this;}min(v){this.x=Math.min(this.x,v.x);this.y=Math.min(this.y,v.y);this.z=Math.min(this.z,v.z);this.w=Math.min(this.w,v.w);return this;}max(v){this.x=Math.max(this.x,v.x);this.y=Math.max(this.y,v.y);this.z=Math.max(this.z,v.z);this.w=Math.max(this.w,v.w);return this;}clamp(min,max){// assumes min < max, componentwise
  63. this.x=Math.max(min.x,Math.min(max.x,this.x));this.y=Math.max(min.y,Math.min(max.y,this.y));this.z=Math.max(min.z,Math.min(max.z,this.z));this.w=Math.max(min.w,Math.min(max.w,this.w));return this;}clampScalar(minVal,maxVal){this.x=Math.max(minVal,Math.min(maxVal,this.x));this.y=Math.max(minVal,Math.min(maxVal,this.y));this.z=Math.max(minVal,Math.min(maxVal,this.z));this.w=Math.max(minVal,Math.min(maxVal,this.w));return this;}clampLength(min,max){var length=this.length();return this.divideScalar(length||1).multiplyScalar(Math.max(min,Math.min(max,length)));}floor(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);this.z=Math.floor(this.z);this.w=Math.floor(this.w);return this;}ceil(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);this.z=Math.ceil(this.z);this.w=Math.ceil(this.w);return this;}round(){this.x=Math.round(this.x);this.y=Math.round(this.y);this.z=Math.round(this.z);this.w=Math.round(this.w);return this;}roundToZero(){this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x);this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y);this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z);this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w);return this;}negate(){this.x=-this.x;this.y=-this.y;this.z=-this.z;this.w=-this.w;return this;}dot(v){return this.x*v.x+this.y*v.y+this.z*v.z+this.w*v.w;}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w;}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w);}normalize(){return this.divideScalar(this.length()||1);}setLength(length){return this.normalize().multiplyScalar(length);}lerp(v,alpha){this.x+=(v.x-this.x)*alpha;this.y+=(v.y-this.y)*alpha;this.z+=(v.z-this.z)*alpha;this.w+=(v.w-this.w)*alpha;return this;}lerpVectors(v1,v2,alpha){this.x=v1.x+(v2.x-v1.x)*alpha;this.y=v1.y+(v2.y-v1.y)*alpha;this.z=v1.z+(v2.z-v1.z)*alpha;this.w=v1.w+(v2.w-v1.w)*alpha;return this;}equals(v){return v.x===this.x&&v.y===this.y&&v.z===this.z&&v.w===this.w;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.x=array[offset];this.y=array[offset+1];this.z=array[offset+2];this.w=array[offset+3];return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this.x;array[offset+1]=this.y;array[offset+2]=this.z;array[offset+3]=this.w;return array;}fromBufferAttribute(attribute,index,offset){if(offset!==undefined){console.warn('THREE.Vector4: offset has been removed from .fromBufferAttribute().');}this.x=attribute.getX(index);this.y=attribute.getY(index);this.z=attribute.getZ(index);this.w=attribute.getW(index);return this;}random(){this.x=Math.random();this.y=Math.random();this.z=Math.random();this.w=Math.random();return this;}}/*
  64. In options, we can specify:
  65. * Texture parameters for an auto-generated target texture
  66. * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
  67. */function WebGLRenderTarget(width,height,options){this.width=width;this.height=height;this.scissor=new Vector4(0,0,width,height);this.scissorTest=false;this.viewport=new Vector4(0,0,width,height);options=options||{};this.texture=new Texture(undefined,options.mapping,options.wrapS,options.wrapT,options.magFilter,options.minFilter,options.format,options.type,options.anisotropy,options.encoding);this.texture.image={};this.texture.image.width=width;this.texture.image.height=height;this.texture.generateMipmaps=options.generateMipmaps!==undefined?options.generateMipmaps:false;this.texture.minFilter=options.minFilter!==undefined?options.minFilter:LinearFilter;this.depthBuffer=options.depthBuffer!==undefined?options.depthBuffer:true;this.stencilBuffer=options.stencilBuffer!==undefined?options.stencilBuffer:false;this.depthTexture=options.depthTexture!==undefined?options.depthTexture:null;}WebGLRenderTarget.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:WebGLRenderTarget,isWebGLRenderTarget:true,setSize:function setSize(width,height){if(this.width!==width||this.height!==height){this.width=width;this.height=height;this.texture.image.width=width;this.texture.image.height=height;this.dispose();}this.viewport.set(0,0,width,height);this.scissor.set(0,0,width,height);},clone:function clone(){return new this.constructor().copy(this);},copy:function copy(source){this.width=source.width;this.height=source.height;this.viewport.copy(source.viewport);this.texture=source.texture.clone();this.depthBuffer=source.depthBuffer;this.stencilBuffer=source.stencilBuffer;this.depthTexture=source.depthTexture;return this;},dispose:function dispose(){this.dispatchEvent({type:'dispose'});}});function WebGLMultisampleRenderTarget(width,height,options){WebGLRenderTarget.call(this,width,height,options);this.samples=4;}WebGLMultisampleRenderTarget.prototype=Object.assign(Object.create(WebGLRenderTarget.prototype),{constructor:WebGLMultisampleRenderTarget,isWebGLMultisampleRenderTarget:true,copy:function copy(source){WebGLRenderTarget.prototype.copy.call(this,source);this.samples=source.samples;return this;}});class Quaternion{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var w=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;Object.defineProperty(this,'isQuaternion',{value:true});this._x=x;this._y=y;this._z=z;this._w=w;}static slerp(qa,qb,qm,t){return qm.copy(qa).slerp(qb,t);}static slerpFlat(dst,dstOffset,src0,srcOffset0,src1,srcOffset1,t){// fuzz-free, array-based Quaternion SLERP operation
  68. var x0=src0[srcOffset0+0],y0=src0[srcOffset0+1],z0=src0[srcOffset0+2],w0=src0[srcOffset0+3];var x1=src1[srcOffset1+0],y1=src1[srcOffset1+1],z1=src1[srcOffset1+2],w1=src1[srcOffset1+3];if(w0!==w1||x0!==x1||y0!==y1||z0!==z1){var s=1-t;var cos=x0*x1+y0*y1+z0*z1+w0*w1,dir=cos>=0?1:-1,sqrSin=1-cos*cos;// Skip the Slerp for tiny steps to avoid numeric problems:
  69. if(sqrSin>Number.EPSILON){var sin=Math.sqrt(sqrSin),len=Math.atan2(sin,cos*dir);s=Math.sin(s*len)/sin;t=Math.sin(t*len)/sin;}var tDir=t*dir;x0=x0*s+x1*tDir;y0=y0*s+y1*tDir;z0=z0*s+z1*tDir;w0=w0*s+w1*tDir;// Normalize in case we just did a lerp:
  70. if(s===1-t){var f=1/Math.sqrt(x0*x0+y0*y0+z0*z0+w0*w0);x0*=f;y0*=f;z0*=f;w0*=f;}}dst[dstOffset]=x0;dst[dstOffset+1]=y0;dst[dstOffset+2]=z0;dst[dstOffset+3]=w0;}static multiplyQuaternionsFlat(dst,dstOffset,src0,srcOffset0,src1,srcOffset1){var x0=src0[srcOffset0];var y0=src0[srcOffset0+1];var z0=src0[srcOffset0+2];var w0=src0[srcOffset0+3];var x1=src1[srcOffset1];var y1=src1[srcOffset1+1];var z1=src1[srcOffset1+2];var w1=src1[srcOffset1+3];dst[dstOffset]=x0*w1+w0*x1+y0*z1-z0*y1;dst[dstOffset+1]=y0*w1+w0*y1+z0*x1-x0*z1;dst[dstOffset+2]=z0*w1+w0*z1+x0*y1-y0*x1;dst[dstOffset+3]=w0*w1-x0*x1-y0*y1-z0*z1;return dst;}get x(){return this._x;}set x(value){this._x=value;this._onChangeCallback();}get y(){return this._y;}set y(value){this._y=value;this._onChangeCallback();}get z(){return this._z;}set z(value){this._z=value;this._onChangeCallback();}get w(){return this._w;}set w(value){this._w=value;this._onChangeCallback();}set(x,y,z,w){this._x=x;this._y=y;this._z=z;this._w=w;this._onChangeCallback();return this;}clone(){return new this.constructor(this._x,this._y,this._z,this._w);}copy(quaternion){this._x=quaternion.x;this._y=quaternion.y;this._z=quaternion.z;this._w=quaternion.w;this._onChangeCallback();return this;}setFromEuler(euler,update){if(!(euler&&euler.isEuler)){throw new Error('THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.');}var x=euler._x,y=euler._y,z=euler._z,order=euler._order;// http://www.mathworks.com/matlabcentral/fileexchange/
  71. // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
  72. // content/SpinCalc.m
  73. var cos=Math.cos;var sin=Math.sin;var c1=cos(x/2);var c2=cos(y/2);var c3=cos(z/2);var s1=sin(x/2);var s2=sin(y/2);var s3=sin(z/2);switch(order){case'XYZ':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case'YXZ':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;case'ZXY':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case'ZYX':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;case'YZX':this._x=s1*c2*c3+c1*s2*s3;this._y=c1*s2*c3+s1*c2*s3;this._z=c1*c2*s3-s1*s2*c3;this._w=c1*c2*c3-s1*s2*s3;break;case'XZY':this._x=s1*c2*c3-c1*s2*s3;this._y=c1*s2*c3-s1*c2*s3;this._z=c1*c2*s3+s1*s2*c3;this._w=c1*c2*c3+s1*s2*s3;break;default:console.warn('THREE.Quaternion: .setFromEuler() encountered an unknown order: '+order);}if(update!==false)this._onChangeCallback();return this;}setFromAxisAngle(axis,angle){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
  74. // assumes axis is normalized
  75. var halfAngle=angle/2,s=Math.sin(halfAngle);this._x=axis.x*s;this._y=axis.y*s;this._z=axis.z*s;this._w=Math.cos(halfAngle);this._onChangeCallback();return this;}setFromRotationMatrix(m){// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  76. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  77. var te=m.elements,m11=te[0],m12=te[4],m13=te[8],m21=te[1],m22=te[5],m23=te[9],m31=te[2],m32=te[6],m33=te[10],trace=m11+m22+m33;if(trace>0){var s=0.5/Math.sqrt(trace+1.0);this._w=0.25/s;this._x=(m32-m23)*s;this._y=(m13-m31)*s;this._z=(m21-m12)*s;}else if(m11>m22&&m11>m33){var _s=2.0*Math.sqrt(1.0+m11-m22-m33);this._w=(m32-m23)/_s;this._x=0.25*_s;this._y=(m12+m21)/_s;this._z=(m13+m31)/_s;}else if(m22>m33){var _s2=2.0*Math.sqrt(1.0+m22-m11-m33);this._w=(m13-m31)/_s2;this._x=(m12+m21)/_s2;this._y=0.25*_s2;this._z=(m23+m32)/_s2;}else {var _s3=2.0*Math.sqrt(1.0+m33-m11-m22);this._w=(m21-m12)/_s3;this._x=(m13+m31)/_s3;this._y=(m23+m32)/_s3;this._z=0.25*_s3;}this._onChangeCallback();return this;}setFromUnitVectors(vFrom,vTo){// assumes direction vectors vFrom and vTo are normalized
  78. var EPS=0.000001;var r=vFrom.dot(vTo)+1;if(r<EPS){r=0;if(Math.abs(vFrom.x)>Math.abs(vFrom.z)){this._x=-vFrom.y;this._y=vFrom.x;this._z=0;this._w=r;}else {this._x=0;this._y=-vFrom.z;this._z=vFrom.y;this._w=r;}}else {// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
  79. this._x=vFrom.y*vTo.z-vFrom.z*vTo.y;this._y=vFrom.z*vTo.x-vFrom.x*vTo.z;this._z=vFrom.x*vTo.y-vFrom.y*vTo.x;this._w=r;}return this.normalize();}angleTo(q){return 2*Math.acos(Math.abs(MathUtils.clamp(this.dot(q),-1,1)));}rotateTowards(q,step){var angle=this.angleTo(q);if(angle===0)return this;var t=Math.min(1,step/angle);this.slerp(q,t);return this;}identity(){return this.set(0,0,0,1);}invert(){// quaternion is assumed to have unit length
  80. return this.conjugate();}conjugate(){this._x*=-1;this._y*=-1;this._z*=-1;this._onChangeCallback();return this;}dot(v){return this._x*v._x+this._y*v._y+this._z*v._z+this._w*v._w;}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w;}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w);}normalize(){var l=this.length();if(l===0){this._x=0;this._y=0;this._z=0;this._w=1;}else {l=1/l;this._x=this._x*l;this._y=this._y*l;this._z=this._z*l;this._w=this._w*l;}this._onChangeCallback();return this;}multiply(q,p){if(p!==undefined){console.warn('THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.');return this.multiplyQuaternions(q,p);}return this.multiplyQuaternions(this,q);}premultiply(q){return this.multiplyQuaternions(q,this);}multiplyQuaternions(a,b){// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  81. var qax=a._x,qay=a._y,qaz=a._z,qaw=a._w;var qbx=b._x,qby=b._y,qbz=b._z,qbw=b._w;this._x=qax*qbw+qaw*qbx+qay*qbz-qaz*qby;this._y=qay*qbw+qaw*qby+qaz*qbx-qax*qbz;this._z=qaz*qbw+qaw*qbz+qax*qby-qay*qbx;this._w=qaw*qbw-qax*qbx-qay*qby-qaz*qbz;this._onChangeCallback();return this;}slerp(qb,t){if(t===0)return this;if(t===1)return this.copy(qb);var x=this._x,y=this._y,z=this._z,w=this._w;// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
  82. var cosHalfTheta=w*qb._w+x*qb._x+y*qb._y+z*qb._z;if(cosHalfTheta<0){this._w=-qb._w;this._x=-qb._x;this._y=-qb._y;this._z=-qb._z;cosHalfTheta=-cosHalfTheta;}else {this.copy(qb);}if(cosHalfTheta>=1.0){this._w=w;this._x=x;this._y=y;this._z=z;return this;}var sqrSinHalfTheta=1.0-cosHalfTheta*cosHalfTheta;if(sqrSinHalfTheta<=Number.EPSILON){var s=1-t;this._w=s*w+t*this._w;this._x=s*x+t*this._x;this._y=s*y+t*this._y;this._z=s*z+t*this._z;this.normalize();this._onChangeCallback();return this;}var sinHalfTheta=Math.sqrt(sqrSinHalfTheta);var halfTheta=Math.atan2(sinHalfTheta,cosHalfTheta);var ratioA=Math.sin((1-t)*halfTheta)/sinHalfTheta,ratioB=Math.sin(t*halfTheta)/sinHalfTheta;this._w=w*ratioA+this._w*ratioB;this._x=x*ratioA+this._x*ratioB;this._y=y*ratioA+this._y*ratioB;this._z=z*ratioA+this._z*ratioB;this._onChangeCallback();return this;}equals(quaternion){return quaternion._x===this._x&&quaternion._y===this._y&&quaternion._z===this._z&&quaternion._w===this._w;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this._x=array[offset];this._y=array[offset+1];this._z=array[offset+2];this._w=array[offset+3];this._onChangeCallback();return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this._x;array[offset+1]=this._y;array[offset+2]=this._z;array[offset+3]=this._w;return array;}fromBufferAttribute(attribute,index){this._x=attribute.getX(index);this._y=attribute.getY(index);this._z=attribute.getZ(index);this._w=attribute.getW(index);return this;}_onChange(callback){this._onChangeCallback=callback;return this;}_onChangeCallback(){}}class Vector3{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;Object.defineProperty(this,'isVector3',{value:true});this.x=x;this.y=y;this.z=z;}set(x,y,z){if(z===undefined)z=this.z;// sprite.scale.set(x,y)
  83. this.x=x;this.y=y;this.z=z;return this;}setScalar(scalar){this.x=scalar;this.y=scalar;this.z=scalar;return this;}setX(x){this.x=x;return this;}setY(y){this.y=y;return this;}setZ(z){this.z=z;return this;}setComponent(index,value){switch(index){case 0:this.x=value;break;case 1:this.y=value;break;case 2:this.z=value;break;default:throw new Error('index is out of range: '+index);}return this;}getComponent(index){switch(index){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error('index is out of range: '+index);}}clone(){return new this.constructor(this.x,this.y,this.z);}copy(v){this.x=v.x;this.y=v.y;this.z=v.z;return this;}add(v,w){if(w!==undefined){console.warn('THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');return this.addVectors(v,w);}this.x+=v.x;this.y+=v.y;this.z+=v.z;return this;}addScalar(s){this.x+=s;this.y+=s;this.z+=s;return this;}addVectors(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this;}addScaledVector(v,s){this.x+=v.x*s;this.y+=v.y*s;this.z+=v.z*s;return this;}sub(v,w){if(w!==undefined){console.warn('THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');return this.subVectors(v,w);}this.x-=v.x;this.y-=v.y;this.z-=v.z;return this;}subScalar(s){this.x-=s;this.y-=s;this.z-=s;return this;}subVectors(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this;}multiply(v,w){if(w!==undefined){console.warn('THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.');return this.multiplyVectors(v,w);}this.x*=v.x;this.y*=v.y;this.z*=v.z;return this;}multiplyScalar(scalar){this.x*=scalar;this.y*=scalar;this.z*=scalar;return this;}multiplyVectors(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this;}applyEuler(euler){if(!(euler&&euler.isEuler)){console.error('THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.');}return this.applyQuaternion(_quaternion.setFromEuler(euler));}applyAxisAngle(axis,angle){return this.applyQuaternion(_quaternion.setFromAxisAngle(axis,angle));}applyMatrix3(m){var x=this.x,y=this.y,z=this.z;var e=m.elements;this.x=e[0]*x+e[3]*y+e[6]*z;this.y=e[1]*x+e[4]*y+e[7]*z;this.z=e[2]*x+e[5]*y+e[8]*z;return this;}applyNormalMatrix(m){return this.applyMatrix3(m).normalize();}applyMatrix4(m){var x=this.x,y=this.y,z=this.z;var e=m.elements;var w=1/(e[3]*x+e[7]*y+e[11]*z+e[15]);this.x=(e[0]*x+e[4]*y+e[8]*z+e[12])*w;this.y=(e[1]*x+e[5]*y+e[9]*z+e[13])*w;this.z=(e[2]*x+e[6]*y+e[10]*z+e[14])*w;return this;}applyQuaternion(q){var x=this.x,y=this.y,z=this.z;var qx=q.x,qy=q.y,qz=q.z,qw=q.w;// calculate quat * vector
  84. var ix=qw*x+qy*z-qz*y;var iy=qw*y+qz*x-qx*z;var iz=qw*z+qx*y-qy*x;var iw=-qx*x-qy*y-qz*z;// calculate result * inverse quat
  85. this.x=ix*qw+iw*-qx+iy*-qz-iz*-qy;this.y=iy*qw+iw*-qy+iz*-qx-ix*-qz;this.z=iz*qw+iw*-qz+ix*-qy-iy*-qx;return this;}project(camera){return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);}unproject(camera){return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld);}transformDirection(m){// input: THREE.Matrix4 affine matrix
  86. // vector interpreted as a direction
  87. var x=this.x,y=this.y,z=this.z;var e=m.elements;this.x=e[0]*x+e[4]*y+e[8]*z;this.y=e[1]*x+e[5]*y+e[9]*z;this.z=e[2]*x+e[6]*y+e[10]*z;return this.normalize();}divide(v){this.x/=v.x;this.y/=v.y;this.z/=v.z;return this;}divideScalar(scalar){return this.multiplyScalar(1/scalar);}min(v){this.x=Math.min(this.x,v.x);this.y=Math.min(this.y,v.y);this.z=Math.min(this.z,v.z);return this;}max(v){this.x=Math.max(this.x,v.x);this.y=Math.max(this.y,v.y);this.z=Math.max(this.z,v.z);return this;}clamp(min,max){// assumes min < max, componentwise
  88. this.x=Math.max(min.x,Math.min(max.x,this.x));this.y=Math.max(min.y,Math.min(max.y,this.y));this.z=Math.max(min.z,Math.min(max.z,this.z));return this;}clampScalar(minVal,maxVal){this.x=Math.max(minVal,Math.min(maxVal,this.x));this.y=Math.max(minVal,Math.min(maxVal,this.y));this.z=Math.max(minVal,Math.min(maxVal,this.z));return this;}clampLength(min,max){var length=this.length();return this.divideScalar(length||1).multiplyScalar(Math.max(min,Math.min(max,length)));}floor(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);this.z=Math.floor(this.z);return this;}ceil(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);this.z=Math.ceil(this.z);return this;}round(){this.x=Math.round(this.x);this.y=Math.round(this.y);this.z=Math.round(this.z);return this;}roundToZero(){this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x);this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y);this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z);return this;}negate(){this.x=-this.x;this.y=-this.y;this.z=-this.z;return this;}dot(v){return this.x*v.x+this.y*v.y+this.z*v.z;}// TODO lengthSquared?
  89. lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z;}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z);}normalize(){return this.divideScalar(this.length()||1);}setLength(length){return this.normalize().multiplyScalar(length);}lerp(v,alpha){this.x+=(v.x-this.x)*alpha;this.y+=(v.y-this.y)*alpha;this.z+=(v.z-this.z)*alpha;return this;}lerpVectors(v1,v2,alpha){this.x=v1.x+(v2.x-v1.x)*alpha;this.y=v1.y+(v2.y-v1.y)*alpha;this.z=v1.z+(v2.z-v1.z)*alpha;return this;}cross(v,w){if(w!==undefined){console.warn('THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.');return this.crossVectors(v,w);}return this.crossVectors(this,v);}crossVectors(a,b){var ax=a.x,ay=a.y,az=a.z;var bx=b.x,by=b.y,bz=b.z;this.x=ay*bz-az*by;this.y=az*bx-ax*bz;this.z=ax*by-ay*bx;return this;}projectOnVector(v){var denominator=v.lengthSq();if(denominator===0)return this.set(0,0,0);var scalar=v.dot(this)/denominator;return this.copy(v).multiplyScalar(scalar);}projectOnPlane(planeNormal){_vector.copy(this).projectOnVector(planeNormal);return this.sub(_vector);}reflect(normal){// reflect incident vector off plane orthogonal to normal
  90. // normal is assumed to have unit length
  91. return this.sub(_vector.copy(normal).multiplyScalar(2*this.dot(normal)));}angleTo(v){var denominator=Math.sqrt(this.lengthSq()*v.lengthSq());if(denominator===0)return Math.PI/2;var theta=this.dot(v)/denominator;// clamp, to handle numerical problems
  92. return Math.acos(MathUtils.clamp(theta,-1,1));}distanceTo(v){return Math.sqrt(this.distanceToSquared(v));}distanceToSquared(v){var dx=this.x-v.x,dy=this.y-v.y,dz=this.z-v.z;return dx*dx+dy*dy+dz*dz;}manhattanDistanceTo(v){return Math.abs(this.x-v.x)+Math.abs(this.y-v.y)+Math.abs(this.z-v.z);}setFromSpherical(s){return this.setFromSphericalCoords(s.radius,s.phi,s.theta);}setFromSphericalCoords(radius,phi,theta){var sinPhiRadius=Math.sin(phi)*radius;this.x=sinPhiRadius*Math.sin(theta);this.y=Math.cos(phi)*radius;this.z=sinPhiRadius*Math.cos(theta);return this;}setFromCylindrical(c){return this.setFromCylindricalCoords(c.radius,c.theta,c.y);}setFromCylindricalCoords(radius,theta,y){this.x=radius*Math.sin(theta);this.y=y;this.z=radius*Math.cos(theta);return this;}setFromMatrixPosition(m){var e=m.elements;this.x=e[12];this.y=e[13];this.z=e[14];return this;}setFromMatrixScale(m){var sx=this.setFromMatrixColumn(m,0).length();var sy=this.setFromMatrixColumn(m,1).length();var sz=this.setFromMatrixColumn(m,2).length();this.x=sx;this.y=sy;this.z=sz;return this;}setFromMatrixColumn(m,index){return this.fromArray(m.elements,index*4);}setFromMatrix3Column(m,index){return this.fromArray(m.elements,index*3);}equals(v){return v.x===this.x&&v.y===this.y&&v.z===this.z;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.x=array[offset];this.y=array[offset+1];this.z=array[offset+2];return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this.x;array[offset+1]=this.y;array[offset+2]=this.z;return array;}fromBufferAttribute(attribute,index,offset){if(offset!==undefined){console.warn('THREE.Vector3: offset has been removed from .fromBufferAttribute().');}this.x=attribute.getX(index);this.y=attribute.getY(index);this.z=attribute.getZ(index);return this;}random(){this.x=Math.random();this.y=Math.random();this.z=Math.random();return this;}}var _vector=/*@__PURE__*/new Vector3();var _quaternion=/*@__PURE__*/new Quaternion();class Box3{constructor(min,max){Object.defineProperty(this,'isBox3',{value:true});this.min=min!==undefined?min:new Vector3(+Infinity,+Infinity,+Infinity);this.max=max!==undefined?max:new Vector3(-Infinity,-Infinity,-Infinity);}set(min,max){this.min.copy(min);this.max.copy(max);return this;}setFromArray(array){var minX=+Infinity;var minY=+Infinity;var minZ=+Infinity;var maxX=-Infinity;var maxY=-Infinity;var maxZ=-Infinity;for(var _i4=0,l=array.length;_i4<l;_i4+=3){var x=array[_i4];var y=array[_i4+1];var z=array[_i4+2];if(x<minX)minX=x;if(y<minY)minY=y;if(z<minZ)minZ=z;if(x>maxX)maxX=x;if(y>maxY)maxY=y;if(z>maxZ)maxZ=z;}this.min.set(minX,minY,minZ);this.max.set(maxX,maxY,maxZ);return this;}setFromBufferAttribute(attribute){var minX=+Infinity;var minY=+Infinity;var minZ=+Infinity;var maxX=-Infinity;var maxY=-Infinity;var maxZ=-Infinity;for(var _i5=0,l=attribute.count;_i5<l;_i5++){var x=attribute.getX(_i5);var y=attribute.getY(_i5);var z=attribute.getZ(_i5);if(x<minX)minX=x;if(y<minY)minY=y;if(z<minZ)minZ=z;if(x>maxX)maxX=x;if(y>maxY)maxY=y;if(z>maxZ)maxZ=z;}this.min.set(minX,minY,minZ);this.max.set(maxX,maxY,maxZ);return this;}setFromPoints(points){this.makeEmpty();for(var _i6=0,il=points.length;_i6<il;_i6++){this.expandByPoint(points[_i6]);}return this;}setFromCenterAndSize(center,size){var halfSize=_vector$1.copy(size).multiplyScalar(0.5);this.min.copy(center).sub(halfSize);this.max.copy(center).add(halfSize);return this;}setFromObject(object){this.makeEmpty();return this.expandByObject(object);}clone(){return new this.constructor().copy(this);}copy(box){this.min.copy(box.min);this.max.copy(box.max);return this;}makeEmpty(){this.min.x=this.min.y=this.min.z=+Infinity;this.max.x=this.max.y=this.max.z=-Infinity;return this;}isEmpty(){// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  93. return this.max.x<this.min.x||this.max.y<this.min.y||this.max.z<this.min.z;}getCenter(target){if(target===undefined){console.warn('THREE.Box3: .getCenter() target is now required');target=new Vector3();}return this.isEmpty()?target.set(0,0,0):target.addVectors(this.min,this.max).multiplyScalar(0.5);}getSize(target){if(target===undefined){console.warn('THREE.Box3: .getSize() target is now required');target=new Vector3();}return this.isEmpty()?target.set(0,0,0):target.subVectors(this.max,this.min);}expandByPoint(point){this.min.min(point);this.max.max(point);return this;}expandByVector(vector){this.min.sub(vector);this.max.add(vector);return this;}expandByScalar(scalar){this.min.addScalar(-scalar);this.max.addScalar(scalar);return this;}expandByObject(object){// Computes the world-axis-aligned bounding box of an object (including its children),
  94. // accounting for both the object's, and children's, world transforms
  95. object.updateWorldMatrix(false,false);var geometry=object.geometry;if(geometry!==undefined){if(geometry.boundingBox===null){geometry.computeBoundingBox();}_box.copy(geometry.boundingBox);_box.applyMatrix4(object.matrixWorld);this.union(_box);}var children=object.children;for(var _i7=0,l=children.length;_i7<l;_i7++){this.expandByObject(children[_i7]);}return this;}containsPoint(point){return point.x<this.min.x||point.x>this.max.x||point.y<this.min.y||point.y>this.max.y||point.z<this.min.z||point.z>this.max.z?false:true;}containsBox(box){return this.min.x<=box.min.x&&box.max.x<=this.max.x&&this.min.y<=box.min.y&&box.max.y<=this.max.y&&this.min.z<=box.min.z&&box.max.z<=this.max.z;}getParameter(point,target){// This can potentially have a divide by zero if the box
  96. // has a size dimension of 0.
  97. if(target===undefined){console.warn('THREE.Box3: .getParameter() target is now required');target=new Vector3();}return target.set((point.x-this.min.x)/(this.max.x-this.min.x),(point.y-this.min.y)/(this.max.y-this.min.y),(point.z-this.min.z)/(this.max.z-this.min.z));}intersectsBox(box){// using 6 splitting planes to rule out intersections.
  98. return box.max.x<this.min.x||box.min.x>this.max.x||box.max.y<this.min.y||box.min.y>this.max.y||box.max.z<this.min.z||box.min.z>this.max.z?false:true;}intersectsSphere(sphere){// Find the point on the AABB closest to the sphere center.
  99. this.clampPoint(sphere.center,_vector$1);// If that point is inside the sphere, the AABB and sphere intersect.
  100. return _vector$1.distanceToSquared(sphere.center)<=sphere.radius*sphere.radius;}intersectsPlane(plane){// We compute the minimum and maximum dot product values. If those values
  101. // are on the same side (back or front) of the plane, then there is no intersection.
  102. var min,max;if(plane.normal.x>0){min=plane.normal.x*this.min.x;max=plane.normal.x*this.max.x;}else {min=plane.normal.x*this.max.x;max=plane.normal.x*this.min.x;}if(plane.normal.y>0){min+=plane.normal.y*this.min.y;max+=plane.normal.y*this.max.y;}else {min+=plane.normal.y*this.max.y;max+=plane.normal.y*this.min.y;}if(plane.normal.z>0){min+=plane.normal.z*this.min.z;max+=plane.normal.z*this.max.z;}else {min+=plane.normal.z*this.max.z;max+=plane.normal.z*this.min.z;}return min<=-plane.constant&&max>=-plane.constant;}intersectsTriangle(triangle){if(this.isEmpty()){return false;}// compute box center and extents
  103. this.getCenter(_center);_extents.subVectors(this.max,_center);// translate triangle to aabb origin
  104. _v0.subVectors(triangle.a,_center);_v1.subVectors(triangle.b,_center);_v2.subVectors(triangle.c,_center);// compute edge vectors for triangle
  105. _f0.subVectors(_v1,_v0);_f1.subVectors(_v2,_v1);_f2.subVectors(_v0,_v2);// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
  106. // 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
  107. // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
  108. var axes=[0,-_f0.z,_f0.y,0,-_f1.z,_f1.y,0,-_f2.z,_f2.y,_f0.z,0,-_f0.x,_f1.z,0,-_f1.x,_f2.z,0,-_f2.x,-_f0.y,_f0.x,0,-_f1.y,_f1.x,0,-_f2.y,_f2.x,0];if(!satForAxes(axes,_v0,_v1,_v2,_extents)){return false;}// test 3 face normals from the aabb
  109. axes=[1,0,0,0,1,0,0,0,1];if(!satForAxes(axes,_v0,_v1,_v2,_extents)){return false;}// finally testing the face normal of the triangle
  110. // use already existing triangle edge vectors here
  111. _triangleNormal.crossVectors(_f0,_f1);axes=[_triangleNormal.x,_triangleNormal.y,_triangleNormal.z];return satForAxes(axes,_v0,_v1,_v2,_extents);}clampPoint(point,target){if(target===undefined){console.warn('THREE.Box3: .clampPoint() target is now required');target=new Vector3();}return target.copy(point).clamp(this.min,this.max);}distanceToPoint(point){var clampedPoint=_vector$1.copy(point).clamp(this.min,this.max);return clampedPoint.sub(point).length();}getBoundingSphere(target){if(target===undefined){console.error('THREE.Box3: .getBoundingSphere() target is now required');//target = new Sphere(); // removed to avoid cyclic dependency
  112. }this.getCenter(target.center);target.radius=this.getSize(_vector$1).length()*0.5;return target;}intersect(box){this.min.max(box.min);this.max.min(box.max);// 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.
  113. if(this.isEmpty())this.makeEmpty();return this;}union(box){this.min.min(box.min);this.max.max(box.max);return this;}applyMatrix4(matrix){// transform of empty box is an empty box.
  114. if(this.isEmpty())return this;// NOTE: I am using a binary pattern to specify all 2^3 combinations below
  115. _points[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(matrix);// 000
  116. _points[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(matrix);// 001
  117. _points[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(matrix);// 010
  118. _points[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(matrix);// 011
  119. _points[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(matrix);// 100
  120. _points[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(matrix);// 101
  121. _points[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(matrix);// 110
  122. _points[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(matrix);// 111
  123. this.setFromPoints(_points);return this;}translate(offset){this.min.add(offset);this.max.add(offset);return this;}equals(box){return box.min.equals(this.min)&&box.max.equals(this.max);}}function satForAxes(axes,v0,v1,v2,extents){for(var _i8=0,j=axes.length-3;_i8<=j;_i8+=3){_testAxis.fromArray(axes,_i8);// project the aabb onto the seperating axis
  124. var r=extents.x*Math.abs(_testAxis.x)+extents.y*Math.abs(_testAxis.y)+extents.z*Math.abs(_testAxis.z);// project all 3 vertices of the triangle onto the seperating axis
  125. var p0=v0.dot(_testAxis);var p1=v1.dot(_testAxis);var p2=v2.dot(_testAxis);// actual test, basically see if either of the most extreme of the triangle points intersects r
  126. if(Math.max(-Math.max(p0,p1,p2),Math.min(p0,p1,p2))>r){// points of the projected triangle are outside the projected half-length of the aabb
  127. // the axis is seperating and we can exit
  128. return false;}}return true;}var _points=[/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3(),/*@__PURE__*/new Vector3()];var _vector$1=/*@__PURE__*/new Vector3();var _box=/*@__PURE__*/new Box3();// triangle centered vertices
  129. var _v0=/*@__PURE__*/new Vector3();var _v1=/*@__PURE__*/new Vector3();var _v2=/*@__PURE__*/new Vector3();// triangle edge vectors
  130. var _f0=/*@__PURE__*/new Vector3();var _f1=/*@__PURE__*/new Vector3();var _f2=/*@__PURE__*/new Vector3();var _center=/*@__PURE__*/new Vector3();var _extents=/*@__PURE__*/new Vector3();var _triangleNormal=/*@__PURE__*/new Vector3();var _testAxis=/*@__PURE__*/new Vector3();var _box$1=/*@__PURE__*/new Box3();class Sphere{constructor(center,radius){this.center=center!==undefined?center:new Vector3();this.radius=radius!==undefined?radius:-1;}set(center,radius){this.center.copy(center);this.radius=radius;return this;}setFromPoints(points,optionalCenter){var center=this.center;if(optionalCenter!==undefined){center.copy(optionalCenter);}else {_box$1.setFromPoints(points).getCenter(center);}var maxRadiusSq=0;for(var _i9=0,il=points.length;_i9<il;_i9++){maxRadiusSq=Math.max(maxRadiusSq,center.distanceToSquared(points[_i9]));}this.radius=Math.sqrt(maxRadiusSq);return this;}clone(){return new this.constructor().copy(this);}copy(sphere){this.center.copy(sphere.center);this.radius=sphere.radius;return this;}isEmpty(){return this.radius<0;}makeEmpty(){this.center.set(0,0,0);this.radius=-1;return this;}containsPoint(point){return point.distanceToSquared(this.center)<=this.radius*this.radius;}distanceToPoint(point){return point.distanceTo(this.center)-this.radius;}intersectsSphere(sphere){var radiusSum=this.radius+sphere.radius;return sphere.center.distanceToSquared(this.center)<=radiusSum*radiusSum;}intersectsBox(box){return box.intersectsSphere(this);}intersectsPlane(plane){return Math.abs(plane.distanceToPoint(this.center))<=this.radius;}clampPoint(point,target){var deltaLengthSq=this.center.distanceToSquared(point);if(target===undefined){console.warn('THREE.Sphere: .clampPoint() target is now required');target=new Vector3();}target.copy(point);if(deltaLengthSq>this.radius*this.radius){target.sub(this.center).normalize();target.multiplyScalar(this.radius).add(this.center);}return target;}getBoundingBox(target){if(target===undefined){console.warn('THREE.Sphere: .getBoundingBox() target is now required');target=new Box3();}if(this.isEmpty()){// Empty sphere produces empty bounding box
  131. target.makeEmpty();return target;}target.set(this.center,this.center);target.expandByScalar(this.radius);return target;}applyMatrix4(matrix){this.center.applyMatrix4(matrix);this.radius=this.radius*matrix.getMaxScaleOnAxis();return this;}translate(offset){this.center.add(offset);return this;}equals(sphere){return sphere.center.equals(this.center)&&sphere.radius===this.radius;}}var _vector$2=/*@__PURE__*/new Vector3();var _segCenter=/*@__PURE__*/new Vector3();var _segDir=/*@__PURE__*/new Vector3();var _diff=/*@__PURE__*/new Vector3();var _edge1=/*@__PURE__*/new Vector3();var _edge2=/*@__PURE__*/new Vector3();var _normal=/*@__PURE__*/new Vector3();class Ray{constructor(origin,direction){this.origin=origin!==undefined?origin:new Vector3();this.direction=direction!==undefined?direction:new Vector3(0,0,-1);}set(origin,direction){this.origin.copy(origin);this.direction.copy(direction);return this;}clone(){return new this.constructor().copy(this);}copy(ray){this.origin.copy(ray.origin);this.direction.copy(ray.direction);return this;}at(t,target){if(target===undefined){console.warn('THREE.Ray: .at() target is now required');target=new Vector3();}return target.copy(this.direction).multiplyScalar(t).add(this.origin);}lookAt(v){this.direction.copy(v).sub(this.origin).normalize();return this;}recast(t){this.origin.copy(this.at(t,_vector$2));return this;}closestPointToPoint(point,target){if(target===undefined){console.warn('THREE.Ray: .closestPointToPoint() target is now required');target=new Vector3();}target.subVectors(point,this.origin);var directionDistance=target.dot(this.direction);if(directionDistance<0){return target.copy(this.origin);}return target.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);}distanceToPoint(point){return Math.sqrt(this.distanceSqToPoint(point));}distanceSqToPoint(point){var directionDistance=_vector$2.subVectors(point,this.origin).dot(this.direction);// point behind the ray
  132. if(directionDistance<0){return this.origin.distanceToSquared(point);}_vector$2.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);return _vector$2.distanceToSquared(point);}distanceSqToSegment(v0,v1,optionalPointOnRay,optionalPointOnSegment){// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
  133. // It returns the min distance between the ray and the segment
  134. // defined by v0 and v1
  135. // It can also set two optional targets :
  136. // - The closest point on the ray
  137. // - The closest point on the segment
  138. _segCenter.copy(v0).add(v1).multiplyScalar(0.5);_segDir.copy(v1).sub(v0).normalize();_diff.copy(this.origin).sub(_segCenter);var segExtent=v0.distanceTo(v1)*0.5;var a01=-this.direction.dot(_segDir);var b0=_diff.dot(this.direction);var b1=-_diff.dot(_segDir);var c=_diff.lengthSq();var det=Math.abs(1-a01*a01);var s0,s1,sqrDist,extDet;if(det>0){// The ray and segment are not parallel.
  139. s0=a01*b1-b0;s1=a01*b0-b1;extDet=segExtent*det;if(s0>=0){if(s1>=-extDet){if(s1<=extDet){// region 0
  140. // Minimum at interior points of ray and segment.
  141. var invDet=1/det;s0*=invDet;s1*=invDet;sqrDist=s0*(s0+a01*s1+2*b0)+s1*(a01*s0+s1+2*b1)+c;}else {// region 1
  142. s1=segExtent;s0=Math.max(0,-(a01*s1+b0));sqrDist=-s0*s0+s1*(s1+2*b1)+c;}}else {// region 5
  143. s1=-segExtent;s0=Math.max(0,-(a01*s1+b0));sqrDist=-s0*s0+s1*(s1+2*b1)+c;}}else {if(s1<=-extDet){// region 4
  144. s0=Math.max(0,-(-a01*segExtent+b0));s1=s0>0?-segExtent:Math.min(Math.max(-segExtent,-b1),segExtent);sqrDist=-s0*s0+s1*(s1+2*b1)+c;}else if(s1<=extDet){// region 3
  145. s0=0;s1=Math.min(Math.max(-segExtent,-b1),segExtent);sqrDist=s1*(s1+2*b1)+c;}else {// region 2
  146. s0=Math.max(0,-(a01*segExtent+b0));s1=s0>0?segExtent:Math.min(Math.max(-segExtent,-b1),segExtent);sqrDist=-s0*s0+s1*(s1+2*b1)+c;}}}else {// Ray and segment are parallel.
  147. s1=a01>0?-segExtent:segExtent;s0=Math.max(0,-(a01*s1+b0));sqrDist=-s0*s0+s1*(s1+2*b1)+c;}if(optionalPointOnRay){optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin);}if(optionalPointOnSegment){optionalPointOnSegment.copy(_segDir).multiplyScalar(s1).add(_segCenter);}return sqrDist;}intersectSphere(sphere,target){_vector$2.subVectors(sphere.center,this.origin);var tca=_vector$2.dot(this.direction);var d2=_vector$2.dot(_vector$2)-tca*tca;var radius2=sphere.radius*sphere.radius;if(d2>radius2)return null;var thc=Math.sqrt(radius2-d2);// t0 = first intersect point - entrance on front of sphere
  148. var t0=tca-thc;// t1 = second intersect point - exit point on back of sphere
  149. var t1=tca+thc;// test to see if both t0 and t1 are behind the ray - if so, return null
  150. if(t0<0&&t1<0)return null;// test to see if t0 is behind the ray:
  151. // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
  152. // in order to always return an intersect point that is in front of the ray.
  153. if(t0<0)return this.at(t1,target);// else t0 is in front of the ray, so return the first collision point scaled by t0
  154. return this.at(t0,target);}intersectsSphere(sphere){return this.distanceSqToPoint(sphere.center)<=sphere.radius*sphere.radius;}distanceToPlane(plane){var denominator=plane.normal.dot(this.direction);if(denominator===0){// line is coplanar, return origin
  155. if(plane.distanceToPoint(this.origin)===0){return 0;}// Null is preferable to undefined since undefined means.... it is undefined
  156. return null;}var t=-(this.origin.dot(plane.normal)+plane.constant)/denominator;// Return if the ray never intersects the plane
  157. return t>=0?t:null;}intersectPlane(plane,target){var t=this.distanceToPlane(plane);if(t===null){return null;}return this.at(t,target);}intersectsPlane(plane){// check if the ray lies on the plane first
  158. var distToPoint=plane.distanceToPoint(this.origin);if(distToPoint===0){return true;}var denominator=plane.normal.dot(this.direction);if(denominator*distToPoint<0){return true;}// ray origin is behind the plane (and is pointing behind it)
  159. return false;}intersectBox(box,target){var tmin,tmax,tymin,tymax,tzmin,tzmax;var invdirx=1/this.direction.x,invdiry=1/this.direction.y,invdirz=1/this.direction.z;var origin=this.origin;if(invdirx>=0){tmin=(box.min.x-origin.x)*invdirx;tmax=(box.max.x-origin.x)*invdirx;}else {tmin=(box.max.x-origin.x)*invdirx;tmax=(box.min.x-origin.x)*invdirx;}if(invdiry>=0){tymin=(box.min.y-origin.y)*invdiry;tymax=(box.max.y-origin.y)*invdiry;}else {tymin=(box.max.y-origin.y)*invdiry;tymax=(box.min.y-origin.y)*invdiry;}if(tmin>tymax||tymin>tmax)return null;// These lines also handle the case where tmin or tmax is NaN
  160. // (result of 0 * Infinity). x !== x returns true if x is NaN
  161. if(tymin>tmin||tmin!==tmin)tmin=tymin;if(tymax<tmax||tmax!==tmax)tmax=tymax;if(invdirz>=0){tzmin=(box.min.z-origin.z)*invdirz;tzmax=(box.max.z-origin.z)*invdirz;}else {tzmin=(box.max.z-origin.z)*invdirz;tzmax=(box.min.z-origin.z)*invdirz;}if(tmin>tzmax||tzmin>tmax)return null;if(tzmin>tmin||tmin!==tmin)tmin=tzmin;if(tzmax<tmax||tmax!==tmax)tmax=tzmax;//return point closest to the ray (positive side)
  162. if(tmax<0)return null;return this.at(tmin>=0?tmin:tmax,target);}intersectsBox(box){return this.intersectBox(box,_vector$2)!==null;}intersectTriangle(a,b,c,backfaceCulling,target){// Compute the offset origin, edges, and normal.
  163. // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
  164. _edge1.subVectors(b,a);_edge2.subVectors(c,a);_normal.crossVectors(_edge1,_edge2);// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
  165. // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
  166. // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
  167. // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
  168. // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
  169. var DdN=this.direction.dot(_normal);var sign;if(DdN>0){if(backfaceCulling)return null;sign=1;}else if(DdN<0){sign=-1;DdN=-DdN;}else {return null;}_diff.subVectors(this.origin,a);var DdQxE2=sign*this.direction.dot(_edge2.crossVectors(_diff,_edge2));// b1 < 0, no intersection
  170. if(DdQxE2<0){return null;}var DdE1xQ=sign*this.direction.dot(_edge1.cross(_diff));// b2 < 0, no intersection
  171. if(DdE1xQ<0){return null;}// b1+b2 > 1, no intersection
  172. if(DdQxE2+DdE1xQ>DdN){return null;}// Line intersects triangle, check if ray does.
  173. var QdN=-sign*_diff.dot(_normal);// t < 0, no intersection
  174. if(QdN<0){return null;}// Ray intersects triangle.
  175. return this.at(QdN/DdN,target);}applyMatrix4(matrix4){this.origin.applyMatrix4(matrix4);this.direction.transformDirection(matrix4);return this;}equals(ray){return ray.origin.equals(this.origin)&&ray.direction.equals(this.direction);}}class Matrix4{constructor(){Object.defineProperty(this,'isMatrix4',{value:true});this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];if(arguments.length>0){console.error('THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.');}}set(n11,n12,n13,n14,n21,n22,n23,n24,n31,n32,n33,n34,n41,n42,n43,n44){var te=this.elements;te[0]=n11;te[4]=n12;te[8]=n13;te[12]=n14;te[1]=n21;te[5]=n22;te[9]=n23;te[13]=n24;te[2]=n31;te[6]=n32;te[10]=n33;te[14]=n34;te[3]=n41;te[7]=n42;te[11]=n43;te[15]=n44;return this;}identity(){this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);return this;}clone(){return new Matrix4().fromArray(this.elements);}copy(m){var te=this.elements;var me=m.elements;te[0]=me[0];te[1]=me[1];te[2]=me[2];te[3]=me[3];te[4]=me[4];te[5]=me[5];te[6]=me[6];te[7]=me[7];te[8]=me[8];te[9]=me[9];te[10]=me[10];te[11]=me[11];te[12]=me[12];te[13]=me[13];te[14]=me[14];te[15]=me[15];return this;}copyPosition(m){var te=this.elements,me=m.elements;te[12]=me[12];te[13]=me[13];te[14]=me[14];return this;}extractBasis(xAxis,yAxis,zAxis){xAxis.setFromMatrixColumn(this,0);yAxis.setFromMatrixColumn(this,1);zAxis.setFromMatrixColumn(this,2);return this;}makeBasis(xAxis,yAxis,zAxis){this.set(xAxis.x,yAxis.x,zAxis.x,0,xAxis.y,yAxis.y,zAxis.y,0,xAxis.z,yAxis.z,zAxis.z,0,0,0,0,1);return this;}extractRotation(m){// this method does not support reflection matrices
  176. var te=this.elements;var me=m.elements;var scaleX=1/_v1$1.setFromMatrixColumn(m,0).length();var scaleY=1/_v1$1.setFromMatrixColumn(m,1).length();var scaleZ=1/_v1$1.setFromMatrixColumn(m,2).length();te[0]=me[0]*scaleX;te[1]=me[1]*scaleX;te[2]=me[2]*scaleX;te[3]=0;te[4]=me[4]*scaleY;te[5]=me[5]*scaleY;te[6]=me[6]*scaleY;te[7]=0;te[8]=me[8]*scaleZ;te[9]=me[9]*scaleZ;te[10]=me[10]*scaleZ;te[11]=0;te[12]=0;te[13]=0;te[14]=0;te[15]=1;return this;}makeRotationFromEuler(euler){if(!(euler&&euler.isEuler)){console.error('THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.');}var te=this.elements;var x=euler.x,y=euler.y,z=euler.z;var a=Math.cos(x),b=Math.sin(x);var c=Math.cos(y),d=Math.sin(y);var e=Math.cos(z),f=Math.sin(z);if(euler.order==='XYZ'){var ae=a*e,af=a*f,be=b*e,bf=b*f;te[0]=c*e;te[4]=-c*f;te[8]=d;te[1]=af+be*d;te[5]=ae-bf*d;te[9]=-b*c;te[2]=bf-ae*d;te[6]=be+af*d;te[10]=a*c;}else if(euler.order==='YXZ'){var ce=c*e,cf=c*f,de=d*e,df=d*f;te[0]=ce+df*b;te[4]=de*b-cf;te[8]=a*d;te[1]=a*f;te[5]=a*e;te[9]=-b;te[2]=cf*b-de;te[6]=df+ce*b;te[10]=a*c;}else if(euler.order==='ZXY'){var _ce=c*e,_cf=c*f,_de=d*e,_df=d*f;te[0]=_ce-_df*b;te[4]=-a*f;te[8]=_de+_cf*b;te[1]=_cf+_de*b;te[5]=a*e;te[9]=_df-_ce*b;te[2]=-a*d;te[6]=b;te[10]=a*c;}else if(euler.order==='ZYX'){var _ae=a*e,_af=a*f,_be=b*e,_bf=b*f;te[0]=c*e;te[4]=_be*d-_af;te[8]=_ae*d+_bf;te[1]=c*f;te[5]=_bf*d+_ae;te[9]=_af*d-_be;te[2]=-d;te[6]=b*c;te[10]=a*c;}else if(euler.order==='YZX'){var ac=a*c,ad=a*d,bc=b*c,bd=b*d;te[0]=c*e;te[4]=bd-ac*f;te[8]=bc*f+ad;te[1]=f;te[5]=a*e;te[9]=-b*e;te[2]=-d*e;te[6]=ad*f+bc;te[10]=ac-bd*f;}else if(euler.order==='XZY'){var _ac=a*c,_ad=a*d,_bc=b*c,_bd=b*d;te[0]=c*e;te[4]=-f;te[8]=d*e;te[1]=_ac*f+_bd;te[5]=a*e;te[9]=_ad*f-_bc;te[2]=_bc*f-_ad;te[6]=b*e;te[10]=_bd*f+_ac;}// bottom row
  177. te[3]=0;te[7]=0;te[11]=0;// last column
  178. te[12]=0;te[13]=0;te[14]=0;te[15]=1;return this;}makeRotationFromQuaternion(q){return this.compose(_zero,q,_one);}lookAt(eye,target,up){var te=this.elements;_z.subVectors(eye,target);if(_z.lengthSq()===0){// eye and target are in the same position
  179. _z.z=1;}_z.normalize();_x.crossVectors(up,_z);if(_x.lengthSq()===0){// up and z are parallel
  180. if(Math.abs(up.z)===1){_z.x+=0.0001;}else {_z.z+=0.0001;}_z.normalize();_x.crossVectors(up,_z);}_x.normalize();_y.crossVectors(_z,_x);te[0]=_x.x;te[4]=_y.x;te[8]=_z.x;te[1]=_x.y;te[5]=_y.y;te[9]=_z.y;te[2]=_x.z;te[6]=_y.z;te[10]=_z.z;return this;}multiply(m,n){if(n!==undefined){console.warn('THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.');return this.multiplyMatrices(m,n);}return this.multiplyMatrices(this,m);}premultiply(m){return this.multiplyMatrices(m,this);}multiplyMatrices(a,b){var ae=a.elements;var be=b.elements;var te=this.elements;var a11=ae[0],a12=ae[4],a13=ae[8],a14=ae[12];var a21=ae[1],a22=ae[5],a23=ae[9],a24=ae[13];var a31=ae[2],a32=ae[6],a33=ae[10],a34=ae[14];var a41=ae[3],a42=ae[7],a43=ae[11],a44=ae[15];var b11=be[0],b12=be[4],b13=be[8],b14=be[12];var b21=be[1],b22=be[5],b23=be[9],b24=be[13];var b31=be[2],b32=be[6],b33=be[10],b34=be[14];var b41=be[3],b42=be[7],b43=be[11],b44=be[15];te[0]=a11*b11+a12*b21+a13*b31+a14*b41;te[4]=a11*b12+a12*b22+a13*b32+a14*b42;te[8]=a11*b13+a12*b23+a13*b33+a14*b43;te[12]=a11*b14+a12*b24+a13*b34+a14*b44;te[1]=a21*b11+a22*b21+a23*b31+a24*b41;te[5]=a21*b12+a22*b22+a23*b32+a24*b42;te[9]=a21*b13+a22*b23+a23*b33+a24*b43;te[13]=a21*b14+a22*b24+a23*b34+a24*b44;te[2]=a31*b11+a32*b21+a33*b31+a34*b41;te[6]=a31*b12+a32*b22+a33*b32+a34*b42;te[10]=a31*b13+a32*b23+a33*b33+a34*b43;te[14]=a31*b14+a32*b24+a33*b34+a34*b44;te[3]=a41*b11+a42*b21+a43*b31+a44*b41;te[7]=a41*b12+a42*b22+a43*b32+a44*b42;te[11]=a41*b13+a42*b23+a43*b33+a44*b43;te[15]=a41*b14+a42*b24+a43*b34+a44*b44;return this;}multiplyScalar(s){var te=this.elements;te[0]*=s;te[4]*=s;te[8]*=s;te[12]*=s;te[1]*=s;te[5]*=s;te[9]*=s;te[13]*=s;te[2]*=s;te[6]*=s;te[10]*=s;te[14]*=s;te[3]*=s;te[7]*=s;te[11]*=s;te[15]*=s;return this;}determinant(){var te=this.elements;var n11=te[0],n12=te[4],n13=te[8],n14=te[12];var n21=te[1],n22=te[5],n23=te[9],n24=te[13];var n31=te[2],n32=te[6],n33=te[10],n34=te[14];var n41=te[3],n42=te[7],n43=te[11],n44=te[15];//TODO: make this more efficient
  181. //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  182. return n41*(+n14*n23*n32-n13*n24*n32-n14*n22*n33+n12*n24*n33+n13*n22*n34-n12*n23*n34)+n42*(+n11*n23*n34-n11*n24*n33+n14*n21*n33-n13*n21*n34+n13*n24*n31-n14*n23*n31)+n43*(+n11*n24*n32-n11*n22*n34-n14*n21*n32+n12*n21*n34+n14*n22*n31-n12*n24*n31)+n44*(-n13*n22*n31-n11*n23*n32+n11*n22*n33+n13*n21*n32-n12*n21*n33+n12*n23*n31);}transpose(){var te=this.elements;var tmp;tmp=te[1];te[1]=te[4];te[4]=tmp;tmp=te[2];te[2]=te[8];te[8]=tmp;tmp=te[6];te[6]=te[9];te[9]=tmp;tmp=te[3];te[3]=te[12];te[12]=tmp;tmp=te[7];te[7]=te[13];te[13]=tmp;tmp=te[11];te[11]=te[14];te[14]=tmp;return this;}setPosition(x,y,z){var te=this.elements;if(x.isVector3){te[12]=x.x;te[13]=x.y;te[14]=x.z;}else {te[12]=x;te[13]=y;te[14]=z;}return this;}invert(){// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
  183. var te=this.elements,n11=te[0],n21=te[1],n31=te[2],n41=te[3],n12=te[4],n22=te[5],n32=te[6],n42=te[7],n13=te[8],n23=te[9],n33=te[10],n43=te[11],n14=te[12],n24=te[13],n34=te[14],n44=te[15],t11=n23*n34*n42-n24*n33*n42+n24*n32*n43-n22*n34*n43-n23*n32*n44+n22*n33*n44,t12=n14*n33*n42-n13*n34*n42-n14*n32*n43+n12*n34*n43+n13*n32*n44-n12*n33*n44,t13=n13*n24*n42-n14*n23*n42+n14*n22*n43-n12*n24*n43-n13*n22*n44+n12*n23*n44,t14=n14*n23*n32-n13*n24*n32-n14*n22*n33+n12*n24*n33+n13*n22*n34-n12*n23*n34;var det=n11*t11+n21*t12+n31*t13+n41*t14;if(det===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);var detInv=1/det;te[0]=t11*detInv;te[1]=(n24*n33*n41-n23*n34*n41-n24*n31*n43+n21*n34*n43+n23*n31*n44-n21*n33*n44)*detInv;te[2]=(n22*n34*n41-n24*n32*n41+n24*n31*n42-n21*n34*n42-n22*n31*n44+n21*n32*n44)*detInv;te[3]=(n23*n32*n41-n22*n33*n41-n23*n31*n42+n21*n33*n42+n22*n31*n43-n21*n32*n43)*detInv;te[4]=t12*detInv;te[5]=(n13*n34*n41-n14*n33*n41+n14*n31*n43-n11*n34*n43-n13*n31*n44+n11*n33*n44)*detInv;te[6]=(n14*n32*n41-n12*n34*n41-n14*n31*n42+n11*n34*n42+n12*n31*n44-n11*n32*n44)*detInv;te[7]=(n12*n33*n41-n13*n32*n41+n13*n31*n42-n11*n33*n42-n12*n31*n43+n11*n32*n43)*detInv;te[8]=t13*detInv;te[9]=(n14*n23*n41-n13*n24*n41-n14*n21*n43+n11*n24*n43+n13*n21*n44-n11*n23*n44)*detInv;te[10]=(n12*n24*n41-n14*n22*n41+n14*n21*n42-n11*n24*n42-n12*n21*n44+n11*n22*n44)*detInv;te[11]=(n13*n22*n41-n12*n23*n41-n13*n21*n42+n11*n23*n42+n12*n21*n43-n11*n22*n43)*detInv;te[12]=t14*detInv;te[13]=(n13*n24*n31-n14*n23*n31+n14*n21*n33-n11*n24*n33-n13*n21*n34+n11*n23*n34)*detInv;te[14]=(n14*n22*n31-n12*n24*n31-n14*n21*n32+n11*n24*n32+n12*n21*n34-n11*n22*n34)*detInv;te[15]=(n12*n23*n31-n13*n22*n31+n13*n21*n32-n11*n23*n32-n12*n21*n33+n11*n22*n33)*detInv;return this;}scale(v){var te=this.elements;var x=v.x,y=v.y,z=v.z;te[0]*=x;te[4]*=y;te[8]*=z;te[1]*=x;te[5]*=y;te[9]*=z;te[2]*=x;te[6]*=y;te[10]*=z;te[3]*=x;te[7]*=y;te[11]*=z;return this;}getMaxScaleOnAxis(){var te=this.elements;var scaleXSq=te[0]*te[0]+te[1]*te[1]+te[2]*te[2];var scaleYSq=te[4]*te[4]+te[5]*te[5]+te[6]*te[6];var scaleZSq=te[8]*te[8]+te[9]*te[9]+te[10]*te[10];return Math.sqrt(Math.max(scaleXSq,scaleYSq,scaleZSq));}makeTranslation(x,y,z){this.set(1,0,0,x,0,1,0,y,0,0,1,z,0,0,0,1);return this;}makeRotationX(theta){var c=Math.cos(theta),s=Math.sin(theta);this.set(1,0,0,0,0,c,-s,0,0,s,c,0,0,0,0,1);return this;}makeRotationY(theta){var c=Math.cos(theta),s=Math.sin(theta);this.set(c,0,s,0,0,1,0,0,-s,0,c,0,0,0,0,1);return this;}makeRotationZ(theta){var c=Math.cos(theta),s=Math.sin(theta);this.set(c,-s,0,0,s,c,0,0,0,0,1,0,0,0,0,1);return this;}makeRotationAxis(axis,angle){// Based on http://www.gamedev.net/reference/articles/article1199.asp
  184. var c=Math.cos(angle);var s=Math.sin(angle);var t=1-c;var x=axis.x,y=axis.y,z=axis.z;var tx=t*x,ty=t*y;this.set(tx*x+c,tx*y-s*z,tx*z+s*y,0,tx*y+s*z,ty*y+c,ty*z-s*x,0,tx*z-s*y,ty*z+s*x,t*z*z+c,0,0,0,0,1);return this;}makeScale(x,y,z){this.set(x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1);return this;}makeShear(x,y,z){this.set(1,y,z,0,x,1,z,0,x,y,1,0,0,0,0,1);return this;}compose(position,quaternion,scale){var te=this.elements;var x=quaternion._x,y=quaternion._y,z=quaternion._z,w=quaternion._w;var x2=x+x,y2=y+y,z2=z+z;var xx=x*x2,xy=x*y2,xz=x*z2;var yy=y*y2,yz=y*z2,zz=z*z2;var wx=w*x2,wy=w*y2,wz=w*z2;var sx=scale.x,sy=scale.y,sz=scale.z;te[0]=(1-(yy+zz))*sx;te[1]=(xy+wz)*sx;te[2]=(xz-wy)*sx;te[3]=0;te[4]=(xy-wz)*sy;te[5]=(1-(xx+zz))*sy;te[6]=(yz+wx)*sy;te[7]=0;te[8]=(xz+wy)*sz;te[9]=(yz-wx)*sz;te[10]=(1-(xx+yy))*sz;te[11]=0;te[12]=position.x;te[13]=position.y;te[14]=position.z;te[15]=1;return this;}decompose(position,quaternion,scale){var te=this.elements;var sx=_v1$1.set(te[0],te[1],te[2]).length();var sy=_v1$1.set(te[4],te[5],te[6]).length();var sz=_v1$1.set(te[8],te[9],te[10]).length();// if determine is negative, we need to invert one scale
  185. var det=this.determinant();if(det<0)sx=-sx;position.x=te[12];position.y=te[13];position.z=te[14];// scale the rotation part
  186. _m1.copy(this);var invSX=1/sx;var invSY=1/sy;var invSZ=1/sz;_m1.elements[0]*=invSX;_m1.elements[1]*=invSX;_m1.elements[2]*=invSX;_m1.elements[4]*=invSY;_m1.elements[5]*=invSY;_m1.elements[6]*=invSY;_m1.elements[8]*=invSZ;_m1.elements[9]*=invSZ;_m1.elements[10]*=invSZ;quaternion.setFromRotationMatrix(_m1);scale.x=sx;scale.y=sy;scale.z=sz;return this;}makePerspective(left,right,top,bottom,near,far){if(far===undefined){console.warn('THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.');}var te=this.elements;var x=2*near/(right-left);var y=2*near/(top-bottom);var a=(right+left)/(right-left);var b=(top+bottom)/(top-bottom);var c=-(far+near)/(far-near);var d=-2*far*near/(far-near);te[0]=x;te[4]=0;te[8]=a;te[12]=0;te[1]=0;te[5]=y;te[9]=b;te[13]=0;te[2]=0;te[6]=0;te[10]=c;te[14]=d;te[3]=0;te[7]=0;te[11]=-1;te[15]=0;return this;}makeOrthographic(left,right,top,bottom,near,far){var te=this.elements;var w=1.0/(right-left);var h=1.0/(top-bottom);var p=1.0/(far-near);var x=(right+left)*w;var y=(top+bottom)*h;var z=(far+near)*p;te[0]=2*w;te[4]=0;te[8]=0;te[12]=-x;te[1]=0;te[5]=2*h;te[9]=0;te[13]=-y;te[2]=0;te[6]=0;te[10]=-2*p;te[14]=-z;te[3]=0;te[7]=0;te[11]=0;te[15]=1;return this;}equals(matrix){var te=this.elements;var me=matrix.elements;for(var _i10=0;_i10<16;_i10++){if(te[_i10]!==me[_i10])return false;}return true;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;for(var _i11=0;_i11<16;_i11++){this.elements[_i11]=array[_i11+offset];}return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var te=this.elements;array[offset]=te[0];array[offset+1]=te[1];array[offset+2]=te[2];array[offset+3]=te[3];array[offset+4]=te[4];array[offset+5]=te[5];array[offset+6]=te[6];array[offset+7]=te[7];array[offset+8]=te[8];array[offset+9]=te[9];array[offset+10]=te[10];array[offset+11]=te[11];array[offset+12]=te[12];array[offset+13]=te[13];array[offset+14]=te[14];array[offset+15]=te[15];return array;}}var _v1$1=/*@__PURE__*/new Vector3();var _m1=/*@__PURE__*/new Matrix4();var _zero=/*@__PURE__*/new Vector3(0,0,0);var _one=/*@__PURE__*/new Vector3(1,1,1);var _x=/*@__PURE__*/new Vector3();var _y=/*@__PURE__*/new Vector3();var _z=/*@__PURE__*/new Vector3();class Euler{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var order=arguments.length>3&&arguments[3]!==undefined?arguments[3]:Euler.DefaultOrder;Object.defineProperty(this,'isEuler',{value:true});this._x=x;this._y=y;this._z=z;this._order=order;}get x(){return this._x;}set x(value){this._x=value;this._onChangeCallback();}get y(){return this._y;}set y(value){this._y=value;this._onChangeCallback();}get z(){return this._z;}set z(value){this._z=value;this._onChangeCallback();}get order(){return this._order;}set order(value){this._order=value;this._onChangeCallback();}set(x,y,z,order){this._x=x;this._y=y;this._z=z;this._order=order||this._order;this._onChangeCallback();return this;}clone(){return new this.constructor(this._x,this._y,this._z,this._order);}copy(euler){this._x=euler._x;this._y=euler._y;this._z=euler._z;this._order=euler._order;this._onChangeCallback();return this;}setFromRotationMatrix(m,order,update){var clamp=MathUtils.clamp;// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  187. var te=m.elements;var m11=te[0],m12=te[4],m13=te[8];var m21=te[1],m22=te[5],m23=te[9];var m31=te[2],m32=te[6],m33=te[10];order=order||this._order;switch(order){case'XYZ':this._y=Math.asin(clamp(m13,-1,1));if(Math.abs(m13)<0.9999999){this._x=Math.atan2(-m23,m33);this._z=Math.atan2(-m12,m11);}else {this._x=Math.atan2(m32,m22);this._z=0;}break;case'YXZ':this._x=Math.asin(-clamp(m23,-1,1));if(Math.abs(m23)<0.9999999){this._y=Math.atan2(m13,m33);this._z=Math.atan2(m21,m22);}else {this._y=Math.atan2(-m31,m11);this._z=0;}break;case'ZXY':this._x=Math.asin(clamp(m32,-1,1));if(Math.abs(m32)<0.9999999){this._y=Math.atan2(-m31,m33);this._z=Math.atan2(-m12,m22);}else {this._y=0;this._z=Math.atan2(m21,m11);}break;case'ZYX':this._y=Math.asin(-clamp(m31,-1,1));if(Math.abs(m31)<0.9999999){this._x=Math.atan2(m32,m33);this._z=Math.atan2(m21,m11);}else {this._x=0;this._z=Math.atan2(-m12,m22);}break;case'YZX':this._z=Math.asin(clamp(m21,-1,1));if(Math.abs(m21)<0.9999999){this._x=Math.atan2(-m23,m22);this._y=Math.atan2(-m31,m11);}else {this._x=0;this._y=Math.atan2(m13,m33);}break;case'XZY':this._z=Math.asin(-clamp(m12,-1,1));if(Math.abs(m12)<0.9999999){this._x=Math.atan2(m32,m22);this._y=Math.atan2(m13,m11);}else {this._x=Math.atan2(-m23,m33);this._y=0;}break;default:console.warn('THREE.Euler: .setFromRotationMatrix() encountered an unknown order: '+order);}this._order=order;if(update!==false)this._onChangeCallback();return this;}setFromQuaternion(q,order,update){_matrix.makeRotationFromQuaternion(q);return this.setFromRotationMatrix(_matrix,order,update);}setFromVector3(v,order){return this.set(v.x,v.y,v.z,order||this._order);}reorder(newOrder){// WARNING: this discards revolution information -bhouston
  188. _quaternion$1.setFromEuler(this);return this.setFromQuaternion(_quaternion$1,newOrder);}equals(euler){return euler._x===this._x&&euler._y===this._y&&euler._z===this._z&&euler._order===this._order;}fromArray(array){this._x=array[0];this._y=array[1];this._z=array[2];if(array[3]!==undefined)this._order=array[3];this._onChangeCallback();return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this._x;array[offset+1]=this._y;array[offset+2]=this._z;array[offset+3]=this._order;return array;}toVector3(optionalResult){if(optionalResult){return optionalResult.set(this._x,this._y,this._z);}else {return new Vector3(this._x,this._y,this._z);}}_onChange(callback){this._onChangeCallback=callback;return this;}_onChangeCallback(){}}Euler.DefaultOrder='XYZ';Euler.RotationOrders=['XYZ','YZX','ZXY','XZY','YXZ','ZYX'];var _matrix=/*@__PURE__*/new Matrix4();var _quaternion$1=/*@__PURE__*/new Quaternion();class Layers{constructor(){this.mask=1|0;}set(channel){this.mask=1<<channel|0;}enable(channel){this.mask|=1<<channel|0;}enableAll(){this.mask=0xffffffff|0;}toggle(channel){this.mask^=1<<channel|0;}disable(channel){this.mask&=~(1<<channel|0);}disableAll(){this.mask=0;}test(layers){return (this.mask&layers.mask)!==0;}}var _object3DId=0;var _v1$2=new Vector3();var _q1=new Quaternion();var _m1$1=new Matrix4();var _target=new Vector3();var _position=new Vector3();var _scale=new Vector3();var _quaternion$2=new Quaternion();var _xAxis=new Vector3(1,0,0);var _yAxis=new Vector3(0,1,0);var _zAxis=new Vector3(0,0,1);var _addedEvent={type:'added'};var _removedEvent={type:'removed'};function Object3D(){Object.defineProperty(this,'id',{value:_object3DId++});this.uuid=MathUtils.generateUUID();this.name='';this.type='Object3D';this.parent=null;this.children=[];this.up=Object3D.DefaultUp.clone();var position=new Vector3();var rotation=new Euler();var quaternion=new Quaternion();var scale=new Vector3(1,1,1);function onRotationChange(){quaternion.setFromEuler(rotation,false);}function onQuaternionChange(){rotation.setFromQuaternion(quaternion,undefined,false);}rotation._onChange(onRotationChange);quaternion._onChange(onQuaternionChange);Object.defineProperties(this,{position:{configurable:true,enumerable:true,value:position},rotation:{configurable:true,enumerable:true,value:rotation},quaternion:{configurable:true,enumerable:true,value:quaternion},scale:{configurable:true,enumerable:true,value:scale},modelViewMatrix:{value:new Matrix4()},normalMatrix:{value:new Matrix3()}});this.matrix=new Matrix4();this.matrixWorld=new Matrix4();this.matrixAutoUpdate=Object3D.DefaultMatrixAutoUpdate;this.matrixWorldNeedsUpdate=false;this.layers=new Layers();this.visible=true;this.castShadow=false;this.receiveShadow=false;this.frustumCulled=true;this.renderOrder=0;this.animations=[];this.userData={};}Object3D.DefaultUp=new Vector3(0,1,0);Object3D.DefaultMatrixAutoUpdate=true;Object3D.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:Object3D,isObject3D:true,onBeforeRender:function onBeforeRender(){},onAfterRender:function onAfterRender(){},applyMatrix4:function applyMatrix4(matrix){if(this.matrixAutoUpdate)this.updateMatrix();this.matrix.premultiply(matrix);this.matrix.decompose(this.position,this.quaternion,this.scale);},applyQuaternion:function applyQuaternion(q){this.quaternion.premultiply(q);return this;},setRotationFromAxisAngle:function setRotationFromAxisAngle(axis,angle){// assumes axis is normalized
  189. this.quaternion.setFromAxisAngle(axis,angle);},setRotationFromEuler:function setRotationFromEuler(euler){this.quaternion.setFromEuler(euler,true);},setRotationFromMatrix:function setRotationFromMatrix(m){// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  190. this.quaternion.setFromRotationMatrix(m);},setRotationFromQuaternion:function setRotationFromQuaternion(q){// assumes q is normalized
  191. this.quaternion.copy(q);},rotateOnAxis:function rotateOnAxis(axis,angle){// rotate object on axis in object space
  192. // axis is assumed to be normalized
  193. _q1.setFromAxisAngle(axis,angle);this.quaternion.multiply(_q1);return this;},rotateOnWorldAxis:function rotateOnWorldAxis(axis,angle){// rotate object on axis in world space
  194. // axis is assumed to be normalized
  195. // method assumes no rotated parent
  196. _q1.setFromAxisAngle(axis,angle);this.quaternion.premultiply(_q1);return this;},rotateX:function rotateX(angle){return this.rotateOnAxis(_xAxis,angle);},rotateY:function rotateY(angle){return this.rotateOnAxis(_yAxis,angle);},rotateZ:function rotateZ(angle){return this.rotateOnAxis(_zAxis,angle);},translateOnAxis:function translateOnAxis(axis,distance){// translate object by distance along axis in object space
  197. // axis is assumed to be normalized
  198. _v1$2.copy(axis).applyQuaternion(this.quaternion);this.position.add(_v1$2.multiplyScalar(distance));return this;},translateX:function translateX(distance){return this.translateOnAxis(_xAxis,distance);},translateY:function translateY(distance){return this.translateOnAxis(_yAxis,distance);},translateZ:function translateZ(distance){return this.translateOnAxis(_zAxis,distance);},localToWorld:function localToWorld(vector){return vector.applyMatrix4(this.matrixWorld);},worldToLocal:function worldToLocal(vector){return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert());},lookAt:function lookAt(x,y,z){// This method does not support objects having non-uniformly-scaled parent(s)
  199. if(x.isVector3){_target.copy(x);}else {_target.set(x,y,z);}var parent=this.parent;this.updateWorldMatrix(true,false);_position.setFromMatrixPosition(this.matrixWorld);if(this.isCamera||this.isLight){_m1$1.lookAt(_position,_target,this.up);}else {_m1$1.lookAt(_target,_position,this.up);}this.quaternion.setFromRotationMatrix(_m1$1);if(parent){_m1$1.extractRotation(parent.matrixWorld);_q1.setFromRotationMatrix(_m1$1);this.quaternion.premultiply(_q1.invert());}},add:function add(object){if(arguments.length>1){for(var _i12=0;_i12<arguments.length;_i12++){this.add(arguments[_i12]);}return this;}if(object===this){console.error('THREE.Object3D.add: object can\'t be added as a child of itself.',object);return this;}if(object&&object.isObject3D){if(object.parent!==null){object.parent.remove(object);}object.parent=this;this.children.push(object);object.dispatchEvent(_addedEvent);}else {console.error('THREE.Object3D.add: object not an instance of THREE.Object3D.',object);}return this;},remove:function remove(object){if(arguments.length>1){for(var _i13=0;_i13<arguments.length;_i13++){this.remove(arguments[_i13]);}return this;}var index=this.children.indexOf(object);if(index!==-1){object.parent=null;this.children.splice(index,1);object.dispatchEvent(_removedEvent);}return this;},clear:function clear(){for(var _i14=0;_i14<this.children.length;_i14++){var object=this.children[_i14];object.parent=null;object.dispatchEvent(_removedEvent);}this.children.length=0;return this;},attach:function attach(object){// adds object as a child of this, while maintaining the object's world transform
  200. this.updateWorldMatrix(true,false);_m1$1.copy(this.matrixWorld).invert();if(object.parent!==null){object.parent.updateWorldMatrix(true,false);_m1$1.multiply(object.parent.matrixWorld);}object.applyMatrix4(_m1$1);object.updateWorldMatrix(false,false);this.add(object);return this;},getObjectById:function getObjectById(id){return this.getObjectByProperty('id',id);},getObjectByName:function getObjectByName(name){return this.getObjectByProperty('name',name);},getObjectByProperty:function getObjectByProperty(name,value){if(this[name]===value)return this;for(var _i15=0,l=this.children.length;_i15<l;_i15++){var child=this.children[_i15];var object=child.getObjectByProperty(name,value);if(object!==undefined){return object;}}return undefined;},getWorldPosition:function getWorldPosition(target){if(target===undefined){console.warn('THREE.Object3D: .getWorldPosition() target is now required');target=new Vector3();}this.updateWorldMatrix(true,false);return target.setFromMatrixPosition(this.matrixWorld);},getWorldQuaternion:function getWorldQuaternion(target){if(target===undefined){console.warn('THREE.Object3D: .getWorldQuaternion() target is now required');target=new Quaternion();}this.updateWorldMatrix(true,false);this.matrixWorld.decompose(_position,target,_scale);return target;},getWorldScale:function getWorldScale(target){if(target===undefined){console.warn('THREE.Object3D: .getWorldScale() target is now required');target=new Vector3();}this.updateWorldMatrix(true,false);this.matrixWorld.decompose(_position,_quaternion$2,target);return target;},getWorldDirection:function getWorldDirection(target){if(target===undefined){console.warn('THREE.Object3D: .getWorldDirection() target is now required');target=new Vector3();}this.updateWorldMatrix(true,false);var e=this.matrixWorld.elements;return target.set(e[8],e[9],e[10]).normalize();},raycast:function raycast(){},traverse:function traverse(callback){callback(this);var children=this.children;for(var _i16=0,l=children.length;_i16<l;_i16++){children[_i16].traverse(callback);}},traverseVisible:function traverseVisible(callback){if(this.visible===false)return;callback(this);var children=this.children;for(var _i17=0,l=children.length;_i17<l;_i17++){children[_i17].traverseVisible(callback);}},traverseAncestors:function traverseAncestors(callback){var parent=this.parent;if(parent!==null){callback(parent);parent.traverseAncestors(callback);}},updateMatrix:function updateMatrix(){this.matrix.compose(this.position,this.quaternion,this.scale);this.matrixWorldNeedsUpdate=true;},updateMatrixWorld:function updateMatrixWorld(force){if(this.matrixAutoUpdate)this.updateMatrix();if(this.matrixWorldNeedsUpdate||force){if(this.parent===null){this.matrixWorld.copy(this.matrix);}else {this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix);}this.matrixWorldNeedsUpdate=false;force=true;}// update children
  201. var children=this.children;for(var _i18=0,l=children.length;_i18<l;_i18++){children[_i18].updateMatrixWorld(force);}},updateWorldMatrix:function updateWorldMatrix(updateParents,updateChildren){var parent=this.parent;if(updateParents===true&&parent!==null){parent.updateWorldMatrix(true,false);}if(this.matrixAutoUpdate)this.updateMatrix();if(this.parent===null){this.matrixWorld.copy(this.matrix);}else {this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix);}// update children
  202. if(updateChildren===true){var children=this.children;for(var _i19=0,l=children.length;_i19<l;_i19++){children[_i19].updateWorldMatrix(false,true);}}},toJSON:function toJSON(meta){// meta is a string when called from JSON.stringify
  203. var isRootObject=meta===undefined||typeof meta==='string';var output={};// meta is a hash used to collect geometries, materials.
  204. // not providing it implies that this is the root object
  205. // being serialized.
  206. if(isRootObject){// initialize meta obj
  207. meta={geometries:{},materials:{},textures:{},images:{},shapes:{},skeletons:{},animations:{}};output.metadata={version:4.5,type:'Object',generator:'Object3D.toJSON'};}// standard Object3D serialization
  208. var object={};object.uuid=this.uuid;object.type=this.type;if(this.name!=='')object.name=this.name;if(this.castShadow===true)object.castShadow=true;if(this.receiveShadow===true)object.receiveShadow=true;if(this.visible===false)object.visible=false;if(this.frustumCulled===false)object.frustumCulled=false;if(this.renderOrder!==0)object.renderOrder=this.renderOrder;if(JSON.stringify(this.userData)!=='{}')object.userData=this.userData;object.layers=this.layers.mask;object.matrix=this.matrix.toArray();if(this.matrixAutoUpdate===false)object.matrixAutoUpdate=false;// object specific properties
  209. if(this.isInstancedMesh){object.type='InstancedMesh';object.count=this.count;object.instanceMatrix=this.instanceMatrix.toJSON();}//
  210. function serialize(library,element){if(library[element.uuid]===undefined){library[element.uuid]=element.toJSON(meta);}return element.uuid;}if(this.isMesh||this.isLine||this.isPoints){object.geometry=serialize(meta.geometries,this.geometry);var parameters=this.geometry.parameters;if(parameters!==undefined&&parameters.shapes!==undefined){var shapes=parameters.shapes;if(Array.isArray(shapes)){for(var _i20=0,l=shapes.length;_i20<l;_i20++){var shape=shapes[_i20];serialize(meta.shapes,shape);}}else {serialize(meta.shapes,shapes);}}}if(this.isSkinnedMesh){object.bindMode=this.bindMode;object.bindMatrix=this.bindMatrix.toArray();if(this.skeleton!==undefined){serialize(meta.skeletons,this.skeleton);object.skeleton=this.skeleton.uuid;}}if(this.material!==undefined){if(Array.isArray(this.material)){var uuids=[];for(var _i21=0,_l=this.material.length;_i21<_l;_i21++){uuids.push(serialize(meta.materials,this.material[_i21]));}object.material=uuids;}else {object.material=serialize(meta.materials,this.material);}}//
  211. if(this.children.length>0){object.children=[];for(var _i22=0;_i22<this.children.length;_i22++){object.children.push(this.children[_i22].toJSON(meta).object);}}//
  212. if(this.animations.length>0){object.animations=[];for(var _i23=0;_i23<this.animations.length;_i23++){var animation=this.animations[_i23];object.animations.push(serialize(meta.animations,animation));}}if(isRootObject){var geometries=extractFromCache(meta.geometries);var materials=extractFromCache(meta.materials);var textures=extractFromCache(meta.textures);var images=extractFromCache(meta.images);var _shapes=extractFromCache(meta.shapes);var skeletons=extractFromCache(meta.skeletons);var animations=extractFromCache(meta.animations);if(geometries.length>0)output.geometries=geometries;if(materials.length>0)output.materials=materials;if(textures.length>0)output.textures=textures;if(images.length>0)output.images=images;if(_shapes.length>0)output.shapes=_shapes;if(skeletons.length>0)output.skeletons=skeletons;if(animations.length>0)output.animations=animations;}output.object=object;return output;// extract data from the cache hash
  213. // remove metadata on each item
  214. // and return as array
  215. function extractFromCache(cache){var values=[];for(var key in cache){var data=cache[key];delete data.metadata;values.push(data);}return values;}},clone:function clone(recursive){return new this.constructor().copy(this,recursive);},copy:function copy(source){var recursive=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;this.name=source.name;this.up.copy(source.up);this.position.copy(source.position);this.rotation.order=source.rotation.order;this.quaternion.copy(source.quaternion);this.scale.copy(source.scale);this.matrix.copy(source.matrix);this.matrixWorld.copy(source.matrixWorld);this.matrixAutoUpdate=source.matrixAutoUpdate;this.matrixWorldNeedsUpdate=source.matrixWorldNeedsUpdate;this.layers.mask=source.layers.mask;this.visible=source.visible;this.castShadow=source.castShadow;this.receiveShadow=source.receiveShadow;this.frustumCulled=source.frustumCulled;this.renderOrder=source.renderOrder;this.userData=JSON.parse(JSON.stringify(source.userData));if(recursive===true){for(var _i24=0;_i24<source.children.length;_i24++){var child=source.children[_i24];this.add(child.clone());}}return this;}});var _vector1=/*@__PURE__*/new Vector3();var _vector2=/*@__PURE__*/new Vector3();var _normalMatrix=/*@__PURE__*/new Matrix3();class Plane{constructor(normal,constant){Object.defineProperty(this,'isPlane',{value:true});// normal is assumed to be normalized
  216. this.normal=normal!==undefined?normal:new Vector3(1,0,0);this.constant=constant!==undefined?constant:0;}set(normal,constant){this.normal.copy(normal);this.constant=constant;return this;}setComponents(x,y,z,w){this.normal.set(x,y,z);this.constant=w;return this;}setFromNormalAndCoplanarPoint(normal,point){this.normal.copy(normal);this.constant=-point.dot(this.normal);return this;}setFromCoplanarPoints(a,b,c){var normal=_vector1.subVectors(c,b).cross(_vector2.subVectors(a,b)).normalize();// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
  217. this.setFromNormalAndCoplanarPoint(normal,a);return this;}clone(){return new this.constructor().copy(this);}copy(plane){this.normal.copy(plane.normal);this.constant=plane.constant;return this;}normalize(){// Note: will lead to a divide by zero if the plane is invalid.
  218. var inverseNormalLength=1.0/this.normal.length();this.normal.multiplyScalar(inverseNormalLength);this.constant*=inverseNormalLength;return this;}negate(){this.constant*=-1;this.normal.negate();return this;}distanceToPoint(point){return this.normal.dot(point)+this.constant;}distanceToSphere(sphere){return this.distanceToPoint(sphere.center)-sphere.radius;}projectPoint(point,target){if(target===undefined){console.warn('THREE.Plane: .projectPoint() target is now required');target=new Vector3();}return target.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point);}intersectLine(line,target){if(target===undefined){console.warn('THREE.Plane: .intersectLine() target is now required');target=new Vector3();}var direction=line.delta(_vector1);var denominator=this.normal.dot(direction);if(denominator===0){// line is coplanar, return origin
  219. if(this.distanceToPoint(line.start)===0){return target.copy(line.start);}// Unsure if this is the correct method to handle this case.
  220. return undefined;}var t=-(line.start.dot(this.normal)+this.constant)/denominator;if(t<0||t>1){return undefined;}return target.copy(direction).multiplyScalar(t).add(line.start);}intersectsLine(line){// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
  221. var startSign=this.distanceToPoint(line.start);var endSign=this.distanceToPoint(line.end);return startSign<0&&endSign>0||endSign<0&&startSign>0;}intersectsBox(box){return box.intersectsPlane(this);}intersectsSphere(sphere){return sphere.intersectsPlane(this);}coplanarPoint(target){if(target===undefined){console.warn('THREE.Plane: .coplanarPoint() target is now required');target=new Vector3();}return target.copy(this.normal).multiplyScalar(-this.constant);}applyMatrix4(matrix,optionalNormalMatrix){var normalMatrix=optionalNormalMatrix||_normalMatrix.getNormalMatrix(matrix);var referencePoint=this.coplanarPoint(_vector1).applyMatrix4(matrix);var normal=this.normal.applyMatrix3(normalMatrix).normalize();this.constant=-referencePoint.dot(normal);return this;}translate(offset){this.constant-=offset.dot(this.normal);return this;}equals(plane){return plane.normal.equals(this.normal)&&plane.constant===this.constant;}}var _v0$1=/*@__PURE__*/new Vector3();var _v1$3=/*@__PURE__*/new Vector3();var _v2$1=/*@__PURE__*/new Vector3();var _v3=/*@__PURE__*/new Vector3();var _vab=/*@__PURE__*/new Vector3();var _vac=/*@__PURE__*/new Vector3();var _vbc=/*@__PURE__*/new Vector3();var _vap=/*@__PURE__*/new Vector3();var _vbp=/*@__PURE__*/new Vector3();var _vcp=/*@__PURE__*/new Vector3();class Triangle{constructor(a,b,c){this.a=a!==undefined?a:new Vector3();this.b=b!==undefined?b:new Vector3();this.c=c!==undefined?c:new Vector3();}static getNormal(a,b,c,target){if(target===undefined){console.warn('THREE.Triangle: .getNormal() target is now required');target=new Vector3();}target.subVectors(c,b);_v0$1.subVectors(a,b);target.cross(_v0$1);var targetLengthSq=target.lengthSq();if(targetLengthSq>0){return target.multiplyScalar(1/Math.sqrt(targetLengthSq));}return target.set(0,0,0);}// static/instance method to calculate barycentric coordinates
  222. // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
  223. static getBarycoord(point,a,b,c,target){_v0$1.subVectors(c,a);_v1$3.subVectors(b,a);_v2$1.subVectors(point,a);var dot00=_v0$1.dot(_v0$1);var dot01=_v0$1.dot(_v1$3);var dot02=_v0$1.dot(_v2$1);var dot11=_v1$3.dot(_v1$3);var dot12=_v1$3.dot(_v2$1);var denom=dot00*dot11-dot01*dot01;if(target===undefined){console.warn('THREE.Triangle: .getBarycoord() target is now required');target=new Vector3();}// collinear or singular triangle
  224. if(denom===0){// arbitrary location outside of triangle?
  225. // not sure if this is the best idea, maybe should be returning undefined
  226. return target.set(-2,-1,-1);}var invDenom=1/denom;var u=(dot11*dot02-dot01*dot12)*invDenom;var v=(dot00*dot12-dot01*dot02)*invDenom;// barycentric coordinates must always sum to 1
  227. return target.set(1-u-v,v,u);}static containsPoint(point,a,b,c){this.getBarycoord(point,a,b,c,_v3);return _v3.x>=0&&_v3.y>=0&&_v3.x+_v3.y<=1;}static getUV(point,p1,p2,p3,uv1,uv2,uv3,target){this.getBarycoord(point,p1,p2,p3,_v3);target.set(0,0);target.addScaledVector(uv1,_v3.x);target.addScaledVector(uv2,_v3.y);target.addScaledVector(uv3,_v3.z);return target;}static isFrontFacing(a,b,c,direction){_v0$1.subVectors(c,b);_v1$3.subVectors(a,b);// strictly front facing
  228. return _v0$1.cross(_v1$3).dot(direction)<0?true:false;}set(a,b,c){this.a.copy(a);this.b.copy(b);this.c.copy(c);return this;}setFromPointsAndIndices(points,i0,i1,i2){this.a.copy(points[i0]);this.b.copy(points[i1]);this.c.copy(points[i2]);return this;}clone(){return new this.constructor().copy(this);}copy(triangle){this.a.copy(triangle.a);this.b.copy(triangle.b);this.c.copy(triangle.c);return this;}getArea(){_v0$1.subVectors(this.c,this.b);_v1$3.subVectors(this.a,this.b);return _v0$1.cross(_v1$3).length()*0.5;}getMidpoint(target){if(target===undefined){console.warn('THREE.Triangle: .getMidpoint() target is now required');target=new Vector3();}return target.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3);}getNormal(target){return Triangle.getNormal(this.a,this.b,this.c,target);}getPlane(target){if(target===undefined){console.warn('THREE.Triangle: .getPlane() target is now required');target=new Plane();}return target.setFromCoplanarPoints(this.a,this.b,this.c);}getBarycoord(point,target){return Triangle.getBarycoord(point,this.a,this.b,this.c,target);}getUV(point,uv1,uv2,uv3,target){return Triangle.getUV(point,this.a,this.b,this.c,uv1,uv2,uv3,target);}containsPoint(point){return Triangle.containsPoint(point,this.a,this.b,this.c);}isFrontFacing(direction){return Triangle.isFrontFacing(this.a,this.b,this.c,direction);}intersectsBox(box){return box.intersectsTriangle(this);}closestPointToPoint(p,target){if(target===undefined){console.warn('THREE.Triangle: .closestPointToPoint() target is now required');target=new Vector3();}var a=this.a,b=this.b,c=this.c;var v,w;// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
  229. // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
  230. // under the accompanying license; see chapter 5.1.5 for detailed explanation.
  231. // basically, we're distinguishing which of the voronoi regions of the triangle
  232. // the point lies in with the minimum amount of redundant computation.
  233. _vab.subVectors(b,a);_vac.subVectors(c,a);_vap.subVectors(p,a);var d1=_vab.dot(_vap);var d2=_vac.dot(_vap);if(d1<=0&&d2<=0){// vertex region of A; barycentric coords (1, 0, 0)
  234. return target.copy(a);}_vbp.subVectors(p,b);var d3=_vab.dot(_vbp);var d4=_vac.dot(_vbp);if(d3>=0&&d4<=d3){// vertex region of B; barycentric coords (0, 1, 0)
  235. return target.copy(b);}var vc=d1*d4-d3*d2;if(vc<=0&&d1>=0&&d3<=0){v=d1/(d1-d3);// edge region of AB; barycentric coords (1-v, v, 0)
  236. return target.copy(a).addScaledVector(_vab,v);}_vcp.subVectors(p,c);var d5=_vab.dot(_vcp);var d6=_vac.dot(_vcp);if(d6>=0&&d5<=d6){// vertex region of C; barycentric coords (0, 0, 1)
  237. return target.copy(c);}var vb=d5*d2-d1*d6;if(vb<=0&&d2>=0&&d6<=0){w=d2/(d2-d6);// edge region of AC; barycentric coords (1-w, 0, w)
  238. return target.copy(a).addScaledVector(_vac,w);}var va=d3*d6-d5*d4;if(va<=0&&d4-d3>=0&&d5-d6>=0){_vbc.subVectors(c,b);w=(d4-d3)/(d4-d3+(d5-d6));// edge region of BC; barycentric coords (0, 1-w, w)
  239. return target.copy(b).addScaledVector(_vbc,w);// edge region of BC
  240. }// face region
  241. var denom=1/(va+vb+vc);// u = va * denom
  242. v=vb*denom;w=vc*denom;return target.copy(a).addScaledVector(_vab,v).addScaledVector(_vac,w);}equals(triangle){return triangle.a.equals(this.a)&&triangle.b.equals(this.b)&&triangle.c.equals(this.c);}}var _colorKeywords={'aliceblue':0xF0F8FF,'antiquewhite':0xFAEBD7,'aqua':0x00FFFF,'aquamarine':0x7FFFD4,'azure':0xF0FFFF,'beige':0xF5F5DC,'bisque':0xFFE4C4,'black':0x000000,'blanchedalmond':0xFFEBCD,'blue':0x0000FF,'blueviolet':0x8A2BE2,'brown':0xA52A2A,'burlywood':0xDEB887,'cadetblue':0x5F9EA0,'chartreuse':0x7FFF00,'chocolate':0xD2691E,'coral':0xFF7F50,'cornflowerblue':0x6495ED,'cornsilk':0xFFF8DC,'crimson':0xDC143C,'cyan':0x00FFFF,'darkblue':0x00008B,'darkcyan':0x008B8B,'darkgoldenrod':0xB8860B,'darkgray':0xA9A9A9,'darkgreen':0x006400,'darkgrey':0xA9A9A9,'darkkhaki':0xBDB76B,'darkmagenta':0x8B008B,'darkolivegreen':0x556B2F,'darkorange':0xFF8C00,'darkorchid':0x9932CC,'darkred':0x8B0000,'darksalmon':0xE9967A,'darkseagreen':0x8FBC8F,'darkslateblue':0x483D8B,'darkslategray':0x2F4F4F,'darkslategrey':0x2F4F4F,'darkturquoise':0x00CED1,'darkviolet':0x9400D3,'deeppink':0xFF1493,'deepskyblue':0x00BFFF,'dimgray':0x696969,'dimgrey':0x696969,'dodgerblue':0x1E90FF,'firebrick':0xB22222,'floralwhite':0xFFFAF0,'forestgreen':0x228B22,'fuchsia':0xFF00FF,'gainsboro':0xDCDCDC,'ghostwhite':0xF8F8FF,'gold':0xFFD700,'goldenrod':0xDAA520,'gray':0x808080,'green':0x008000,'greenyellow':0xADFF2F,'grey':0x808080,'honeydew':0xF0FFF0,'hotpink':0xFF69B4,'indianred':0xCD5C5C,'indigo':0x4B0082,'ivory':0xFFFFF0,'khaki':0xF0E68C,'lavender':0xE6E6FA,'lavenderblush':0xFFF0F5,'lawngreen':0x7CFC00,'lemonchiffon':0xFFFACD,'lightblue':0xADD8E6,'lightcoral':0xF08080,'lightcyan':0xE0FFFF,'lightgoldenrodyellow':0xFAFAD2,'lightgray':0xD3D3D3,'lightgreen':0x90EE90,'lightgrey':0xD3D3D3,'lightpink':0xFFB6C1,'lightsalmon':0xFFA07A,'lightseagreen':0x20B2AA,'lightskyblue':0x87CEFA,'lightslategray':0x778899,'lightslategrey':0x778899,'lightsteelblue':0xB0C4DE,'lightyellow':0xFFFFE0,'lime':0x00FF00,'limegreen':0x32CD32,'linen':0xFAF0E6,'magenta':0xFF00FF,'maroon':0x800000,'mediumaquamarine':0x66CDAA,'mediumblue':0x0000CD,'mediumorchid':0xBA55D3,'mediumpurple':0x9370DB,'mediumseagreen':0x3CB371,'mediumslateblue':0x7B68EE,'mediumspringgreen':0x00FA9A,'mediumturquoise':0x48D1CC,'mediumvioletred':0xC71585,'midnightblue':0x191970,'mintcream':0xF5FFFA,'mistyrose':0xFFE4E1,'moccasin':0xFFE4B5,'navajowhite':0xFFDEAD,'navy':0x000080,'oldlace':0xFDF5E6,'olive':0x808000,'olivedrab':0x6B8E23,'orange':0xFFA500,'orangered':0xFF4500,'orchid':0xDA70D6,'palegoldenrod':0xEEE8AA,'palegreen':0x98FB98,'paleturquoise':0xAFEEEE,'palevioletred':0xDB7093,'papayawhip':0xFFEFD5,'peachpuff':0xFFDAB9,'peru':0xCD853F,'pink':0xFFC0CB,'plum':0xDDA0DD,'powderblue':0xB0E0E6,'purple':0x800080,'rebeccapurple':0x663399,'red':0xFF0000,'rosybrown':0xBC8F8F,'royalblue':0x4169E1,'saddlebrown':0x8B4513,'salmon':0xFA8072,'sandybrown':0xF4A460,'seagreen':0x2E8B57,'seashell':0xFFF5EE,'sienna':0xA0522D,'silver':0xC0C0C0,'skyblue':0x87CEEB,'slateblue':0x6A5ACD,'slategray':0x708090,'slategrey':0x708090,'snow':0xFFFAFA,'springgreen':0x00FF7F,'steelblue':0x4682B4,'tan':0xD2B48C,'teal':0x008080,'thistle':0xD8BFD8,'tomato':0xFF6347,'turquoise':0x40E0D0,'violet':0xEE82EE,'wheat':0xF5DEB3,'white':0xFFFFFF,'whitesmoke':0xF5F5F5,'yellow':0xFFFF00,'yellowgreen':0x9ACD32};var _hslA={h:0,s:0,l:0};var _hslB={h:0,s:0,l:0};function hue2rgb(p,q,t){if(t<0)t+=1;if(t>1)t-=1;if(t<1/6)return p+(q-p)*6*t;if(t<1/2)return q;if(t<2/3)return p+(q-p)*6*(2/3-t);return p;}function SRGBToLinear(c){return c<0.04045?c*0.0773993808:Math.pow(c*0.9478672986+0.0521327014,2.4);}function LinearToSRGB(c){return c<0.0031308?c*12.92:1.055*Math.pow(c,0.41666)-0.055;}class Color{constructor(r,g,b){Object.defineProperty(this,'isColor',{value:true});if(g===undefined&&b===undefined){// r is THREE.Color, hex or string
  243. return this.set(r);}return this.setRGB(r,g,b);}set(value){if(value&&value.isColor){this.copy(value);}else if(typeof value==='number'){this.setHex(value);}else if(typeof value==='string'){this.setStyle(value);}return this;}setScalar(scalar){this.r=scalar;this.g=scalar;this.b=scalar;return this;}setHex(hex){hex=Math.floor(hex);this.r=(hex>>16&255)/255;this.g=(hex>>8&255)/255;this.b=(hex&255)/255;return this;}setRGB(r,g,b){this.r=r;this.g=g;this.b=b;return this;}setHSL(h,s,l){// h,s,l ranges are in 0.0 - 1.0
  244. h=MathUtils.euclideanModulo(h,1);s=MathUtils.clamp(s,0,1);l=MathUtils.clamp(l,0,1);if(s===0){this.r=this.g=this.b=l;}else {var p=l<=0.5?l*(1+s):l+s-l*s;var q=2*l-p;this.r=hue2rgb(q,p,h+1/3);this.g=hue2rgb(q,p,h);this.b=hue2rgb(q,p,h-1/3);}return this;}setStyle(style){function handleAlpha(string){if(string===undefined)return;if(parseFloat(string)<1){console.warn('THREE.Color: Alpha component of '+style+' will be ignored.');}}var m;if(m=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(style)){// rgb / hsl
  245. var color;var name=m[1];var components=m[2];switch(name){case'rgb':case'rgba':if(color=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)){// rgb(255,0,0) rgba(255,0,0,0.5)
  246. this.r=Math.min(255,parseInt(color[1],10))/255;this.g=Math.min(255,parseInt(color[2],10))/255;this.b=Math.min(255,parseInt(color[3],10))/255;handleAlpha(color[4]);return this;}if(color=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)){// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
  247. this.r=Math.min(100,parseInt(color[1],10))/100;this.g=Math.min(100,parseInt(color[2],10))/100;this.b=Math.min(100,parseInt(color[3],10))/100;handleAlpha(color[4]);return this;}break;case'hsl':case'hsla':if(color=/^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)){// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
  248. var h=parseFloat(color[1])/360;var s=parseInt(color[2],10)/100;var l=parseInt(color[3],10)/100;handleAlpha(color[4]);return this.setHSL(h,s,l);}break;}}else if(m=/^\#([A-Fa-f\d]+)$/.exec(style)){// hex color
  249. var hex=m[1];var size=hex.length;if(size===3){// #ff0
  250. this.r=parseInt(hex.charAt(0)+hex.charAt(0),16)/255;this.g=parseInt(hex.charAt(1)+hex.charAt(1),16)/255;this.b=parseInt(hex.charAt(2)+hex.charAt(2),16)/255;return this;}else if(size===6){// #ff0000
  251. this.r=parseInt(hex.charAt(0)+hex.charAt(1),16)/255;this.g=parseInt(hex.charAt(2)+hex.charAt(3),16)/255;this.b=parseInt(hex.charAt(4)+hex.charAt(5),16)/255;return this;}}if(style&&style.length>0){return this.setColorName(style);}return this;}setColorName(style){// color keywords
  252. var hex=_colorKeywords[style];if(hex!==undefined){// red
  253. this.setHex(hex);}else {// unknown color
  254. console.warn('THREE.Color: Unknown color '+style);}return this;}clone(){return new this.constructor(this.r,this.g,this.b);}copy(color){this.r=color.r;this.g=color.g;this.b=color.b;return this;}copyGammaToLinear(color){var gammaFactor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:2.0;this.r=Math.pow(color.r,gammaFactor);this.g=Math.pow(color.g,gammaFactor);this.b=Math.pow(color.b,gammaFactor);return this;}copyLinearToGamma(color){var gammaFactor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:2.0;var safeInverse=gammaFactor>0?1.0/gammaFactor:1.0;this.r=Math.pow(color.r,safeInverse);this.g=Math.pow(color.g,safeInverse);this.b=Math.pow(color.b,safeInverse);return this;}convertGammaToLinear(gammaFactor){this.copyGammaToLinear(this,gammaFactor);return this;}convertLinearToGamma(gammaFactor){this.copyLinearToGamma(this,gammaFactor);return this;}copySRGBToLinear(color){this.r=SRGBToLinear(color.r);this.g=SRGBToLinear(color.g);this.b=SRGBToLinear(color.b);return this;}copyLinearToSRGB(color){this.r=LinearToSRGB(color.r);this.g=LinearToSRGB(color.g);this.b=LinearToSRGB(color.b);return this;}convertSRGBToLinear(){this.copySRGBToLinear(this);return this;}convertLinearToSRGB(){this.copyLinearToSRGB(this);return this;}getHex(){return this.r*255<<16^this.g*255<<8^this.b*255<<0;}getHexString(){return ('000000'+this.getHex().toString(16)).slice(-6);}getHSL(target){// h,s,l ranges are in 0.0 - 1.0
  255. if(target===undefined){console.warn('THREE.Color: .getHSL() target is now required');target={h:0,s:0,l:0};}var r=this.r,g=this.g,b=this.b;var max=Math.max(r,g,b);var min=Math.min(r,g,b);var hue,saturation;var lightness=(min+max)/2.0;if(min===max){hue=0;saturation=0;}else {var delta=max-min;saturation=lightness<=0.5?delta/(max+min):delta/(2-max-min);switch(max){case r:hue=(g-b)/delta+(g<b?6:0);break;case g:hue=(b-r)/delta+2;break;case b:hue=(r-g)/delta+4;break;}hue/=6;}target.h=hue;target.s=saturation;target.l=lightness;return target;}getStyle(){return 'rgb('+(this.r*255|0)+','+(this.g*255|0)+','+(this.b*255|0)+')';}offsetHSL(h,s,l){this.getHSL(_hslA);_hslA.h+=h;_hslA.s+=s;_hslA.l+=l;this.setHSL(_hslA.h,_hslA.s,_hslA.l);return this;}add(color){this.r+=color.r;this.g+=color.g;this.b+=color.b;return this;}addColors(color1,color2){this.r=color1.r+color2.r;this.g=color1.g+color2.g;this.b=color1.b+color2.b;return this;}addScalar(s){this.r+=s;this.g+=s;this.b+=s;return this;}sub(color){this.r=Math.max(0,this.r-color.r);this.g=Math.max(0,this.g-color.g);this.b=Math.max(0,this.b-color.b);return this;}multiply(color){this.r*=color.r;this.g*=color.g;this.b*=color.b;return this;}multiplyScalar(s){this.r*=s;this.g*=s;this.b*=s;return this;}lerp(color,alpha){this.r+=(color.r-this.r)*alpha;this.g+=(color.g-this.g)*alpha;this.b+=(color.b-this.b)*alpha;return this;}lerpHSL(color,alpha){this.getHSL(_hslA);color.getHSL(_hslB);var h=MathUtils.lerp(_hslA.h,_hslB.h,alpha);var s=MathUtils.lerp(_hslA.s,_hslB.s,alpha);var l=MathUtils.lerp(_hslA.l,_hslB.l,alpha);this.setHSL(h,s,l);return this;}equals(c){return c.r===this.r&&c.g===this.g&&c.b===this.b;}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.r=array[offset];this.g=array[offset+1];this.b=array[offset+2];return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;array[offset]=this.r;array[offset+1]=this.g;array[offset+2]=this.b;return array;}fromBufferAttribute(attribute,index){this.r=attribute.getX(index);this.g=attribute.getY(index);this.b=attribute.getZ(index);if(attribute.normalized===true){// assuming Uint8Array
  256. this.r/=255;this.g/=255;this.b/=255;}return this;}toJSON(){return this.getHex();}}Color.NAMES=_colorKeywords;Color.prototype.r=1;Color.prototype.g=1;Color.prototype.b=1;class Face3{constructor(a,b,c,normal,color){var materialIndex=arguments.length>5&&arguments[5]!==undefined?arguments[5]:0;this.a=a;this.b=b;this.c=c;this.normal=normal&&normal.isVector3?normal:new Vector3();this.vertexNormals=Array.isArray(normal)?normal:[];this.color=color&&color.isColor?color:new Color();this.vertexColors=Array.isArray(color)?color:[];this.materialIndex=materialIndex;}clone(){return new this.constructor().copy(this);}copy(source){this.a=source.a;this.b=source.b;this.c=source.c;this.normal.copy(source.normal);this.color.copy(source.color);this.materialIndex=source.materialIndex;for(var _i25=0,il=source.vertexNormals.length;_i25<il;_i25++){this.vertexNormals[_i25]=source.vertexNormals[_i25].clone();}for(var _i26=0,_il=source.vertexColors.length;_i26<_il;_i26++){this.vertexColors[_i26]=source.vertexColors[_i26].clone();}return this;}}var materialId=0;function Material(){Object.defineProperty(this,'id',{value:materialId++});this.uuid=MathUtils.generateUUID();this.name='';this.type='Material';this.fog=true;this.blending=NormalBlending;this.side=FrontSide;this.flatShading=false;this.vertexColors=false;this.opacity=1;this.transparent=false;this.blendSrc=SrcAlphaFactor;this.blendDst=OneMinusSrcAlphaFactor;this.blendEquation=AddEquation;this.blendSrcAlpha=null;this.blendDstAlpha=null;this.blendEquationAlpha=null;this.depthFunc=LessEqualDepth;this.depthTest=true;this.depthWrite=true;this.stencilWriteMask=0xff;this.stencilFunc=AlwaysStencilFunc;this.stencilRef=0;this.stencilFuncMask=0xff;this.stencilFail=KeepStencilOp;this.stencilZFail=KeepStencilOp;this.stencilZPass=KeepStencilOp;this.stencilWrite=false;this.clippingPlanes=null;this.clipIntersection=false;this.clipShadows=false;this.shadowSide=null;this.colorWrite=true;this.precision=null;// override the renderer's default precision for this material
  257. this.polygonOffset=false;this.polygonOffsetFactor=0;this.polygonOffsetUnits=0;this.dithering=false;this.alphaTest=0;this.premultipliedAlpha=false;this.visible=true;this.toneMapped=true;this.userData={};this.version=0;}Material.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:Material,isMaterial:true,onBeforeCompile:function onBeforeCompile(/* shaderobject, renderer */){},customProgramCacheKey:function customProgramCacheKey(){return this.onBeforeCompile.toString();},setValues:function setValues(values){if(values===undefined)return;for(var key in values){var newValue=values[key];if(newValue===undefined){console.warn('THREE.Material: \''+key+'\' parameter is undefined.');continue;}// for backward compatability if shading is set in the constructor
  258. if(key==='shading'){console.warn('THREE.'+this.type+': .shading has been removed. Use the boolean .flatShading instead.');this.flatShading=newValue===FlatShading$1?true:false;continue;}var currentValue=this[key];if(currentValue===undefined){//console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
  259. continue;}if(currentValue&&currentValue.isColor){currentValue.set(newValue);}else if(currentValue&&currentValue.isVector3&&newValue&&newValue.isVector3){currentValue.copy(newValue);}else {this[key]=newValue;}}},toJSON:function toJSON(meta){var isRoot=meta===undefined||typeof meta==='string';if(isRoot){meta={textures:{},images:{}};}var data={metadata:{version:4.5,type:'Material',generator:'Material.toJSON'}};// standard Material serialization
  260. data.uuid=this.uuid;data.type=this.type;if(this.name!=='')data.name=this.name;if(this.color&&this.color.isColor)data.color=this.color.getHex();if(this.roughness!==undefined)data.roughness=this.roughness;if(this.metalness!==undefined)data.metalness=this.metalness;if(this.sheen&&this.sheen.isColor)data.sheen=this.sheen.getHex();if(this.emissive&&this.emissive.isColor)data.emissive=this.emissive.getHex();if(this.emissiveIntensity&&this.emissiveIntensity!==1)data.emissiveIntensity=this.emissiveIntensity;if(this.specular&&this.specular.isColor)data.specular=this.specular.getHex();if(this.shininess!==undefined)data.shininess=this.shininess;if(this.clearcoat!==undefined)data.clearcoat=this.clearcoat;if(this.clearcoatRoughness!==undefined)data.clearcoatRoughness=this.clearcoatRoughness;if(this.clearcoatMap&&this.clearcoatMap.isTexture){data.clearcoatMap=this.clearcoatMap.toJSON(meta).uuid;}if(this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture){data.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(meta).uuid;}if(this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture){data.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(meta).uuid;data.clearcoatNormalScale=this.clearcoatNormalScale.toArray();}if(this.map&&this.map.isTexture)data.map=this.map.toJSON(meta).uuid;if(this.matcap&&this.matcap.isTexture)data.matcap=this.matcap.toJSON(meta).uuid;if(this.alphaMap&&this.alphaMap.isTexture)data.alphaMap=this.alphaMap.toJSON(meta).uuid;if(this.lightMap&&this.lightMap.isTexture)data.lightMap=this.lightMap.toJSON(meta).uuid;if(this.aoMap&&this.aoMap.isTexture){data.aoMap=this.aoMap.toJSON(meta).uuid;data.aoMapIntensity=this.aoMapIntensity;}if(this.bumpMap&&this.bumpMap.isTexture){data.bumpMap=this.bumpMap.toJSON(meta).uuid;data.bumpScale=this.bumpScale;}if(this.normalMap&&this.normalMap.isTexture){data.normalMap=this.normalMap.toJSON(meta).uuid;data.normalMapType=this.normalMapType;data.normalScale=this.normalScale.toArray();}if(this.displacementMap&&this.displacementMap.isTexture){data.displacementMap=this.displacementMap.toJSON(meta).uuid;data.displacementScale=this.displacementScale;data.displacementBias=this.displacementBias;}if(this.roughnessMap&&this.roughnessMap.isTexture)data.roughnessMap=this.roughnessMap.toJSON(meta).uuid;if(this.metalnessMap&&this.metalnessMap.isTexture)data.metalnessMap=this.metalnessMap.toJSON(meta).uuid;if(this.emissiveMap&&this.emissiveMap.isTexture)data.emissiveMap=this.emissiveMap.toJSON(meta).uuid;if(this.specularMap&&this.specularMap.isTexture)data.specularMap=this.specularMap.toJSON(meta).uuid;if(this.envMap&&this.envMap.isTexture){data.envMap=this.envMap.toJSON(meta).uuid;data.reflectivity=this.reflectivity;// Scale behind envMap
  261. data.refractionRatio=this.refractionRatio;if(this.combine!==undefined)data.combine=this.combine;if(this.envMapIntensity!==undefined)data.envMapIntensity=this.envMapIntensity;}if(this.gradientMap&&this.gradientMap.isTexture){data.gradientMap=this.gradientMap.toJSON(meta).uuid;}if(this.size!==undefined)data.size=this.size;if(this.sizeAttenuation!==undefined)data.sizeAttenuation=this.sizeAttenuation;if(this.blending!==NormalBlending)data.blending=this.blending;if(this.flatShading===true)data.flatShading=this.flatShading;if(this.side!==FrontSide)data.side=this.side;if(this.vertexColors)data.vertexColors=true;if(this.opacity<1)data.opacity=this.opacity;if(this.transparent===true)data.transparent=this.transparent;data.depthFunc=this.depthFunc;data.depthTest=this.depthTest;data.depthWrite=this.depthWrite;data.stencilWrite=this.stencilWrite;data.stencilWriteMask=this.stencilWriteMask;data.stencilFunc=this.stencilFunc;data.stencilRef=this.stencilRef;data.stencilFuncMask=this.stencilFuncMask;data.stencilFail=this.stencilFail;data.stencilZFail=this.stencilZFail;data.stencilZPass=this.stencilZPass;// rotation (SpriteMaterial)
  262. if(this.rotation&&this.rotation!==0)data.rotation=this.rotation;if(this.polygonOffset===true)data.polygonOffset=true;if(this.polygonOffsetFactor!==0)data.polygonOffsetFactor=this.polygonOffsetFactor;if(this.polygonOffsetUnits!==0)data.polygonOffsetUnits=this.polygonOffsetUnits;if(this.linewidth&&this.linewidth!==1)data.linewidth=this.linewidth;if(this.dashSize!==undefined)data.dashSize=this.dashSize;if(this.gapSize!==undefined)data.gapSize=this.gapSize;if(this.scale!==undefined)data.scale=this.scale;if(this.dithering===true)data.dithering=true;if(this.alphaTest>0)data.alphaTest=this.alphaTest;if(this.premultipliedAlpha===true)data.premultipliedAlpha=this.premultipliedAlpha;if(this.wireframe===true)data.wireframe=this.wireframe;if(this.wireframeLinewidth>1)data.wireframeLinewidth=this.wireframeLinewidth;if(this.wireframeLinecap!=='round')data.wireframeLinecap=this.wireframeLinecap;if(this.wireframeLinejoin!=='round')data.wireframeLinejoin=this.wireframeLinejoin;if(this.morphTargets===true)data.morphTargets=true;if(this.morphNormals===true)data.morphNormals=true;if(this.skinning===true)data.skinning=true;if(this.visible===false)data.visible=false;if(this.toneMapped===false)data.toneMapped=false;if(JSON.stringify(this.userData)!=='{}')data.userData=this.userData;// TODO: Copied from Object3D.toJSON
  263. function extractFromCache(cache){var values=[];for(var key in cache){var _data=cache[key];delete _data.metadata;values.push(_data);}return values;}if(isRoot){var textures=extractFromCache(meta.textures);var images=extractFromCache(meta.images);if(textures.length>0)data.textures=textures;if(images.length>0)data.images=images;}return data;},clone:function clone(){return new this.constructor().copy(this);},copy:function copy(source){this.name=source.name;this.fog=source.fog;this.blending=source.blending;this.side=source.side;this.flatShading=source.flatShading;this.vertexColors=source.vertexColors;this.opacity=source.opacity;this.transparent=source.transparent;this.blendSrc=source.blendSrc;this.blendDst=source.blendDst;this.blendEquation=source.blendEquation;this.blendSrcAlpha=source.blendSrcAlpha;this.blendDstAlpha=source.blendDstAlpha;this.blendEquationAlpha=source.blendEquationAlpha;this.depthFunc=source.depthFunc;this.depthTest=source.depthTest;this.depthWrite=source.depthWrite;this.stencilWriteMask=source.stencilWriteMask;this.stencilFunc=source.stencilFunc;this.stencilRef=source.stencilRef;this.stencilFuncMask=source.stencilFuncMask;this.stencilFail=source.stencilFail;this.stencilZFail=source.stencilZFail;this.stencilZPass=source.stencilZPass;this.stencilWrite=source.stencilWrite;var srcPlanes=source.clippingPlanes;var dstPlanes=null;if(srcPlanes!==null){var n=srcPlanes.length;dstPlanes=new Array(n);for(var _i27=0;_i27!==n;++_i27){dstPlanes[_i27]=srcPlanes[_i27].clone();}}this.clippingPlanes=dstPlanes;this.clipIntersection=source.clipIntersection;this.clipShadows=source.clipShadows;this.shadowSide=source.shadowSide;this.colorWrite=source.colorWrite;this.precision=source.precision;this.polygonOffset=source.polygonOffset;this.polygonOffsetFactor=source.polygonOffsetFactor;this.polygonOffsetUnits=source.polygonOffsetUnits;this.dithering=source.dithering;this.alphaTest=source.alphaTest;this.premultipliedAlpha=source.premultipliedAlpha;this.visible=source.visible;this.toneMapped=source.toneMapped;this.userData=JSON.parse(JSON.stringify(source.userData));return this;},dispose:function dispose(){this.dispatchEvent({type:'dispose'});}});Object.defineProperty(Material.prototype,'needsUpdate',{set:function set(value){if(value===true)this.version++;}});/**
  264. * parameters = {
  265. * color: <hex>,
  266. * opacity: <float>,
  267. * map: new THREE.Texture( <Image> ),
  268. *
  269. * lightMap: new THREE.Texture( <Image> ),
  270. * lightMapIntensity: <float>
  271. *
  272. * aoMap: new THREE.Texture( <Image> ),
  273. * aoMapIntensity: <float>
  274. *
  275. * specularMap: new THREE.Texture( <Image> ),
  276. *
  277. * alphaMap: new THREE.Texture( <Image> ),
  278. *
  279. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  280. * combine: THREE.Multiply,
  281. * reflectivity: <float>,
  282. * refractionRatio: <float>,
  283. *
  284. * depthTest: <bool>,
  285. * depthWrite: <bool>,
  286. *
  287. * wireframe: <boolean>,
  288. * wireframeLinewidth: <float>,
  289. *
  290. * skinning: <bool>,
  291. * morphTargets: <bool>
  292. * }
  293. */function MeshBasicMaterial(parameters){Material.call(this);this.type='MeshBasicMaterial';this.color=new Color(0xffffff);// emissive
  294. this.map=null;this.lightMap=null;this.lightMapIntensity=1.0;this.aoMap=null;this.aoMapIntensity=1.0;this.specularMap=null;this.alphaMap=null;this.envMap=null;this.combine=MultiplyOperation;this.reflectivity=1;this.refractionRatio=0.98;this.wireframe=false;this.wireframeLinewidth=1;this.wireframeLinecap='round';this.wireframeLinejoin='round';this.skinning=false;this.morphTargets=false;this.setValues(parameters);}MeshBasicMaterial.prototype=Object.create(Material.prototype);MeshBasicMaterial.prototype.constructor=MeshBasicMaterial;MeshBasicMaterial.prototype.isMeshBasicMaterial=true;MeshBasicMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.map=source.map;this.lightMap=source.lightMap;this.lightMapIntensity=source.lightMapIntensity;this.aoMap=source.aoMap;this.aoMapIntensity=source.aoMapIntensity;this.specularMap=source.specularMap;this.alphaMap=source.alphaMap;this.envMap=source.envMap;this.combine=source.combine;this.reflectivity=source.reflectivity;this.refractionRatio=source.refractionRatio;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.wireframeLinecap=source.wireframeLinecap;this.wireframeLinejoin=source.wireframeLinejoin;this.skinning=source.skinning;this.morphTargets=source.morphTargets;return this;};var _vector$3=new Vector3();var _vector2$1=new Vector2();function BufferAttribute(array,itemSize,normalized){if(Array.isArray(array)){throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.');}this.name='';this.array=array;this.itemSize=itemSize;this.count=array!==undefined?array.length/itemSize:0;this.normalized=normalized===true;this.usage=StaticDrawUsage;this.updateRange={offset:0,count:-1};this.version=0;}Object.defineProperty(BufferAttribute.prototype,'needsUpdate',{set:function set(value){if(value===true)this.version++;}});Object.assign(BufferAttribute.prototype,{isBufferAttribute:true,onUploadCallback:function onUploadCallback(){},setUsage:function setUsage(value){this.usage=value;return this;},copy:function copy(source){this.name=source.name;this.array=new source.array.constructor(source.array);this.itemSize=source.itemSize;this.count=source.count;this.normalized=source.normalized;this.usage=source.usage;return this;},copyAt:function copyAt(index1,attribute,index2){index1*=this.itemSize;index2*=attribute.itemSize;for(var _i28=0,l=this.itemSize;_i28<l;_i28++){this.array[index1+_i28]=attribute.array[index2+_i28];}return this;},copyArray:function copyArray(array){this.array.set(array);return this;},copyColorsArray:function copyColorsArray(colors){var array=this.array;var offset=0;for(var _i29=0,l=colors.length;_i29<l;_i29++){var color=colors[_i29];if(color===undefined){console.warn('THREE.BufferAttribute.copyColorsArray(): color is undefined',_i29);color=new Color();}array[offset++]=color.r;array[offset++]=color.g;array[offset++]=color.b;}return this;},copyVector2sArray:function copyVector2sArray(vectors){var array=this.array;var offset=0;for(var _i30=0,l=vectors.length;_i30<l;_i30++){var vector=vectors[_i30];if(vector===undefined){console.warn('THREE.BufferAttribute.copyVector2sArray(): vector is undefined',_i30);vector=new Vector2();}array[offset++]=vector.x;array[offset++]=vector.y;}return this;},copyVector3sArray:function copyVector3sArray(vectors){var array=this.array;var offset=0;for(var _i31=0,l=vectors.length;_i31<l;_i31++){var vector=vectors[_i31];if(vector===undefined){console.warn('THREE.BufferAttribute.copyVector3sArray(): vector is undefined',_i31);vector=new Vector3();}array[offset++]=vector.x;array[offset++]=vector.y;array[offset++]=vector.z;}return this;},copyVector4sArray:function copyVector4sArray(vectors){var array=this.array;var offset=0;for(var _i32=0,l=vectors.length;_i32<l;_i32++){var vector=vectors[_i32];if(vector===undefined){console.warn('THREE.BufferAttribute.copyVector4sArray(): vector is undefined',_i32);vector=new Vector4();}array[offset++]=vector.x;array[offset++]=vector.y;array[offset++]=vector.z;array[offset++]=vector.w;}return this;},applyMatrix3:function applyMatrix3(m){if(this.itemSize===2){for(var _i33=0,l=this.count;_i33<l;_i33++){_vector2$1.fromBufferAttribute(this,_i33);_vector2$1.applyMatrix3(m);this.setXY(_i33,_vector2$1.x,_vector2$1.y);}}else if(this.itemSize===3){for(var _i34=0,_l2=this.count;_i34<_l2;_i34++){_vector$3.fromBufferAttribute(this,_i34);_vector$3.applyMatrix3(m);this.setXYZ(_i34,_vector$3.x,_vector$3.y,_vector$3.z);}}return this;},applyMatrix4:function applyMatrix4(m){for(var _i35=0,l=this.count;_i35<l;_i35++){_vector$3.x=this.getX(_i35);_vector$3.y=this.getY(_i35);_vector$3.z=this.getZ(_i35);_vector$3.applyMatrix4(m);this.setXYZ(_i35,_vector$3.x,_vector$3.y,_vector$3.z);}return this;},applyNormalMatrix:function applyNormalMatrix(m){for(var _i36=0,l=this.count;_i36<l;_i36++){_vector$3.x=this.getX(_i36);_vector$3.y=this.getY(_i36);_vector$3.z=this.getZ(_i36);_vector$3.applyNormalMatrix(m);this.setXYZ(_i36,_vector$3.x,_vector$3.y,_vector$3.z);}return this;},transformDirection:function transformDirection(m){for(var _i37=0,l=this.count;_i37<l;_i37++){_vector$3.x=this.getX(_i37);_vector$3.y=this.getY(_i37);_vector$3.z=this.getZ(_i37);_vector$3.transformDirection(m);this.setXYZ(_i37,_vector$3.x,_vector$3.y,_vector$3.z);}return this;},set:function set(value){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.array.set(value,offset);return this;},getX:function getX(index){return this.array[index*this.itemSize];},setX:function setX(index,x){this.array[index*this.itemSize]=x;return this;},getY:function getY(index){return this.array[index*this.itemSize+1];},setY:function setY(index,y){this.array[index*this.itemSize+1]=y;return this;},getZ:function getZ(index){return this.array[index*this.itemSize+2];},setZ:function setZ(index,z){this.array[index*this.itemSize+2]=z;return this;},getW:function getW(index){return this.array[index*this.itemSize+3];},setW:function setW(index,w){this.array[index*this.itemSize+3]=w;return this;},setXY:function setXY(index,x,y){index*=this.itemSize;this.array[index+0]=x;this.array[index+1]=y;return this;},setXYZ:function setXYZ(index,x,y,z){index*=this.itemSize;this.array[index+0]=x;this.array[index+1]=y;this.array[index+2]=z;return this;},setXYZW:function setXYZW(index,x,y,z,w){index*=this.itemSize;this.array[index+0]=x;this.array[index+1]=y;this.array[index+2]=z;this.array[index+3]=w;return this;},onUpload:function onUpload(callback){this.onUploadCallback=callback;return this;},clone:function clone(){return new this.constructor(this.array,this.itemSize).copy(this);},toJSON:function toJSON(){return {itemSize:this.itemSize,type:this.array.constructor.name,array:Array.prototype.slice.call(this.array),normalized:this.normalized};}});//
  295. function Int8BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Int8Array(array),itemSize,normalized);}Int8BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Int8BufferAttribute.prototype.constructor=Int8BufferAttribute;function Uint8BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Uint8Array(array),itemSize,normalized);}Uint8BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Uint8BufferAttribute.prototype.constructor=Uint8BufferAttribute;function Uint8ClampedBufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Uint8ClampedArray(array),itemSize,normalized);}Uint8ClampedBufferAttribute.prototype=Object.create(BufferAttribute.prototype);Uint8ClampedBufferAttribute.prototype.constructor=Uint8ClampedBufferAttribute;function Int16BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Int16Array(array),itemSize,normalized);}Int16BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Int16BufferAttribute.prototype.constructor=Int16BufferAttribute;function Uint16BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Uint16Array(array),itemSize,normalized);}Uint16BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Uint16BufferAttribute.prototype.constructor=Uint16BufferAttribute;function Int32BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Int32Array(array),itemSize,normalized);}Int32BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Int32BufferAttribute.prototype.constructor=Int32BufferAttribute;function Uint32BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Uint32Array(array),itemSize,normalized);}Uint32BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Uint32BufferAttribute.prototype.constructor=Uint32BufferAttribute;function Float16BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Uint16Array(array),itemSize,normalized);}Float16BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Float16BufferAttribute.prototype.constructor=Float16BufferAttribute;Float16BufferAttribute.prototype.isFloat16BufferAttribute=true;function Float32BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Float32Array(array),itemSize,normalized);}Float32BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Float32BufferAttribute.prototype.constructor=Float32BufferAttribute;function Float64BufferAttribute(array,itemSize,normalized){BufferAttribute.call(this,new Float64Array(array),itemSize,normalized);}Float64BufferAttribute.prototype=Object.create(BufferAttribute.prototype);Float64BufferAttribute.prototype.constructor=Float64BufferAttribute;class DirectGeometry{constructor(){this.vertices=[];this.normals=[];this.colors=[];this.uvs=[];this.uvs2=[];this.groups=[];this.morphTargets={};this.skinWeights=[];this.skinIndices=[];// this.lineDistances = [];
  296. this.boundingBox=null;this.boundingSphere=null;// update flags
  297. this.verticesNeedUpdate=false;this.normalsNeedUpdate=false;this.colorsNeedUpdate=false;this.uvsNeedUpdate=false;this.groupsNeedUpdate=false;}computeGroups(geometry){var groups=[];var group,i;var materialIndex=undefined;var faces=geometry.faces;for(i=0;i<faces.length;i++){var face=faces[i];// materials
  298. if(face.materialIndex!==materialIndex){materialIndex=face.materialIndex;if(group!==undefined){group.count=i*3-group.start;groups.push(group);}group={start:i*3,materialIndex:materialIndex};}}if(group!==undefined){group.count=i*3-group.start;groups.push(group);}this.groups=groups;}fromGeometry(geometry){var faces=geometry.faces;var vertices=geometry.vertices;var faceVertexUvs=geometry.faceVertexUvs;var hasFaceVertexUv=faceVertexUvs[0]&&faceVertexUvs[0].length>0;var hasFaceVertexUv2=faceVertexUvs[1]&&faceVertexUvs[1].length>0;// morphs
  299. var morphTargets=geometry.morphTargets;var morphTargetsLength=morphTargets.length;var morphTargetsPosition;if(morphTargetsLength>0){morphTargetsPosition=[];for(var _i38=0;_i38<morphTargetsLength;_i38++){morphTargetsPosition[_i38]={name:morphTargets[_i38].name,data:[]};}this.morphTargets.position=morphTargetsPosition;}var morphNormals=geometry.morphNormals;var morphNormalsLength=morphNormals.length;var morphTargetsNormal;if(morphNormalsLength>0){morphTargetsNormal=[];for(var _i39=0;_i39<morphNormalsLength;_i39++){morphTargetsNormal[_i39]={name:morphNormals[_i39].name,data:[]};}this.morphTargets.normal=morphTargetsNormal;}// skins
  300. var skinIndices=geometry.skinIndices;var skinWeights=geometry.skinWeights;var hasSkinIndices=skinIndices.length===vertices.length;var hasSkinWeights=skinWeights.length===vertices.length;//
  301. if(vertices.length>0&&faces.length===0){console.error('THREE.DirectGeometry: Faceless geometries are not supported.');}for(var _i40=0;_i40<faces.length;_i40++){var face=faces[_i40];this.vertices.push(vertices[face.a],vertices[face.b],vertices[face.c]);var vertexNormals=face.vertexNormals;if(vertexNormals.length===3){this.normals.push(vertexNormals[0],vertexNormals[1],vertexNormals[2]);}else {var normal=face.normal;this.normals.push(normal,normal,normal);}var vertexColors=face.vertexColors;if(vertexColors.length===3){this.colors.push(vertexColors[0],vertexColors[1],vertexColors[2]);}else {var color=face.color;this.colors.push(color,color,color);}if(hasFaceVertexUv===true){var vertexUvs=faceVertexUvs[0][_i40];if(vertexUvs!==undefined){this.uvs.push(vertexUvs[0],vertexUvs[1],vertexUvs[2]);}else {console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ',_i40);this.uvs.push(new Vector2(),new Vector2(),new Vector2());}}if(hasFaceVertexUv2===true){var _vertexUvs=faceVertexUvs[1][_i40];if(_vertexUvs!==undefined){this.uvs2.push(_vertexUvs[0],_vertexUvs[1],_vertexUvs[2]);}else {console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ',_i40);this.uvs2.push(new Vector2(),new Vector2(),new Vector2());}}// morphs
  302. for(var j=0;j<morphTargetsLength;j++){var morphTarget=morphTargets[j].vertices;morphTargetsPosition[j].data.push(morphTarget[face.a],morphTarget[face.b],morphTarget[face.c]);}for(var _j=0;_j<morphNormalsLength;_j++){var morphNormal=morphNormals[_j].vertexNormals[_i40];morphTargetsNormal[_j].data.push(morphNormal.a,morphNormal.b,morphNormal.c);}// skins
  303. if(hasSkinIndices){this.skinIndices.push(skinIndices[face.a],skinIndices[face.b],skinIndices[face.c]);}if(hasSkinWeights){this.skinWeights.push(skinWeights[face.a],skinWeights[face.b],skinWeights[face.c]);}}this.computeGroups(geometry);this.verticesNeedUpdate=geometry.verticesNeedUpdate;this.normalsNeedUpdate=geometry.normalsNeedUpdate;this.colorsNeedUpdate=geometry.colorsNeedUpdate;this.uvsNeedUpdate=geometry.uvsNeedUpdate;this.groupsNeedUpdate=geometry.groupsNeedUpdate;if(geometry.boundingSphere!==null){this.boundingSphere=geometry.boundingSphere.clone();}if(geometry.boundingBox!==null){this.boundingBox=geometry.boundingBox.clone();}return this;}}function arrayMax(array){if(array.length===0)return -Infinity;var max=array[0];for(var _i41=1,l=array.length;_i41<l;++_i41){if(array[_i41]>max)max=array[_i41];}return max;}var TYPED_ARRAYS={Int8Array:Int8Array,Uint8Array:Uint8Array,// Workaround for IE11 pre KB2929437. See #11440
  304. Uint8ClampedArray:typeof Uint8ClampedArray!=='undefined'?Uint8ClampedArray:Uint8Array,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function getTypedArray(type,buffer){return new TYPED_ARRAYS[type](buffer);}var _bufferGeometryId=1;// BufferGeometry uses odd numbers as Id
  305. var _m1$2=new Matrix4();var _obj=new Object3D();var _offset=new Vector3();var _box$2=new Box3();var _boxMorphTargets=new Box3();var _vector$4=new Vector3();function BufferGeometry(){Object.defineProperty(this,'id',{value:_bufferGeometryId+=2});this.uuid=MathUtils.generateUUID();this.name='';this.type='BufferGeometry';this.index=null;this.attributes={};this.morphAttributes={};this.morphTargetsRelative=false;this.groups=[];this.boundingBox=null;this.boundingSphere=null;this.drawRange={start:0,count:Infinity};this.userData={};}BufferGeometry.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:BufferGeometry,isBufferGeometry:true,getIndex:function getIndex(){return this.index;},setIndex:function setIndex(index){if(Array.isArray(index)){this.index=new(arrayMax(index)>65535?Uint32BufferAttribute:Uint16BufferAttribute)(index,1);}else {this.index=index;}return this;},getAttribute:function getAttribute(name){return this.attributes[name];},setAttribute:function setAttribute(name,attribute){this.attributes[name]=attribute;return this;},deleteAttribute:function deleteAttribute(name){delete this.attributes[name];return this;},hasAttribute:function hasAttribute(name){return this.attributes[name]!==undefined;},addGroup:function addGroup(start,count){var materialIndex=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;this.groups.push({start:start,count:count,materialIndex:materialIndex});},clearGroups:function clearGroups(){this.groups=[];},setDrawRange:function setDrawRange(start,count){this.drawRange.start=start;this.drawRange.count=count;},applyMatrix4:function applyMatrix4(matrix){var position=this.attributes.position;if(position!==undefined){position.applyMatrix4(matrix);position.needsUpdate=true;}var normal=this.attributes.normal;if(normal!==undefined){var normalMatrix=new Matrix3().getNormalMatrix(matrix);normal.applyNormalMatrix(normalMatrix);normal.needsUpdate=true;}var tangent=this.attributes.tangent;if(tangent!==undefined){tangent.transformDirection(matrix);tangent.needsUpdate=true;}if(this.boundingBox!==null){this.computeBoundingBox();}if(this.boundingSphere!==null){this.computeBoundingSphere();}return this;},rotateX:function rotateX(angle){// rotate geometry around world x-axis
  306. _m1$2.makeRotationX(angle);this.applyMatrix4(_m1$2);return this;},rotateY:function rotateY(angle){// rotate geometry around world y-axis
  307. _m1$2.makeRotationY(angle);this.applyMatrix4(_m1$2);return this;},rotateZ:function rotateZ(angle){// rotate geometry around world z-axis
  308. _m1$2.makeRotationZ(angle);this.applyMatrix4(_m1$2);return this;},translate:function translate(x,y,z){// translate geometry
  309. _m1$2.makeTranslation(x,y,z);this.applyMatrix4(_m1$2);return this;},scale:function scale(x,y,z){// scale geometry
  310. _m1$2.makeScale(x,y,z);this.applyMatrix4(_m1$2);return this;},lookAt:function lookAt(vector){_obj.lookAt(vector);_obj.updateMatrix();this.applyMatrix4(_obj.matrix);return this;},center:function center(){this.computeBoundingBox();this.boundingBox.getCenter(_offset).negate();this.translate(_offset.x,_offset.y,_offset.z);return this;},setFromObject:function setFromObject(object){// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
  311. var geometry=object.geometry;if(object.isPoints||object.isLine){var positions=new Float32BufferAttribute(geometry.vertices.length*3,3);var colors=new Float32BufferAttribute(geometry.colors.length*3,3);this.setAttribute('position',positions.copyVector3sArray(geometry.vertices));this.setAttribute('color',colors.copyColorsArray(geometry.colors));if(geometry.lineDistances&&geometry.lineDistances.length===geometry.vertices.length){var lineDistances=new Float32BufferAttribute(geometry.lineDistances.length,1);this.setAttribute('lineDistance',lineDistances.copyArray(geometry.lineDistances));}if(geometry.boundingSphere!==null){this.boundingSphere=geometry.boundingSphere.clone();}if(geometry.boundingBox!==null){this.boundingBox=geometry.boundingBox.clone();}}else if(object.isMesh){if(geometry&&geometry.isGeometry){this.fromGeometry(geometry);}}return this;},setFromPoints:function setFromPoints(points){var position=[];for(var _i42=0,l=points.length;_i42<l;_i42++){var point=points[_i42];position.push(point.x,point.y,point.z||0);}this.setAttribute('position',new Float32BufferAttribute(position,3));return this;},updateFromObject:function updateFromObject(object){var geometry=object.geometry;if(object.isMesh){var direct=geometry.__directGeometry;if(geometry.elementsNeedUpdate===true){direct=undefined;geometry.elementsNeedUpdate=false;}if(direct===undefined){return this.fromGeometry(geometry);}direct.verticesNeedUpdate=geometry.verticesNeedUpdate;direct.normalsNeedUpdate=geometry.normalsNeedUpdate;direct.colorsNeedUpdate=geometry.colorsNeedUpdate;direct.uvsNeedUpdate=geometry.uvsNeedUpdate;direct.groupsNeedUpdate=geometry.groupsNeedUpdate;geometry.verticesNeedUpdate=false;geometry.normalsNeedUpdate=false;geometry.colorsNeedUpdate=false;geometry.uvsNeedUpdate=false;geometry.groupsNeedUpdate=false;geometry=direct;}if(geometry.verticesNeedUpdate===true){var attribute=this.attributes.position;if(attribute!==undefined){attribute.copyVector3sArray(geometry.vertices);attribute.needsUpdate=true;}geometry.verticesNeedUpdate=false;}if(geometry.normalsNeedUpdate===true){var _attribute=this.attributes.normal;if(_attribute!==undefined){_attribute.copyVector3sArray(geometry.normals);_attribute.needsUpdate=true;}geometry.normalsNeedUpdate=false;}if(geometry.colorsNeedUpdate===true){var _attribute2=this.attributes.color;if(_attribute2!==undefined){_attribute2.copyColorsArray(geometry.colors);_attribute2.needsUpdate=true;}geometry.colorsNeedUpdate=false;}if(geometry.uvsNeedUpdate){var _attribute3=this.attributes.uv;if(_attribute3!==undefined){_attribute3.copyVector2sArray(geometry.uvs);_attribute3.needsUpdate=true;}geometry.uvsNeedUpdate=false;}if(geometry.lineDistancesNeedUpdate){var _attribute4=this.attributes.lineDistance;if(_attribute4!==undefined){_attribute4.copyArray(geometry.lineDistances);_attribute4.needsUpdate=true;}geometry.lineDistancesNeedUpdate=false;}if(geometry.groupsNeedUpdate){geometry.computeGroups(object.geometry);this.groups=geometry.groups;geometry.groupsNeedUpdate=false;}return this;},fromGeometry:function fromGeometry(geometry){geometry.__directGeometry=new DirectGeometry().fromGeometry(geometry);return this.fromDirectGeometry(geometry.__directGeometry);},fromDirectGeometry:function fromDirectGeometry(geometry){var positions=new Float32Array(geometry.vertices.length*3);this.setAttribute('position',new BufferAttribute(positions,3).copyVector3sArray(geometry.vertices));if(geometry.normals.length>0){var normals=new Float32Array(geometry.normals.length*3);this.setAttribute('normal',new BufferAttribute(normals,3).copyVector3sArray(geometry.normals));}if(geometry.colors.length>0){var colors=new Float32Array(geometry.colors.length*3);this.setAttribute('color',new BufferAttribute(colors,3).copyColorsArray(geometry.colors));}if(geometry.uvs.length>0){var uvs=new Float32Array(geometry.uvs.length*2);this.setAttribute('uv',new BufferAttribute(uvs,2).copyVector2sArray(geometry.uvs));}if(geometry.uvs2.length>0){var uvs2=new Float32Array(geometry.uvs2.length*2);this.setAttribute('uv2',new BufferAttribute(uvs2,2).copyVector2sArray(geometry.uvs2));}// groups
  312. this.groups=geometry.groups;// morphs
  313. for(var name in geometry.morphTargets){var array=[];var morphTargets=geometry.morphTargets[name];for(var _i43=0,l=morphTargets.length;_i43<l;_i43++){var morphTarget=morphTargets[_i43];var attribute=new Float32BufferAttribute(morphTarget.data.length*3,3);attribute.name=morphTarget.name;array.push(attribute.copyVector3sArray(morphTarget.data));}this.morphAttributes[name]=array;}// skinning
  314. if(geometry.skinIndices.length>0){var skinIndices=new Float32BufferAttribute(geometry.skinIndices.length*4,4);this.setAttribute('skinIndex',skinIndices.copyVector4sArray(geometry.skinIndices));}if(geometry.skinWeights.length>0){var skinWeights=new Float32BufferAttribute(geometry.skinWeights.length*4,4);this.setAttribute('skinWeight',skinWeights.copyVector4sArray(geometry.skinWeights));}//
  315. if(geometry.boundingSphere!==null){this.boundingSphere=geometry.boundingSphere.clone();}if(geometry.boundingBox!==null){this.boundingBox=geometry.boundingBox.clone();}return this;},computeBoundingBox:function computeBoundingBox(){if(this.boundingBox===null){this.boundingBox=new Box3();}var position=this.attributes.position;var morphAttributesPosition=this.morphAttributes.position;if(position&&position.isGLBufferAttribute){console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".',this);this.boundingBox.set(new Vector3(-Infinity,-Infinity,-Infinity),new Vector3(+Infinity,+Infinity,+Infinity));return;}if(position!==undefined){this.boundingBox.setFromBufferAttribute(position);// process morph attributes if present
  316. if(morphAttributesPosition){for(var _i44=0,il=morphAttributesPosition.length;_i44<il;_i44++){var morphAttribute=morphAttributesPosition[_i44];_box$2.setFromBufferAttribute(morphAttribute);if(this.morphTargetsRelative){_vector$4.addVectors(this.boundingBox.min,_box$2.min);this.boundingBox.expandByPoint(_vector$4);_vector$4.addVectors(this.boundingBox.max,_box$2.max);this.boundingBox.expandByPoint(_vector$4);}else {this.boundingBox.expandByPoint(_box$2.min);this.boundingBox.expandByPoint(_box$2.max);}}}}else {this.boundingBox.makeEmpty();}if(isNaN(this.boundingBox.min.x)||isNaN(this.boundingBox.min.y)||isNaN(this.boundingBox.min.z)){console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.',this);}},computeBoundingSphere:function computeBoundingSphere(){if(this.boundingSphere===null){this.boundingSphere=new Sphere();}var position=this.attributes.position;var morphAttributesPosition=this.morphAttributes.position;if(position&&position.isGLBufferAttribute){console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".',this);this.boundingSphere.set(new Vector3(),Infinity);return;}if(position){// first, find the center of the bounding sphere
  317. var center=this.boundingSphere.center;_box$2.setFromBufferAttribute(position);// process morph attributes if present
  318. if(morphAttributesPosition){for(var _i45=0,il=morphAttributesPosition.length;_i45<il;_i45++){var morphAttribute=morphAttributesPosition[_i45];_boxMorphTargets.setFromBufferAttribute(morphAttribute);if(this.morphTargetsRelative){_vector$4.addVectors(_box$2.min,_boxMorphTargets.min);_box$2.expandByPoint(_vector$4);_vector$4.addVectors(_box$2.max,_boxMorphTargets.max);_box$2.expandByPoint(_vector$4);}else {_box$2.expandByPoint(_boxMorphTargets.min);_box$2.expandByPoint(_boxMorphTargets.max);}}}_box$2.getCenter(center);// second, try to find a boundingSphere with a radius smaller than the
  319. // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
  320. var maxRadiusSq=0;for(var _i46=0,_il2=position.count;_i46<_il2;_i46++){_vector$4.fromBufferAttribute(position,_i46);maxRadiusSq=Math.max(maxRadiusSq,center.distanceToSquared(_vector$4));}// process morph attributes if present
  321. if(morphAttributesPosition){for(var _i47=0,_il3=morphAttributesPosition.length;_i47<_il3;_i47++){var _morphAttribute=morphAttributesPosition[_i47];var morphTargetsRelative=this.morphTargetsRelative;for(var j=0,jl=_morphAttribute.count;j<jl;j++){_vector$4.fromBufferAttribute(_morphAttribute,j);if(morphTargetsRelative){_offset.fromBufferAttribute(position,j);_vector$4.add(_offset);}maxRadiusSq=Math.max(maxRadiusSq,center.distanceToSquared(_vector$4));}}}this.boundingSphere.radius=Math.sqrt(maxRadiusSq);if(isNaN(this.boundingSphere.radius)){console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.',this);}}},computeFaceNormals:function computeFaceNormals(){// backwards compatibility
  322. },computeVertexNormals:function computeVertexNormals(){var index=this.index;var positionAttribute=this.getAttribute('position');if(positionAttribute!==undefined){var normalAttribute=this.getAttribute('normal');if(normalAttribute===undefined){normalAttribute=new BufferAttribute(new Float32Array(positionAttribute.count*3),3);this.setAttribute('normal',normalAttribute);}else {// reset existing normals to zero
  323. for(var _i48=0,il=normalAttribute.count;_i48<il;_i48++){normalAttribute.setXYZ(_i48,0,0,0);}}var pA=new Vector3(),pB=new Vector3(),pC=new Vector3();var nA=new Vector3(),nB=new Vector3(),nC=new Vector3();var cb=new Vector3(),ab=new Vector3();// indexed elements
  324. if(index){for(var _i49=0,_il4=index.count;_i49<_il4;_i49+=3){var vA=index.getX(_i49+0);var vB=index.getX(_i49+1);var vC=index.getX(_i49+2);pA.fromBufferAttribute(positionAttribute,vA);pB.fromBufferAttribute(positionAttribute,vB);pC.fromBufferAttribute(positionAttribute,vC);cb.subVectors(pC,pB);ab.subVectors(pA,pB);cb.cross(ab);nA.fromBufferAttribute(normalAttribute,vA);nB.fromBufferAttribute(normalAttribute,vB);nC.fromBufferAttribute(normalAttribute,vC);nA.add(cb);nB.add(cb);nC.add(cb);normalAttribute.setXYZ(vA,nA.x,nA.y,nA.z);normalAttribute.setXYZ(vB,nB.x,nB.y,nB.z);normalAttribute.setXYZ(vC,nC.x,nC.y,nC.z);}}else {// non-indexed elements (unconnected triangle soup)
  325. for(var _i50=0,_il5=positionAttribute.count;_i50<_il5;_i50+=3){pA.fromBufferAttribute(positionAttribute,_i50+0);pB.fromBufferAttribute(positionAttribute,_i50+1);pC.fromBufferAttribute(positionAttribute,_i50+2);cb.subVectors(pC,pB);ab.subVectors(pA,pB);cb.cross(ab);normalAttribute.setXYZ(_i50+0,cb.x,cb.y,cb.z);normalAttribute.setXYZ(_i50+1,cb.x,cb.y,cb.z);normalAttribute.setXYZ(_i50+2,cb.x,cb.y,cb.z);}}this.normalizeNormals();normalAttribute.needsUpdate=true;}},merge:function merge(geometry,offset){if(!(geometry&&geometry.isBufferGeometry)){console.error('THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.',geometry);return;}if(offset===undefined){offset=0;console.warn('THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '+'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.');}var attributes=this.attributes;for(var key in attributes){if(geometry.attributes[key]===undefined)continue;var attribute1=attributes[key];var attributeArray1=attribute1.array;var attribute2=geometry.attributes[key];var attributeArray2=attribute2.array;var attributeOffset=attribute2.itemSize*offset;var length=Math.min(attributeArray2.length,attributeArray1.length-attributeOffset);for(var _i51=0,j=attributeOffset;_i51<length;_i51++,j++){attributeArray1[j]=attributeArray2[_i51];}}return this;},normalizeNormals:function normalizeNormals(){var normals=this.attributes.normal;for(var _i52=0,il=normals.count;_i52<il;_i52++){_vector$4.fromBufferAttribute(normals,_i52);_vector$4.normalize();normals.setXYZ(_i52,_vector$4.x,_vector$4.y,_vector$4.z);}},toNonIndexed:function toNonIndexed(){function convertBufferAttribute(attribute,indices){var array=attribute.array;var itemSize=attribute.itemSize;var normalized=attribute.normalized;var array2=new array.constructor(indices.length*itemSize);var index=0,index2=0;for(var _i53=0,l=indices.length;_i53<l;_i53++){index=indices[_i53]*itemSize;for(var j=0;j<itemSize;j++){array2[index2++]=array[index++];}}return new BufferAttribute(array2,itemSize,normalized);}//
  326. if(this.index===null){console.warn('THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.');return this;}var geometry2=new BufferGeometry();var indices=this.index.array;var attributes=this.attributes;// attributes
  327. for(var name in attributes){var attribute=attributes[name];var newAttribute=convertBufferAttribute(attribute,indices);geometry2.setAttribute(name,newAttribute);}// morph attributes
  328. var morphAttributes=this.morphAttributes;for(var _name in morphAttributes){var morphArray=[];var morphAttribute=morphAttributes[_name];// morphAttribute: array of Float32BufferAttributes
  329. for(var _i54=0,il=morphAttribute.length;_i54<il;_i54++){var _attribute5=morphAttribute[_i54];var _newAttribute=convertBufferAttribute(_attribute5,indices);morphArray.push(_newAttribute);}geometry2.morphAttributes[_name]=morphArray;}geometry2.morphTargetsRelative=this.morphTargetsRelative;// groups
  330. var groups=this.groups;for(var _i55=0,l=groups.length;_i55<l;_i55++){var group=groups[_i55];geometry2.addGroup(group.start,group.count,group.materialIndex);}return geometry2;},toJSON:function toJSON(){var data={metadata:{version:4.5,type:'BufferGeometry',generator:'BufferGeometry.toJSON'}};// standard BufferGeometry serialization
  331. data.uuid=this.uuid;data.type=this.type;if(this.name!=='')data.name=this.name;if(Object.keys(this.userData).length>0)data.userData=this.userData;if(this.parameters!==undefined){var parameters=this.parameters;for(var key in parameters){if(parameters[key]!==undefined)data[key]=parameters[key];}return data;}data.data={attributes:{}};var index=this.index;if(index!==null){data.data.index={type:index.array.constructor.name,array:Array.prototype.slice.call(index.array)};}var attributes=this.attributes;for(var _key in attributes){var attribute=attributes[_key];var attributeData=attribute.toJSON(data.data);if(attribute.name!=='')attributeData.name=attribute.name;data.data.attributes[_key]=attributeData;}var morphAttributes={};var hasMorphAttributes=false;for(var _key2 in this.morphAttributes){var attributeArray=this.morphAttributes[_key2];var array=[];for(var _i56=0,il=attributeArray.length;_i56<il;_i56++){var _attribute6=attributeArray[_i56];var _attributeData=_attribute6.toJSON(data.data);if(_attribute6.name!=='')_attributeData.name=_attribute6.name;array.push(_attributeData);}if(array.length>0){morphAttributes[_key2]=array;hasMorphAttributes=true;}}if(hasMorphAttributes){data.data.morphAttributes=morphAttributes;data.data.morphTargetsRelative=this.morphTargetsRelative;}var groups=this.groups;if(groups.length>0){data.data.groups=JSON.parse(JSON.stringify(groups));}var boundingSphere=this.boundingSphere;if(boundingSphere!==null){data.data.boundingSphere={center:boundingSphere.center.toArray(),radius:boundingSphere.radius};}return data;},clone:function clone(){/*
  332. // Handle primitives
  333. const parameters = this.parameters;
  334. if ( parameters !== undefined ) {
  335. const values = [];
  336. for ( const key in parameters ) {
  337. values.push( parameters[ key ] );
  338. }
  339. const geometry = Object.create( this.constructor.prototype );
  340. this.constructor.apply( geometry, values );
  341. return geometry;
  342. }
  343. return new this.constructor().copy( this );
  344. */return new BufferGeometry().copy(this);},copy:function copy(source){// reset
  345. this.index=null;this.attributes={};this.morphAttributes={};this.groups=[];this.boundingBox=null;this.boundingSphere=null;// used for storing cloned, shared data
  346. var data={};// name
  347. this.name=source.name;// index
  348. var index=source.index;if(index!==null){this.setIndex(index.clone(data));}// attributes
  349. var attributes=source.attributes;for(var name in attributes){var attribute=attributes[name];this.setAttribute(name,attribute.clone(data));}// morph attributes
  350. var morphAttributes=source.morphAttributes;for(var _name2 in morphAttributes){var array=[];var morphAttribute=morphAttributes[_name2];// morphAttribute: array of Float32BufferAttributes
  351. for(var _i57=0,l=morphAttribute.length;_i57<l;_i57++){array.push(morphAttribute[_i57].clone(data));}this.morphAttributes[_name2]=array;}this.morphTargetsRelative=source.morphTargetsRelative;// groups
  352. var groups=source.groups;for(var _i58=0,_l3=groups.length;_i58<_l3;_i58++){var group=groups[_i58];this.addGroup(group.start,group.count,group.materialIndex);}// bounding box
  353. var boundingBox=source.boundingBox;if(boundingBox!==null){this.boundingBox=boundingBox.clone();}// bounding sphere
  354. var boundingSphere=source.boundingSphere;if(boundingSphere!==null){this.boundingSphere=boundingSphere.clone();}// draw range
  355. this.drawRange.start=source.drawRange.start;this.drawRange.count=source.drawRange.count;// user data
  356. this.userData=source.userData;return this;},dispose:function dispose(){this.dispatchEvent({type:'dispose'});}});var _inverseMatrix=new Matrix4();var _ray=new Ray();var _sphere=new Sphere();var _vA=new Vector3();var _vB=new Vector3();var _vC=new Vector3();var _tempA=new Vector3();var _tempB=new Vector3();var _tempC=new Vector3();var _morphA=new Vector3();var _morphB=new Vector3();var _morphC=new Vector3();var _uvA=new Vector2();var _uvB=new Vector2();var _uvC=new Vector2();var _intersectionPoint=new Vector3();var _intersectionPointWorld=new Vector3();function Mesh(){var geometry=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new BufferGeometry();var material=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new MeshBasicMaterial();Object3D.call(this);this.type='Mesh';this.geometry=geometry;this.material=material;this.updateMorphTargets();}Mesh.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Mesh,isMesh:true,copy:function copy(source){Object3D.prototype.copy.call(this,source);if(source.morphTargetInfluences!==undefined){this.morphTargetInfluences=source.morphTargetInfluences.slice();}if(source.morphTargetDictionary!==undefined){this.morphTargetDictionary=Object.assign({},source.morphTargetDictionary);}this.material=source.material;this.geometry=source.geometry;return this;},updateMorphTargets:function updateMorphTargets(){var geometry=this.geometry;if(geometry.isBufferGeometry){var morphAttributes=geometry.morphAttributes;var keys=Object.keys(morphAttributes);if(keys.length>0){var morphAttribute=morphAttributes[keys[0]];if(morphAttribute!==undefined){this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var m=0,ml=morphAttribute.length;m<ml;m++){var name=morphAttribute[m].name||String(m);this.morphTargetInfluences.push(0);this.morphTargetDictionary[name]=m;}}}}else {var morphTargets=geometry.morphTargets;if(morphTargets!==undefined&&morphTargets.length>0){console.error('THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');}}},raycast:function raycast(raycaster,intersects){var geometry=this.geometry;var material=this.material;var matrixWorld=this.matrixWorld;if(material===undefined)return;// Checking boundingSphere distance to ray
  357. if(geometry.boundingSphere===null)geometry.computeBoundingSphere();_sphere.copy(geometry.boundingSphere);_sphere.applyMatrix4(matrixWorld);if(raycaster.ray.intersectsSphere(_sphere)===false)return;//
  358. _inverseMatrix.copy(matrixWorld).invert();_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix);// Check boundingBox before continuing
  359. if(geometry.boundingBox!==null){if(_ray.intersectsBox(geometry.boundingBox)===false)return;}var intersection;if(geometry.isBufferGeometry){var index=geometry.index;var position=geometry.attributes.position;var morphPosition=geometry.morphAttributes.position;var morphTargetsRelative=geometry.morphTargetsRelative;var uv=geometry.attributes.uv;var uv2=geometry.attributes.uv2;var groups=geometry.groups;var drawRange=geometry.drawRange;if(index!==null){// indexed buffer geometry
  360. if(Array.isArray(material)){for(var _i59=0,il=groups.length;_i59<il;_i59++){var group=groups[_i59];var groupMaterial=material[group.materialIndex];var start=Math.max(group.start,drawRange.start);var end=Math.min(group.start+group.count,drawRange.start+drawRange.count);for(var j=start,jl=end;j<jl;j+=3){var a=index.getX(j);var b=index.getX(j+1);var c=index.getX(j+2);intersection=checkBufferGeometryIntersection(this,groupMaterial,raycaster,_ray,position,morphPosition,morphTargetsRelative,uv,uv2,a,b,c);if(intersection){intersection.faceIndex=Math.floor(j/3);// triangle number in indexed buffer semantics
  361. intersection.face.materialIndex=group.materialIndex;intersects.push(intersection);}}}}else {var _start2=Math.max(0,drawRange.start);var _end2=Math.min(index.count,drawRange.start+drawRange.count);for(var _i60=_start2,_il6=_end2;_i60<_il6;_i60+=3){var _a=index.getX(_i60);var _b=index.getX(_i60+1);var _c=index.getX(_i60+2);intersection=checkBufferGeometryIntersection(this,material,raycaster,_ray,position,morphPosition,morphTargetsRelative,uv,uv2,_a,_b,_c);if(intersection){intersection.faceIndex=Math.floor(_i60/3);// triangle number in indexed buffer semantics
  362. intersects.push(intersection);}}}}else if(position!==undefined){// non-indexed buffer geometry
  363. if(Array.isArray(material)){for(var _i61=0,_il7=groups.length;_i61<_il7;_i61++){var _group=groups[_i61];var _groupMaterial=material[_group.materialIndex];var _start3=Math.max(_group.start,drawRange.start);var _end3=Math.min(_group.start+_group.count,drawRange.start+drawRange.count);for(var _j2=_start3,_jl=_end3;_j2<_jl;_j2+=3){var _a2=_j2;var _b2=_j2+1;var _c2=_j2+2;intersection=checkBufferGeometryIntersection(this,_groupMaterial,raycaster,_ray,position,morphPosition,morphTargetsRelative,uv,uv2,_a2,_b2,_c2);if(intersection){intersection.faceIndex=Math.floor(_j2/3);// triangle number in non-indexed buffer semantics
  364. intersection.face.materialIndex=_group.materialIndex;intersects.push(intersection);}}}}else {var _start4=Math.max(0,drawRange.start);var _end4=Math.min(position.count,drawRange.start+drawRange.count);for(var _i62=_start4,_il8=_end4;_i62<_il8;_i62+=3){var _a3=_i62;var _b3=_i62+1;var _c3=_i62+2;intersection=checkBufferGeometryIntersection(this,material,raycaster,_ray,position,morphPosition,morphTargetsRelative,uv,uv2,_a3,_b3,_c3);if(intersection){intersection.faceIndex=Math.floor(_i62/3);// triangle number in non-indexed buffer semantics
  365. intersects.push(intersection);}}}}}else if(geometry.isGeometry){var isMultiMaterial=Array.isArray(material);var vertices=geometry.vertices;var faces=geometry.faces;var uvs;var faceVertexUvs=geometry.faceVertexUvs[0];if(faceVertexUvs.length>0)uvs=faceVertexUvs;for(var f=0,fl=faces.length;f<fl;f++){var face=faces[f];var faceMaterial=isMultiMaterial?material[face.materialIndex]:material;if(faceMaterial===undefined)continue;var fvA=vertices[face.a];var fvB=vertices[face.b];var fvC=vertices[face.c];intersection=checkIntersection(this,faceMaterial,raycaster,_ray,fvA,fvB,fvC,_intersectionPoint);if(intersection){if(uvs&&uvs[f]){var uvs_f=uvs[f];_uvA.copy(uvs_f[0]);_uvB.copy(uvs_f[1]);_uvC.copy(uvs_f[2]);intersection.uv=Triangle.getUV(_intersectionPoint,fvA,fvB,fvC,_uvA,_uvB,_uvC,new Vector2());}intersection.face=face;intersection.faceIndex=f;intersects.push(intersection);}}}}});function checkIntersection(object,material,raycaster,ray,pA,pB,pC,point){var intersect;if(material.side===BackSide){intersect=ray.intersectTriangle(pC,pB,pA,true,point);}else {intersect=ray.intersectTriangle(pA,pB,pC,material.side!==DoubleSide,point);}if(intersect===null)return null;_intersectionPointWorld.copy(point);_intersectionPointWorld.applyMatrix4(object.matrixWorld);var distance=raycaster.ray.origin.distanceTo(_intersectionPointWorld);if(distance<raycaster.near||distance>raycaster.far)return null;return {distance:distance,point:_intersectionPointWorld.clone(),object:object};}function checkBufferGeometryIntersection(object,material,raycaster,ray,position,morphPosition,morphTargetsRelative,uv,uv2,a,b,c){_vA.fromBufferAttribute(position,a);_vB.fromBufferAttribute(position,b);_vC.fromBufferAttribute(position,c);var morphInfluences=object.morphTargetInfluences;if(material.morphTargets&&morphPosition&&morphInfluences){_morphA.set(0,0,0);_morphB.set(0,0,0);_morphC.set(0,0,0);for(var _i63=0,il=morphPosition.length;_i63<il;_i63++){var influence=morphInfluences[_i63];var morphAttribute=morphPosition[_i63];if(influence===0)continue;_tempA.fromBufferAttribute(morphAttribute,a);_tempB.fromBufferAttribute(morphAttribute,b);_tempC.fromBufferAttribute(morphAttribute,c);if(morphTargetsRelative){_morphA.addScaledVector(_tempA,influence);_morphB.addScaledVector(_tempB,influence);_morphC.addScaledVector(_tempC,influence);}else {_morphA.addScaledVector(_tempA.sub(_vA),influence);_morphB.addScaledVector(_tempB.sub(_vB),influence);_morphC.addScaledVector(_tempC.sub(_vC),influence);}}_vA.add(_morphA);_vB.add(_morphB);_vC.add(_morphC);}if(object.isSkinnedMesh){object.boneTransform(a,_vA);object.boneTransform(b,_vB);object.boneTransform(c,_vC);}var intersection=checkIntersection(object,material,raycaster,ray,_vA,_vB,_vC,_intersectionPoint);if(intersection){if(uv){_uvA.fromBufferAttribute(uv,a);_uvB.fromBufferAttribute(uv,b);_uvC.fromBufferAttribute(uv,c);intersection.uv=Triangle.getUV(_intersectionPoint,_vA,_vB,_vC,_uvA,_uvB,_uvC,new Vector2());}if(uv2){_uvA.fromBufferAttribute(uv2,a);_uvB.fromBufferAttribute(uv2,b);_uvC.fromBufferAttribute(uv2,c);intersection.uv2=Triangle.getUV(_intersectionPoint,_vA,_vB,_vC,_uvA,_uvB,_uvC,new Vector2());}var face=new Face3(a,b,c);Triangle.getNormal(_vA,_vB,_vC,face.normal);intersection.face=face;}return intersection;}class BoxBufferGeometry extends BufferGeometry{constructor(){var width=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var height=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var depth=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var widthSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;var heightSegments=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var depthSegments=arguments.length>5&&arguments[5]!==undefined?arguments[5]:1;super();this.type='BoxBufferGeometry';this.parameters={width:width,height:height,depth:depth,widthSegments:widthSegments,heightSegments:heightSegments,depthSegments:depthSegments};var scope=this;// segments
  366. widthSegments=Math.floor(widthSegments);heightSegments=Math.floor(heightSegments);depthSegments=Math.floor(depthSegments);// buffers
  367. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  368. var numberOfVertices=0;var groupStart=0;// build each side of the box geometry
  369. buildPlane('z','y','x',-1,-1,depth,height,width,depthSegments,heightSegments,0);// px
  370. buildPlane('z','y','x',1,-1,depth,height,-width,depthSegments,heightSegments,1);// nx
  371. buildPlane('x','z','y',1,1,width,depth,height,widthSegments,depthSegments,2);// py
  372. buildPlane('x','z','y',1,-1,width,depth,-height,widthSegments,depthSegments,3);// ny
  373. buildPlane('x','y','z',1,-1,width,height,depth,widthSegments,heightSegments,4);// pz
  374. buildPlane('x','y','z',-1,-1,width,height,-depth,widthSegments,heightSegments,5);// nz
  375. // build geometry
  376. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));function buildPlane(u,v,w,udir,vdir,width,height,depth,gridX,gridY,materialIndex){var segmentWidth=width/gridX;var segmentHeight=height/gridY;var widthHalf=width/2;var heightHalf=height/2;var depthHalf=depth/2;var gridX1=gridX+1;var gridY1=gridY+1;var vertexCounter=0;var groupCount=0;var vector=new Vector3();// generate vertices, normals and uvs
  377. for(var iy=0;iy<gridY1;iy++){var y=iy*segmentHeight-heightHalf;for(var ix=0;ix<gridX1;ix++){var x=ix*segmentWidth-widthHalf;// set values to correct vector component
  378. vector[u]=x*udir;vector[v]=y*vdir;vector[w]=depthHalf;// now apply vector to vertex buffer
  379. vertices.push(vector.x,vector.y,vector.z);// set values to correct vector component
  380. vector[u]=0;vector[v]=0;vector[w]=depth>0?1:-1;// now apply vector to normal buffer
  381. normals.push(vector.x,vector.y,vector.z);// uvs
  382. uvs.push(ix/gridX);uvs.push(1-iy/gridY);// counters
  383. vertexCounter+=1;}}// indices
  384. // 1. you need three indices to draw a single face
  385. // 2. a single segment consists of two faces
  386. // 3. so we need to generate six (2*3) indices per segment
  387. for(var _iy=0;_iy<gridY;_iy++){for(var _ix=0;_ix<gridX;_ix++){var a=numberOfVertices+_ix+gridX1*_iy;var b=numberOfVertices+_ix+gridX1*(_iy+1);var c=numberOfVertices+(_ix+1)+gridX1*(_iy+1);var d=numberOfVertices+(_ix+1)+gridX1*_iy;// faces
  388. indices.push(a,b,d);indices.push(b,c,d);// increase counter
  389. groupCount+=6;}}// add a group to the geometry. this will ensure multi material support
  390. scope.addGroup(groupStart,groupCount,materialIndex);// calculate new start value for groups
  391. groupStart+=groupCount;// update total number of vertices
  392. numberOfVertices+=vertexCounter;}}}/**
  393. * Uniform Utilities
  394. */function cloneUniforms(src){var dst={};for(var u in src){dst[u]={};for(var p in src[u]){var property=src[u][p];if(property&&(property.isColor||property.isMatrix3||property.isMatrix4||property.isVector2||property.isVector3||property.isVector4||property.isTexture)){dst[u][p]=property.clone();}else if(Array.isArray(property)){dst[u][p]=property.slice();}else {dst[u][p]=property;}}}return dst;}function mergeUniforms(uniforms){var merged={};for(var u=0;u<uniforms.length;u++){var _tmp=cloneUniforms(uniforms[u]);for(var p in _tmp){merged[p]=_tmp[p];}}return merged;}// Legacy
  395. var UniformsUtils={clone:cloneUniforms,merge:mergeUniforms};var default_vertex="void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";var default_fragment="void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";/**
  396. * parameters = {
  397. * defines: { "label" : "value" },
  398. * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
  399. *
  400. * fragmentShader: <string>,
  401. * vertexShader: <string>,
  402. *
  403. * wireframe: <boolean>,
  404. * wireframeLinewidth: <float>,
  405. *
  406. * lights: <bool>,
  407. *
  408. * skinning: <bool>,
  409. * morphTargets: <bool>,
  410. * morphNormals: <bool>
  411. * }
  412. */function ShaderMaterial(parameters){Material.call(this);this.type='ShaderMaterial';this.defines={};this.uniforms={};this.vertexShader=default_vertex;this.fragmentShader=default_fragment;this.linewidth=1;this.wireframe=false;this.wireframeLinewidth=1;this.fog=false;// set to use scene fog
  413. this.lights=false;// set to use scene lights
  414. this.clipping=false;// set to use user-defined clipping planes
  415. this.skinning=false;// set to use skinning attribute streams
  416. this.morphTargets=false;// set to use morph targets
  417. this.morphNormals=false;// set to use morph normals
  418. this.extensions={derivatives:false,// set to use derivatives
  419. fragDepth:false,// set to use fragment depth values
  420. drawBuffers:false,// set to use draw buffers
  421. shaderTextureLOD:false// set to use shader texture LOD
  422. };// When rendered geometry doesn't include these attributes but the material does,
  423. // use these default values in WebGL. This avoids errors when buffer data is missing.
  424. this.defaultAttributeValues={'color':[1,1,1],'uv':[0,0],'uv2':[0,0]};this.index0AttributeName=undefined;this.uniformsNeedUpdate=false;this.glslVersion=null;if(parameters!==undefined){if(parameters.attributes!==undefined){console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.');}this.setValues(parameters);}}ShaderMaterial.prototype=Object.create(Material.prototype);ShaderMaterial.prototype.constructor=ShaderMaterial;ShaderMaterial.prototype.isShaderMaterial=true;ShaderMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.fragmentShader=source.fragmentShader;this.vertexShader=source.vertexShader;this.uniforms=cloneUniforms(source.uniforms);this.defines=Object.assign({},source.defines);this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.lights=source.lights;this.clipping=source.clipping;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;this.extensions=Object.assign({},source.extensions);this.glslVersion=source.glslVersion;return this;};ShaderMaterial.prototype.toJSON=function(meta){var data=Material.prototype.toJSON.call(this,meta);data.glslVersion=this.glslVersion;data.uniforms={};for(var name in this.uniforms){var uniform=this.uniforms[name];var value=uniform.value;if(value&&value.isTexture){data.uniforms[name]={type:'t',value:value.toJSON(meta).uuid};}else if(value&&value.isColor){data.uniforms[name]={type:'c',value:value.getHex()};}else if(value&&value.isVector2){data.uniforms[name]={type:'v2',value:value.toArray()};}else if(value&&value.isVector3){data.uniforms[name]={type:'v3',value:value.toArray()};}else if(value&&value.isVector4){data.uniforms[name]={type:'v4',value:value.toArray()};}else if(value&&value.isMatrix3){data.uniforms[name]={type:'m3',value:value.toArray()};}else if(value&&value.isMatrix4){data.uniforms[name]={type:'m4',value:value.toArray()};}else {data.uniforms[name]={value:value};// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
  425. }}if(Object.keys(this.defines).length>0)data.defines=this.defines;data.vertexShader=this.vertexShader;data.fragmentShader=this.fragmentShader;var extensions={};for(var key in this.extensions){if(this.extensions[key]===true)extensions[key]=true;}if(Object.keys(extensions).length>0)data.extensions=extensions;return data;};function Camera(){Object3D.call(this);this.type='Camera';this.matrixWorldInverse=new Matrix4();this.projectionMatrix=new Matrix4();this.projectionMatrixInverse=new Matrix4();}Camera.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Camera,isCamera:true,copy:function copy(source,recursive){Object3D.prototype.copy.call(this,source,recursive);this.matrixWorldInverse.copy(source.matrixWorldInverse);this.projectionMatrix.copy(source.projectionMatrix);this.projectionMatrixInverse.copy(source.projectionMatrixInverse);return this;},getWorldDirection:function getWorldDirection(target){if(target===undefined){console.warn('THREE.Camera: .getWorldDirection() target is now required');target=new Vector3();}this.updateWorldMatrix(true,false);var e=this.matrixWorld.elements;return target.set(-e[8],-e[9],-e[10]).normalize();},updateMatrixWorld:function updateMatrixWorld(force){Object3D.prototype.updateMatrixWorld.call(this,force);this.matrixWorldInverse.copy(this.matrixWorld).invert();},updateWorldMatrix:function updateWorldMatrix(updateParents,updateChildren){Object3D.prototype.updateWorldMatrix.call(this,updateParents,updateChildren);this.matrixWorldInverse.copy(this.matrixWorld).invert();},clone:function clone(){return new this.constructor().copy(this);}});function PerspectiveCamera(){var fov=arguments.length>0&&arguments[0]!==undefined?arguments[0]:50;var aspect=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var near=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0.1;var far=arguments.length>3&&arguments[3]!==undefined?arguments[3]:2000;Camera.call(this);this.type='PerspectiveCamera';this.fov=fov;this.zoom=1;this.near=near;this.far=far;this.focus=10;this.aspect=aspect;this.view=null;this.filmGauge=35;// width of the film (default in millimeters)
  426. this.filmOffset=0;// horizontal film offset (same unit as gauge)
  427. this.updateProjectionMatrix();}PerspectiveCamera.prototype=Object.assign(Object.create(Camera.prototype),{constructor:PerspectiveCamera,isPerspectiveCamera:true,copy:function copy(source,recursive){Camera.prototype.copy.call(this,source,recursive);this.fov=source.fov;this.zoom=source.zoom;this.near=source.near;this.far=source.far;this.focus=source.focus;this.aspect=source.aspect;this.view=source.view===null?null:Object.assign({},source.view);this.filmGauge=source.filmGauge;this.filmOffset=source.filmOffset;return this;},/**
  428. * Sets the FOV by focal length in respect to the current .filmGauge.
  429. *
  430. * The default film gauge is 35, so that the focal length can be specified for
  431. * a 35mm (full frame) camera.
  432. *
  433. * Values for focal length and film gauge must have the same unit.
  434. */setFocalLength:function setFocalLength(focalLength){// see http://www.bobatkins.com/photography/technical/field_of_view.html
  435. var vExtentSlope=0.5*this.getFilmHeight()/focalLength;this.fov=MathUtils.RAD2DEG*2*Math.atan(vExtentSlope);this.updateProjectionMatrix();},/**
  436. * Calculates the focal length from the current .fov and .filmGauge.
  437. */getFocalLength:function getFocalLength(){var vExtentSlope=Math.tan(MathUtils.DEG2RAD*0.5*this.fov);return 0.5*this.getFilmHeight()/vExtentSlope;},getEffectiveFOV:function getEffectiveFOV(){return MathUtils.RAD2DEG*2*Math.atan(Math.tan(MathUtils.DEG2RAD*0.5*this.fov)/this.zoom);},getFilmWidth:function getFilmWidth(){// film not completely covered in portrait format (aspect < 1)
  438. return this.filmGauge*Math.min(this.aspect,1);},getFilmHeight:function getFilmHeight(){// film not completely covered in landscape format (aspect > 1)
  439. return this.filmGauge/Math.max(this.aspect,1);},/**
  440. * Sets an offset in a larger frustum. This is useful for multi-window or
  441. * multi-monitor/multi-machine setups.
  442. *
  443. * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
  444. * the monitors are in grid like this
  445. *
  446. * +---+---+---+
  447. * | A | B | C |
  448. * +---+---+---+
  449. * | D | E | F |
  450. * +---+---+---+
  451. *
  452. * then for each monitor you would call it like this
  453. *
  454. * const w = 1920;
  455. * const h = 1080;
  456. * const fullWidth = w * 3;
  457. * const fullHeight = h * 2;
  458. *
  459. * --A--
  460. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
  461. * --B--
  462. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
  463. * --C--
  464. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
  465. * --D--
  466. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
  467. * --E--
  468. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
  469. * --F--
  470. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
  471. *
  472. * Note there is no reason monitors have to be the same size or in a grid.
  473. */setViewOffset:function setViewOffset(fullWidth,fullHeight,x,y,width,height){this.aspect=fullWidth/fullHeight;if(this.view===null){this.view={enabled:true,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1};}this.view.enabled=true;this.view.fullWidth=fullWidth;this.view.fullHeight=fullHeight;this.view.offsetX=x;this.view.offsetY=y;this.view.width=width;this.view.height=height;this.updateProjectionMatrix();},clearViewOffset:function clearViewOffset(){if(this.view!==null){this.view.enabled=false;}this.updateProjectionMatrix();},updateProjectionMatrix:function updateProjectionMatrix(){var near=this.near;var top=near*Math.tan(MathUtils.DEG2RAD*0.5*this.fov)/this.zoom;var height=2*top;var width=this.aspect*height;var left=-0.5*width;var view=this.view;if(this.view!==null&&this.view.enabled){var fullWidth=view.fullWidth,fullHeight=view.fullHeight;left+=view.offsetX*width/fullWidth;top-=view.offsetY*height/fullHeight;width*=view.width/fullWidth;height*=view.height/fullHeight;}var skew=this.filmOffset;if(skew!==0)left+=near*skew/this.getFilmWidth();this.projectionMatrix.makePerspective(left,left+width,top,top-height,near,this.far);this.projectionMatrixInverse.copy(this.projectionMatrix).invert();},toJSON:function toJSON(meta){var data=Object3D.prototype.toJSON.call(this,meta);data.object.fov=this.fov;data.object.zoom=this.zoom;data.object.near=this.near;data.object.far=this.far;data.object.focus=this.focus;data.object.aspect=this.aspect;if(this.view!==null)data.object.view=Object.assign({},this.view);data.object.filmGauge=this.filmGauge;data.object.filmOffset=this.filmOffset;return data;}});var fov=90,aspect=1;function CubeCamera(near,far,renderTarget){Object3D.call(this);this.type='CubeCamera';if(renderTarget.isWebGLCubeRenderTarget!==true){console.error('THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.');return;}this.renderTarget=renderTarget;var cameraPX=new PerspectiveCamera(fov,aspect,near,far);cameraPX.layers=this.layers;cameraPX.up.set(0,-1,0);cameraPX.lookAt(new Vector3(1,0,0));this.add(cameraPX);var cameraNX=new PerspectiveCamera(fov,aspect,near,far);cameraNX.layers=this.layers;cameraNX.up.set(0,-1,0);cameraNX.lookAt(new Vector3(-1,0,0));this.add(cameraNX);var cameraPY=new PerspectiveCamera(fov,aspect,near,far);cameraPY.layers=this.layers;cameraPY.up.set(0,0,1);cameraPY.lookAt(new Vector3(0,1,0));this.add(cameraPY);var cameraNY=new PerspectiveCamera(fov,aspect,near,far);cameraNY.layers=this.layers;cameraNY.up.set(0,0,-1);cameraNY.lookAt(new Vector3(0,-1,0));this.add(cameraNY);var cameraPZ=new PerspectiveCamera(fov,aspect,near,far);cameraPZ.layers=this.layers;cameraPZ.up.set(0,-1,0);cameraPZ.lookAt(new Vector3(0,0,1));this.add(cameraPZ);var cameraNZ=new PerspectiveCamera(fov,aspect,near,far);cameraNZ.layers=this.layers;cameraNZ.up.set(0,-1,0);cameraNZ.lookAt(new Vector3(0,0,-1));this.add(cameraNZ);this.update=function(renderer,scene){if(this.parent===null)this.updateMatrixWorld();var currentXrEnabled=renderer.xr.enabled;var currentRenderTarget=renderer.getRenderTarget();renderer.xr.enabled=false;var generateMipmaps=renderTarget.texture.generateMipmaps;renderTarget.texture.generateMipmaps=false;renderer.setRenderTarget(renderTarget,0);renderer.render(scene,cameraPX);renderer.setRenderTarget(renderTarget,1);renderer.render(scene,cameraNX);renderer.setRenderTarget(renderTarget,2);renderer.render(scene,cameraPY);renderer.setRenderTarget(renderTarget,3);renderer.render(scene,cameraNY);renderer.setRenderTarget(renderTarget,4);renderer.render(scene,cameraPZ);renderTarget.texture.generateMipmaps=generateMipmaps;renderer.setRenderTarget(renderTarget,5);renderer.render(scene,cameraNZ);renderer.setRenderTarget(currentRenderTarget);renderer.xr.enabled=currentXrEnabled;};}CubeCamera.prototype=Object.create(Object3D.prototype);CubeCamera.prototype.constructor=CubeCamera;function CubeTexture(images,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy,encoding){images=images!==undefined?images:[];mapping=mapping!==undefined?mapping:CubeReflectionMapping;format=format!==undefined?format:RGBFormat;Texture.call(this,images,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy,encoding);this.flipY=false;// Why CubeTexture._needsFlipEnvMap is necessary:
  474. //
  475. // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
  476. // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
  477. // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
  478. // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
  479. // and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
  480. // when using WebGLCubeRenderTarget.texture as a cube texture.
  481. this._needsFlipEnvMap=true;}CubeTexture.prototype=Object.create(Texture.prototype);CubeTexture.prototype.constructor=CubeTexture;CubeTexture.prototype.isCubeTexture=true;Object.defineProperty(CubeTexture.prototype,'images',{get:function get(){return this.image;},set:function set(value){this.image=value;}});function WebGLCubeRenderTarget(size,options,dummy){if(Number.isInteger(options)){console.warn('THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )');options=dummy;}WebGLRenderTarget.call(this,size,size,options);options=options||{};this.texture=new CubeTexture(undefined,options.mapping,options.wrapS,options.wrapT,options.magFilter,options.minFilter,options.format,options.type,options.anisotropy,options.encoding);this.texture._needsFlipEnvMap=false;}WebGLCubeRenderTarget.prototype=Object.create(WebGLRenderTarget.prototype);WebGLCubeRenderTarget.prototype.constructor=WebGLCubeRenderTarget;WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget=true;WebGLCubeRenderTarget.prototype.fromEquirectangularTexture=function(renderer,texture){this.texture.type=texture.type;this.texture.format=RGBAFormat;// see #18859
  482. this.texture.encoding=texture.encoding;this.texture.generateMipmaps=texture.generateMipmaps;this.texture.minFilter=texture.minFilter;this.texture.magFilter=texture.magFilter;var shader={uniforms:{tEquirect:{value:null}},vertexShader:/* glsl */"\n\n\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t#include <begin_vertex>\n\t\t\t\t#include <project_vertex>\n\n\t\t\t}\n\t\t",fragmentShader:/* glsl */"\n\n\t\t\tuniform sampler2D tEquirect;\n\n\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t#include <common>\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t}\n\t\t"};var geometry=new BoxBufferGeometry(5,5,5);var material=new ShaderMaterial({name:'CubemapFromEquirect',uniforms:cloneUniforms(shader.uniforms),vertexShader:shader.vertexShader,fragmentShader:shader.fragmentShader,side:BackSide,blending:NoBlending});material.uniforms.tEquirect.value=texture;var mesh=new Mesh(geometry,material);var currentMinFilter=texture.minFilter;// Avoid blurred poles
  483. if(texture.minFilter===LinearMipmapLinearFilter)texture.minFilter=LinearFilter;var camera=new CubeCamera(1,10,this);camera.update(renderer,mesh);texture.minFilter=currentMinFilter;mesh.geometry.dispose();mesh.material.dispose();return this;};WebGLCubeRenderTarget.prototype.clear=function(renderer,color,depth,stencil){var currentRenderTarget=renderer.getRenderTarget();for(var _i64=0;_i64<6;_i64++){renderer.setRenderTarget(this,_i64);renderer.clear(color,depth,stencil);}renderer.setRenderTarget(currentRenderTarget);};function DataTexture(data,width,height,format,type,mapping,wrapS,wrapT,magFilter,minFilter,anisotropy,encoding){Texture.call(this,null,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy,encoding);this.image={data:data||null,width:width||1,height:height||1};this.magFilter=magFilter!==undefined?magFilter:NearestFilter;this.minFilter=minFilter!==undefined?minFilter:NearestFilter;this.generateMipmaps=false;this.flipY=false;this.unpackAlignment=1;this.needsUpdate=true;}DataTexture.prototype=Object.create(Texture.prototype);DataTexture.prototype.constructor=DataTexture;DataTexture.prototype.isDataTexture=true;var _sphere$1=/*@__PURE__*/new Sphere();var _vector$5=/*@__PURE__*/new Vector3();class Frustum{constructor(p0,p1,p2,p3,p4,p5){this.planes=[p0!==undefined?p0:new Plane(),p1!==undefined?p1:new Plane(),p2!==undefined?p2:new Plane(),p3!==undefined?p3:new Plane(),p4!==undefined?p4:new Plane(),p5!==undefined?p5:new Plane()];}set(p0,p1,p2,p3,p4,p5){var planes=this.planes;planes[0].copy(p0);planes[1].copy(p1);planes[2].copy(p2);planes[3].copy(p3);planes[4].copy(p4);planes[5].copy(p5);return this;}clone(){return new this.constructor().copy(this);}copy(frustum){var planes=this.planes;for(var _i65=0;_i65<6;_i65++){planes[_i65].copy(frustum.planes[_i65]);}return this;}setFromProjectionMatrix(m){var planes=this.planes;var me=m.elements;var me0=me[0],me1=me[1],me2=me[2],me3=me[3];var me4=me[4],me5=me[5],me6=me[6],me7=me[7];var me8=me[8],me9=me[9],me10=me[10],me11=me[11];var me12=me[12],me13=me[13],me14=me[14],me15=me[15];planes[0].setComponents(me3-me0,me7-me4,me11-me8,me15-me12).normalize();planes[1].setComponents(me3+me0,me7+me4,me11+me8,me15+me12).normalize();planes[2].setComponents(me3+me1,me7+me5,me11+me9,me15+me13).normalize();planes[3].setComponents(me3-me1,me7-me5,me11-me9,me15-me13).normalize();planes[4].setComponents(me3-me2,me7-me6,me11-me10,me15-me14).normalize();planes[5].setComponents(me3+me2,me7+me6,me11+me10,me15+me14).normalize();return this;}intersectsObject(object){var geometry=object.geometry;if(geometry.boundingSphere===null)geometry.computeBoundingSphere();_sphere$1.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);return this.intersectsSphere(_sphere$1);}intersectsSprite(sprite){_sphere$1.center.set(0,0,0);_sphere$1.radius=0.7071067811865476;_sphere$1.applyMatrix4(sprite.matrixWorld);return this.intersectsSphere(_sphere$1);}intersectsSphere(sphere){var planes=this.planes;var center=sphere.center;var negRadius=-sphere.radius;for(var _i66=0;_i66<6;_i66++){var distance=planes[_i66].distanceToPoint(center);if(distance<negRadius){return false;}}return true;}intersectsBox(box){var planes=this.planes;for(var _i67=0;_i67<6;_i67++){var plane=planes[_i67];// corner at max distance
  484. _vector$5.x=plane.normal.x>0?box.max.x:box.min.x;_vector$5.y=plane.normal.y>0?box.max.y:box.min.y;_vector$5.z=plane.normal.z>0?box.max.z:box.min.z;if(plane.distanceToPoint(_vector$5)<0){return false;}}return true;}containsPoint(point){var planes=this.planes;for(var _i68=0;_i68<6;_i68++){if(planes[_i68].distanceToPoint(point)<0){return false;}}return true;}}function WebGLAnimation(){var context=null;var isAnimating=false;var animationLoop=null;var requestId=null;function onAnimationFrame(time,frame){animationLoop(time,frame);requestId=context.requestAnimationFrame(onAnimationFrame);}return {start:function start(){if(isAnimating===true)return;if(animationLoop===null)return;requestId=context.requestAnimationFrame(onAnimationFrame);isAnimating=true;},stop:function stop(){context.cancelAnimationFrame(requestId);isAnimating=false;},setAnimationLoop:function setAnimationLoop(callback){animationLoop=callback;},setContext:function setContext(value){context=value;}};}function WebGLAttributes(gl,capabilities){var isWebGL2=capabilities.isWebGL2;var buffers=new WeakMap();function createBuffer(attribute,bufferType){var array=attribute.array;var usage=attribute.usage;var buffer=gl.createBuffer();gl.bindBuffer(bufferType,buffer);gl.bufferData(bufferType,array,usage);attribute.onUploadCallback();var type=5126;if(array instanceof Float32Array){type=5126;}else if(array instanceof Float64Array){console.warn('THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.');}else if(array instanceof Uint16Array){if(attribute.isFloat16BufferAttribute){if(isWebGL2){type=5131;}else {console.warn('THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.');}}else {type=5123;}}else if(array instanceof Int16Array){type=5122;}else if(array instanceof Uint32Array){type=5125;}else if(array instanceof Int32Array){type=5124;}else if(array instanceof Int8Array){type=5120;}else if(array instanceof Uint8Array){type=5121;}return {buffer:buffer,type:type,bytesPerElement:array.BYTES_PER_ELEMENT,version:attribute.version};}function updateBuffer(buffer,attribute,bufferType){var array=attribute.array;var updateRange=attribute.updateRange;gl.bindBuffer(bufferType,buffer);if(updateRange.count===-1){// Not using update ranges
  485. gl.bufferSubData(bufferType,0,array);}else {if(isWebGL2){gl.bufferSubData(bufferType,updateRange.offset*array.BYTES_PER_ELEMENT,array,updateRange.offset,updateRange.count);}else {gl.bufferSubData(bufferType,updateRange.offset*array.BYTES_PER_ELEMENT,array.subarray(updateRange.offset,updateRange.offset+updateRange.count));}updateRange.count=-1;// reset range
  486. }}//
  487. function get(attribute){if(attribute.isInterleavedBufferAttribute)attribute=attribute.data;return buffers.get(attribute);}function remove(attribute){if(attribute.isInterleavedBufferAttribute)attribute=attribute.data;var data=buffers.get(attribute);if(data){gl.deleteBuffer(data.buffer);buffers.delete(attribute);}}function update(attribute,bufferType){if(attribute.isGLBufferAttribute){var cached=buffers.get(attribute);if(!cached||cached.version<attribute.version){buffers.set(attribute,{buffer:attribute.buffer,type:attribute.type,bytesPerElement:attribute.elementSize,version:attribute.version});}return;}if(attribute.isInterleavedBufferAttribute)attribute=attribute.data;var data=buffers.get(attribute);if(data===undefined){buffers.set(attribute,createBuffer(attribute,bufferType));}else if(data.version<attribute.version){updateBuffer(data.buffer,attribute,bufferType);data.version=attribute.version;}}return {get:get,remove:remove,update:update};}class PlaneBufferGeometry extends BufferGeometry{constructor(){var width=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var height=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var widthSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var heightSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;super();this.type='PlaneBufferGeometry';this.parameters={width:width,height:height,widthSegments:widthSegments,heightSegments:heightSegments};var width_half=width/2;var height_half=height/2;var gridX=Math.floor(widthSegments);var gridY=Math.floor(heightSegments);var gridX1=gridX+1;var gridY1=gridY+1;var segment_width=width/gridX;var segment_height=height/gridY;//
  488. var indices=[];var vertices=[];var normals=[];var uvs=[];for(var iy=0;iy<gridY1;iy++){var y=iy*segment_height-height_half;for(var ix=0;ix<gridX1;ix++){var x=ix*segment_width-width_half;vertices.push(x,-y,0);normals.push(0,0,1);uvs.push(ix/gridX);uvs.push(1-iy/gridY);}}for(var _iy2=0;_iy2<gridY;_iy2++){for(var _ix2=0;_ix2<gridX;_ix2++){var a=_ix2+gridX1*_iy2;var b=_ix2+gridX1*(_iy2+1);var c=_ix2+1+gridX1*(_iy2+1);var d=_ix2+1+gridX1*_iy2;indices.push(a,b,d);indices.push(b,c,d);}}this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}}var alphamap_fragment="#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";var alphamap_pars_fragment="#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";var alphatest_fragment="#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";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";var aomap_pars_fragment="#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";var begin_vertex="vec3 transformed = vec3( position );";var beginnormal_vertex="vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";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";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";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";var clipping_planes_pars_fragment="#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";var clipping_planes_pars_vertex="#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";var clipping_planes_vertex="#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";var color_fragment="#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";var color_pars_fragment="#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";var color_pars_vertex="#if defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";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";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}";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";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";var displacementmap_pars_vertex="#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";var displacementmap_vertex="#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";var emissivemap_fragment="#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";var emissivemap_pars_fragment="#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";var encodings_fragment="gl_FragColor = linearToOutputTexel( gl_FragColor );";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}";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";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";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";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";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";var fog_vertex="#ifdef USE_FOG\n\tfogDepth = - mvPosition.z;\n#endif";var fog_pars_vertex="#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";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";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";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}";var lightmap_fragment="#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";var lightmap_pars_fragment="#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";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";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";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";var lights_toon_fragment="ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";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)";var lights_phong_fragment="BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";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)";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";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}";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";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";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";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";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";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";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";var map_fragment="#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";var map_pars_fragment="#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";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";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";var metalnessmap_fragment="float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";var metalnessmap_pars_fragment="#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";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";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";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";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;";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";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";var clearcoat_normal_fragment_begin="#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";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";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";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}";var premultiplied_alpha_fragment="#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";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;";var dithering_fragment="#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";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";var roughnessmap_fragment="float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";var roughnessmap_pars_fragment="#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";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";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";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";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}";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";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";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";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";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";var specularmap_pars_fragment="#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";var tonemapping_fragment="#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";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; }";var transmissionmap_fragment="#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif";var transmissionmap_pars_fragment="#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\n#endif";var uv_pars_fragment="#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";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";var uv_vertex="#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";var uv2_pars_fragment="#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";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";var uv2_vertex="#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";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";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";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}";var ShaderChunk={alphamap_fragment:alphamap_fragment,alphamap_pars_fragment:alphamap_pars_fragment,alphatest_fragment:alphatest_fragment,aomap_fragment:aomap_fragment,aomap_pars_fragment:aomap_pars_fragment,begin_vertex:begin_vertex,beginnormal_vertex:beginnormal_vertex,bsdfs:bsdfs,bumpmap_pars_fragment:bumpmap_pars_fragment,clipping_planes_fragment:clipping_planes_fragment,clipping_planes_pars_fragment:clipping_planes_pars_fragment,clipping_planes_pars_vertex:clipping_planes_pars_vertex,clipping_planes_vertex:clipping_planes_vertex,color_fragment:color_fragment,color_pars_fragment:color_pars_fragment,color_pars_vertex:color_pars_vertex,color_vertex:color_vertex,common:common,cube_uv_reflection_fragment:cube_uv_reflection_fragment,defaultnormal_vertex:defaultnormal_vertex,displacementmap_pars_vertex:displacementmap_pars_vertex,displacementmap_vertex:displacementmap_vertex,emissivemap_fragment:emissivemap_fragment,emissivemap_pars_fragment:emissivemap_pars_fragment,encodings_fragment:encodings_fragment,encodings_pars_fragment:encodings_pars_fragment,envmap_fragment:envmap_fragment,envmap_common_pars_fragment:envmap_common_pars_fragment,envmap_pars_fragment:envmap_pars_fragment,envmap_pars_vertex:envmap_pars_vertex,envmap_physical_pars_fragment:envmap_physical_pars_fragment,envmap_vertex:envmap_vertex,fog_vertex:fog_vertex,fog_pars_vertex:fog_pars_vertex,fog_fragment:fog_fragment,fog_pars_fragment:fog_pars_fragment,gradientmap_pars_fragment:gradientmap_pars_fragment,lightmap_fragment:lightmap_fragment,lightmap_pars_fragment:lightmap_pars_fragment,lights_lambert_vertex:lights_lambert_vertex,lights_pars_begin:lights_pars_begin,lights_toon_fragment:lights_toon_fragment,lights_toon_pars_fragment:lights_toon_pars_fragment,lights_phong_fragment:lights_phong_fragment,lights_phong_pars_fragment:lights_phong_pars_fragment,lights_physical_fragment:lights_physical_fragment,lights_physical_pars_fragment:lights_physical_pars_fragment,lights_fragment_begin:lights_fragment_begin,lights_fragment_maps:lights_fragment_maps,lights_fragment_end:lights_fragment_end,logdepthbuf_fragment:logdepthbuf_fragment,logdepthbuf_pars_fragment:logdepthbuf_pars_fragment,logdepthbuf_pars_vertex:logdepthbuf_pars_vertex,logdepthbuf_vertex:logdepthbuf_vertex,map_fragment:map_fragment,map_pars_fragment:map_pars_fragment,map_particle_fragment:map_particle_fragment,map_particle_pars_fragment:map_particle_pars_fragment,metalnessmap_fragment:metalnessmap_fragment,metalnessmap_pars_fragment:metalnessmap_pars_fragment,morphnormal_vertex:morphnormal_vertex,morphtarget_pars_vertex:morphtarget_pars_vertex,morphtarget_vertex:morphtarget_vertex,normal_fragment_begin:normal_fragment_begin,normal_fragment_maps:normal_fragment_maps,normalmap_pars_fragment:normalmap_pars_fragment,clearcoat_normal_fragment_begin:clearcoat_normal_fragment_begin,clearcoat_normal_fragment_maps:clearcoat_normal_fragment_maps,clearcoat_pars_fragment:clearcoat_pars_fragment,packing:packing,premultiplied_alpha_fragment:premultiplied_alpha_fragment,project_vertex:project_vertex,dithering_fragment:dithering_fragment,dithering_pars_fragment:dithering_pars_fragment,roughnessmap_fragment:roughnessmap_fragment,roughnessmap_pars_fragment:roughnessmap_pars_fragment,shadowmap_pars_fragment:shadowmap_pars_fragment,shadowmap_pars_vertex:shadowmap_pars_vertex,shadowmap_vertex:shadowmap_vertex,shadowmask_pars_fragment:shadowmask_pars_fragment,skinbase_vertex:skinbase_vertex,skinning_pars_vertex:skinning_pars_vertex,skinning_vertex:skinning_vertex,skinnormal_vertex:skinnormal_vertex,specularmap_fragment:specularmap_fragment,specularmap_pars_fragment:specularmap_pars_fragment,tonemapping_fragment:tonemapping_fragment,tonemapping_pars_fragment:tonemapping_pars_fragment,transmissionmap_fragment:transmissionmap_fragment,transmissionmap_pars_fragment:transmissionmap_pars_fragment,uv_pars_fragment:uv_pars_fragment,uv_pars_vertex:uv_pars_vertex,uv_vertex:uv_vertex,uv2_pars_fragment:uv2_pars_fragment,uv2_pars_vertex:uv2_pars_vertex,uv2_vertex:uv2_vertex,worldpos_vertex:worldpos_vertex,background_frag:background_frag,background_vert:background_vert,cube_frag:cube_frag,cube_vert:cube_vert,depth_frag:depth_frag,depth_vert:depth_vert,distanceRGBA_frag:distanceRGBA_frag,distanceRGBA_vert:distanceRGBA_vert,equirect_frag:equirect_frag,equirect_vert:equirect_vert,linedashed_frag:linedashed_frag,linedashed_vert:linedashed_vert,meshbasic_frag:meshbasic_frag,meshbasic_vert:meshbasic_vert,meshlambert_frag:meshlambert_frag,meshlambert_vert:meshlambert_vert,meshmatcap_frag:meshmatcap_frag,meshmatcap_vert:meshmatcap_vert,meshtoon_frag:meshtoon_frag,meshtoon_vert:meshtoon_vert,meshphong_frag:meshphong_frag,meshphong_vert:meshphong_vert,meshphysical_frag:meshphysical_frag,meshphysical_vert:meshphysical_vert,normal_frag:normal_frag,normal_vert:normal_vert,points_frag:points_frag,points_vert:points_vert,shadow_frag:shadow_frag,shadow_vert:shadow_vert,sprite_frag:sprite_frag,sprite_vert:sprite_vert};/**
  489. * Uniforms library for shared webgl shaders
  490. */var UniformsLib={common:{diffuse:{value:new Color(0xeeeeee)},opacity:{value:1.0},map:{value:null},uvTransform:{value:new Matrix3()},uv2Transform:{value:new Matrix3()},alphaMap:{value:null}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1.0},refractionRatio:{value:0.98},maxMipLevel:{value:0}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new Vector2(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:0.00025},fogNear:{value:1},fogFar:{value:2000},fogColor:{value:new Color(0xffffff)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
  491. rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Color(0xeeeeee)},opacity:{value:1.0},size:{value:1.0},scale:{value:1.0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new Matrix3()}},sprite:{diffuse:{value:new Color(0xeeeeee)},opacity:{value:1.0},center:{value:new Vector2(0.5,0.5)},rotation:{value:0.0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new Matrix3()}}};var ShaderLib={basic:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.specularmap,UniformsLib.envmap,UniformsLib.aomap,UniformsLib.lightmap,UniformsLib.fog]),vertexShader:ShaderChunk.meshbasic_vert,fragmentShader:ShaderChunk.meshbasic_frag},lambert:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.specularmap,UniformsLib.envmap,UniformsLib.aomap,UniformsLib.lightmap,UniformsLib.emissivemap,UniformsLib.fog,UniformsLib.lights,{emissive:{value:new Color(0x000000)}}]),vertexShader:ShaderChunk.meshlambert_vert,fragmentShader:ShaderChunk.meshlambert_frag},phong:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.specularmap,UniformsLib.envmap,UniformsLib.aomap,UniformsLib.lightmap,UniformsLib.emissivemap,UniformsLib.bumpmap,UniformsLib.normalmap,UniformsLib.displacementmap,UniformsLib.fog,UniformsLib.lights,{emissive:{value:new Color(0x000000)},specular:{value:new Color(0x111111)},shininess:{value:30}}]),vertexShader:ShaderChunk.meshphong_vert,fragmentShader:ShaderChunk.meshphong_frag},standard:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.envmap,UniformsLib.aomap,UniformsLib.lightmap,UniformsLib.emissivemap,UniformsLib.bumpmap,UniformsLib.normalmap,UniformsLib.displacementmap,UniformsLib.roughnessmap,UniformsLib.metalnessmap,UniformsLib.fog,UniformsLib.lights,{emissive:{value:new Color(0x000000)},roughness:{value:1.0},metalness:{value:0.0},envMapIntensity:{value:1}// temporary
  492. }]),vertexShader:ShaderChunk.meshphysical_vert,fragmentShader:ShaderChunk.meshphysical_frag},toon:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.aomap,UniformsLib.lightmap,UniformsLib.emissivemap,UniformsLib.bumpmap,UniformsLib.normalmap,UniformsLib.displacementmap,UniformsLib.gradientmap,UniformsLib.fog,UniformsLib.lights,{emissive:{value:new Color(0x000000)}}]),vertexShader:ShaderChunk.meshtoon_vert,fragmentShader:ShaderChunk.meshtoon_frag},matcap:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.bumpmap,UniformsLib.normalmap,UniformsLib.displacementmap,UniformsLib.fog,{matcap:{value:null}}]),vertexShader:ShaderChunk.meshmatcap_vert,fragmentShader:ShaderChunk.meshmatcap_frag},points:{uniforms:mergeUniforms([UniformsLib.points,UniformsLib.fog]),vertexShader:ShaderChunk.points_vert,fragmentShader:ShaderChunk.points_frag},dashed:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:ShaderChunk.linedashed_vert,fragmentShader:ShaderChunk.linedashed_frag},depth:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.displacementmap]),vertexShader:ShaderChunk.depth_vert,fragmentShader:ShaderChunk.depth_frag},normal:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.bumpmap,UniformsLib.normalmap,UniformsLib.displacementmap,{opacity:{value:1.0}}]),vertexShader:ShaderChunk.normal_vert,fragmentShader:ShaderChunk.normal_frag},sprite:{uniforms:mergeUniforms([UniformsLib.sprite,UniformsLib.fog]),vertexShader:ShaderChunk.sprite_vert,fragmentShader:ShaderChunk.sprite_frag},background:{uniforms:{uvTransform:{value:new Matrix3()},t2D:{value:null}},vertexShader:ShaderChunk.background_vert,fragmentShader:ShaderChunk.background_frag},/* -------------------------------------------------------------------------
  493. // Cube map shader
  494. ------------------------------------------------------------------------- */cube:{uniforms:mergeUniforms([UniformsLib.envmap,{opacity:{value:1.0}}]),vertexShader:ShaderChunk.cube_vert,fragmentShader:ShaderChunk.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:ShaderChunk.equirect_vert,fragmentShader:ShaderChunk.equirect_frag},distanceRGBA:{uniforms:mergeUniforms([UniformsLib.common,UniformsLib.displacementmap,{referencePosition:{value:new Vector3()},nearDistance:{value:1},farDistance:{value:1000}}]),vertexShader:ShaderChunk.distanceRGBA_vert,fragmentShader:ShaderChunk.distanceRGBA_frag},shadow:{uniforms:mergeUniforms([UniformsLib.lights,UniformsLib.fog,{color:{value:new Color(0x00000)},opacity:{value:1.0}}]),vertexShader:ShaderChunk.shadow_vert,fragmentShader:ShaderChunk.shadow_frag}};ShaderLib.physical={uniforms:mergeUniforms([ShaderLib.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new Vector2(1,1)},clearcoatNormalMap:{value:null},sheen:{value:new Color(0x000000)},transmission:{value:0},transmissionMap:{value:null}}]),vertexShader:ShaderChunk.meshphysical_vert,fragmentShader:ShaderChunk.meshphysical_frag};function WebGLBackground(renderer,cubemaps,state,objects,premultipliedAlpha){var clearColor=new Color(0x000000);var clearAlpha=0;var planeMesh;var boxMesh;var currentBackground=null;var currentBackgroundVersion=0;var currentTonemapping=null;function render(renderList,scene,camera,forceClear){var background=scene.isScene===true?scene.background:null;if(background&&background.isTexture){background=cubemaps.get(background);}// Ignore background in AR
  495. // TODO: Reconsider this.
  496. var xr=renderer.xr;var session=xr.getSession&&xr.getSession();if(session&&session.environmentBlendMode==='additive'){background=null;}if(background===null){setClear(clearColor,clearAlpha);}else if(background&&background.isColor){setClear(background,1);forceClear=true;}if(renderer.autoClear||forceClear){renderer.clear(renderer.autoClearColor,renderer.autoClearDepth,renderer.autoClearStencil);}if(background&&(background.isCubeTexture||background.isWebGLCubeRenderTarget||background.mapping===CubeUVReflectionMapping)){if(boxMesh===undefined){boxMesh=new Mesh(new BoxBufferGeometry(1,1,1),new ShaderMaterial({name:'BackgroundCubeMaterial',uniforms:cloneUniforms(ShaderLib.cube.uniforms),vertexShader:ShaderLib.cube.vertexShader,fragmentShader:ShaderLib.cube.fragmentShader,side:BackSide,depthTest:false,depthWrite:false,fog:false}));boxMesh.geometry.deleteAttribute('normal');boxMesh.geometry.deleteAttribute('uv');boxMesh.onBeforeRender=function(renderer,scene,camera){this.matrixWorld.copyPosition(camera.matrixWorld);};// enable code injection for non-built-in material
  497. Object.defineProperty(boxMesh.material,'envMap',{get:function get(){return this.uniforms.envMap.value;}});objects.update(boxMesh);}if(background.isWebGLCubeRenderTarget){// TODO Deprecate
  498. background=background.texture;}boxMesh.material.uniforms.envMap.value=background;boxMesh.material.uniforms.flipEnvMap.value=background.isCubeTexture&&background._needsFlipEnvMap?-1:1;if(currentBackground!==background||currentBackgroundVersion!==background.version||currentTonemapping!==renderer.toneMapping){boxMesh.material.needsUpdate=true;currentBackground=background;currentBackgroundVersion=background.version;currentTonemapping=renderer.toneMapping;}// push to the pre-sorted opaque render list
  499. renderList.unshift(boxMesh,boxMesh.geometry,boxMesh.material,0,0,null);}else if(background&&background.isTexture){if(planeMesh===undefined){planeMesh=new Mesh(new PlaneBufferGeometry(2,2),new ShaderMaterial({name:'BackgroundMaterial',uniforms:cloneUniforms(ShaderLib.background.uniforms),vertexShader:ShaderLib.background.vertexShader,fragmentShader:ShaderLib.background.fragmentShader,side:FrontSide,depthTest:false,depthWrite:false,fog:false}));planeMesh.geometry.deleteAttribute('normal');// enable code injection for non-built-in material
  500. Object.defineProperty(planeMesh.material,'map',{get:function get(){return this.uniforms.t2D.value;}});objects.update(planeMesh);}planeMesh.material.uniforms.t2D.value=background;if(background.matrixAutoUpdate===true){background.updateMatrix();}planeMesh.material.uniforms.uvTransform.value.copy(background.matrix);if(currentBackground!==background||currentBackgroundVersion!==background.version||currentTonemapping!==renderer.toneMapping){planeMesh.material.needsUpdate=true;currentBackground=background;currentBackgroundVersion=background.version;currentTonemapping=renderer.toneMapping;}// push to the pre-sorted opaque render list
  501. renderList.unshift(planeMesh,planeMesh.geometry,planeMesh.material,0,0,null);}}function setClear(color,alpha){state.buffers.color.setClear(color.r,color.g,color.b,alpha,premultipliedAlpha);}return {getClearColor:function getClearColor(){return clearColor;},setClearColor:function setClearColor(color){var alpha=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;clearColor.set(color);clearAlpha=alpha;setClear(clearColor,clearAlpha);},getClearAlpha:function getClearAlpha(){return clearAlpha;},setClearAlpha:function setClearAlpha(alpha){clearAlpha=alpha;setClear(clearColor,clearAlpha);},render:render};}function WebGLBindingStates(gl,extensions,attributes,capabilities){var maxVertexAttributes=gl.getParameter(34921);var extension=capabilities.isWebGL2?null:extensions.get('OES_vertex_array_object');var vaoAvailable=capabilities.isWebGL2||extension!==null;var bindingStates={};var defaultState=createBindingState(null);var currentState=defaultState;function setup(object,material,program,geometry,index){var updateBuffers=false;if(vaoAvailable){var state=getBindingState(geometry,program,material);if(currentState!==state){currentState=state;bindVertexArrayObject(currentState.object);}updateBuffers=needsUpdate(geometry,index);if(updateBuffers)saveCache(geometry,index);}else {var wireframe=material.wireframe===true;if(currentState.geometry!==geometry.id||currentState.program!==program.id||currentState.wireframe!==wireframe){currentState.geometry=geometry.id;currentState.program=program.id;currentState.wireframe=wireframe;updateBuffers=true;}}if(object.isInstancedMesh===true){updateBuffers=true;}if(index!==null){attributes.update(index,34963);}if(updateBuffers){setupVertexAttributes(object,material,program,geometry);if(index!==null){gl.bindBuffer(34963,attributes.get(index).buffer);}}}function createVertexArrayObject(){if(capabilities.isWebGL2)return gl.createVertexArray();return extension.createVertexArrayOES();}function bindVertexArrayObject(vao){if(capabilities.isWebGL2)return gl.bindVertexArray(vao);return extension.bindVertexArrayOES(vao);}function deleteVertexArrayObject(vao){if(capabilities.isWebGL2)return gl.deleteVertexArray(vao);return extension.deleteVertexArrayOES(vao);}function getBindingState(geometry,program,material){var wireframe=material.wireframe===true;var programMap=bindingStates[geometry.id];if(programMap===undefined){programMap={};bindingStates[geometry.id]=programMap;}var stateMap=programMap[program.id];if(stateMap===undefined){stateMap={};programMap[program.id]=stateMap;}var state=stateMap[wireframe];if(state===undefined){state=createBindingState(createVertexArrayObject());stateMap[wireframe]=state;}return state;}function createBindingState(vao){var newAttributes=[];var enabledAttributes=[];var attributeDivisors=[];for(var _i69=0;_i69<maxVertexAttributes;_i69++){newAttributes[_i69]=0;enabledAttributes[_i69]=0;attributeDivisors[_i69]=0;}return {// for backward compatibility on non-VAO support browser
  502. geometry:null,program:null,wireframe:false,newAttributes:newAttributes,enabledAttributes:enabledAttributes,attributeDivisors:attributeDivisors,object:vao,attributes:{},index:null};}function needsUpdate(geometry,index){var cachedAttributes=currentState.attributes;var geometryAttributes=geometry.attributes;var attributesNum=0;for(var key in geometryAttributes){var cachedAttribute=cachedAttributes[key];var geometryAttribute=geometryAttributes[key];if(cachedAttribute===undefined)return true;if(cachedAttribute.attribute!==geometryAttribute)return true;if(cachedAttribute.data!==geometryAttribute.data)return true;attributesNum++;}if(currentState.attributesNum!==attributesNum)return true;if(currentState.index!==index)return true;return false;}function saveCache(geometry,index){var cache={};var attributes=geometry.attributes;var attributesNum=0;for(var key in attributes){var attribute=attributes[key];var data={};data.attribute=attribute;if(attribute.data){data.data=attribute.data;}cache[key]=data;attributesNum++;}currentState.attributes=cache;currentState.attributesNum=attributesNum;currentState.index=index;}function initAttributes(){var newAttributes=currentState.newAttributes;for(var _i70=0,il=newAttributes.length;_i70<il;_i70++){newAttributes[_i70]=0;}}function enableAttribute(attribute){enableAttributeAndDivisor(attribute,0);}function enableAttributeAndDivisor(attribute,meshPerAttribute){var newAttributes=currentState.newAttributes;var enabledAttributes=currentState.enabledAttributes;var attributeDivisors=currentState.attributeDivisors;newAttributes[attribute]=1;if(enabledAttributes[attribute]===0){gl.enableVertexAttribArray(attribute);enabledAttributes[attribute]=1;}if(attributeDivisors[attribute]!==meshPerAttribute){var _extension=capabilities.isWebGL2?gl:extensions.get('ANGLE_instanced_arrays');_extension[capabilities.isWebGL2?'vertexAttribDivisor':'vertexAttribDivisorANGLE'](attribute,meshPerAttribute);attributeDivisors[attribute]=meshPerAttribute;}}function disableUnusedAttributes(){var newAttributes=currentState.newAttributes;var enabledAttributes=currentState.enabledAttributes;for(var _i71=0,il=enabledAttributes.length;_i71<il;_i71++){if(enabledAttributes[_i71]!==newAttributes[_i71]){gl.disableVertexAttribArray(_i71);enabledAttributes[_i71]=0;}}}function vertexAttribPointer(index,size,type,normalized,stride,offset){if(capabilities.isWebGL2===true&&(type===5124||type===5125)){gl.vertexAttribIPointer(index,size,type,stride,offset);}else {gl.vertexAttribPointer(index,size,type,normalized,stride,offset);}}function setupVertexAttributes(object,material,program,geometry){if(capabilities.isWebGL2===false&&(object.isInstancedMesh||geometry.isInstancedBufferGeometry)){if(extensions.get('ANGLE_instanced_arrays')===null)return;}initAttributes();var geometryAttributes=geometry.attributes;var programAttributes=program.getAttributes();var materialDefaultAttributeValues=material.defaultAttributeValues;for(var name in programAttributes){var programAttribute=programAttributes[name];if(programAttribute>=0){var geometryAttribute=geometryAttributes[name];if(geometryAttribute!==undefined){var normalized=geometryAttribute.normalized;var size=geometryAttribute.itemSize;var attribute=attributes.get(geometryAttribute);// TODO Attribute may not be available on context restore
  503. if(attribute===undefined)continue;var buffer=attribute.buffer;var type=attribute.type;var bytesPerElement=attribute.bytesPerElement;if(geometryAttribute.isInterleavedBufferAttribute){var data=geometryAttribute.data;var stride=data.stride;var offset=geometryAttribute.offset;if(data&&data.isInstancedInterleavedBuffer){enableAttributeAndDivisor(programAttribute,data.meshPerAttribute);if(geometry._maxInstanceCount===undefined){geometry._maxInstanceCount=data.meshPerAttribute*data.count;}}else {enableAttribute(programAttribute);}gl.bindBuffer(34962,buffer);vertexAttribPointer(programAttribute,size,type,normalized,stride*bytesPerElement,offset*bytesPerElement);}else {if(geometryAttribute.isInstancedBufferAttribute){enableAttributeAndDivisor(programAttribute,geometryAttribute.meshPerAttribute);if(geometry._maxInstanceCount===undefined){geometry._maxInstanceCount=geometryAttribute.meshPerAttribute*geometryAttribute.count;}}else {enableAttribute(programAttribute);}gl.bindBuffer(34962,buffer);vertexAttribPointer(programAttribute,size,type,normalized,0,0);}}else if(name==='instanceMatrix'){var _attribute7=attributes.get(object.instanceMatrix);// TODO Attribute may not be available on context restore
  504. if(_attribute7===undefined)continue;var _buffer=_attribute7.buffer;var _type=_attribute7.type;enableAttributeAndDivisor(programAttribute+0,1);enableAttributeAndDivisor(programAttribute+1,1);enableAttributeAndDivisor(programAttribute+2,1);enableAttributeAndDivisor(programAttribute+3,1);gl.bindBuffer(34962,_buffer);gl.vertexAttribPointer(programAttribute+0,4,_type,false,64,0);gl.vertexAttribPointer(programAttribute+1,4,_type,false,64,16);gl.vertexAttribPointer(programAttribute+2,4,_type,false,64,32);gl.vertexAttribPointer(programAttribute+3,4,_type,false,64,48);}else if(name==='instanceColor'){var _attribute8=attributes.get(object.instanceColor);// TODO Attribute may not be available on context restore
  505. if(_attribute8===undefined)continue;var _buffer2=_attribute8.buffer;var _type2=_attribute8.type;enableAttributeAndDivisor(programAttribute,1);gl.bindBuffer(34962,_buffer2);gl.vertexAttribPointer(programAttribute,3,_type2,false,12,0);}else if(materialDefaultAttributeValues!==undefined){var value=materialDefaultAttributeValues[name];if(value!==undefined){switch(value.length){case 2:gl.vertexAttrib2fv(programAttribute,value);break;case 3:gl.vertexAttrib3fv(programAttribute,value);break;case 4:gl.vertexAttrib4fv(programAttribute,value);break;default:gl.vertexAttrib1fv(programAttribute,value);}}}}}disableUnusedAttributes();}function dispose(){reset();for(var geometryId in bindingStates){var programMap=bindingStates[geometryId];for(var programId in programMap){var stateMap=programMap[programId];for(var wireframe in stateMap){deleteVertexArrayObject(stateMap[wireframe].object);delete stateMap[wireframe];}delete programMap[programId];}delete bindingStates[geometryId];}}function releaseStatesOfGeometry(geometry){if(bindingStates[geometry.id]===undefined)return;var programMap=bindingStates[geometry.id];for(var programId in programMap){var stateMap=programMap[programId];for(var wireframe in stateMap){deleteVertexArrayObject(stateMap[wireframe].object);delete stateMap[wireframe];}delete programMap[programId];}delete bindingStates[geometry.id];}function releaseStatesOfProgram(program){for(var geometryId in bindingStates){var programMap=bindingStates[geometryId];if(programMap[program.id]===undefined)continue;var stateMap=programMap[program.id];for(var wireframe in stateMap){deleteVertexArrayObject(stateMap[wireframe].object);delete stateMap[wireframe];}delete programMap[program.id];}}function reset(){resetDefaultState();if(currentState===defaultState)return;currentState=defaultState;bindVertexArrayObject(currentState.object);}// for backward-compatilibity
  506. function resetDefaultState(){defaultState.geometry=null;defaultState.program=null;defaultState.wireframe=false;}return {setup:setup,reset:reset,resetDefaultState:resetDefaultState,dispose:dispose,releaseStatesOfGeometry:releaseStatesOfGeometry,releaseStatesOfProgram:releaseStatesOfProgram,initAttributes:initAttributes,enableAttribute:enableAttribute,disableUnusedAttributes:disableUnusedAttributes};}function WebGLBufferRenderer(gl,extensions,info,capabilities){var isWebGL2=capabilities.isWebGL2;var mode;function setMode(value){mode=value;}function render(start,count){gl.drawArrays(mode,start,count);info.update(count,mode,1);}function renderInstances(start,count,primcount){if(primcount===0)return;var extension,methodName;if(isWebGL2){extension=gl;methodName='drawArraysInstanced';}else {extension=extensions.get('ANGLE_instanced_arrays');methodName='drawArraysInstancedANGLE';if(extension===null){console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');return;}}extension[methodName](mode,start,count,primcount);info.update(count,mode,primcount);}//
  507. this.setMode=setMode;this.render=render;this.renderInstances=renderInstances;}function WebGLCapabilities(gl,extensions,parameters){var maxAnisotropy;function getMaxAnisotropy(){if(maxAnisotropy!==undefined)return maxAnisotropy;var extension=extensions.get('EXT_texture_filter_anisotropic');if(extension!==null){maxAnisotropy=gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);}else {maxAnisotropy=0;}return maxAnisotropy;}function getMaxPrecision(precision){if(precision==='highp'){if(gl.getShaderPrecisionFormat(35633,36338).precision>0&&gl.getShaderPrecisionFormat(35632,36338).precision>0){return 'highp';}precision='mediump';}if(precision==='mediump'){if(gl.getShaderPrecisionFormat(35633,36337).precision>0&&gl.getShaderPrecisionFormat(35632,36337).precision>0){return 'mediump';}}return 'lowp';}/* eslint-disable no-undef */var isWebGL2=typeof WebGL2RenderingContext!=='undefined'&&gl instanceof WebGL2RenderingContext||typeof WebGL2ComputeRenderingContext!=='undefined'&&gl instanceof WebGL2ComputeRenderingContext;/* eslint-enable no-undef */var precision=parameters.precision!==undefined?parameters.precision:'highp';var maxPrecision=getMaxPrecision(precision);if(maxPrecision!==precision){console.warn('THREE.WebGLRenderer:',precision,'not supported, using',maxPrecision,'instead.');precision=maxPrecision;}var logarithmicDepthBuffer=parameters.logarithmicDepthBuffer===true;var maxTextures=gl.getParameter(34930);var maxVertexTextures=gl.getParameter(35660);var maxTextureSize=gl.getParameter(3379);var maxCubemapSize=gl.getParameter(34076);var maxAttributes=gl.getParameter(34921);var maxVertexUniforms=gl.getParameter(36347);var maxVaryings=gl.getParameter(36348);var maxFragmentUniforms=gl.getParameter(36349);var vertexTextures=maxVertexTextures>0;var floatFragmentTextures=isWebGL2||!!extensions.get('OES_texture_float');var floatVertexTextures=vertexTextures&&floatFragmentTextures;var maxSamples=isWebGL2?gl.getParameter(36183):0;return {isWebGL2:isWebGL2,getMaxAnisotropy:getMaxAnisotropy,getMaxPrecision:getMaxPrecision,precision:precision,logarithmicDepthBuffer:logarithmicDepthBuffer,maxTextures:maxTextures,maxVertexTextures:maxVertexTextures,maxTextureSize:maxTextureSize,maxCubemapSize:maxCubemapSize,maxAttributes:maxAttributes,maxVertexUniforms:maxVertexUniforms,maxVaryings:maxVaryings,maxFragmentUniforms:maxFragmentUniforms,vertexTextures:vertexTextures,floatFragmentTextures:floatFragmentTextures,floatVertexTextures:floatVertexTextures,maxSamples:maxSamples};}function WebGLClipping(properties){var scope=this;var globalState=null,numGlobalPlanes=0,localClippingEnabled=false,renderingShadows=false;var plane=new Plane(),viewNormalMatrix=new Matrix3(),uniform={value:null,needsUpdate:false};this.uniform=uniform;this.numPlanes=0;this.numIntersection=0;this.init=function(planes,enableLocalClipping,camera){var enabled=planes.length!==0||enableLocalClipping||// enable state of previous frame - the clipping code has to
  508. // run another frame in order to reset the state:
  509. numGlobalPlanes!==0||localClippingEnabled;localClippingEnabled=enableLocalClipping;globalState=projectPlanes(planes,camera,0);numGlobalPlanes=planes.length;return enabled;};this.beginShadows=function(){renderingShadows=true;projectPlanes(null);};this.endShadows=function(){renderingShadows=false;resetGlobalState();};this.setState=function(material,camera,useCache){var planes=material.clippingPlanes,clipIntersection=material.clipIntersection,clipShadows=material.clipShadows;var materialProperties=properties.get(material);if(!localClippingEnabled||planes===null||planes.length===0||renderingShadows&&!clipShadows){// there's no local clipping
  510. if(renderingShadows){// there's no global clipping
  511. projectPlanes(null);}else {resetGlobalState();}}else {var nGlobal=renderingShadows?0:numGlobalPlanes,lGlobal=nGlobal*4;var dstArray=materialProperties.clippingState||null;uniform.value=dstArray;// ensure unique state
  512. dstArray=projectPlanes(planes,camera,lGlobal,useCache);for(var _i72=0;_i72!==lGlobal;++_i72){dstArray[_i72]=globalState[_i72];}materialProperties.clippingState=dstArray;this.numIntersection=clipIntersection?this.numPlanes:0;this.numPlanes+=nGlobal;}};function resetGlobalState(){if(uniform.value!==globalState){uniform.value=globalState;uniform.needsUpdate=numGlobalPlanes>0;}scope.numPlanes=numGlobalPlanes;scope.numIntersection=0;}function projectPlanes(planes,camera,dstOffset,skipTransform){var nPlanes=planes!==null?planes.length:0;var dstArray=null;if(nPlanes!==0){dstArray=uniform.value;if(skipTransform!==true||dstArray===null){var flatSize=dstOffset+nPlanes*4,viewMatrix=camera.matrixWorldInverse;viewNormalMatrix.getNormalMatrix(viewMatrix);if(dstArray===null||dstArray.length<flatSize){dstArray=new Float32Array(flatSize);}for(var _i73=0,i4=dstOffset;_i73!==nPlanes;++_i73,i4+=4){plane.copy(planes[_i73]).applyMatrix4(viewMatrix,viewNormalMatrix);plane.normal.toArray(dstArray,i4);dstArray[i4+3]=plane.constant;}}uniform.value=dstArray;uniform.needsUpdate=true;}scope.numPlanes=nPlanes;scope.numIntersection=0;return dstArray;}}function WebGLCubeMaps(renderer){var cubemaps=new WeakMap();function mapTextureMapping(texture,mapping){if(mapping===EquirectangularReflectionMapping){texture.mapping=CubeReflectionMapping;}else if(mapping===EquirectangularRefractionMapping){texture.mapping=CubeRefractionMapping;}return texture;}function get(texture){if(texture&&texture.isTexture){var mapping=texture.mapping;if(mapping===EquirectangularReflectionMapping||mapping===EquirectangularRefractionMapping){if(cubemaps.has(texture)){var cubemap=cubemaps.get(texture).texture;return mapTextureMapping(cubemap,texture.mapping);}else {var image=texture.image;if(image&&image.height>0){var currentRenderList=renderer.getRenderList();var currentRenderTarget=renderer.getRenderTarget();var renderTarget=new WebGLCubeRenderTarget(image.height/2);renderTarget.fromEquirectangularTexture(renderer,texture);cubemaps.set(texture,renderTarget);renderer.setRenderTarget(currentRenderTarget);renderer.setRenderList(currentRenderList);texture.addEventListener('dispose',onTextureDispose);return mapTextureMapping(renderTarget.texture,texture.mapping);}else {// image not yet ready. try the conversion next frame
  513. return null;}}}}return texture;}function onTextureDispose(event){var texture=event.target;texture.removeEventListener('dispose',onTextureDispose);var cubemap=cubemaps.get(texture);if(cubemap!==undefined){cubemaps.delete(texture);cubemap.dispose();}}function dispose(){cubemaps=new WeakMap();}return {get:get,dispose:dispose};}function WebGLExtensions(gl){var extensions={};return {has:function has(name){if(extensions[name]!==undefined){return extensions[name]!==null;}var extension;switch(name){case'WEBGL_depth_texture':extension=gl.getExtension('WEBGL_depth_texture')||gl.getExtension('MOZ_WEBGL_depth_texture')||gl.getExtension('WEBKIT_WEBGL_depth_texture');break;case'EXT_texture_filter_anisotropic':extension=gl.getExtension('EXT_texture_filter_anisotropic')||gl.getExtension('MOZ_EXT_texture_filter_anisotropic')||gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');break;case'WEBGL_compressed_texture_s3tc':extension=gl.getExtension('WEBGL_compressed_texture_s3tc')||gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc')||gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');break;case'WEBGL_compressed_texture_pvrtc':extension=gl.getExtension('WEBGL_compressed_texture_pvrtc')||gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');break;default:extension=gl.getExtension(name);}extensions[name]=extension;return extension!==null;},get:function get(name){if(!this.has(name)){console.warn('THREE.WebGLRenderer: '+name+' extension not supported.');}return extensions[name];}};}function WebGLGeometries(gl,attributes,info,bindingStates){var geometries=new WeakMap();var wireframeAttributes=new WeakMap();function onGeometryDispose(event){var geometry=event.target;var buffergeometry=geometries.get(geometry);if(buffergeometry.index!==null){attributes.remove(buffergeometry.index);}for(var name in buffergeometry.attributes){attributes.remove(buffergeometry.attributes[name]);}geometry.removeEventListener('dispose',onGeometryDispose);geometries.delete(geometry);var attribute=wireframeAttributes.get(buffergeometry);if(attribute){attributes.remove(attribute);wireframeAttributes.delete(buffergeometry);}bindingStates.releaseStatesOfGeometry(buffergeometry);if(geometry.isInstancedBufferGeometry===true){delete geometry._maxInstanceCount;}//
  514. info.memory.geometries--;}function get(object,geometry){var buffergeometry=geometries.get(geometry);if(buffergeometry)return buffergeometry;geometry.addEventListener('dispose',onGeometryDispose);if(geometry.isBufferGeometry){buffergeometry=geometry;}else if(geometry.isGeometry){if(geometry._bufferGeometry===undefined){geometry._bufferGeometry=new BufferGeometry().setFromObject(object);}buffergeometry=geometry._bufferGeometry;}geometries.set(geometry,buffergeometry);info.memory.geometries++;return buffergeometry;}function update(geometry){var geometryAttributes=geometry.attributes;// Updating index buffer in VAO now. See WebGLBindingStates.
  515. for(var name in geometryAttributes){attributes.update(geometryAttributes[name],34962);}// morph targets
  516. var morphAttributes=geometry.morphAttributes;for(var _name3 in morphAttributes){var array=morphAttributes[_name3];for(var _i74=0,l=array.length;_i74<l;_i74++){attributes.update(array[_i74],34962);}}}function updateWireframeAttribute(geometry){var indices=[];var geometryIndex=geometry.index;var geometryPosition=geometry.attributes.position;var version=0;if(geometryIndex!==null){var array=geometryIndex.array;version=geometryIndex.version;for(var _i75=0,l=array.length;_i75<l;_i75+=3){var a=array[_i75+0];var b=array[_i75+1];var c=array[_i75+2];indices.push(a,b,b,c,c,a);}}else {var _array=geometryPosition.array;version=geometryPosition.version;for(var _i76=0,_l4=_array.length/3-1;_i76<_l4;_i76+=3){var _a4=_i76+0;var _b4=_i76+1;var _c4=_i76+2;indices.push(_a4,_b4,_b4,_c4,_c4,_a4);}}var attribute=new(arrayMax(indices)>65535?Uint32BufferAttribute:Uint16BufferAttribute)(indices,1);attribute.version=version;// Updating index buffer in VAO now. See WebGLBindingStates
  517. //
  518. var previousAttribute=wireframeAttributes.get(geometry);if(previousAttribute)attributes.remove(previousAttribute);//
  519. wireframeAttributes.set(geometry,attribute);}function getWireframeAttribute(geometry){var currentAttribute=wireframeAttributes.get(geometry);if(currentAttribute){var geometryIndex=geometry.index;if(geometryIndex!==null){// if the attribute is obsolete, create a new one
  520. if(currentAttribute.version<geometryIndex.version){updateWireframeAttribute(geometry);}}}else {updateWireframeAttribute(geometry);}return wireframeAttributes.get(geometry);}return {get:get,update:update,getWireframeAttribute:getWireframeAttribute};}function WebGLIndexedBufferRenderer(gl,extensions,info,capabilities){var isWebGL2=capabilities.isWebGL2;var mode;function setMode(value){mode=value;}var type,bytesPerElement;function setIndex(value){type=value.type;bytesPerElement=value.bytesPerElement;}function render(start,count){gl.drawElements(mode,count,type,start*bytesPerElement);info.update(count,mode,1);}function renderInstances(start,count,primcount){if(primcount===0)return;var extension,methodName;if(isWebGL2){extension=gl;methodName='drawElementsInstanced';}else {extension=extensions.get('ANGLE_instanced_arrays');methodName='drawElementsInstancedANGLE';if(extension===null){console.error('THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');return;}}extension[methodName](mode,count,type,start*bytesPerElement,primcount);info.update(count,mode,primcount);}//
  521. this.setMode=setMode;this.setIndex=setIndex;this.render=render;this.renderInstances=renderInstances;}function WebGLInfo(gl){var memory={geometries:0,textures:0};var render={frame:0,calls:0,triangles:0,points:0,lines:0};function update(count,mode,instanceCount){render.calls++;switch(mode){case 4:render.triangles+=instanceCount*(count/3);break;case 1:render.lines+=instanceCount*(count/2);break;case 3:render.lines+=instanceCount*(count-1);break;case 2:render.lines+=instanceCount*count;break;case 0:render.points+=instanceCount*count;break;default:console.error('THREE.WebGLInfo: Unknown draw mode:',mode);break;}}function reset(){render.frame++;render.calls=0;render.triangles=0;render.points=0;render.lines=0;}return {memory:memory,render:render,programs:null,autoReset:true,reset:reset,update:update};}function numericalSort(a,b){return a[0]-b[0];}function absNumericalSort(a,b){return Math.abs(b[1])-Math.abs(a[1]);}function WebGLMorphtargets(gl){var influencesList={};var morphInfluences=new Float32Array(8);var workInfluences=[];for(var _i77=0;_i77<8;_i77++){workInfluences[_i77]=[_i77,0];}function update(object,geometry,material,program){var objectInfluences=object.morphTargetInfluences;// When object doesn't have morph target influences defined, we treat it as a 0-length array
  522. // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
  523. var length=objectInfluences===undefined?0:objectInfluences.length;var influences=influencesList[geometry.id];if(influences===undefined){// initialise list
  524. influences=[];for(var _i78=0;_i78<length;_i78++){influences[_i78]=[_i78,0];}influencesList[geometry.id]=influences;}// Collect influences
  525. for(var _i79=0;_i79<length;_i79++){var influence=influences[_i79];influence[0]=_i79;influence[1]=objectInfluences[_i79];}influences.sort(absNumericalSort);for(var _i80=0;_i80<8;_i80++){if(_i80<length&&influences[_i80][1]){workInfluences[_i80][0]=influences[_i80][0];workInfluences[_i80][1]=influences[_i80][1];}else {workInfluences[_i80][0]=Number.MAX_SAFE_INTEGER;workInfluences[_i80][1]=0;}}workInfluences.sort(numericalSort);var morphTargets=material.morphTargets&&geometry.morphAttributes.position;var morphNormals=material.morphNormals&&geometry.morphAttributes.normal;var morphInfluencesSum=0;for(var _i81=0;_i81<8;_i81++){var _influence=workInfluences[_i81];var index=_influence[0];var value=_influence[1];if(index!==Number.MAX_SAFE_INTEGER&&value){if(morphTargets&&geometry.getAttribute('morphTarget'+_i81)!==morphTargets[index]){geometry.setAttribute('morphTarget'+_i81,morphTargets[index]);}if(morphNormals&&geometry.getAttribute('morphNormal'+_i81)!==morphNormals[index]){geometry.setAttribute('morphNormal'+_i81,morphNormals[index]);}morphInfluences[_i81]=value;morphInfluencesSum+=value;}else {if(morphTargets&&geometry.hasAttribute('morphTarget'+_i81)===true){geometry.deleteAttribute('morphTarget'+_i81);}if(morphNormals&&geometry.hasAttribute('morphNormal'+_i81)===true){geometry.deleteAttribute('morphNormal'+_i81);}morphInfluences[_i81]=0;}}// GLSL shader uses formula baseinfluence * base + sum(target * influence)
  526. // This allows us to switch between absolute morphs and relative morphs without changing shader code
  527. // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
  528. var morphBaseInfluence=geometry.morphTargetsRelative?1:1-morphInfluencesSum;program.getUniforms().setValue(gl,'morphTargetBaseInfluence',morphBaseInfluence);program.getUniforms().setValue(gl,'morphTargetInfluences',morphInfluences);}return {update:update};}function WebGLObjects(gl,geometries,attributes,info){var updateMap=new WeakMap();function update(object){var frame=info.render.frame;var geometry=object.geometry;var buffergeometry=geometries.get(object,geometry);// Update once per frame
  529. if(updateMap.get(buffergeometry)!==frame){if(geometry.isGeometry){buffergeometry.updateFromObject(object);}geometries.update(buffergeometry);updateMap.set(buffergeometry,frame);}if(object.isInstancedMesh){if(object.hasEventListener('dispose',onInstancedMeshDispose)===false){object.addEventListener('dispose',onInstancedMeshDispose);}attributes.update(object.instanceMatrix,34962);if(object.instanceColor!==null){attributes.update(object.instanceColor,34962);}}return buffergeometry;}function dispose(){updateMap=new WeakMap();}function onInstancedMeshDispose(event){var instancedMesh=event.target;instancedMesh.removeEventListener('dispose',onInstancedMeshDispose);attributes.remove(instancedMesh.instanceMatrix);if(instancedMesh.instanceColor!==null)attributes.remove(instancedMesh.instanceColor);}return {update:update,dispose:dispose};}function DataTexture2DArray(){var data=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;var width=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var height=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var depth=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;Texture.call(this,null);this.image={data,width,height,depth};this.magFilter=NearestFilter;this.minFilter=NearestFilter;this.wrapR=ClampToEdgeWrapping;this.generateMipmaps=false;this.flipY=false;this.needsUpdate=true;}DataTexture2DArray.prototype=Object.create(Texture.prototype);DataTexture2DArray.prototype.constructor=DataTexture2DArray;DataTexture2DArray.prototype.isDataTexture2DArray=true;function DataTexture3D(){var data=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;var width=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var height=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var depth=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;// We're going to add .setXXX() methods for setting properties later.
  530. // Users can still set in DataTexture3D directly.
  531. //
  532. // const texture = new THREE.DataTexture3D( data, width, height, depth );
  533. // texture.anisotropy = 16;
  534. //
  535. // See #14839
  536. Texture.call(this,null);this.image={data,width,height,depth};this.magFilter=NearestFilter;this.minFilter=NearestFilter;this.wrapR=ClampToEdgeWrapping;this.generateMipmaps=false;this.flipY=false;this.needsUpdate=true;}DataTexture3D.prototype=Object.create(Texture.prototype);DataTexture3D.prototype.constructor=DataTexture3D;DataTexture3D.prototype.isDataTexture3D=true;/**
  537. * Uniforms of a program.
  538. * Those form a tree structure with a special top-level container for the root,
  539. * which you get by calling 'new WebGLUniforms( gl, program )'.
  540. *
  541. *
  542. * Properties of inner nodes including the top-level container:
  543. *
  544. * .seq - array of nested uniforms
  545. * .map - nested uniforms by name
  546. *
  547. *
  548. * Methods of all nodes except the top-level container:
  549. *
  550. * .setValue( gl, value, [textures] )
  551. *
  552. * uploads a uniform value(s)
  553. * the 'textures' parameter is needed for sampler uniforms
  554. *
  555. *
  556. * Static methods of the top-level container (textures factorizations):
  557. *
  558. * .upload( gl, seq, values, textures )
  559. *
  560. * sets uniforms in 'seq' to 'values[id].value'
  561. *
  562. * .seqWithValue( seq, values ) : filteredSeq
  563. *
  564. * filters 'seq' entries with corresponding entry in values
  565. *
  566. *
  567. * Methods of the top-level container (textures factorizations):
  568. *
  569. * .setValue( gl, name, value, textures )
  570. *
  571. * sets uniform with name 'name' to 'value'
  572. *
  573. * .setOptional( gl, obj, prop )
  574. *
  575. * like .set for an optional property of the object
  576. *
  577. */var emptyTexture=new Texture();var emptyTexture2dArray=new DataTexture2DArray();var emptyTexture3d=new DataTexture3D();var emptyCubeTexture=new CubeTexture();// --- Utilities ---
  578. // Array Caches (provide typed arrays for temporary by size)
  579. var arrayCacheF32=[];var arrayCacheI32=[];// Float32Array caches used for uploading Matrix uniforms
  580. var mat4array=new Float32Array(16);var mat3array=new Float32Array(9);var mat2array=new Float32Array(4);// Flattening for arrays of vectors and matrices
  581. function flatten(array,nBlocks,blockSize){var firstElem=array[0];if(firstElem<=0||firstElem>0)return array;// unoptimized: ! isNaN( firstElem )
  582. // see http://jacksondunstan.com/articles/983
  583. var n=nBlocks*blockSize;var r=arrayCacheF32[n];if(r===undefined){r=new Float32Array(n);arrayCacheF32[n]=r;}if(nBlocks!==0){firstElem.toArray(r,0);for(var _i82=1,offset=0;_i82!==nBlocks;++_i82){offset+=blockSize;array[_i82].toArray(r,offset);}}return r;}function arraysEqual(a,b){if(a.length!==b.length)return false;for(var _i83=0,l=a.length;_i83<l;_i83++){if(a[_i83]!==b[_i83])return false;}return true;}function copyArray(a,b){for(var _i84=0,l=b.length;_i84<l;_i84++){a[_i84]=b[_i84];}}// Texture unit allocation
  584. function allocTexUnits(textures,n){var r=arrayCacheI32[n];if(r===undefined){r=new Int32Array(n);arrayCacheI32[n]=r;}for(var _i85=0;_i85!==n;++_i85){r[_i85]=textures.allocateTextureUnit();}return r;}// --- Setters ---
  585. // Note: Defining these methods externally, because they come in a bunch
  586. // and this way their names minify.
  587. // Single scalar
  588. function setValueV1f(gl,v){var cache=this.cache;if(cache[0]===v)return;gl.uniform1f(this.addr,v);cache[0]=v;}// Single float vector (from flat array or THREE.VectorN)
  589. function setValueV2f(gl,v){var cache=this.cache;if(v.x!==undefined){if(cache[0]!==v.x||cache[1]!==v.y){gl.uniform2f(this.addr,v.x,v.y);cache[0]=v.x;cache[1]=v.y;}}else {if(arraysEqual(cache,v))return;gl.uniform2fv(this.addr,v);copyArray(cache,v);}}function setValueV3f(gl,v){var cache=this.cache;if(v.x!==undefined){if(cache[0]!==v.x||cache[1]!==v.y||cache[2]!==v.z){gl.uniform3f(this.addr,v.x,v.y,v.z);cache[0]=v.x;cache[1]=v.y;cache[2]=v.z;}}else if(v.r!==undefined){if(cache[0]!==v.r||cache[1]!==v.g||cache[2]!==v.b){gl.uniform3f(this.addr,v.r,v.g,v.b);cache[0]=v.r;cache[1]=v.g;cache[2]=v.b;}}else {if(arraysEqual(cache,v))return;gl.uniform3fv(this.addr,v);copyArray(cache,v);}}function setValueV4f(gl,v){var cache=this.cache;if(v.x!==undefined){if(cache[0]!==v.x||cache[1]!==v.y||cache[2]!==v.z||cache[3]!==v.w){gl.uniform4f(this.addr,v.x,v.y,v.z,v.w);cache[0]=v.x;cache[1]=v.y;cache[2]=v.z;cache[3]=v.w;}}else {if(arraysEqual(cache,v))return;gl.uniform4fv(this.addr,v);copyArray(cache,v);}}// Single matrix (from flat array or MatrixN)
  590. function setValueM2(gl,v){var cache=this.cache;var elements=v.elements;if(elements===undefined){if(arraysEqual(cache,v))return;gl.uniformMatrix2fv(this.addr,false,v);copyArray(cache,v);}else {if(arraysEqual(cache,elements))return;mat2array.set(elements);gl.uniformMatrix2fv(this.addr,false,mat2array);copyArray(cache,elements);}}function setValueM3(gl,v){var cache=this.cache;var elements=v.elements;if(elements===undefined){if(arraysEqual(cache,v))return;gl.uniformMatrix3fv(this.addr,false,v);copyArray(cache,v);}else {if(arraysEqual(cache,elements))return;mat3array.set(elements);gl.uniformMatrix3fv(this.addr,false,mat3array);copyArray(cache,elements);}}function setValueM4(gl,v){var cache=this.cache;var elements=v.elements;if(elements===undefined){if(arraysEqual(cache,v))return;gl.uniformMatrix4fv(this.addr,false,v);copyArray(cache,v);}else {if(arraysEqual(cache,elements))return;mat4array.set(elements);gl.uniformMatrix4fv(this.addr,false,mat4array);copyArray(cache,elements);}}// Single texture (2D / Cube)
  591. function setValueT1(gl,v,textures){var cache=this.cache;var unit=textures.allocateTextureUnit();if(cache[0]!==unit){gl.uniform1i(this.addr,unit);cache[0]=unit;}textures.safeSetTexture2D(v||emptyTexture,unit);}function setValueT2DArray1(gl,v,textures){var cache=this.cache;var unit=textures.allocateTextureUnit();if(cache[0]!==unit){gl.uniform1i(this.addr,unit);cache[0]=unit;}textures.setTexture2DArray(v||emptyTexture2dArray,unit);}function setValueT3D1(gl,v,textures){var cache=this.cache;var unit=textures.allocateTextureUnit();if(cache[0]!==unit){gl.uniform1i(this.addr,unit);cache[0]=unit;}textures.setTexture3D(v||emptyTexture3d,unit);}function setValueT6(gl,v,textures){var cache=this.cache;var unit=textures.allocateTextureUnit();if(cache[0]!==unit){gl.uniform1i(this.addr,unit);cache[0]=unit;}textures.safeSetTextureCube(v||emptyCubeTexture,unit);}// Integer / Boolean vectors or arrays thereof (always flat arrays)
  592. function setValueV1i(gl,v){var cache=this.cache;if(cache[0]===v)return;gl.uniform1i(this.addr,v);cache[0]=v;}function setValueV2i(gl,v){var cache=this.cache;if(arraysEqual(cache,v))return;gl.uniform2iv(this.addr,v);copyArray(cache,v);}function setValueV3i(gl,v){var cache=this.cache;if(arraysEqual(cache,v))return;gl.uniform3iv(this.addr,v);copyArray(cache,v);}function setValueV4i(gl,v){var cache=this.cache;if(arraysEqual(cache,v))return;gl.uniform4iv(this.addr,v);copyArray(cache,v);}// uint
  593. function setValueV1ui(gl,v){var cache=this.cache;if(cache[0]===v)return;gl.uniform1ui(this.addr,v);cache[0]=v;}// Helper to pick the right setter for the singular case
  594. function getSingularSetter(type){switch(type){case 0x1406:return setValueV1f;// FLOAT
  595. case 0x8b50:return setValueV2f;// _VEC2
  596. case 0x8b51:return setValueV3f;// _VEC3
  597. case 0x8b52:return setValueV4f;// _VEC4
  598. case 0x8b5a:return setValueM2;// _MAT2
  599. case 0x8b5b:return setValueM3;// _MAT3
  600. case 0x8b5c:return setValueM4;// _MAT4
  601. case 0x1404:case 0x8b56:return setValueV1i;// INT, BOOL
  602. case 0x8b53:case 0x8b57:return setValueV2i;// _VEC2
  603. case 0x8b54:case 0x8b58:return setValueV3i;// _VEC3
  604. case 0x8b55:case 0x8b59:return setValueV4i;// _VEC4
  605. case 0x1405:return setValueV1ui;// UINT
  606. case 0x8b5e:// SAMPLER_2D
  607. case 0x8d66:// SAMPLER_EXTERNAL_OES
  608. case 0x8dca:// INT_SAMPLER_2D
  609. case 0x8dd2:// UNSIGNED_INT_SAMPLER_2D
  610. case 0x8b62:// SAMPLER_2D_SHADOW
  611. return setValueT1;case 0x8b5f:// SAMPLER_3D
  612. case 0x8dcb:// INT_SAMPLER_3D
  613. case 0x8dd3:// UNSIGNED_INT_SAMPLER_3D
  614. return setValueT3D1;case 0x8b60:// SAMPLER_CUBE
  615. case 0x8dcc:// INT_SAMPLER_CUBE
  616. case 0x8dd4:// UNSIGNED_INT_SAMPLER_CUBE
  617. case 0x8dc5:// SAMPLER_CUBE_SHADOW
  618. return setValueT6;case 0x8dc1:// SAMPLER_2D_ARRAY
  619. case 0x8dcf:// INT_SAMPLER_2D_ARRAY
  620. case 0x8dd7:// UNSIGNED_INT_SAMPLER_2D_ARRAY
  621. case 0x8dc4:// SAMPLER_2D_ARRAY_SHADOW
  622. return setValueT2DArray1;}}// Array of scalars
  623. function setValueV1fArray(gl,v){gl.uniform1fv(this.addr,v);}// Integer / Boolean vectors or arrays thereof (always flat arrays)
  624. function setValueV1iArray(gl,v){gl.uniform1iv(this.addr,v);}function setValueV2iArray(gl,v){gl.uniform2iv(this.addr,v);}function setValueV3iArray(gl,v){gl.uniform3iv(this.addr,v);}function setValueV4iArray(gl,v){gl.uniform4iv(this.addr,v);}// Array of vectors (flat or from THREE classes)
  625. function setValueV2fArray(gl,v){var data=flatten(v,this.size,2);gl.uniform2fv(this.addr,data);}function setValueV3fArray(gl,v){var data=flatten(v,this.size,3);gl.uniform3fv(this.addr,data);}function setValueV4fArray(gl,v){var data=flatten(v,this.size,4);gl.uniform4fv(this.addr,data);}// Array of matrices (flat or from THREE clases)
  626. function setValueM2Array(gl,v){var data=flatten(v,this.size,4);gl.uniformMatrix2fv(this.addr,false,data);}function setValueM3Array(gl,v){var data=flatten(v,this.size,9);gl.uniformMatrix3fv(this.addr,false,data);}function setValueM4Array(gl,v){var data=flatten(v,this.size,16);gl.uniformMatrix4fv(this.addr,false,data);}// Array of textures (2D / Cube)
  627. function setValueT1Array(gl,v,textures){var n=v.length;var units=allocTexUnits(textures,n);gl.uniform1iv(this.addr,units);for(var _i86=0;_i86!==n;++_i86){textures.safeSetTexture2D(v[_i86]||emptyTexture,units[_i86]);}}function setValueT6Array(gl,v,textures){var n=v.length;var units=allocTexUnits(textures,n);gl.uniform1iv(this.addr,units);for(var _i87=0;_i87!==n;++_i87){textures.safeSetTextureCube(v[_i87]||emptyCubeTexture,units[_i87]);}}// Helper to pick the right setter for a pure (bottom-level) array
  628. function getPureArraySetter(type){switch(type){case 0x1406:return setValueV1fArray;// FLOAT
  629. case 0x8b50:return setValueV2fArray;// _VEC2
  630. case 0x8b51:return setValueV3fArray;// _VEC3
  631. case 0x8b52:return setValueV4fArray;// _VEC4
  632. case 0x8b5a:return setValueM2Array;// _MAT2
  633. case 0x8b5b:return setValueM3Array;// _MAT3
  634. case 0x8b5c:return setValueM4Array;// _MAT4
  635. case 0x1404:case 0x8b56:return setValueV1iArray;// INT, BOOL
  636. case 0x8b53:case 0x8b57:return setValueV2iArray;// _VEC2
  637. case 0x8b54:case 0x8b58:return setValueV3iArray;// _VEC3
  638. case 0x8b55:case 0x8b59:return setValueV4iArray;// _VEC4
  639. case 0x8b5e:// SAMPLER_2D
  640. case 0x8d66:// SAMPLER_EXTERNAL_OES
  641. case 0x8dca:// INT_SAMPLER_2D
  642. case 0x8dd2:// UNSIGNED_INT_SAMPLER_2D
  643. case 0x8b62:// SAMPLER_2D_SHADOW
  644. return setValueT1Array;case 0x8b60:// SAMPLER_CUBE
  645. case 0x8dcc:// INT_SAMPLER_CUBE
  646. case 0x8dd4:// UNSIGNED_INT_SAMPLER_CUBE
  647. case 0x8dc5:// SAMPLER_CUBE_SHADOW
  648. return setValueT6Array;}}// --- Uniform Classes ---
  649. function SingleUniform(id,activeInfo,addr){this.id=id;this.addr=addr;this.cache=[];this.setValue=getSingularSetter(activeInfo.type);// this.path = activeInfo.name; // DEBUG
  650. }function PureArrayUniform(id,activeInfo,addr){this.id=id;this.addr=addr;this.cache=[];this.size=activeInfo.size;this.setValue=getPureArraySetter(activeInfo.type);// this.path = activeInfo.name; // DEBUG
  651. }PureArrayUniform.prototype.updateCache=function(data){var cache=this.cache;if(data instanceof Float32Array&&cache.length!==data.length){this.cache=new Float32Array(data.length);}copyArray(cache,data);};function StructuredUniform(id){this.id=id;this.seq=[];this.map={};}StructuredUniform.prototype.setValue=function(gl,value,textures){var seq=this.seq;for(var _i88=0,n=seq.length;_i88!==n;++_i88){var u=seq[_i88];u.setValue(gl,value[u.id],textures);}};// --- Top-level ---
  652. // Parser - builds up the property tree from the path strings
  653. var RePathPart=/(\w+)(\])?(\[|\.)?/g;// extracts
  654. // - the identifier (member name or array index)
  655. // - followed by an optional right bracket (found when array index)
  656. // - followed by an optional left bracket or dot (type of subscript)
  657. //
  658. // Note: These portions can be read in a non-overlapping fashion and
  659. // allow straightforward parsing of the hierarchy that WebGL encodes
  660. // in the uniform names.
  661. function addUniform(container,uniformObject){container.seq.push(uniformObject);container.map[uniformObject.id]=uniformObject;}function parseUniform(activeInfo,addr,container){var path=activeInfo.name,pathLength=path.length;// reset RegExp object, because of the early exit of a previous run
  662. RePathPart.lastIndex=0;while(true){var match=RePathPart.exec(path),matchEnd=RePathPart.lastIndex;var id=match[1];var idIsIndex=match[2]===']',subscript=match[3];if(idIsIndex)id=id|0;// convert to integer
  663. if(subscript===undefined||subscript==='['&&matchEnd+2===pathLength){// bare name or "pure" bottom-level array "[0]" suffix
  664. addUniform(container,subscript===undefined?new SingleUniform(id,activeInfo,addr):new PureArrayUniform(id,activeInfo,addr));break;}else {// step into inner node / create it in case it doesn't exist
  665. var map=container.map;var next=map[id];if(next===undefined){next=new StructuredUniform(id);addUniform(container,next);}container=next;}}}// Root Container
  666. function WebGLUniforms(gl,program){this.seq=[];this.map={};var n=gl.getProgramParameter(program,35718);for(var _i89=0;_i89<n;++_i89){var info=gl.getActiveUniform(program,_i89),addr=gl.getUniformLocation(program,info.name);parseUniform(info,addr,this);}}WebGLUniforms.prototype.setValue=function(gl,name,value,textures){var u=this.map[name];if(u!==undefined)u.setValue(gl,value,textures);};WebGLUniforms.prototype.setOptional=function(gl,object,name){var v=object[name];if(v!==undefined)this.setValue(gl,name,v);};// Static interface
  667. WebGLUniforms.upload=function(gl,seq,values,textures){for(var _i90=0,n=seq.length;_i90!==n;++_i90){var u=seq[_i90],v=values[u.id];if(v.needsUpdate!==false){// note: always updating when .needsUpdate is undefined
  668. u.setValue(gl,v.value,textures);}}};WebGLUniforms.seqWithValue=function(seq,values){var r=[];for(var _i91=0,n=seq.length;_i91!==n;++_i91){var u=seq[_i91];if(u.id in values)r.push(u);}return r;};function WebGLShader(gl,type,string){var shader=gl.createShader(type);gl.shaderSource(shader,string);gl.compileShader(shader);return shader;}var programIdCount=0;function addLineNumbers(string){var lines=string.split('\n');for(var _i92=0;_i92<lines.length;_i92++){lines[_i92]=_i92+1+': '+lines[_i92];}return lines.join('\n');}function getEncodingComponents(encoding){switch(encoding){case LinearEncoding:return ['Linear','( value )'];case sRGBEncoding:return ['sRGB','( value )'];case RGBEEncoding:return ['RGBE','( value )'];case RGBM7Encoding:return ['RGBM','( value, 7.0 )'];case RGBM16Encoding:return ['RGBM','( value, 16.0 )'];case RGBDEncoding:return ['RGBD','( value, 256.0 )'];case GammaEncoding:return ['Gamma','( value, float( GAMMA_FACTOR ) )'];case LogLuvEncoding:return ['LogLuv','( value )'];default:console.warn('THREE.WebGLProgram: Unsupported encoding:',encoding);return ['Linear','( value )'];}}function getShaderErrors(gl,shader,type){var status=gl.getShaderParameter(shader,35713);var log=gl.getShaderInfoLog(shader).trim();if(status&&log==='')return '';// --enable-privileged-webgl-extension
  669. // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
  670. var source=gl.getShaderSource(shader);return 'THREE.WebGLShader: gl.getShaderInfoLog() '+type+'\n'+log+addLineNumbers(source);}function getTexelDecodingFunction(functionName,encoding){var components=getEncodingComponents(encoding);return 'vec4 '+functionName+'( vec4 value ) { return '+components[0]+'ToLinear'+components[1]+'; }';}function getTexelEncodingFunction(functionName,encoding){var components=getEncodingComponents(encoding);return 'vec4 '+functionName+'( vec4 value ) { return LinearTo'+components[0]+components[1]+'; }';}function getToneMappingFunction(functionName,toneMapping){var toneMappingName;switch(toneMapping){case LinearToneMapping:toneMappingName='Linear';break;case ReinhardToneMapping:toneMappingName='Reinhard';break;case CineonToneMapping:toneMappingName='OptimizedCineon';break;case ACESFilmicToneMapping:toneMappingName='ACESFilmic';break;case CustomToneMapping:toneMappingName='Custom';break;default:console.warn('THREE.WebGLProgram: Unsupported toneMapping:',toneMapping);toneMappingName='Linear';}return 'vec3 '+functionName+'( vec3 color ) { return '+toneMappingName+'ToneMapping( color ); }';}function generateExtensions(parameters){var chunks=[parameters.extensionDerivatives||parameters.envMapCubeUV||parameters.bumpMap||parameters.tangentSpaceNormalMap||parameters.clearcoatNormalMap||parameters.flatShading||parameters.shaderID==='physical'?'#extension GL_OES_standard_derivatives : enable':'',(parameters.extensionFragDepth||parameters.logarithmicDepthBuffer)&&parameters.rendererExtensionFragDepth?'#extension GL_EXT_frag_depth : enable':'',parameters.extensionDrawBuffers&&parameters.rendererExtensionDrawBuffers?'#extension GL_EXT_draw_buffers : require':'',(parameters.extensionShaderTextureLOD||parameters.envMap)&&parameters.rendererExtensionShaderTextureLod?'#extension GL_EXT_shader_texture_lod : enable':''];return chunks.filter(filterEmptyLine).join('\n');}function generateDefines(defines){var chunks=[];for(var name in defines){var value=defines[name];if(value===false)continue;chunks.push('#define '+name+' '+value);}return chunks.join('\n');}function fetchAttributeLocations(gl,program){var attributes={};var n=gl.getProgramParameter(program,35721);for(var _i93=0;_i93<n;_i93++){var info=gl.getActiveAttrib(program,_i93);var name=info.name;// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
  671. attributes[name]=gl.getAttribLocation(program,name);}return attributes;}function filterEmptyLine(string){return string!=='';}function replaceLightNums(string,parameters){return string.replace(/NUM_DIR_LIGHTS/g,parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g,parameters.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g,parameters.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g,parameters.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,parameters.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS/g,parameters.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,parameters.numPointLightShadows);}function replaceClippingPlaneNums(string,parameters){return string.replace(/NUM_CLIPPING_PLANES/g,parameters.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,parameters.numClippingPlanes-parameters.numClipIntersection);}// Resolve Includes
  672. var includePattern=/^[ \t]*#include +<([\w\d./]+)>/gm;function resolveIncludes(string){return string.replace(includePattern,includeReplacer);}function includeReplacer(match,include){var string=ShaderChunk[include];if(string===undefined){throw new Error('Can not resolve #include <'+include+'>');}return resolveIncludes(string);}// Unroll Loops
  673. var deprecatedUnrollLoopPattern=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;var 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;function unrollLoops(string){return string.replace(unrollLoopPattern,loopReplacer).replace(deprecatedUnrollLoopPattern,deprecatedLoopReplacer);}function deprecatedLoopReplacer(match,start,end,snippet){console.warn('WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.');return loopReplacer(match,start,end,snippet);}function loopReplacer(match,start,end,snippet){var string='';for(var _i94=parseInt(start);_i94<parseInt(end);_i94++){string+=snippet.replace(/\[\s*i\s*\]/g,'[ '+_i94+' ]').replace(/UNROLLED_LOOP_INDEX/g,_i94);}return string;}//
  674. function generatePrecision(parameters){var precisionstring='precision '+parameters.precision+' float;\nprecision '+parameters.precision+' int;';if(parameters.precision==='highp'){precisionstring+='\n#define HIGH_PRECISION';}else if(parameters.precision==='mediump'){precisionstring+='\n#define MEDIUM_PRECISION';}else if(parameters.precision==='lowp'){precisionstring+='\n#define LOW_PRECISION';}return precisionstring;}function generateShadowMapTypeDefine(parameters){var shadowMapTypeDefine='SHADOWMAP_TYPE_BASIC';if(parameters.shadowMapType===PCFShadowMap){shadowMapTypeDefine='SHADOWMAP_TYPE_PCF';}else if(parameters.shadowMapType===PCFSoftShadowMap){shadowMapTypeDefine='SHADOWMAP_TYPE_PCF_SOFT';}else if(parameters.shadowMapType===VSMShadowMap){shadowMapTypeDefine='SHADOWMAP_TYPE_VSM';}return shadowMapTypeDefine;}function generateEnvMapTypeDefine(parameters){var envMapTypeDefine='ENVMAP_TYPE_CUBE';if(parameters.envMap){switch(parameters.envMapMode){case CubeReflectionMapping:case CubeRefractionMapping:envMapTypeDefine='ENVMAP_TYPE_CUBE';break;case CubeUVReflectionMapping:case CubeUVRefractionMapping:envMapTypeDefine='ENVMAP_TYPE_CUBE_UV';break;}}return envMapTypeDefine;}function generateEnvMapModeDefine(parameters){var envMapModeDefine='ENVMAP_MODE_REFLECTION';if(parameters.envMap){switch(parameters.envMapMode){case CubeRefractionMapping:case CubeUVRefractionMapping:envMapModeDefine='ENVMAP_MODE_REFRACTION';break;}}return envMapModeDefine;}function generateEnvMapBlendingDefine(parameters){var envMapBlendingDefine='ENVMAP_BLENDING_NONE';if(parameters.envMap){switch(parameters.combine){case MultiplyOperation:envMapBlendingDefine='ENVMAP_BLENDING_MULTIPLY';break;case MixOperation:envMapBlendingDefine='ENVMAP_BLENDING_MIX';break;case AddOperation:envMapBlendingDefine='ENVMAP_BLENDING_ADD';break;}}return envMapBlendingDefine;}function WebGLProgram(renderer,cacheKey,parameters,bindingStates){var gl=renderer.getContext();var defines=parameters.defines;var vertexShader=parameters.vertexShader;var fragmentShader=parameters.fragmentShader;var shadowMapTypeDefine=generateShadowMapTypeDefine(parameters);var envMapTypeDefine=generateEnvMapTypeDefine(parameters);var envMapModeDefine=generateEnvMapModeDefine(parameters);var envMapBlendingDefine=generateEnvMapBlendingDefine(parameters);var gammaFactorDefine=renderer.gammaFactor>0?renderer.gammaFactor:1.0;var customExtensions=parameters.isWebGL2?'':generateExtensions(parameters);var customDefines=generateDefines(defines);var program=gl.createProgram();var prefixVertex,prefixFragment;var versionString=parameters.glslVersion?'#version '+parameters.glslVersion+'\n':'';if(parameters.isRawShaderMaterial){prefixVertex=[customDefines].filter(filterEmptyLine).join('\n');if(prefixVertex.length>0){prefixVertex+='\n';}prefixFragment=[customExtensions,customDefines].filter(filterEmptyLine).join('\n');if(prefixFragment.length>0){prefixFragment+='\n';}}else {prefixVertex=[generatePrecision(parameters),'#define SHADER_NAME '+parameters.shaderName,customDefines,parameters.instancing?'#define USE_INSTANCING':'',parameters.instancingColor?'#define USE_INSTANCING_COLOR':'',parameters.supportsVertexTextures?'#define VERTEX_TEXTURES':'','#define GAMMA_FACTOR '+gammaFactorDefine,'#define MAX_BONES '+parameters.maxBones,parameters.useFog&&parameters.fog?'#define USE_FOG':'',parameters.useFog&&parameters.fogExp2?'#define FOG_EXP2':'',parameters.map?'#define USE_MAP':'',parameters.envMap?'#define USE_ENVMAP':'',parameters.envMap?'#define '+envMapModeDefine:'',parameters.lightMap?'#define USE_LIGHTMAP':'',parameters.aoMap?'#define USE_AOMAP':'',parameters.emissiveMap?'#define USE_EMISSIVEMAP':'',parameters.bumpMap?'#define USE_BUMPMAP':'',parameters.normalMap?'#define USE_NORMALMAP':'',parameters.normalMap&&parameters.objectSpaceNormalMap?'#define OBJECTSPACE_NORMALMAP':'',parameters.normalMap&&parameters.tangentSpaceNormalMap?'#define TANGENTSPACE_NORMALMAP':'',parameters.clearcoatMap?'#define USE_CLEARCOATMAP':'',parameters.clearcoatRoughnessMap?'#define USE_CLEARCOAT_ROUGHNESSMAP':'',parameters.clearcoatNormalMap?'#define USE_CLEARCOAT_NORMALMAP':'',parameters.displacementMap&&parameters.supportsVertexTextures?'#define USE_DISPLACEMENTMAP':'',parameters.specularMap?'#define USE_SPECULARMAP':'',parameters.roughnessMap?'#define USE_ROUGHNESSMAP':'',parameters.metalnessMap?'#define USE_METALNESSMAP':'',parameters.alphaMap?'#define USE_ALPHAMAP':'',parameters.transmissionMap?'#define USE_TRANSMISSIONMAP':'',parameters.vertexTangents?'#define USE_TANGENT':'',parameters.vertexColors?'#define USE_COLOR':'',parameters.vertexUvs?'#define USE_UV':'',parameters.uvsVertexOnly?'#define UVS_VERTEX_ONLY':'',parameters.flatShading?'#define FLAT_SHADED':'',parameters.skinning?'#define USE_SKINNING':'',parameters.useVertexTexture?'#define BONE_TEXTURE':'',parameters.morphTargets?'#define USE_MORPHTARGETS':'',parameters.morphNormals&&parameters.flatShading===false?'#define USE_MORPHNORMALS':'',parameters.doubleSided?'#define DOUBLE_SIDED':'',parameters.flipSided?'#define FLIP_SIDED':'',parameters.shadowMapEnabled?'#define USE_SHADOWMAP':'',parameters.shadowMapEnabled?'#define '+shadowMapTypeDefine:'',parameters.sizeAttenuation?'#define USE_SIZEATTENUATION':'',parameters.logarithmicDepthBuffer?'#define USE_LOGDEPTHBUF':'',parameters.logarithmicDepthBuffer&&parameters.rendererExtensionFragDepth?'#define USE_LOGDEPTHBUF_EXT':'','uniform mat4 modelMatrix;','uniform mat4 modelViewMatrix;','uniform mat4 projectionMatrix;','uniform mat4 viewMatrix;','uniform mat3 normalMatrix;','uniform vec3 cameraPosition;','uniform bool isOrthographic;','#ifdef USE_INSTANCING',' attribute mat4 instanceMatrix;','#endif','#ifdef USE_INSTANCING_COLOR',' attribute vec3 instanceColor;','#endif','attribute vec3 position;','attribute vec3 normal;','attribute vec2 uv;','#ifdef USE_TANGENT',' attribute vec4 tangent;','#endif','#ifdef USE_COLOR',' attribute vec3 color;','#endif','#ifdef USE_MORPHTARGETS',' attribute vec3 morphTarget0;',' attribute vec3 morphTarget1;',' attribute vec3 morphTarget2;',' attribute vec3 morphTarget3;',' #ifdef USE_MORPHNORMALS',' attribute vec3 morphNormal0;',' attribute vec3 morphNormal1;',' attribute vec3 morphNormal2;',' attribute vec3 morphNormal3;',' #else',' attribute vec3 morphTarget4;',' attribute vec3 morphTarget5;',' attribute vec3 morphTarget6;',' attribute vec3 morphTarget7;',' #endif','#endif','#ifdef USE_SKINNING',' attribute vec4 skinIndex;',' attribute vec4 skinWeight;','#endif','\n'].filter(filterEmptyLine).join('\n');prefixFragment=[customExtensions,generatePrecision(parameters),'#define SHADER_NAME '+parameters.shaderName,customDefines,parameters.alphaTest?'#define ALPHATEST '+parameters.alphaTest+(parameters.alphaTest%1?'':'.0'):'',// add '.0' if integer
  675. '#define GAMMA_FACTOR '+gammaFactorDefine,parameters.useFog&&parameters.fog?'#define USE_FOG':'',parameters.useFog&&parameters.fogExp2?'#define FOG_EXP2':'',parameters.map?'#define USE_MAP':'',parameters.matcap?'#define USE_MATCAP':'',parameters.envMap?'#define USE_ENVMAP':'',parameters.envMap?'#define '+envMapTypeDefine:'',parameters.envMap?'#define '+envMapModeDefine:'',parameters.envMap?'#define '+envMapBlendingDefine:'',parameters.lightMap?'#define USE_LIGHTMAP':'',parameters.aoMap?'#define USE_AOMAP':'',parameters.emissiveMap?'#define USE_EMISSIVEMAP':'',parameters.bumpMap?'#define USE_BUMPMAP':'',parameters.normalMap?'#define USE_NORMALMAP':'',parameters.normalMap&&parameters.objectSpaceNormalMap?'#define OBJECTSPACE_NORMALMAP':'',parameters.normalMap&&parameters.tangentSpaceNormalMap?'#define TANGENTSPACE_NORMALMAP':'',parameters.clearcoatMap?'#define USE_CLEARCOATMAP':'',parameters.clearcoatRoughnessMap?'#define USE_CLEARCOAT_ROUGHNESSMAP':'',parameters.clearcoatNormalMap?'#define USE_CLEARCOAT_NORMALMAP':'',parameters.specularMap?'#define USE_SPECULARMAP':'',parameters.roughnessMap?'#define USE_ROUGHNESSMAP':'',parameters.metalnessMap?'#define USE_METALNESSMAP':'',parameters.alphaMap?'#define USE_ALPHAMAP':'',parameters.sheen?'#define USE_SHEEN':'',parameters.transmissionMap?'#define USE_TRANSMISSIONMAP':'',parameters.vertexTangents?'#define USE_TANGENT':'',parameters.vertexColors||parameters.instancingColor?'#define USE_COLOR':'',parameters.vertexUvs?'#define USE_UV':'',parameters.uvsVertexOnly?'#define UVS_VERTEX_ONLY':'',parameters.gradientMap?'#define USE_GRADIENTMAP':'',parameters.flatShading?'#define FLAT_SHADED':'',parameters.doubleSided?'#define DOUBLE_SIDED':'',parameters.flipSided?'#define FLIP_SIDED':'',parameters.shadowMapEnabled?'#define USE_SHADOWMAP':'',parameters.shadowMapEnabled?'#define '+shadowMapTypeDefine:'',parameters.premultipliedAlpha?'#define PREMULTIPLIED_ALPHA':'',parameters.physicallyCorrectLights?'#define PHYSICALLY_CORRECT_LIGHTS':'',parameters.logarithmicDepthBuffer?'#define USE_LOGDEPTHBUF':'',parameters.logarithmicDepthBuffer&&parameters.rendererExtensionFragDepth?'#define USE_LOGDEPTHBUF_EXT':'',(parameters.extensionShaderTextureLOD||parameters.envMap)&&parameters.rendererExtensionShaderTextureLod?'#define TEXTURE_LOD_EXT':'','uniform mat4 viewMatrix;','uniform vec3 cameraPosition;','uniform bool isOrthographic;',parameters.toneMapping!==NoToneMapping?'#define TONE_MAPPING':'',parameters.toneMapping!==NoToneMapping?ShaderChunk['tonemapping_pars_fragment']:'',// this code is required here because it is used by the toneMapping() function defined below
  676. parameters.toneMapping!==NoToneMapping?getToneMappingFunction('toneMapping',parameters.toneMapping):'',parameters.dithering?'#define DITHERING':'',ShaderChunk['encodings_pars_fragment'],// this code is required here because it is used by the various encoding/decoding function defined below
  677. parameters.map?getTexelDecodingFunction('mapTexelToLinear',parameters.mapEncoding):'',parameters.matcap?getTexelDecodingFunction('matcapTexelToLinear',parameters.matcapEncoding):'',parameters.envMap?getTexelDecodingFunction('envMapTexelToLinear',parameters.envMapEncoding):'',parameters.emissiveMap?getTexelDecodingFunction('emissiveMapTexelToLinear',parameters.emissiveMapEncoding):'',parameters.lightMap?getTexelDecodingFunction('lightMapTexelToLinear',parameters.lightMapEncoding):'',getTexelEncodingFunction('linearToOutputTexel',parameters.outputEncoding),parameters.depthPacking?'#define DEPTH_PACKING '+parameters.depthPacking:'','\n'].filter(filterEmptyLine).join('\n');}vertexShader=resolveIncludes(vertexShader);vertexShader=replaceLightNums(vertexShader,parameters);vertexShader=replaceClippingPlaneNums(vertexShader,parameters);fragmentShader=resolveIncludes(fragmentShader);fragmentShader=replaceLightNums(fragmentShader,parameters);fragmentShader=replaceClippingPlaneNums(fragmentShader,parameters);vertexShader=unrollLoops(vertexShader);fragmentShader=unrollLoops(fragmentShader);if(parameters.isWebGL2&&parameters.isRawShaderMaterial!==true){// GLSL 3.0 conversion for built-in materials and ShaderMaterial
  678. versionString='#version 300 es\n';prefixVertex=['#define attribute in','#define varying out','#define texture2D texture'].join('\n')+'\n'+prefixVertex;prefixFragment=['#define varying in',parameters.glslVersion===GLSL3?'':'out highp vec4 pc_fragColor;',parameters.glslVersion===GLSL3?'':'#define gl_FragColor pc_fragColor','#define gl_FragDepthEXT gl_FragDepth','#define texture2D texture','#define textureCube texture','#define texture2DProj textureProj','#define texture2DLodEXT textureLod','#define texture2DProjLodEXT textureProjLod','#define textureCubeLodEXT textureLod','#define texture2DGradEXT textureGrad','#define texture2DProjGradEXT textureProjGrad','#define textureCubeGradEXT textureGrad'].join('\n')+'\n'+prefixFragment;}var vertexGlsl=versionString+prefixVertex+vertexShader;var fragmentGlsl=versionString+prefixFragment+fragmentShader;// console.log( '*VERTEX*', vertexGlsl );
  679. // console.log( '*FRAGMENT*', fragmentGlsl );
  680. var glVertexShader=WebGLShader(gl,35633,vertexGlsl);var glFragmentShader=WebGLShader(gl,35632,fragmentGlsl);gl.attachShader(program,glVertexShader);gl.attachShader(program,glFragmentShader);// Force a particular attribute to index 0.
  681. if(parameters.index0AttributeName!==undefined){gl.bindAttribLocation(program,0,parameters.index0AttributeName);}else if(parameters.morphTargets===true){// programs with morphTargets displace position out of attribute 0
  682. gl.bindAttribLocation(program,0,'position');}gl.linkProgram(program);// check for link errors
  683. if(renderer.debug.checkShaderErrors){var programLog=gl.getProgramInfoLog(program).trim();var vertexLog=gl.getShaderInfoLog(glVertexShader).trim();var fragmentLog=gl.getShaderInfoLog(glFragmentShader).trim();var runnable=true;var haveDiagnostics=true;if(gl.getProgramParameter(program,35714)===false){runnable=false;var vertexErrors=getShaderErrors(gl,glVertexShader,'vertex');var fragmentErrors=getShaderErrors(gl,glFragmentShader,'fragment');console.error('THREE.WebGLProgram: shader error: ',gl.getError(),'35715',gl.getProgramParameter(program,35715),'gl.getProgramInfoLog',programLog,vertexErrors,fragmentErrors);//xzw add:
  684. if(fragmentErrors){console.log(fragmentGlsl.split("\n").map((a,i)=>"".concat(i+1).padEnd(5)+a).join("\n"));}else {console.log(vertexGlsl.split("\n").map((a,i)=>"".concat(i+1).padEnd(5)+a).join("\n"));}}else if(programLog!==''){console.warn('THREE.WebGLProgram: gl.getProgramInfoLog()',programLog);}else if(vertexLog===''||fragmentLog===''){haveDiagnostics=false;}if(haveDiagnostics){this.diagnostics={runnable:runnable,programLog:programLog,vertexShader:{log:vertexLog,prefix:prefixVertex},fragmentShader:{log:fragmentLog,prefix:prefixFragment}};}}// Clean up
  685. // Crashes in iOS9 and iOS10. #18402
  686. // gl.detachShader( program, glVertexShader );
  687. // gl.detachShader( program, glFragmentShader );
  688. gl.deleteShader(glVertexShader);gl.deleteShader(glFragmentShader);// set up caching for uniform locations
  689. var cachedUniforms;this.getUniforms=function(){if(cachedUniforms===undefined){cachedUniforms=new WebGLUniforms(gl,program);}return cachedUniforms;};// set up caching for attribute locations
  690. var cachedAttributes;this.getAttributes=function(){if(cachedAttributes===undefined){cachedAttributes=fetchAttributeLocations(gl,program);}return cachedAttributes;};// free resource
  691. this.destroy=function(){bindingStates.releaseStatesOfProgram(this);gl.deleteProgram(program);this.program=undefined;};//
  692. this.name=parameters.shaderName;this.id=programIdCount++;this.cacheKey=cacheKey;this.usedTimes=1;this.program=program;this.vertexShader=glVertexShader;this.fragmentShader=glFragmentShader;return this;}function WebGLPrograms(renderer,cubemaps,extensions,capabilities,bindingStates,clipping){var programs=[];var isWebGL2=capabilities.isWebGL2;var logarithmicDepthBuffer=capabilities.logarithmicDepthBuffer;var floatVertexTextures=capabilities.floatVertexTextures;var maxVertexUniforms=capabilities.maxVertexUniforms;var vertexTextures=capabilities.vertexTextures;var precision=capabilities.precision;var shaderIDs={MeshDepthMaterial:'depth',MeshDistanceMaterial:'distanceRGBA',MeshNormalMaterial:'normal',MeshBasicMaterial:'basic',MeshLambertMaterial:'lambert',MeshPhongMaterial:'phong',MeshToonMaterial:'toon',MeshStandardMaterial:'physical',MeshPhysicalMaterial:'physical',MeshMatcapMaterial:'matcap',LineBasicMaterial:'basic',LineDashedMaterial:'dashed',PointsMaterial:'points',ShadowMaterial:'shadow',SpriteMaterial:'sprite'};var parameterNames=['precision','isWebGL2','supportsVertexTextures','outputEncoding','instancing','instancingColor','map','mapEncoding','matcap','matcapEncoding','envMap','envMapMode','envMapEncoding','envMapCubeUV','lightMap','lightMapEncoding','aoMap','emissiveMap','emissiveMapEncoding','bumpMap','normalMap','objectSpaceNormalMap','tangentSpaceNormalMap','clearcoatMap','clearcoatRoughnessMap','clearcoatNormalMap','displacementMap','specularMap','roughnessMap','metalnessMap','gradientMap','alphaMap','combine','vertexColors','vertexTangents','vertexUvs','uvsVertexOnly','fog','useFog','fogExp2','flatShading','sizeAttenuation','logarithmicDepthBuffer','skinning','maxBones','useVertexTexture','morphTargets','morphNormals','maxMorphTargets','maxMorphNormals','premultipliedAlpha','numDirLights','numPointLights','numSpotLights','numHemiLights','numRectAreaLights','numDirLightShadows','numPointLightShadows','numSpotLightShadows','shadowMapEnabled','shadowMapType','toneMapping','physicallyCorrectLights','alphaTest','doubleSided','flipSided','numClippingPlanes','numClipIntersection','depthPacking','dithering','sheen','transmissionMap'];function getMaxBones(object){var skeleton=object.skeleton;var bones=skeleton.bones;if(floatVertexTextures){return 1024;}else {// default for when object is not specified
  693. // ( for example when prebuilding shader to be used with multiple objects )
  694. //
  695. // - leave some extra space for other uniforms
  696. // - limit here is ANGLE's 254 max uniform vectors
  697. // (up to 54 should be safe)
  698. var nVertexUniforms=maxVertexUniforms;var nVertexMatrices=Math.floor((nVertexUniforms-20)/4);var maxBones=Math.min(nVertexMatrices,bones.length);if(maxBones<bones.length){console.warn('THREE.WebGLRenderer: Skeleton has '+bones.length+' bones. This GPU supports '+maxBones+'.');return 0;}return maxBones;}}function getTextureEncodingFromMap(map){var encoding;if(map&&map.isTexture){encoding=map.encoding;}else if(map&&map.isWebGLRenderTarget){console.warn('THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.');encoding=map.texture.encoding;}else {encoding=LinearEncoding;}return encoding;}function getParameters(material,lights,shadows,scene,object){var fog=scene.fog;var environment=material.isMeshStandardMaterial?scene.environment:null;var envMap=cubemaps.get(material.envMap||environment);var shaderID=shaderIDs[material.type];// heuristics to create shader parameters according to lights in the scene
  699. // (not to blow over maxLights budget)
  700. var maxBones=object.isSkinnedMesh?getMaxBones(object):0;if(material.precision!==null){precision=capabilities.getMaxPrecision(material.precision);if(precision!==material.precision){console.warn('THREE.WebGLProgram.getParameters:',material.precision,'not supported, using',precision,'instead.');}}var vertexShader,fragmentShader;if(shaderID){var shader=ShaderLib[shaderID];vertexShader=shader.vertexShader;fragmentShader=shader.fragmentShader;}else {vertexShader=material.vertexShader;fragmentShader=material.fragmentShader;}var currentRenderTarget=renderer.getRenderTarget();var parameters={isWebGL2:isWebGL2,shaderID:shaderID,shaderName:material.type,vertexShader:vertexShader,fragmentShader:fragmentShader,defines:material.defines,isRawShaderMaterial:material.isRawShaderMaterial===true,glslVersion:material.glslVersion,precision:precision,instancing:object.isInstancedMesh===true,instancingColor:object.isInstancedMesh===true&&object.instanceColor!==null,supportsVertexTextures:vertexTextures,outputEncoding:currentRenderTarget!==null?getTextureEncodingFromMap(currentRenderTarget.texture):renderer.outputEncoding,map:!!material.map,mapEncoding:getTextureEncodingFromMap(material.map),matcap:!!material.matcap,matcapEncoding:getTextureEncodingFromMap(material.matcap),envMap:!!envMap,envMapMode:envMap&&envMap.mapping,envMapEncoding:getTextureEncodingFromMap(envMap),envMapCubeUV:!!envMap&&(envMap.mapping===CubeUVReflectionMapping||envMap.mapping===CubeUVRefractionMapping),lightMap:!!material.lightMap,lightMapEncoding:getTextureEncodingFromMap(material.lightMap),aoMap:!!material.aoMap,emissiveMap:!!material.emissiveMap,emissiveMapEncoding:getTextureEncodingFromMap(material.emissiveMap),bumpMap:!!material.bumpMap,normalMap:!!material.normalMap,objectSpaceNormalMap:material.normalMapType===ObjectSpaceNormalMap,tangentSpaceNormalMap:material.normalMapType===TangentSpaceNormalMap,clearcoatMap:!!material.clearcoatMap,clearcoatRoughnessMap:!!material.clearcoatRoughnessMap,clearcoatNormalMap:!!material.clearcoatNormalMap,displacementMap:!!material.displacementMap,roughnessMap:!!material.roughnessMap,metalnessMap:!!material.metalnessMap,specularMap:!!material.specularMap,alphaMap:!!material.alphaMap,gradientMap:!!material.gradientMap,sheen:!!material.sheen,transmissionMap:!!material.transmissionMap,combine:material.combine,vertexTangents:material.normalMap&&material.vertexTangents,vertexColors:material.vertexColors,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,uvsVertexOnly:!(!!material.map||!!material.bumpMap||!!material.normalMap||!!material.specularMap||!!material.alphaMap||!!material.emissiveMap||!!material.roughnessMap||!!material.metalnessMap||!!material.clearcoatNormalMap||!!material.transmissionMap)&&!!material.displacementMap,fog:!!fog,useFog:material.fog,fogExp2:fog&&fog.isFogExp2,flatShading:material.flatShading,sizeAttenuation:material.sizeAttenuation,logarithmicDepthBuffer:logarithmicDepthBuffer,skinning:material.skinning&&maxBones>0,maxBones:maxBones,useVertexTexture:floatVertexTextures,morphTargets:material.morphTargets,morphNormals:material.morphNormals,maxMorphTargets:renderer.maxMorphTargets,maxMorphNormals:renderer.maxMorphNormals,numDirLights:lights.directional.length,numPointLights:lights.point.length,numSpotLights:lights.spot.length,numRectAreaLights:lights.rectArea.length,numHemiLights:lights.hemi.length,numDirLightShadows:lights.directionalShadowMap.length,numPointLightShadows:lights.pointShadowMap.length,numSpotLightShadows:lights.spotShadowMap.length,numClippingPlanes:clipping.numPlanes,numClipIntersection:clipping.numIntersection,dithering:material.dithering,shadowMapEnabled:renderer.shadowMap.enabled&&shadows.length>0,shadowMapType:renderer.shadowMap.type,toneMapping:material.toneMapped?renderer.toneMapping:NoToneMapping,physicallyCorrectLights:renderer.physicallyCorrectLights,premultipliedAlpha:material.premultipliedAlpha,alphaTest:material.alphaTest,doubleSided:material.side===DoubleSide,flipSided:material.side===BackSide,depthPacking:material.depthPacking!==undefined?material.depthPacking:false,index0AttributeName:material.index0AttributeName,extensionDerivatives:material.extensions&&material.extensions.derivatives,extensionFragDepth:material.extensions&&material.extensions.fragDepth,extensionDrawBuffers:material.extensions&&material.extensions.drawBuffers,extensionShaderTextureLOD:material.extensions&&material.extensions.shaderTextureLOD,rendererExtensionFragDepth:isWebGL2||extensions.has('EXT_frag_depth'),rendererExtensionDrawBuffers:isWebGL2||extensions.has('WEBGL_draw_buffers'),rendererExtensionShaderTextureLod:isWebGL2||extensions.has('EXT_shader_texture_lod'),customProgramCacheKey:material.customProgramCacheKey()};return parameters;}function getProgramCacheKey(parameters){var array=[];if(parameters.shaderID){array.push(parameters.shaderID);}else {array.push(parameters.fragmentShader);array.push(parameters.vertexShader);}if(parameters.defines!==undefined){for(var name in parameters.defines){array.push(name);array.push(parameters.defines[name]);}}if(parameters.isRawShaderMaterial===false){for(var _i95=0;_i95<parameterNames.length;_i95++){array.push(parameters[parameterNames[_i95]]);}array.push(renderer.outputEncoding);array.push(renderer.gammaFactor);}array.push(parameters.customProgramCacheKey);return array.join();}function getUniforms(material){var shaderID=shaderIDs[material.type];var uniforms;if(shaderID){var shader=ShaderLib[shaderID];uniforms=UniformsUtils.clone(shader.uniforms);}else {uniforms=material.uniforms;}return uniforms;}function acquireProgram(parameters,cacheKey){var program;// Check if code has been already compiled
  701. for(var p=0,pl=programs.length;p<pl;p++){var preexistingProgram=programs[p];if(preexistingProgram.cacheKey===cacheKey){program=preexistingProgram;++program.usedTimes;break;}}if(program===undefined){program=new WebGLProgram(renderer,cacheKey,parameters,bindingStates);programs.push(program);}return program;}function releaseProgram(program){if(--program.usedTimes===0){// Remove from unordered set
  702. var _i96=programs.indexOf(program);programs[_i96]=programs[programs.length-1];programs.pop();// Free WebGL resources
  703. program.destroy();}}return {getParameters:getParameters,getProgramCacheKey:getProgramCacheKey,getUniforms:getUniforms,acquireProgram:acquireProgram,releaseProgram:releaseProgram,// Exposed for resource monitoring & error feedback via renderer.info:
  704. programs:programs};}function WebGLProperties(){var properties=new WeakMap();function get(object){var map=properties.get(object);if(map===undefined){map={};properties.set(object,map);}return map;}function remove(object){properties.delete(object);}function update(object,key,value){properties.get(object)[key]=value;}function dispose(){properties=new WeakMap();}return {get:get,remove:remove,update:update,dispose:dispose};}function painterSortStable(a,b){if(a.groupOrder!==b.groupOrder){return a.groupOrder-b.groupOrder;}else if(a.renderOrder!==b.renderOrder){return a.renderOrder-b.renderOrder;}else if(a.program!==b.program){return a.program.id-b.program.id;}else if(a.material.id!==b.material.id){return a.material.id-b.material.id;}else if(a.z!==b.z){return a.z-b.z;}else {return a.id-b.id;}}function reversePainterSortStable(a,b){if(a.groupOrder!==b.groupOrder){return a.groupOrder-b.groupOrder;}else if(a.renderOrder!==b.renderOrder){return a.renderOrder-b.renderOrder;}else if(a.z!==b.z){return b.z-a.z;}else {return a.id-b.id;}}function WebGLRenderList(properties){var renderItems=[];var renderItemsIndex=0;var opaque=[];var transparent=[];var defaultProgram={id:-1};function init(){renderItemsIndex=0;opaque.length=0;transparent.length=0;}function getNextRenderItem(object,geometry,material,groupOrder,z,group){var renderItem=renderItems[renderItemsIndex];var materialProperties=properties.get(material);if(renderItem===undefined){renderItem={id:object.id,object:object,geometry:geometry,material:material,program:materialProperties.program||defaultProgram,groupOrder:groupOrder,renderOrder:object.renderOrder,z:z,group:group};renderItems[renderItemsIndex]=renderItem;}else {renderItem.id=object.id;renderItem.object=object;renderItem.geometry=geometry;renderItem.material=material;renderItem.program=materialProperties.program||defaultProgram;renderItem.groupOrder=groupOrder;renderItem.renderOrder=object.renderOrder;renderItem.z=z;renderItem.group=group;}renderItemsIndex++;return renderItem;}function push(object,geometry,material,groupOrder,z,group){var renderItem=getNextRenderItem(object,geometry,material,groupOrder,z,group);(material.transparent===true?transparent:opaque).push(renderItem);}function unshift(object,geometry,material,groupOrder,z,group){var renderItem=getNextRenderItem(object,geometry,material,groupOrder,z,group);(material.transparent===true?transparent:opaque).unshift(renderItem);}function sort(customOpaqueSort,customTransparentSort){if(opaque.length>1)opaque.sort(customOpaqueSort||painterSortStable);if(transparent.length>1)transparent.sort(customTransparentSort||reversePainterSortStable);}function finish(){// Clear references from inactive renderItems in the list
  705. for(var _i97=renderItemsIndex,il=renderItems.length;_i97<il;_i97++){var renderItem=renderItems[_i97];if(renderItem.id===null)break;renderItem.id=null;renderItem.object=null;renderItem.geometry=null;renderItem.material=null;renderItem.program=null;renderItem.group=null;}}return {opaque:opaque,transparent:transparent,init:init,push:push,unshift:unshift,finish:finish,sort:sort};}function WebGLRenderLists(properties){var lists=new WeakMap();function get(scene,camera){var cameras=lists.get(scene);var list;if(cameras===undefined){list=new WebGLRenderList(properties);lists.set(scene,new WeakMap());lists.get(scene).set(camera,list);}else {list=cameras.get(camera);if(list===undefined){list=new WebGLRenderList(properties);cameras.set(camera,list);}}return list;}function dispose(){lists=new WeakMap();}return {get:get,dispose:dispose};}function UniformsCache(){var lights={};return {get:function get(light){if(lights[light.id]!==undefined){return lights[light.id];}var uniforms;switch(light.type){case'DirectionalLight':uniforms={direction:new Vector3(),color:new Color()};break;case'SpotLight':uniforms={position:new Vector3(),direction:new Vector3(),color:new Color(),distance:0,coneCos:0,penumbraCos:0,decay:0};break;case'PointLight':uniforms={position:new Vector3(),color:new Color(),distance:0,decay:0};break;case'HemisphereLight':uniforms={direction:new Vector3(),skyColor:new Color(),groundColor:new Color()};break;case'RectAreaLight':uniforms={color:new Color(),position:new Vector3(),halfWidth:new Vector3(),halfHeight:new Vector3()};break;}lights[light.id]=uniforms;return uniforms;}};}function ShadowUniformsCache(){var lights={};return {get:function get(light){if(lights[light.id]!==undefined){return lights[light.id];}var uniforms;switch(light.type){case'DirectionalLight':uniforms={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Vector2()};break;case'SpotLight':uniforms={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Vector2()};break;case'PointLight':uniforms={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Vector2(),shadowCameraNear:1,shadowCameraFar:1000};break;// TODO (abelnation): set RectAreaLight shadow uniforms
  706. }lights[light.id]=uniforms;return uniforms;}};}var nextVersion=0;function shadowCastingLightsFirst(lightA,lightB){return (lightB.castShadow?1:0)-(lightA.castShadow?1:0);}function WebGLLights(extensions,capabilities){var cache=new UniformsCache();var shadowCache=ShadowUniformsCache();var state={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]};for(var _i98=0;_i98<9;_i98++)state.probe.push(new Vector3());var vector3=new Vector3();var matrix4=new Matrix4();var matrix42=new Matrix4();function setup(lights){var r=0,g=0,b=0;for(var _i99=0;_i99<9;_i99++)state.probe[_i99].set(0,0,0);var directionalLength=0;var pointLength=0;var spotLength=0;var rectAreaLength=0;var hemiLength=0;var numDirectionalShadows=0;var numPointShadows=0;var numSpotShadows=0;lights.sort(shadowCastingLightsFirst);for(var _i100=0,l=lights.length;_i100<l;_i100++){var light=lights[_i100];var color=light.color;var intensity=light.intensity;var distance=light.distance;var shadowMap=light.shadow&&light.shadow.map?light.shadow.map.texture:null;if(light.isAmbientLight){r+=color.r*intensity;g+=color.g*intensity;b+=color.b*intensity;}else if(light.isLightProbe){for(var j=0;j<9;j++){state.probe[j].addScaledVector(light.sh.coefficients[j],intensity);}}else if(light.isDirectionalLight){var uniforms=cache.get(light);uniforms.color.copy(light.color).multiplyScalar(light.intensity);if(light.castShadow){var shadow=light.shadow;var shadowUniforms=shadowCache.get(light);shadowUniforms.shadowBias=shadow.bias;shadowUniforms.shadowNormalBias=shadow.normalBias;shadowUniforms.shadowRadius=shadow.radius;shadowUniforms.shadowMapSize=shadow.mapSize;state.directionalShadow[directionalLength]=shadowUniforms;state.directionalShadowMap[directionalLength]=shadowMap;state.directionalShadowMatrix[directionalLength]=light.shadow.matrix;numDirectionalShadows++;}state.directional[directionalLength]=uniforms;directionalLength++;}else if(light.isSpotLight){var _uniforms=cache.get(light);_uniforms.position.setFromMatrixPosition(light.matrixWorld);_uniforms.color.copy(color).multiplyScalar(intensity);_uniforms.distance=distance;_uniforms.coneCos=Math.cos(light.angle);_uniforms.penumbraCos=Math.cos(light.angle*(1-light.penumbra));_uniforms.decay=light.decay;if(light.castShadow){var _shadow=light.shadow;var _shadowUniforms=shadowCache.get(light);_shadowUniforms.shadowBias=_shadow.bias;_shadowUniforms.shadowNormalBias=_shadow.normalBias;_shadowUniforms.shadowRadius=_shadow.radius;_shadowUniforms.shadowMapSize=_shadow.mapSize;state.spotShadow[spotLength]=_shadowUniforms;state.spotShadowMap[spotLength]=shadowMap;state.spotShadowMatrix[spotLength]=light.shadow.matrix;numSpotShadows++;}state.spot[spotLength]=_uniforms;spotLength++;}else if(light.isRectAreaLight){var _uniforms2=cache.get(light);// (a) intensity is the total visible light emitted
  707. //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
  708. // (b) intensity is the brightness of the light
  709. _uniforms2.color.copy(color).multiplyScalar(intensity);_uniforms2.halfWidth.set(light.width*0.5,0.0,0.0);_uniforms2.halfHeight.set(0.0,light.height*0.5,0.0);state.rectArea[rectAreaLength]=_uniforms2;rectAreaLength++;}else if(light.isPointLight){var _uniforms3=cache.get(light);_uniforms3.color.copy(light.color).multiplyScalar(light.intensity);_uniforms3.distance=light.distance;_uniforms3.decay=light.decay;if(light.castShadow){var _shadow2=light.shadow;var _shadowUniforms2=shadowCache.get(light);_shadowUniforms2.shadowBias=_shadow2.bias;_shadowUniforms2.shadowNormalBias=_shadow2.normalBias;_shadowUniforms2.shadowRadius=_shadow2.radius;_shadowUniforms2.shadowMapSize=_shadow2.mapSize;_shadowUniforms2.shadowCameraNear=_shadow2.camera.near;_shadowUniforms2.shadowCameraFar=_shadow2.camera.far;state.pointShadow[pointLength]=_shadowUniforms2;state.pointShadowMap[pointLength]=shadowMap;state.pointShadowMatrix[pointLength]=light.shadow.matrix;numPointShadows++;}state.point[pointLength]=_uniforms3;pointLength++;}else if(light.isHemisphereLight){var _uniforms4=cache.get(light);_uniforms4.skyColor.copy(light.color).multiplyScalar(intensity);_uniforms4.groundColor.copy(light.groundColor).multiplyScalar(intensity);state.hemi[hemiLength]=_uniforms4;hemiLength++;}}if(rectAreaLength>0){if(capabilities.isWebGL2){// WebGL 2
  710. state.rectAreaLTC1=UniformsLib.LTC_FLOAT_1;state.rectAreaLTC2=UniformsLib.LTC_FLOAT_2;}else {// WebGL 1
  711. if(extensions.has('OES_texture_float_linear')===true){state.rectAreaLTC1=UniformsLib.LTC_FLOAT_1;state.rectAreaLTC2=UniformsLib.LTC_FLOAT_2;}else if(extensions.has('OES_texture_half_float_linear')===true){state.rectAreaLTC1=UniformsLib.LTC_HALF_1;state.rectAreaLTC2=UniformsLib.LTC_HALF_2;}else {console.error('THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.');}}}state.ambient[0]=r;state.ambient[1]=g;state.ambient[2]=b;var hash=state.hash;if(hash.directionalLength!==directionalLength||hash.pointLength!==pointLength||hash.spotLength!==spotLength||hash.rectAreaLength!==rectAreaLength||hash.hemiLength!==hemiLength||hash.numDirectionalShadows!==numDirectionalShadows||hash.numPointShadows!==numPointShadows||hash.numSpotShadows!==numSpotShadows){state.directional.length=directionalLength;state.spot.length=spotLength;state.rectArea.length=rectAreaLength;state.point.length=pointLength;state.hemi.length=hemiLength;state.directionalShadow.length=numDirectionalShadows;state.directionalShadowMap.length=numDirectionalShadows;state.pointShadow.length=numPointShadows;state.pointShadowMap.length=numPointShadows;state.spotShadow.length=numSpotShadows;state.spotShadowMap.length=numSpotShadows;state.directionalShadowMatrix.length=numDirectionalShadows;state.pointShadowMatrix.length=numPointShadows;state.spotShadowMatrix.length=numSpotShadows;hash.directionalLength=directionalLength;hash.pointLength=pointLength;hash.spotLength=spotLength;hash.rectAreaLength=rectAreaLength;hash.hemiLength=hemiLength;hash.numDirectionalShadows=numDirectionalShadows;hash.numPointShadows=numPointShadows;hash.numSpotShadows=numSpotShadows;state.version=nextVersion++;}}function setupView(lights,camera){var directionalLength=0;var pointLength=0;var spotLength=0;var rectAreaLength=0;var hemiLength=0;var viewMatrix=camera.matrixWorldInverse;for(var _i101=0,l=lights.length;_i101<l;_i101++){var light=lights[_i101];if(light.isDirectionalLight){var uniforms=state.directional[directionalLength];uniforms.direction.setFromMatrixPosition(light.matrixWorld);vector3.setFromMatrixPosition(light.target.matrixWorld);uniforms.direction.sub(vector3);uniforms.direction.transformDirection(viewMatrix);directionalLength++;}else if(light.isSpotLight){var _uniforms5=state.spot[spotLength];_uniforms5.position.setFromMatrixPosition(light.matrixWorld);_uniforms5.position.applyMatrix4(viewMatrix);_uniforms5.direction.setFromMatrixPosition(light.matrixWorld);vector3.setFromMatrixPosition(light.target.matrixWorld);_uniforms5.direction.sub(vector3);_uniforms5.direction.transformDirection(viewMatrix);spotLength++;}else if(light.isRectAreaLight){var _uniforms6=state.rectArea[rectAreaLength];_uniforms6.position.setFromMatrixPosition(light.matrixWorld);_uniforms6.position.applyMatrix4(viewMatrix);// extract local rotation of light to derive width/height half vectors
  712. matrix42.identity();matrix4.copy(light.matrixWorld);matrix4.premultiply(viewMatrix);matrix42.extractRotation(matrix4);_uniforms6.halfWidth.set(light.width*0.5,0.0,0.0);_uniforms6.halfHeight.set(0.0,light.height*0.5,0.0);_uniforms6.halfWidth.applyMatrix4(matrix42);_uniforms6.halfHeight.applyMatrix4(matrix42);rectAreaLength++;}else if(light.isPointLight){var _uniforms7=state.point[pointLength];_uniforms7.position.setFromMatrixPosition(light.matrixWorld);_uniforms7.position.applyMatrix4(viewMatrix);pointLength++;}else if(light.isHemisphereLight){var _uniforms8=state.hemi[hemiLength];_uniforms8.direction.setFromMatrixPosition(light.matrixWorld);_uniforms8.direction.transformDirection(viewMatrix);_uniforms8.direction.normalize();hemiLength++;}}}return {setup:setup,setupView:setupView,state:state};}function WebGLRenderState(extensions,capabilities){var lights=new WebGLLights(extensions,capabilities);var lightsArray=[];var shadowsArray=[];function init(){lightsArray.length=0;shadowsArray.length=0;}function pushLight(light){lightsArray.push(light);}function pushShadow(shadowLight){shadowsArray.push(shadowLight);}function setupLights(){lights.setup(lightsArray);}function setupLightsView(camera){lights.setupView(lightsArray,camera);}var state={lightsArray:lightsArray,shadowsArray:shadowsArray,lights:lights};return {init:init,state:state,setupLights:setupLights,setupLightsView:setupLightsView,pushLight:pushLight,pushShadow:pushShadow};}function WebGLRenderStates(extensions,capabilities){var renderStates=new WeakMap();function get(scene){var renderCallDepth=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var renderState;if(renderStates.has(scene)===false){renderState=new WebGLRenderState(extensions,capabilities);renderStates.set(scene,[]);renderStates.get(scene).push(renderState);}else {if(renderCallDepth>=renderStates.get(scene).length){renderState=new WebGLRenderState(extensions,capabilities);renderStates.get(scene).push(renderState);}else {renderState=renderStates.get(scene)[renderCallDepth];}}return renderState;}function dispose(){renderStates=new WeakMap();}return {get:get,dispose:dispose};}/**
  713. * parameters = {
  714. *
  715. * opacity: <float>,
  716. *
  717. * map: new THREE.Texture( <Image> ),
  718. *
  719. * alphaMap: new THREE.Texture( <Image> ),
  720. *
  721. * displacementMap: new THREE.Texture( <Image> ),
  722. * displacementScale: <float>,
  723. * displacementBias: <float>,
  724. *
  725. * wireframe: <boolean>,
  726. * wireframeLinewidth: <float>
  727. * }
  728. */function MeshDepthMaterial(parameters){Material.call(this);this.type='MeshDepthMaterial';this.depthPacking=BasicDepthPacking;this.skinning=false;this.morphTargets=false;this.map=null;this.alphaMap=null;this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.wireframe=false;this.wireframeLinewidth=1;this.fog=false;this.setValues(parameters);}MeshDepthMaterial.prototype=Object.create(Material.prototype);MeshDepthMaterial.prototype.constructor=MeshDepthMaterial;MeshDepthMaterial.prototype.isMeshDepthMaterial=true;MeshDepthMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.depthPacking=source.depthPacking;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.map=source.map;this.alphaMap=source.alphaMap;this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;return this;};/**
  729. * parameters = {
  730. *
  731. * referencePosition: <float>,
  732. * nearDistance: <float>,
  733. * farDistance: <float>,
  734. *
  735. * skinning: <bool>,
  736. * morphTargets: <bool>,
  737. *
  738. * map: new THREE.Texture( <Image> ),
  739. *
  740. * alphaMap: new THREE.Texture( <Image> ),
  741. *
  742. * displacementMap: new THREE.Texture( <Image> ),
  743. * displacementScale: <float>,
  744. * displacementBias: <float>
  745. *
  746. * }
  747. */function MeshDistanceMaterial(parameters){Material.call(this);this.type='MeshDistanceMaterial';this.referencePosition=new Vector3();this.nearDistance=1;this.farDistance=1000;this.skinning=false;this.morphTargets=false;this.map=null;this.alphaMap=null;this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.fog=false;this.setValues(parameters);}MeshDistanceMaterial.prototype=Object.create(Material.prototype);MeshDistanceMaterial.prototype.constructor=MeshDistanceMaterial;MeshDistanceMaterial.prototype.isMeshDistanceMaterial=true;MeshDistanceMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.referencePosition.copy(source.referencePosition);this.nearDistance=source.nearDistance;this.farDistance=source.farDistance;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.map=source.map;this.alphaMap=source.alphaMap;this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;return this;};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}";var vsm_vert="void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";function WebGLShadowMap(_renderer,_objects,maxTextureSize){var _frustum=new Frustum();var _shadowMapSize=new Vector2(),_viewportSize=new Vector2(),_viewport=new Vector4(),_depthMaterials=[],_distanceMaterials=[],_materialCache={};var shadowSide={0:BackSide,1:FrontSide,2:DoubleSide};var shadowMaterialVertical=new ShaderMaterial({defines:{SAMPLE_RATE:2.0/8.0,HALF_SAMPLE_RATE:1.0/8.0},uniforms:{shadow_pass:{value:null},resolution:{value:new Vector2()},radius:{value:4.0}},vertexShader:vsm_vert,fragmentShader:vsm_frag});var shadowMaterialHorizontal=shadowMaterialVertical.clone();shadowMaterialHorizontal.defines.HORIZONTAL_PASS=1;var fullScreenTri=new BufferGeometry();fullScreenTri.setAttribute('position',new BufferAttribute(new Float32Array([-1,-1,0.5,3,-1,0.5,-1,3,0.5]),3));var fullScreenMesh=new Mesh(fullScreenTri,shadowMaterialVertical);var scope=this;this.enabled=false;this.autoUpdate=true;this.needsUpdate=false;this.type=PCFShadowMap;this.render=function(lights,scene,camera){if(scope.enabled===false)return;if(scope.autoUpdate===false&&scope.needsUpdate===false)return;if(lights.length===0)return;var currentRenderTarget=_renderer.getRenderTarget();var activeCubeFace=_renderer.getActiveCubeFace();var activeMipmapLevel=_renderer.getActiveMipmapLevel();var _state=_renderer.state;// Set GL state for depth map.
  748. _state.setBlending(NoBlending);_state.buffers.color.setClear(1,1,1,1);_state.buffers.depth.setTest(true);_state.setScissorTest(false);// render depth map
  749. for(var _i102=0,il=lights.length;_i102<il;_i102++){var light=lights[_i102];var shadow=light.shadow;if(shadow===undefined){console.warn('THREE.WebGLShadowMap:',light,'has no shadow.');continue;}if(shadow.autoUpdate===false&&shadow.needsUpdate===false)continue;_shadowMapSize.copy(shadow.mapSize);var shadowFrameExtents=shadow.getFrameExtents();_shadowMapSize.multiply(shadowFrameExtents);_viewportSize.copy(shadow.mapSize);if(_shadowMapSize.x>maxTextureSize||_shadowMapSize.y>maxTextureSize){if(_shadowMapSize.x>maxTextureSize){_viewportSize.x=Math.floor(maxTextureSize/shadowFrameExtents.x);_shadowMapSize.x=_viewportSize.x*shadowFrameExtents.x;shadow.mapSize.x=_viewportSize.x;}if(_shadowMapSize.y>maxTextureSize){_viewportSize.y=Math.floor(maxTextureSize/shadowFrameExtents.y);_shadowMapSize.y=_viewportSize.y*shadowFrameExtents.y;shadow.mapSize.y=_viewportSize.y;}}if(shadow.map===null&&!shadow.isPointLightShadow&&this.type===VSMShadowMap){var pars={minFilter:LinearFilter,magFilter:LinearFilter,format:RGBAFormat};shadow.map=new WebGLRenderTarget(_shadowMapSize.x,_shadowMapSize.y,pars);shadow.map.texture.name=light.name+'.shadowMap';shadow.mapPass=new WebGLRenderTarget(_shadowMapSize.x,_shadowMapSize.y,pars);shadow.camera.updateProjectionMatrix();}if(shadow.map===null){var _pars={minFilter:NearestFilter,magFilter:NearestFilter,format:RGBAFormat};shadow.map=new WebGLRenderTarget(_shadowMapSize.x,_shadowMapSize.y,_pars);shadow.map.texture.name=light.name+'.shadowMap';shadow.camera.updateProjectionMatrix();}_renderer.setRenderTarget(shadow.map);_renderer.clear();var viewportCount=shadow.getViewportCount();for(var vp=0;vp<viewportCount;vp++){var viewport=shadow.getViewport(vp);_viewport.set(_viewportSize.x*viewport.x,_viewportSize.y*viewport.y,_viewportSize.x*viewport.z,_viewportSize.y*viewport.w);_state.viewport(_viewport);shadow.updateMatrices(light,vp);_frustum=shadow.getFrustum();renderObject(scene,camera,shadow.camera,light,this.type);}// do blur pass for VSM
  750. if(!shadow.isPointLightShadow&&this.type===VSMShadowMap){VSMPass(shadow,camera);}shadow.needsUpdate=false;}scope.needsUpdate=false;_renderer.setRenderTarget(currentRenderTarget,activeCubeFace,activeMipmapLevel);};function VSMPass(shadow,camera){var geometry=_objects.update(fullScreenMesh);// vertical pass
  751. shadowMaterialVertical.uniforms.shadow_pass.value=shadow.map.texture;shadowMaterialVertical.uniforms.resolution.value=shadow.mapSize;shadowMaterialVertical.uniforms.radius.value=shadow.radius;_renderer.setRenderTarget(shadow.mapPass);_renderer.clear();_renderer.renderBufferDirect(camera,null,geometry,shadowMaterialVertical,fullScreenMesh,null);// horizontal pass
  752. shadowMaterialHorizontal.uniforms.shadow_pass.value=shadow.mapPass.texture;shadowMaterialHorizontal.uniforms.resolution.value=shadow.mapSize;shadowMaterialHorizontal.uniforms.radius.value=shadow.radius;_renderer.setRenderTarget(shadow.map);_renderer.clear();_renderer.renderBufferDirect(camera,null,geometry,shadowMaterialHorizontal,fullScreenMesh,null);}function getDepthMaterialVariant(useMorphing,useSkinning,useInstancing){var index=useMorphing<<0|useSkinning<<1|useInstancing<<2;var material=_depthMaterials[index];if(material===undefined){material=new MeshDepthMaterial({depthPacking:RGBADepthPacking,morphTargets:useMorphing,skinning:useSkinning});_depthMaterials[index]=material;}return material;}function getDistanceMaterialVariant(useMorphing,useSkinning,useInstancing){var index=useMorphing<<0|useSkinning<<1|useInstancing<<2;var material=_distanceMaterials[index];if(material===undefined){material=new MeshDistanceMaterial({morphTargets:useMorphing,skinning:useSkinning});_distanceMaterials[index]=material;}return material;}function getDepthMaterial(object,geometry,material,light,shadowCameraNear,shadowCameraFar,type){var result=null;var getMaterialVariant=getDepthMaterialVariant;var customMaterial=object.customDepthMaterial;if(light.isPointLight===true){getMaterialVariant=getDistanceMaterialVariant;customMaterial=object.customDistanceMaterial;}if(customMaterial===undefined){var useMorphing=false;if(material.morphTargets===true){useMorphing=geometry.morphAttributes&&geometry.morphAttributes.position&&geometry.morphAttributes.position.length>0;}var useSkinning=false;if(object.isSkinnedMesh===true){if(material.skinning===true){useSkinning=true;}else {console.warn('THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:',object);}}var useInstancing=object.isInstancedMesh===true;result=getMaterialVariant(useMorphing,useSkinning,useInstancing);}else {result=customMaterial;}if(_renderer.localClippingEnabled&&material.clipShadows===true&&material.clippingPlanes.length!==0){// in this case we need a unique material instance reflecting the
  753. // appropriate state
  754. var keyA=result.uuid,keyB=material.uuid;var materialsForVariant=_materialCache[keyA];if(materialsForVariant===undefined){materialsForVariant={};_materialCache[keyA]=materialsForVariant;}var cachedMaterial=materialsForVariant[keyB];if(cachedMaterial===undefined){cachedMaterial=result.clone();materialsForVariant[keyB]=cachedMaterial;}result=cachedMaterial;}result.visible=material.visible;result.wireframe=material.wireframe;if(type===VSMShadowMap){result.side=material.shadowSide!==null?material.shadowSide:material.side;}else {result.side=material.shadowSide!==null?material.shadowSide:shadowSide[material.side];}result.clipShadows=material.clipShadows;result.clippingPlanes=material.clippingPlanes;result.clipIntersection=material.clipIntersection;result.wireframeLinewidth=material.wireframeLinewidth;result.linewidth=material.linewidth;if(light.isPointLight===true&&result.isMeshDistanceMaterial===true){result.referencePosition.setFromMatrixPosition(light.matrixWorld);result.nearDistance=shadowCameraNear;result.farDistance=shadowCameraFar;}return result;}function renderObject(object,camera,shadowCamera,light,type){if(object.visible===false)return;var visible=object.layers.test(camera.layers);if(visible&&(object.isMesh||object.isLine||object.isPoints)){if((object.castShadow||object.receiveShadow&&type===VSMShadowMap)&&(!object.frustumCulled||_frustum.intersectsObject(object))){object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse,object.matrixWorld);var geometry=_objects.update(object);var material=object.material;if(Array.isArray(material)){var groups=geometry.groups;for(var k=0,kl=groups.length;k<kl;k++){var group=groups[k];var groupMaterial=material[group.materialIndex];if(groupMaterial&&groupMaterial.visible){var depthMaterial=getDepthMaterial(object,geometry,groupMaterial,light,shadowCamera.near,shadowCamera.far,type);_renderer.renderBufferDirect(shadowCamera,null,geometry,depthMaterial,object,group);}}}else if(material.visible){var _depthMaterial=getDepthMaterial(object,geometry,material,light,shadowCamera.near,shadowCamera.far,type);_renderer.renderBufferDirect(shadowCamera,null,geometry,_depthMaterial,object,null);}}}var children=object.children;for(var _i103=0,l=children.length;_i103<l;_i103++){renderObject(children[_i103],camera,shadowCamera,light,type);}}}function WebGLState(gl,extensions,capabilities){var isWebGL2=capabilities.isWebGL2;function ColorBuffer(){var locked=false;var color=new Vector4();var currentColorMask=null;var currentColorClear=new Vector4(0,0,0,0);return {setMask:function setMask(colorMask){if(currentColorMask!==colorMask&&!locked){gl.colorMask(colorMask,colorMask,colorMask,colorMask);currentColorMask=colorMask;}},setLocked:function setLocked(lock){locked=lock;},setClear:function setClear(r,g,b,a,premultipliedAlpha){if(premultipliedAlpha===true){r*=a;g*=a;b*=a;}color.set(r,g,b,a);if(currentColorClear.equals(color)===false){gl.clearColor(r,g,b,a);currentColorClear.copy(color);}},reset:function reset(){locked=false;currentColorMask=null;currentColorClear.set(-1,0,0,0);// set to invalid state
  755. }};}function DepthBuffer(){var locked=false;var currentDepthMask=null;var currentDepthFunc=null;var currentDepthClear=null;return {setTest:function setTest(depthTest){if(depthTest){enable(2929);}else {disable(2929);}},setMask:function setMask(depthMask){if(currentDepthMask!==depthMask&&!locked){gl.depthMask(depthMask);currentDepthMask=depthMask;}},setFunc:function setFunc(depthFunc){if(currentDepthFunc!==depthFunc){if(depthFunc){switch(depthFunc){case NeverDepth:gl.depthFunc(512);break;case AlwaysDepth:gl.depthFunc(519);break;case LessDepth:gl.depthFunc(513);break;case LessEqualDepth:gl.depthFunc(515);break;case EqualDepth:gl.depthFunc(514);break;case GreaterEqualDepth:gl.depthFunc(518);break;case GreaterDepth:gl.depthFunc(516);break;case NotEqualDepth:gl.depthFunc(517);break;default:gl.depthFunc(515);}}else {gl.depthFunc(515);}currentDepthFunc=depthFunc;}},setLocked:function setLocked(lock){locked=lock;},setClear:function setClear(depth){if(currentDepthClear!==depth){gl.clearDepth(depth);currentDepthClear=depth;}},reset:function reset(){locked=false;currentDepthMask=null;currentDepthFunc=null;currentDepthClear=null;}};}function StencilBuffer(){var locked=false;var currentStencilMask=null;var currentStencilFunc=null;var currentStencilRef=null;var currentStencilFuncMask=null;var currentStencilFail=null;var currentStencilZFail=null;var currentStencilZPass=null;var currentStencilClear=null;return {setTest:function setTest(stencilTest){if(!locked){if(stencilTest){enable(2960);}else {disable(2960);}}},setMask:function setMask(stencilMask){if(currentStencilMask!==stencilMask&&!locked){gl.stencilMask(stencilMask);currentStencilMask=stencilMask;}},setFunc:function setFunc(stencilFunc,stencilRef,stencilMask){if(currentStencilFunc!==stencilFunc||currentStencilRef!==stencilRef||currentStencilFuncMask!==stencilMask){gl.stencilFunc(stencilFunc,stencilRef,stencilMask);currentStencilFunc=stencilFunc;currentStencilRef=stencilRef;currentStencilFuncMask=stencilMask;}},setOp:function setOp(stencilFail,stencilZFail,stencilZPass){if(currentStencilFail!==stencilFail||currentStencilZFail!==stencilZFail||currentStencilZPass!==stencilZPass){gl.stencilOp(stencilFail,stencilZFail,stencilZPass);currentStencilFail=stencilFail;currentStencilZFail=stencilZFail;currentStencilZPass=stencilZPass;}},setLocked:function setLocked(lock){locked=lock;},setClear:function setClear(stencil){if(currentStencilClear!==stencil){gl.clearStencil(stencil);currentStencilClear=stencil;}},reset:function reset(){locked=false;currentStencilMask=null;currentStencilFunc=null;currentStencilRef=null;currentStencilFuncMask=null;currentStencilFail=null;currentStencilZFail=null;currentStencilZPass=null;currentStencilClear=null;}};}//
  756. var colorBuffer=new ColorBuffer();var depthBuffer=new DepthBuffer();var stencilBuffer=new StencilBuffer();var enabledCapabilities={};var currentProgram=null;var currentBlendingEnabled=null;var currentBlending=null;var currentBlendEquation=null;var currentBlendSrc=null;var currentBlendDst=null;var currentBlendEquationAlpha=null;var currentBlendSrcAlpha=null;var currentBlendDstAlpha=null;var currentPremultipledAlpha=false;var currentFlipSided=null;var currentCullFace=null;var currentLineWidth=null;var currentPolygonOffsetFactor=null;var currentPolygonOffsetUnits=null;var maxTextures=gl.getParameter(35661);var lineWidthAvailable=false;var version=0;var glVersion=gl.getParameter(7938);if(glVersion.indexOf('WebGL')!==-1){version=parseFloat(/^WebGL (\d)/.exec(glVersion)[1]);lineWidthAvailable=version>=1.0;}else if(glVersion.indexOf('OpenGL ES')!==-1){version=parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]);lineWidthAvailable=version>=2.0;}var currentTextureSlot=null;var currentBoundTextures={};var currentScissor=new Vector4();var currentViewport=new Vector4();function createTexture(type,target,count){var data=new Uint8Array(4);// 4 is required to match default unpack alignment of 4.
  757. var texture=gl.createTexture();gl.bindTexture(type,texture);gl.texParameteri(type,10241,9728);gl.texParameteri(type,10240,9728);for(var _i104=0;_i104<count;_i104++){gl.texImage2D(target+_i104,0,6408,1,1,0,6408,5121,data);}return texture;}var emptyTextures={};emptyTextures[3553]=createTexture(3553,3553,1);emptyTextures[34067]=createTexture(34067,34069,6);// init
  758. colorBuffer.setClear(0,0,0,1);depthBuffer.setClear(1);stencilBuffer.setClear(0);enable(2929);depthBuffer.setFunc(LessEqualDepth);setFlipSided(false);setCullFace(CullFaceBack);enable(2884);setBlending(NoBlending);//
  759. function enable(id){if(enabledCapabilities[id]!==true){gl.enable(id);enabledCapabilities[id]=true;}}function disable(id){if(enabledCapabilities[id]!==false){gl.disable(id);enabledCapabilities[id]=false;}}function useProgram(program){if(currentProgram!==program){gl.useProgram(program);currentProgram=program;return true;}return false;}var equationToGL={[AddEquation]:32774,[SubtractEquation]:32778,[ReverseSubtractEquation]:32779};if(isWebGL2){equationToGL[MinEquation]=32775;equationToGL[MaxEquation]=32776;}else {var extension=extensions.get('EXT_blend_minmax');if(extension!==null){equationToGL[MinEquation]=extension.MIN_EXT;equationToGL[MaxEquation]=extension.MAX_EXT;}}var factorToGL={[ZeroFactor]:0,[OneFactor]:1,[SrcColorFactor]:768,[SrcAlphaFactor]:770,[SrcAlphaSaturateFactor]:776,[DstColorFactor]:774,[DstAlphaFactor]:772,[OneMinusSrcColorFactor]:769,[OneMinusSrcAlphaFactor]:771,[OneMinusDstColorFactor]:775,[OneMinusDstAlphaFactor]:773};function setBlending(blending,blendEquation,blendSrc,blendDst,blendEquationAlpha,blendSrcAlpha,blendDstAlpha,premultipliedAlpha){if(blending===NoBlending){if(currentBlendingEnabled){disable(3042);currentBlendingEnabled=false;}return;}if(!currentBlendingEnabled){enable(3042);currentBlendingEnabled=true;}if(blending!==CustomBlending){if(blending!==currentBlending||premultipliedAlpha!==currentPremultipledAlpha){if(currentBlendEquation!==AddEquation||currentBlendEquationAlpha!==AddEquation){gl.blendEquation(32774);currentBlendEquation=AddEquation;currentBlendEquationAlpha=AddEquation;}if(premultipliedAlpha){switch(blending){case NormalBlending:gl.blendFuncSeparate(1,771,1,771);break;case AdditiveBlending:gl.blendFunc(1,1);break;case SubtractiveBlending:gl.blendFuncSeparate(0,0,769,771);break;case MultiplyBlending:gl.blendFuncSeparate(0,768,0,770);break;default:console.error('THREE.WebGLState: Invalid blending: ',blending);break;}}else {switch(blending){case NormalBlending:gl.blendFuncSeparate(770,771,1,771);break;case AdditiveBlending:gl.blendFunc(770,1);break;case SubtractiveBlending:gl.blendFunc(0,769);break;case MultiplyBlending:gl.blendFunc(0,768);break;default:console.error('THREE.WebGLState: Invalid blending: ',blending);break;}}currentBlendSrc=null;currentBlendDst=null;currentBlendSrcAlpha=null;currentBlendDstAlpha=null;currentBlending=blending;currentPremultipledAlpha=premultipliedAlpha;}return;}// custom blending
  760. blendEquationAlpha=blendEquationAlpha||blendEquation;blendSrcAlpha=blendSrcAlpha||blendSrc;blendDstAlpha=blendDstAlpha||blendDst;if(blendEquation!==currentBlendEquation||blendEquationAlpha!==currentBlendEquationAlpha){gl.blendEquationSeparate(equationToGL[blendEquation],equationToGL[blendEquationAlpha]);currentBlendEquation=blendEquation;currentBlendEquationAlpha=blendEquationAlpha;}if(blendSrc!==currentBlendSrc||blendDst!==currentBlendDst||blendSrcAlpha!==currentBlendSrcAlpha||blendDstAlpha!==currentBlendDstAlpha){gl.blendFuncSeparate(factorToGL[blendSrc],factorToGL[blendDst],factorToGL[blendSrcAlpha],factorToGL[blendDstAlpha]);currentBlendSrc=blendSrc;currentBlendDst=blendDst;currentBlendSrcAlpha=blendSrcAlpha;currentBlendDstAlpha=blendDstAlpha;}currentBlending=blending;currentPremultipledAlpha=null;}function setMaterial(material,frontFaceCW){material.side===DoubleSide?disable(2884):enable(2884);var flipSided=material.side===BackSide;if(frontFaceCW)flipSided=!flipSided;setFlipSided(flipSided);material.blending===NormalBlending&&material.transparent===false?setBlending(NoBlending):setBlending(material.blending,material.blendEquation,material.blendSrc,material.blendDst,material.blendEquationAlpha,material.blendSrcAlpha,material.blendDstAlpha,material.premultipliedAlpha);depthBuffer.setFunc(material.depthFunc);depthBuffer.setTest(material.depthTest);depthBuffer.setMask(material.depthWrite);colorBuffer.setMask(material.colorWrite);var stencilWrite=material.stencilWrite;stencilBuffer.setTest(stencilWrite);if(stencilWrite){stencilBuffer.setMask(material.stencilWriteMask);stencilBuffer.setFunc(material.stencilFunc,material.stencilRef,material.stencilFuncMask);stencilBuffer.setOp(material.stencilFail,material.stencilZFail,material.stencilZPass);}setPolygonOffset(material.polygonOffset,material.polygonOffsetFactor,material.polygonOffsetUnits);}//
  761. function setFlipSided(flipSided){if(currentFlipSided!==flipSided){if(flipSided){gl.frontFace(2304);}else {gl.frontFace(2305);}currentFlipSided=flipSided;}}function setCullFace(cullFace){if(cullFace!==CullFaceNone){enable(2884);if(cullFace!==currentCullFace){if(cullFace===CullFaceBack){gl.cullFace(1029);}else if(cullFace===CullFaceFront){gl.cullFace(1028);}else {gl.cullFace(1032);}}}else {disable(2884);}currentCullFace=cullFace;}function setLineWidth(width){if(width!==currentLineWidth){if(lineWidthAvailable)gl.lineWidth(width);currentLineWidth=width;}}function setPolygonOffset(polygonOffset,factor,units){if(polygonOffset){enable(32823);if(currentPolygonOffsetFactor!==factor||currentPolygonOffsetUnits!==units){gl.polygonOffset(factor,units);currentPolygonOffsetFactor=factor;currentPolygonOffsetUnits=units;}}else {disable(32823);}}function setScissorTest(scissorTest){if(scissorTest){enable(3089);}else {disable(3089);}}// texture
  762. function activeTexture(webglSlot){if(webglSlot===undefined)webglSlot=33984+maxTextures-1;if(currentTextureSlot!==webglSlot){gl.activeTexture(webglSlot);currentTextureSlot=webglSlot;}}function bindTexture(webglType,webglTexture){if(currentTextureSlot===null){activeTexture();}var boundTexture=currentBoundTextures[currentTextureSlot];if(boundTexture===undefined){boundTexture={type:undefined,texture:undefined};currentBoundTextures[currentTextureSlot]=boundTexture;}if(boundTexture.type!==webglType||boundTexture.texture!==webglTexture){gl.bindTexture(webglType,webglTexture||emptyTextures[webglType]);boundTexture.type=webglType;boundTexture.texture=webglTexture;}}function unbindTexture(){var boundTexture=currentBoundTextures[currentTextureSlot];if(boundTexture!==undefined&&boundTexture.type!==undefined){gl.bindTexture(boundTexture.type,null);boundTexture.type=undefined;boundTexture.texture=undefined;}}function compressedTexImage2D(){try{gl.compressedTexImage2D.apply(gl,arguments);}catch(error){console.error('THREE.WebGLState:',error);}}function texImage2D(){try{gl.texImage2D.apply(gl,arguments);}catch(error){console.error('THREE.WebGLState:',error);}}function texImage3D(){try{gl.texImage3D.apply(gl,arguments);}catch(error){console.error('THREE.WebGLState:',error);}}//
  763. function scissor(scissor){if(currentScissor.equals(scissor)===false){gl.scissor(scissor.x,scissor.y,scissor.z,scissor.w);currentScissor.copy(scissor);}}function viewport(viewport){if(currentViewport.equals(viewport)===false){gl.viewport(viewport.x,viewport.y,viewport.z,viewport.w);currentViewport.copy(viewport);}}//
  764. function reset(){enabledCapabilities={};currentTextureSlot=null;currentBoundTextures={};currentProgram=null;currentBlendingEnabled=null;currentBlending=null;currentBlendEquation=null;currentBlendSrc=null;currentBlendDst=null;currentBlendEquationAlpha=null;currentBlendSrcAlpha=null;currentBlendDstAlpha=null;currentPremultipledAlpha=false;currentFlipSided=null;currentCullFace=null;currentLineWidth=null;currentPolygonOffsetFactor=null;currentPolygonOffsetUnits=null;colorBuffer.reset();depthBuffer.reset();stencilBuffer.reset();}return {buffers:{color:colorBuffer,depth:depthBuffer,stencil:stencilBuffer},enable:enable,disable:disable,useProgram:useProgram,setBlending:setBlending,setMaterial:setMaterial,setFlipSided:setFlipSided,setCullFace:setCullFace,setLineWidth:setLineWidth,setPolygonOffset:setPolygonOffset,setScissorTest:setScissorTest,activeTexture:activeTexture,bindTexture:bindTexture,unbindTexture:unbindTexture,compressedTexImage2D:compressedTexImage2D,texImage2D:texImage2D,texImage3D:texImage3D,scissor:scissor,viewport:viewport,reset:reset};}function WebGLTextures(_gl,extensions,state,properties,capabilities,utils,info){var isWebGL2=capabilities.isWebGL2;var maxTextures=capabilities.maxTextures;var maxCubemapSize=capabilities.maxCubemapSize;var maxTextureSize=capabilities.maxTextureSize;var maxSamples=capabilities.maxSamples;var _videoTextures=new WeakMap();var _canvas;// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
  765. // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
  766. // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
  767. var useOffscreenCanvas=false;try{useOffscreenCanvas=typeof OffscreenCanvas!=='undefined'&&new OffscreenCanvas(1,1).getContext('2d')!==null;}catch(err){// Ignore any errors
  768. }function createCanvas(width,height){// Use OffscreenCanvas when available. Specially needed in web workers
  769. return useOffscreenCanvas?new OffscreenCanvas(width,height):document.createElementNS('http://www.w3.org/1999/xhtml','canvas');}function resizeImage(image,needsPowerOfTwo,needsNewCanvas,maxSize){var scale=1;// handle case if texture exceeds max size
  770. if(image.width>maxSize||image.height>maxSize){scale=maxSize/Math.max(image.width,image.height);}// only perform resize if necessary
  771. if(scale<1||needsPowerOfTwo===true){// only perform resize for certain image types
  772. if(typeof HTMLImageElement!=='undefined'&&image instanceof HTMLImageElement||typeof HTMLCanvasElement!=='undefined'&&image instanceof HTMLCanvasElement||typeof ImageBitmap!=='undefined'&&image instanceof ImageBitmap){var floor=needsPowerOfTwo?MathUtils.floorPowerOfTwo:Math.floor;var width=floor(scale*image.width);var height=floor(scale*image.height);if(_canvas===undefined)_canvas=createCanvas(width,height);// cube textures can't reuse the same canvas
  773. var canvas=needsNewCanvas?createCanvas(width,height):_canvas;canvas.width=width;canvas.height=height;var context=canvas.getContext('2d');context.drawImage(image,0,0,width,height);console.warn('THREE.WebGLRenderer: Texture has been resized from ('+image.width+'x'+image.height+') to ('+width+'x'+height+').');return canvas;}else {if('data'in image){console.warn('THREE.WebGLRenderer: Image in DataTexture is too big ('+image.width+'x'+image.height+').');}return image;}}return image;}function isPowerOfTwo(image){return MathUtils.isPowerOfTwo(image.width)&&MathUtils.isPowerOfTwo(image.height);}function textureNeedsPowerOfTwo(texture){if(isWebGL2)return false;return texture.wrapS!==ClampToEdgeWrapping||texture.wrapT!==ClampToEdgeWrapping||texture.minFilter!==NearestFilter&&texture.minFilter!==LinearFilter;}function textureNeedsGenerateMipmaps(texture,supportsMips){return texture.generateMipmaps&&supportsMips&&texture.minFilter!==NearestFilter&&texture.minFilter!==LinearFilter;}function generateMipmap(target,texture,width,height){_gl.generateMipmap(target);var textureProperties=properties.get(texture);// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
  774. textureProperties.__maxMipLevel=Math.log(Math.max(width,height))*Math.LOG2E;}function getInternalFormat(internalFormatName,glFormat,glType){if(isWebGL2===false)return glFormat;if(internalFormatName!==null){if(_gl[internalFormatName]!==undefined)return _gl[internalFormatName];console.warn('THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \''+internalFormatName+'\'');}var internalFormat=glFormat;if(glFormat===6403){if(glType===5126)internalFormat=33326;if(glType===5131)internalFormat=33325;if(glType===5121)internalFormat=33321;}if(glFormat===6407){if(glType===5126)internalFormat=34837;if(glType===5131)internalFormat=34843;if(glType===5121)internalFormat=32849;}if(glFormat===6408){if(glType===5126)internalFormat=34836;if(glType===5131)internalFormat=34842;if(glType===5121)internalFormat=32856;}if(internalFormat===33325||internalFormat===33326||internalFormat===34842||internalFormat===34836){extensions.get('EXT_color_buffer_float');}return internalFormat;}// Fallback filters for non-power-of-2 textures
  775. function filterFallback(f){if(f===NearestFilter||f===NearestMipmapNearestFilter||f===NearestMipmapLinearFilter){return 9728;}return 9729;}//
  776. function onTextureDispose(event){var texture=event.target;texture.removeEventListener('dispose',onTextureDispose);deallocateTexture(texture);if(texture.isVideoTexture){_videoTextures.delete(texture);}info.memory.textures--;}function onRenderTargetDispose(event){var renderTarget=event.target;renderTarget.removeEventListener('dispose',onRenderTargetDispose);deallocateRenderTarget(renderTarget);info.memory.textures--;}//
  777. function deallocateTexture(texture){var textureProperties=properties.get(texture);if(textureProperties.__webglInit===undefined)return;_gl.deleteTexture(textureProperties.__webglTexture);properties.remove(texture);}function deallocateRenderTarget(renderTarget){var renderTargetProperties=properties.get(renderTarget);var textureProperties=properties.get(renderTarget.texture);if(!renderTarget)return;if(textureProperties.__webglTexture!==undefined){_gl.deleteTexture(textureProperties.__webglTexture);}if(renderTarget.depthTexture){renderTarget.depthTexture.dispose();}if(renderTarget.isWebGLCubeRenderTarget){for(var _i105=0;_i105<6;_i105++){_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[_i105]);if(renderTargetProperties.__webglDepthbuffer)_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[_i105]);}}else {_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer);if(renderTargetProperties.__webglDepthbuffer)_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer);if(renderTargetProperties.__webglMultisampledFramebuffer)_gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer);if(renderTargetProperties.__webglColorRenderbuffer)_gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer);if(renderTargetProperties.__webglDepthRenderbuffer)_gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer);}properties.remove(renderTarget.texture);properties.remove(renderTarget);}//
  778. var textureUnits=0;function resetTextureUnits(){textureUnits=0;}function allocateTextureUnit(){var textureUnit=textureUnits;if(textureUnit>=maxTextures){console.warn('THREE.WebGLTextures: Trying to use '+textureUnit+' texture units while this GPU supports only '+maxTextures);}textureUnits+=1;return textureUnit;}//
  779. function setTexture2D(texture,slot){var textureProperties=properties.get(texture);if(texture.isVideoTexture)updateVideoTexture(texture);if(texture.version>0&&textureProperties.__version!==texture.version){var image=texture.image;if(image===undefined){console.warn('THREE.WebGLRenderer: Texture marked for update but image is undefined');}else if(image.complete===false){console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete');}else {uploadTexture(textureProperties,texture,slot);return;}}state.activeTexture(33984+slot);state.bindTexture(3553,textureProperties.__webglTexture);}function setTexture2DArray(texture,slot){var textureProperties=properties.get(texture);if(texture.version>0&&textureProperties.__version!==texture.version){uploadTexture(textureProperties,texture,slot);return;}state.activeTexture(33984+slot);state.bindTexture(35866,textureProperties.__webglTexture);}function setTexture3D(texture,slot){var textureProperties=properties.get(texture);if(texture.version>0&&textureProperties.__version!==texture.version){uploadTexture(textureProperties,texture,slot);return;}state.activeTexture(33984+slot);state.bindTexture(32879,textureProperties.__webglTexture);}function setTextureCube(texture,slot){var textureProperties=properties.get(texture);if(texture.version>0&&textureProperties.__version!==texture.version){uploadCubeTexture(textureProperties,texture,slot);return;}state.activeTexture(33984+slot);state.bindTexture(34067,textureProperties.__webglTexture);}var wrappingToGL={[RepeatWrapping]:10497,[ClampToEdgeWrapping]:33071,[MirroredRepeatWrapping]:33648};var filterToGL={[NearestFilter]:9728,[NearestMipmapNearestFilter]:9984,[NearestMipmapLinearFilter]:9986,[LinearFilter]:9729,[LinearMipmapNearestFilter]:9985,[LinearMipmapLinearFilter]:9987};function setTextureParameters(textureType,texture,supportsMips){if(supportsMips){_gl.texParameteri(textureType,10242,wrappingToGL[texture.wrapS]);_gl.texParameteri(textureType,10243,wrappingToGL[texture.wrapT]);if(textureType===32879||textureType===35866){_gl.texParameteri(textureType,32882,wrappingToGL[texture.wrapR]);}_gl.texParameteri(textureType,10240,filterToGL[texture.magFilter]);_gl.texParameteri(textureType,10241,filterToGL[texture.minFilter]);}else {_gl.texParameteri(textureType,10242,33071);_gl.texParameteri(textureType,10243,33071);if(textureType===32879||textureType===35866){_gl.texParameteri(textureType,32882,33071);}if(texture.wrapS!==ClampToEdgeWrapping||texture.wrapT!==ClampToEdgeWrapping){console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.');}_gl.texParameteri(textureType,10240,filterFallback(texture.magFilter));_gl.texParameteri(textureType,10241,filterFallback(texture.minFilter));if(texture.minFilter!==NearestFilter&&texture.minFilter!==LinearFilter){console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.');}}var extension=extensions.get('EXT_texture_filter_anisotropic');if(extension){if(texture.type===FloatType&&extensions.get('OES_texture_float_linear')===null)return;if(texture.type===HalfFloatType&&(isWebGL2||extensions.get('OES_texture_half_float_linear'))===null)return;if(texture.anisotropy>1||properties.get(texture).__currentAnisotropy){_gl.texParameterf(textureType,extension.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(texture.anisotropy,capabilities.getMaxAnisotropy()));properties.get(texture).__currentAnisotropy=texture.anisotropy;}}}function initTexture(textureProperties,texture){if(textureProperties.__webglInit===undefined){textureProperties.__webglInit=true;texture.addEventListener('dispose',onTextureDispose);textureProperties.__webglTexture=_gl.createTexture();info.memory.textures++;}}function uploadTexture(textureProperties,texture,slot){var textureType=3553;if(texture.isDataTexture2DArray)textureType=35866;if(texture.isDataTexture3D)textureType=32879;initTexture(textureProperties,texture);state.activeTexture(33984+slot);state.bindTexture(textureType,textureProperties.__webglTexture);_gl.pixelStorei(37440,texture.flipY);_gl.pixelStorei(37441,texture.premultiplyAlpha);_gl.pixelStorei(3317,texture.unpackAlignment);var needsPowerOfTwo=textureNeedsPowerOfTwo(texture)&&isPowerOfTwo(texture.image)===false;var image=resizeImage(texture.image,needsPowerOfTwo,false,maxTextureSize);var supportsMips=isPowerOfTwo(image)||isWebGL2,glFormat=utils.convert(texture.format);var glType=utils.convert(texture.type),glInternalFormat=getInternalFormat(texture.internalFormat,glFormat,glType);setTextureParameters(textureType,texture,supportsMips);var mipmap;var mipmaps=texture.mipmaps;if(texture.isDepthTexture){// populate depth texture with dummy data
  780. glInternalFormat=6402;if(isWebGL2){if(texture.type===FloatType){glInternalFormat=36012;}else if(texture.type===UnsignedIntType){glInternalFormat=33190;}else if(texture.type===UnsignedInt248Type$1){glInternalFormat=35056;}else {glInternalFormat=33189;// WebGL2 requires sized internalformat for glTexImage2D
  781. }}else {if(texture.type===FloatType){console.error('WebGLRenderer: Floating point depth texture requires WebGL2.');}}// validation checks for WebGL 1
  782. if(texture.format===DepthFormat&&glInternalFormat===6402){// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  783. // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
  784. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  785. if(texture.type!==UnsignedShortType&&texture.type!==UnsignedIntType){console.warn('THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.');texture.type=UnsignedShortType;glType=utils.convert(texture.type);}}if(texture.format===DepthStencilFormat&&glInternalFormat===6402){// Depth stencil textures need the DEPTH_STENCIL internal format
  786. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  787. glInternalFormat=34041;// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  788. // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
  789. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  790. if(texture.type!==UnsignedInt248Type$1){console.warn('THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.');texture.type=UnsignedInt248Type$1;glType=utils.convert(texture.type);}}//
  791. state.texImage2D(3553,0,glInternalFormat,image.width,image.height,0,glFormat,glType,null);}else if(texture.isDataTexture){// use manually created mipmaps if available
  792. // if there are no manual mipmaps
  793. // set 0 level mipmap and then use GL to generate other mipmap levels
  794. if(mipmaps.length>0&&supportsMips){for(var _i106=0,il=mipmaps.length;_i106<il;_i106++){mipmap=mipmaps[_i106];state.texImage2D(3553,_i106,glInternalFormat,mipmap.width,mipmap.height,0,glFormat,glType,mipmap.data);}texture.generateMipmaps=false;textureProperties.__maxMipLevel=mipmaps.length-1;}else {state.texImage2D(3553,0,glInternalFormat,image.width,image.height,0,glFormat,glType,image.data);textureProperties.__maxMipLevel=0;}}else if(texture.isCompressedTexture){for(var _i107=0,_il9=mipmaps.length;_i107<_il9;_i107++){mipmap=mipmaps[_i107];if(texture.format!==RGBAFormat&&texture.format!==RGBFormat){if(glFormat!==null){state.compressedTexImage2D(3553,_i107,glInternalFormat,mipmap.width,mipmap.height,0,mipmap.data);}else {console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()');}}else {state.texImage2D(3553,_i107,glInternalFormat,mipmap.width,mipmap.height,0,glFormat,glType,mipmap.data);}}textureProperties.__maxMipLevel=mipmaps.length-1;}else if(texture.isDataTexture2DArray){state.texImage3D(35866,0,glInternalFormat,image.width,image.height,image.depth,0,glFormat,glType,image.data);textureProperties.__maxMipLevel=0;}else if(texture.isDataTexture3D){state.texImage3D(32879,0,glInternalFormat,image.width,image.height,image.depth,0,glFormat,glType,image.data);textureProperties.__maxMipLevel=0;}else {// regular Texture (image, video, canvas)
  795. // use manually created mipmaps if available
  796. // if there are no manual mipmaps
  797. // set 0 level mipmap and then use GL to generate other mipmap levels
  798. if(mipmaps.length>0&&supportsMips){for(var _i108=0,_il10=mipmaps.length;_i108<_il10;_i108++){mipmap=mipmaps[_i108];state.texImage2D(3553,_i108,glInternalFormat,glFormat,glType,mipmap);}texture.generateMipmaps=false;textureProperties.__maxMipLevel=mipmaps.length-1;}else {state.texImage2D(3553,0,glInternalFormat,glFormat,glType,image);textureProperties.__maxMipLevel=0;}}if(textureNeedsGenerateMipmaps(texture,supportsMips)){generateMipmap(textureType,texture,image.width,image.height);}textureProperties.__version=texture.version;if(texture.onUpdate)texture.onUpdate(texture);}function uploadCubeTexture(textureProperties,texture,slot){if(texture.image.length!==6)return;initTexture(textureProperties,texture);state.activeTexture(33984+slot);state.bindTexture(34067,textureProperties.__webglTexture);_gl.pixelStorei(37440,texture.flipY);var isCompressed=texture&&(texture.isCompressedTexture||texture.image[0].isCompressedTexture);var isDataTexture=texture.image[0]&&texture.image[0].isDataTexture;var cubeImage=[];for(var _i109=0;_i109<6;_i109++){if(!isCompressed&&!isDataTexture){cubeImage[_i109]=resizeImage(texture.image[_i109],false,true,maxCubemapSize);}else {cubeImage[_i109]=isDataTexture?texture.image[_i109].image:texture.image[_i109];}}var image=cubeImage[0],supportsMips=isPowerOfTwo(image)||isWebGL2,glFormat=utils.convert(texture.format),glType=utils.convert(texture.type),glInternalFormat=getInternalFormat(texture.internalFormat,glFormat,glType);setTextureParameters(34067,texture,supportsMips);var mipmaps;if(isCompressed){for(var _i110=0;_i110<6;_i110++){mipmaps=cubeImage[_i110].mipmaps;for(var j=0;j<mipmaps.length;j++){var mipmap=mipmaps[j];if(texture.format!==RGBAFormat&&texture.format!==RGBFormat){if(glFormat!==null){state.compressedTexImage2D(34069+_i110,j,glInternalFormat,mipmap.width,mipmap.height,0,mipmap.data);}else {console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()');}}else {state.texImage2D(34069+_i110,j,glInternalFormat,mipmap.width,mipmap.height,0,glFormat,glType,mipmap.data);}}}textureProperties.__maxMipLevel=mipmaps.length-1;}else {mipmaps=texture.mipmaps;for(var _i111=0;_i111<6;_i111++){if(isDataTexture){state.texImage2D(34069+_i111,0,glInternalFormat,cubeImage[_i111].width,cubeImage[_i111].height,0,glFormat,glType,cubeImage[_i111].data);for(var _j3=0;_j3<mipmaps.length;_j3++){var _mipmap=mipmaps[_j3];var mipmapImage=_mipmap.image[_i111].image;state.texImage2D(34069+_i111,_j3+1,glInternalFormat,mipmapImage.width,mipmapImage.height,0,glFormat,glType,mipmapImage.data);}}else {state.texImage2D(34069+_i111,0,glInternalFormat,glFormat,glType,cubeImage[_i111]);for(var _j4=0;_j4<mipmaps.length;_j4++){var _mipmap2=mipmaps[_j4];state.texImage2D(34069+_i111,_j4+1,glInternalFormat,glFormat,glType,_mipmap2.image[_i111]);}}}textureProperties.__maxMipLevel=mipmaps.length;}if(textureNeedsGenerateMipmaps(texture,supportsMips)){// We assume images for cube map have the same size.
  799. generateMipmap(34067,texture,image.width,image.height);}textureProperties.__version=texture.version;if(texture.onUpdate)texture.onUpdate(texture);}// Render targets
  800. // Setup storage for target texture and bind it to correct framebuffer
  801. function setupFrameBufferTexture(framebuffer,renderTarget,attachment,textureTarget){var glFormat=utils.convert(renderTarget.texture.format);var glType=utils.convert(renderTarget.texture.type);var glInternalFormat=getInternalFormat(renderTarget.texture.internalFormat,glFormat,glType);state.texImage2D(textureTarget,0,glInternalFormat,renderTarget.width,renderTarget.height,0,glFormat,glType,null);_gl.bindFramebuffer(36160,framebuffer);_gl.framebufferTexture2D(36160,attachment,textureTarget,properties.get(renderTarget.texture).__webglTexture,0);_gl.bindFramebuffer(36160,null);}// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
  802. function setupRenderBufferStorage(renderbuffer,renderTarget,isMultisample){_gl.bindRenderbuffer(36161,renderbuffer);if(renderTarget.depthBuffer&&!renderTarget.stencilBuffer){var glInternalFormat=33189;if(isMultisample){var depthTexture=renderTarget.depthTexture;if(depthTexture&&depthTexture.isDepthTexture){if(depthTexture.type===FloatType){glInternalFormat=36012;}else if(depthTexture.type===UnsignedIntType){glInternalFormat=33190;}}var samples=getRenderTargetSamples(renderTarget);_gl.renderbufferStorageMultisample(36161,samples,glInternalFormat,renderTarget.width,renderTarget.height);}else {_gl.renderbufferStorage(36161,glInternalFormat,renderTarget.width,renderTarget.height);}_gl.framebufferRenderbuffer(36160,36096,36161,renderbuffer);}else if(renderTarget.depthBuffer&&renderTarget.stencilBuffer){if(isMultisample){var _samples=getRenderTargetSamples(renderTarget);_gl.renderbufferStorageMultisample(36161,_samples,35056,renderTarget.width,renderTarget.height);}else {_gl.renderbufferStorage(36161,34041,renderTarget.width,renderTarget.height);}_gl.framebufferRenderbuffer(36160,33306,36161,renderbuffer);}else {var glFormat=utils.convert(renderTarget.texture.format);var glType=utils.convert(renderTarget.texture.type);var _glInternalFormat=getInternalFormat(renderTarget.texture.internalFormat,glFormat,glType);if(isMultisample){var _samples2=getRenderTargetSamples(renderTarget);_gl.renderbufferStorageMultisample(36161,_samples2,_glInternalFormat,renderTarget.width,renderTarget.height);}else {_gl.renderbufferStorage(36161,_glInternalFormat,renderTarget.width,renderTarget.height);}}_gl.bindRenderbuffer(36161,null);}// Setup resources for a Depth Texture for a FBO (needs an extension)
  803. function setupDepthTexture(framebuffer,renderTarget){var isCube=renderTarget&&renderTarget.isWebGLCubeRenderTarget;if(isCube)throw new Error('Depth Texture with cube render targets is not supported');_gl.bindFramebuffer(36160,framebuffer);if(!(renderTarget.depthTexture&&renderTarget.depthTexture.isDepthTexture)){throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture');}// upload an empty depth texture with framebuffer size
  804. if(!properties.get(renderTarget.depthTexture).__webglTexture||renderTarget.depthTexture.image.width!==renderTarget.width||renderTarget.depthTexture.image.height!==renderTarget.height){renderTarget.depthTexture.image.width=renderTarget.width;renderTarget.depthTexture.image.height=renderTarget.height;renderTarget.depthTexture.needsUpdate=true;}setTexture2D(renderTarget.depthTexture,0);var webglDepthTexture=properties.get(renderTarget.depthTexture).__webglTexture;if(renderTarget.depthTexture.format===DepthFormat){_gl.framebufferTexture2D(36160,36096,3553,webglDepthTexture,0);}else if(renderTarget.depthTexture.format===DepthStencilFormat){_gl.framebufferTexture2D(36160,33306,3553,webglDepthTexture,0);}else {throw new Error('Unknown depthTexture format');}}// Setup GL resources for a non-texture depth buffer
  805. function setupDepthRenderbuffer(renderTarget){var renderTargetProperties=properties.get(renderTarget);var isCube=renderTarget.isWebGLCubeRenderTarget===true;if(renderTarget.depthTexture){if(isCube)throw new Error('target.depthTexture not supported in Cube render targets');setupDepthTexture(renderTargetProperties.__webglFramebuffer,renderTarget);}else {if(isCube){renderTargetProperties.__webglDepthbuffer=[];for(var _i112=0;_i112<6;_i112++){_gl.bindFramebuffer(36160,renderTargetProperties.__webglFramebuffer[_i112]);renderTargetProperties.__webglDepthbuffer[_i112]=_gl.createRenderbuffer();setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[_i112],renderTarget,false);}}else {_gl.bindFramebuffer(36160,renderTargetProperties.__webglFramebuffer);renderTargetProperties.__webglDepthbuffer=_gl.createRenderbuffer();setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer,renderTarget,false);}}_gl.bindFramebuffer(36160,null);}// Set up GL resources for the render target
  806. function setupRenderTarget(renderTarget){var renderTargetProperties=properties.get(renderTarget);var textureProperties=properties.get(renderTarget.texture);renderTarget.addEventListener('dispose',onRenderTargetDispose);textureProperties.__webglTexture=_gl.createTexture();info.memory.textures++;var isCube=renderTarget.isWebGLCubeRenderTarget===true;var isMultisample=renderTarget.isWebGLMultisampleRenderTarget===true;var supportsMips=isPowerOfTwo(renderTarget)||isWebGL2;// Handles WebGL2 RGBFormat fallback - #18858
  807. if(isWebGL2&&renderTarget.texture.format===RGBFormat&&(renderTarget.texture.type===FloatType||renderTarget.texture.type===HalfFloatType)){renderTarget.texture.format=RGBAFormat;console.warn('THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.');}// Setup framebuffer
  808. if(isCube){renderTargetProperties.__webglFramebuffer=[];for(var _i113=0;_i113<6;_i113++){renderTargetProperties.__webglFramebuffer[_i113]=_gl.createFramebuffer();}}else {renderTargetProperties.__webglFramebuffer=_gl.createFramebuffer();if(isMultisample){if(isWebGL2){renderTargetProperties.__webglMultisampledFramebuffer=_gl.createFramebuffer();renderTargetProperties.__webglColorRenderbuffer=_gl.createRenderbuffer();_gl.bindRenderbuffer(36161,renderTargetProperties.__webglColorRenderbuffer);var glFormat=utils.convert(renderTarget.texture.format);var glType=utils.convert(renderTarget.texture.type);var glInternalFormat=getInternalFormat(renderTarget.texture.internalFormat,glFormat,glType);var samples=getRenderTargetSamples(renderTarget);_gl.renderbufferStorageMultisample(36161,samples,glInternalFormat,renderTarget.width,renderTarget.height);_gl.bindFramebuffer(36160,renderTargetProperties.__webglMultisampledFramebuffer);_gl.framebufferRenderbuffer(36160,36064,36161,renderTargetProperties.__webglColorRenderbuffer);_gl.bindRenderbuffer(36161,null);if(renderTarget.depthBuffer){renderTargetProperties.__webglDepthRenderbuffer=_gl.createRenderbuffer();setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer,renderTarget,true);}_gl.bindFramebuffer(36160,null);}else {console.warn('THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.');}}}// Setup color buffer
  809. if(isCube){state.bindTexture(34067,textureProperties.__webglTexture);setTextureParameters(34067,renderTarget.texture,supportsMips);for(var _i114=0;_i114<6;_i114++){setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[_i114],renderTarget,36064,34069+_i114);}if(textureNeedsGenerateMipmaps(renderTarget.texture,supportsMips)){generateMipmap(34067,renderTarget.texture,renderTarget.width,renderTarget.height);}state.bindTexture(34067,null);}else {state.bindTexture(3553,textureProperties.__webglTexture);setTextureParameters(3553,renderTarget.texture,supportsMips);setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer,renderTarget,36064,3553);if(textureNeedsGenerateMipmaps(renderTarget.texture,supportsMips)){generateMipmap(3553,renderTarget.texture,renderTarget.width,renderTarget.height);}state.bindTexture(3553,null);}// Setup depth and stencil buffers
  810. if(renderTarget.depthBuffer){setupDepthRenderbuffer(renderTarget);}}function updateRenderTargetMipmap(renderTarget){var texture=renderTarget.texture;var supportsMips=isPowerOfTwo(renderTarget)||isWebGL2;if(textureNeedsGenerateMipmaps(texture,supportsMips)){var target=renderTarget.isWebGLCubeRenderTarget?34067:3553;var webglTexture=properties.get(texture).__webglTexture;state.bindTexture(target,webglTexture);generateMipmap(target,texture,renderTarget.width,renderTarget.height);state.bindTexture(target,null);}}function updateMultisampleRenderTarget(renderTarget){if(renderTarget.isWebGLMultisampleRenderTarget){if(isWebGL2){var renderTargetProperties=properties.get(renderTarget);_gl.bindFramebuffer(36008,renderTargetProperties.__webglMultisampledFramebuffer);_gl.bindFramebuffer(36009,renderTargetProperties.__webglFramebuffer);var width=renderTarget.width;var height=renderTarget.height;var mask=16384;if(renderTarget.depthBuffer)mask|=256;if(renderTarget.stencilBuffer)mask|=1024;_gl.blitFramebuffer(0,0,width,height,0,0,width,height,mask,9728);_gl.bindFramebuffer(36160,renderTargetProperties.__webglMultisampledFramebuffer);// see #18905
  811. }else {console.warn('THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.');}}}function getRenderTargetSamples(renderTarget){return isWebGL2&&renderTarget.isWebGLMultisampleRenderTarget?Math.min(maxSamples,renderTarget.samples):0;}function updateVideoTexture(texture){var frame=info.render.frame;// Check the last frame we updated the VideoTexture
  812. if(_videoTextures.get(texture)!==frame){_videoTextures.set(texture,frame);texture.update();}}// backwards compatibility
  813. var warnedTexture2D=false;var warnedTextureCube=false;function safeSetTexture2D(texture,slot){if(texture&&texture.isWebGLRenderTarget){if(warnedTexture2D===false){console.warn('THREE.WebGLTextures.safeSetTexture2D: don\'t use render targets as textures. Use their .texture property instead.');warnedTexture2D=true;}texture=texture.texture;}setTexture2D(texture,slot);}function safeSetTextureCube(texture,slot){if(texture&&texture.isWebGLCubeRenderTarget){if(warnedTextureCube===false){console.warn('THREE.WebGLTextures.safeSetTextureCube: don\'t use cube render targets as textures. Use their .texture property instead.');warnedTextureCube=true;}texture=texture.texture;}setTextureCube(texture,slot);}//
  814. this.allocateTextureUnit=allocateTextureUnit;this.resetTextureUnits=resetTextureUnits;this.setTexture2D=setTexture2D;this.setTexture2DArray=setTexture2DArray;this.setTexture3D=setTexture3D;this.setTextureCube=setTextureCube;this.setupRenderTarget=setupRenderTarget;this.updateRenderTargetMipmap=updateRenderTargetMipmap;this.updateMultisampleRenderTarget=updateMultisampleRenderTarget;this.safeSetTexture2D=safeSetTexture2D;this.safeSetTextureCube=safeSetTextureCube;}function WebGLUtils(gl,extensions,capabilities){var isWebGL2=capabilities.isWebGL2;function convert(p){var extension;if(p===UnsignedByteType)return 5121;if(p===UnsignedShort4444Type)return 32819;if(p===UnsignedShort5551Type)return 32820;if(p===UnsignedShort565Type)return 33635;if(p===ByteType)return 5120;if(p===ShortType)return 5122;if(p===UnsignedShortType)return 5123;if(p===IntType)return 5124;if(p===UnsignedIntType)return 5125;if(p===FloatType)return 5126;if(p===HalfFloatType){if(isWebGL2)return 5131;extension=extensions.get('OES_texture_half_float');if(extension!==null){return extension.HALF_FLOAT_OES;}else {return null;}}if(p===AlphaFormat)return 6406;if(p===RGBFormat)return 6407;if(p===RGBAFormat)return 6408;if(p===LuminanceFormat)return 6409;if(p===LuminanceAlphaFormat)return 6410;if(p===DepthFormat)return 6402;if(p===DepthStencilFormat)return 34041;if(p===RedFormat)return 6403;// WebGL2 formats.
  815. if(p===RedIntegerFormat)return 36244;if(p===RGFormat)return 33319;if(p===RGIntegerFormat)return 33320;if(p===RGBIntegerFormat)return 36248;if(p===RGBAIntegerFormat)return 36249;if(p===RGB_S3TC_DXT1_Format||p===RGBA_S3TC_DXT1_Format$1||p===RGBA_S3TC_DXT3_Format||p===RGBA_S3TC_DXT5_Format$1){extension=extensions.get('WEBGL_compressed_texture_s3tc');if(extension!==null){if(p===RGB_S3TC_DXT1_Format)return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;if(p===RGBA_S3TC_DXT1_Format$1)return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(p===RGBA_S3TC_DXT3_Format)return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(p===RGBA_S3TC_DXT5_Format$1)return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;}else {return null;}}if(p===RGB_PVRTC_4BPPV1_Format||p===RGB_PVRTC_2BPPV1_Format||p===RGBA_PVRTC_4BPPV1_Format||p===RGBA_PVRTC_2BPPV1_Format){extension=extensions.get('WEBGL_compressed_texture_pvrtc');if(extension!==null){if(p===RGB_PVRTC_4BPPV1_Format)return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(p===RGB_PVRTC_2BPPV1_Format)return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(p===RGBA_PVRTC_4BPPV1_Format)return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(p===RGBA_PVRTC_2BPPV1_Format)return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;}else {return null;}}if(p===RGB_ETC1_Format){extension=extensions.get('WEBGL_compressed_texture_etc1');if(extension!==null){return extension.COMPRESSED_RGB_ETC1_WEBGL;}else {return null;}}if(p===RGB_ETC2_Format||p===RGBA_ETC2_EAC_Format){extension=extensions.get('WEBGL_compressed_texture_etc');if(extension!==null){if(p===RGB_ETC2_Format)return extension.COMPRESSED_RGB8_ETC2;if(p===RGBA_ETC2_EAC_Format)return extension.COMPRESSED_RGBA8_ETC2_EAC;}}if(p===RGBA_ASTC_4x4_Format||p===RGBA_ASTC_5x4_Format||p===RGBA_ASTC_5x5_Format||p===RGBA_ASTC_6x5_Format||p===RGBA_ASTC_6x6_Format||p===RGBA_ASTC_8x5_Format||p===RGBA_ASTC_8x6_Format||p===RGBA_ASTC_8x8_Format||p===RGBA_ASTC_10x5_Format||p===RGBA_ASTC_10x6_Format||p===RGBA_ASTC_10x8_Format||p===RGBA_ASTC_10x10_Format||p===RGBA_ASTC_12x10_Format||p===RGBA_ASTC_12x12_Format||p===SRGB8_ALPHA8_ASTC_4x4_Format||p===SRGB8_ALPHA8_ASTC_5x4_Format||p===SRGB8_ALPHA8_ASTC_5x5_Format||p===SRGB8_ALPHA8_ASTC_6x5_Format||p===SRGB8_ALPHA8_ASTC_6x6_Format||p===SRGB8_ALPHA8_ASTC_8x5_Format||p===SRGB8_ALPHA8_ASTC_8x6_Format||p===SRGB8_ALPHA8_ASTC_8x8_Format||p===SRGB8_ALPHA8_ASTC_10x5_Format||p===SRGB8_ALPHA8_ASTC_10x6_Format||p===SRGB8_ALPHA8_ASTC_10x8_Format||p===SRGB8_ALPHA8_ASTC_10x10_Format||p===SRGB8_ALPHA8_ASTC_12x10_Format||p===SRGB8_ALPHA8_ASTC_12x12_Format){extension=extensions.get('WEBGL_compressed_texture_astc');if(extension!==null){// TODO Complete?
  816. return p;}else {return null;}}if(p===RGBA_BPTC_Format){extension=extensions.get('EXT_texture_compression_bptc');if(extension!==null){// TODO Complete?
  817. return p;}else {return null;}}if(p===UnsignedInt248Type$1){if(isWebGL2)return 34042;extension=extensions.get('WEBGL_depth_texture');if(extension!==null){return extension.UNSIGNED_INT_24_8_WEBGL;}else {return null;}}}return {convert:convert};}function ArrayCamera(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];PerspectiveCamera.call(this);this.cameras=array;}ArrayCamera.prototype=Object.assign(Object.create(PerspectiveCamera.prototype),{constructor:ArrayCamera,isArrayCamera:true});function Group(){Object3D.call(this);this.type='Group';}Group.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Group,isGroup:true});function WebXRController(){this._targetRay=null;this._grip=null;this._hand=null;}Object.assign(WebXRController.prototype,{constructor:WebXRController,getHandSpace:function getHandSpace(){if(this._hand===null){this._hand=new Group();this._hand.matrixAutoUpdate=false;this._hand.visible=false;this._hand.joints=[];this._hand.inputState={pinching:false};if(window.XRHand){for(var _i115=0;_i115<=window.XRHand.LITTLE_PHALANX_TIP;_i115++){// The transform of this joint will be updated with the joint pose on each frame
  818. var joint=new Group();joint.matrixAutoUpdate=false;joint.visible=false;this._hand.joints.push(joint);// ??
  819. this._hand.add(joint);}}}return this._hand;},getTargetRaySpace:function getTargetRaySpace(){if(this._targetRay===null){this._targetRay=new Group();this._targetRay.matrixAutoUpdate=false;this._targetRay.visible=false;}return this._targetRay;},getGripSpace:function getGripSpace(){if(this._grip===null){this._grip=new Group();this._grip.matrixAutoUpdate=false;this._grip.visible=false;}return this._grip;},dispatchEvent:function dispatchEvent(event){if(this._targetRay!==null){this._targetRay.dispatchEvent(event);}if(this._grip!==null){this._grip.dispatchEvent(event);}if(this._hand!==null){this._hand.dispatchEvent(event);}return this;},disconnect:function disconnect(inputSource){this.dispatchEvent({type:'disconnected',data:inputSource});if(this._targetRay!==null){this._targetRay.visible=false;}if(this._grip!==null){this._grip.visible=false;}if(this._hand!==null){this._hand.visible=false;}return this;},update:function update(inputSource,frame,referenceSpace){var inputPose=null;var gripPose=null;var handPose=null;var targetRay=this._targetRay;var grip=this._grip;var hand=this._hand;if(inputSource&&frame.session.visibilityState!=='visible-blurred'){if(hand&&inputSource.hand){handPose=true;for(var _i116=0;_i116<=window.XRHand.LITTLE_PHALANX_TIP;_i116++){if(inputSource.hand[_i116]){// Update the joints groups with the XRJoint poses
  820. var jointPose=frame.getJointPose(inputSource.hand[_i116],referenceSpace);var joint=hand.joints[_i116];if(jointPose!==null){joint.matrix.fromArray(jointPose.transform.matrix);joint.matrix.decompose(joint.position,joint.rotation,joint.scale);joint.jointRadius=jointPose.radius;}joint.visible=jointPose!==null;// Custom events
  821. // Check pinch
  822. var indexTip=hand.joints[window.XRHand.INDEX_PHALANX_TIP];var thumbTip=hand.joints[window.XRHand.THUMB_PHALANX_TIP];var distance=indexTip.position.distanceTo(thumbTip.position);var distanceToPinch=0.02;var threshold=0.005;if(hand.inputState.pinching&&distance>distanceToPinch+threshold){hand.inputState.pinching=false;this.dispatchEvent({type:'pinchend',handedness:inputSource.handedness,target:this});}else if(!hand.inputState.pinching&&distance<=distanceToPinch-threshold){hand.inputState.pinching=true;this.dispatchEvent({type:'pinchstart',handedness:inputSource.handedness,target:this});}}}}else {if(targetRay!==null){inputPose=frame.getPose(inputSource.targetRaySpace,referenceSpace);if(inputPose!==null){targetRay.matrix.fromArray(inputPose.transform.matrix);targetRay.matrix.decompose(targetRay.position,targetRay.rotation,targetRay.scale);}}if(grip!==null&&inputSource.gripSpace){gripPose=frame.getPose(inputSource.gripSpace,referenceSpace);if(gripPose!==null){grip.matrix.fromArray(gripPose.transform.matrix);grip.matrix.decompose(grip.position,grip.rotation,grip.scale);}}}}if(targetRay!==null){targetRay.visible=inputPose!==null;}if(grip!==null){grip.visible=gripPose!==null;}if(hand!==null){hand.visible=handPose!==null;}return this;}});function WebXRManager(renderer,gl){var scope=this;var session=null;var framebufferScaleFactor=1.0;var referenceSpace=null;var referenceSpaceType='local-floor';var pose=null;var controllers=[];var inputSourcesMap=new Map();//
  823. var cameraL=new PerspectiveCamera();cameraL.layers.enable(1);cameraL.viewport=new Vector4();var cameraR=new PerspectiveCamera();cameraR.layers.enable(2);cameraR.viewport=new Vector4();var cameras=[cameraL,cameraR];var cameraVR=new ArrayCamera();cameraVR.layers.enable(1);cameraVR.layers.enable(2);var _currentDepthNear=null;var _currentDepthFar=null;//
  824. this.enabled=false;this.isPresenting=false;this.getController=function(index){var controller=controllers[index];if(controller===undefined){controller=new WebXRController();controllers[index]=controller;}return controller.getTargetRaySpace();};this.getControllerGrip=function(index){var controller=controllers[index];if(controller===undefined){controller=new WebXRController();controllers[index]=controller;}return controller.getGripSpace();};this.getHand=function(index){var controller=controllers[index];if(controller===undefined){controller=new WebXRController();controllers[index]=controller;}return controller.getHandSpace();};//
  825. function onSessionEvent(event){var controller=inputSourcesMap.get(event.inputSource);if(controller){controller.dispatchEvent({type:event.type,data:event.inputSource});}}function onSessionEnd(){inputSourcesMap.forEach(function(controller,inputSource){controller.disconnect(inputSource);});inputSourcesMap.clear();//
  826. renderer.setFramebuffer(null);renderer.setRenderTarget(renderer.getRenderTarget());// Hack #15830
  827. animation.stop();scope.isPresenting=false;scope.dispatchEvent({type:'sessionend'});}function onRequestReferenceSpace(value){referenceSpace=value;animation.setContext(session);animation.start();scope.isPresenting=true;scope.dispatchEvent({type:'sessionstart'});}this.setFramebufferScaleFactor=function(value){framebufferScaleFactor=value;if(scope.isPresenting===true){console.warn('THREE.WebXRManager: Cannot change framebuffer scale while presenting.');}};this.setReferenceSpaceType=function(value){referenceSpaceType=value;if(scope.isPresenting===true){console.warn('THREE.WebXRManager: Cannot change reference space type while presenting.');}};this.getReferenceSpace=function(){return referenceSpace;};this.getSession=function(){return session;};this.setSession=function(value){session=value;if(session!==null){session.addEventListener('select',onSessionEvent);session.addEventListener('selectstart',onSessionEvent);session.addEventListener('selectend',onSessionEvent);session.addEventListener('squeeze',onSessionEvent);session.addEventListener('squeezestart',onSessionEvent);session.addEventListener('squeezeend',onSessionEvent);session.addEventListener('end',onSessionEnd);var attributes=gl.getContextAttributes();if(attributes.xrCompatible!==true){gl.makeXRCompatible();}var layerInit={antialias:attributes.antialias,alpha:attributes.alpha,depth:attributes.depth,stencil:attributes.stencil,framebufferScaleFactor:framebufferScaleFactor};// eslint-disable-next-line no-undef
  828. var baseLayer=new XRWebGLLayer(session,gl,layerInit);session.updateRenderState({baseLayer:baseLayer});session.requestReferenceSpace(referenceSpaceType).then(onRequestReferenceSpace);//
  829. session.addEventListener('inputsourceschange',updateInputSources);}};function updateInputSources(event){var inputSources=session.inputSources;// Assign inputSources to available controllers
  830. for(var _i117=0;_i117<controllers.length;_i117++){inputSourcesMap.set(inputSources[_i117],controllers[_i117]);}// Notify disconnected
  831. for(var _i118=0;_i118<event.removed.length;_i118++){var inputSource=event.removed[_i118];var controller=inputSourcesMap.get(inputSource);if(controller){controller.dispatchEvent({type:'disconnected',data:inputSource});inputSourcesMap.delete(inputSource);}}// Notify connected
  832. for(var _i119=0;_i119<event.added.length;_i119++){var _inputSource=event.added[_i119];var _controller=inputSourcesMap.get(_inputSource);if(_controller){_controller.dispatchEvent({type:'connected',data:_inputSource});}}}//
  833. var cameraLPos=new Vector3();var cameraRPos=new Vector3();/**
  834. * Assumes 2 cameras that are parallel and share an X-axis, and that
  835. * the cameras' projection and world matrices have already been set.
  836. * And that near and far planes are identical for both cameras.
  837. * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
  838. */function setProjectionFromUnion(camera,cameraL,cameraR){cameraLPos.setFromMatrixPosition(cameraL.matrixWorld);cameraRPos.setFromMatrixPosition(cameraR.matrixWorld);var ipd=cameraLPos.distanceTo(cameraRPos);var projL=cameraL.projectionMatrix.elements;var projR=cameraR.projectionMatrix.elements;// VR systems will have identical far and near planes, and
  839. // most likely identical top and bottom frustum extents.
  840. // Use the left camera for these values.
  841. var near=projL[14]/(projL[10]-1);var far=projL[14]/(projL[10]+1);var topFov=(projL[9]+1)/projL[5];var bottomFov=(projL[9]-1)/projL[5];var leftFov=(projL[8]-1)/projL[0];var rightFov=(projR[8]+1)/projR[0];var left=near*leftFov;var right=near*rightFov;// Calculate the new camera's position offset from the
  842. // left camera. xOffset should be roughly half `ipd`.
  843. var zOffset=ipd/(-leftFov+rightFov);var xOffset=zOffset*-leftFov;// TODO: Better way to apply this offset?
  844. cameraL.matrixWorld.decompose(camera.position,camera.quaternion,camera.scale);camera.translateX(xOffset);camera.translateZ(zOffset);camera.matrixWorld.compose(camera.position,camera.quaternion,camera.scale);camera.matrixWorldInverse.copy(camera.matrixWorld).invert();// Find the union of the frustum values of the cameras and scale
  845. // the values so that the near plane's position does not change in world space,
  846. // although must now be relative to the new union camera.
  847. var near2=near+zOffset;var far2=far+zOffset;var left2=left-xOffset;var right2=right+(ipd-xOffset);var top2=topFov*far/far2*near2;var bottom2=bottomFov*far/far2*near2;camera.projectionMatrix.makePerspective(left2,right2,top2,bottom2,near2,far2);}function updateCamera(camera,parent){if(parent===null){camera.matrixWorld.copy(camera.matrix);}else {camera.matrixWorld.multiplyMatrices(parent.matrixWorld,camera.matrix);}camera.matrixWorldInverse.copy(camera.matrixWorld).invert();}this.getCamera=function(camera){cameraVR.near=cameraR.near=cameraL.near=camera.near;cameraVR.far=cameraR.far=cameraL.far=camera.far;if(_currentDepthNear!==cameraVR.near||_currentDepthFar!==cameraVR.far){// Note that the new renderState won't apply until the next frame. See #18320
  848. session.updateRenderState({depthNear:cameraVR.near,depthFar:cameraVR.far});_currentDepthNear=cameraVR.near;_currentDepthFar=cameraVR.far;}var parent=camera.parent;var cameras=cameraVR.cameras;updateCamera(cameraVR,parent);for(var _i120=0;_i120<cameras.length;_i120++){updateCamera(cameras[_i120],parent);}// update camera and its children
  849. camera.matrixWorld.copy(cameraVR.matrixWorld);var children=camera.children;for(var _i121=0,l=children.length;_i121<l;_i121++){children[_i121].updateMatrixWorld(true);}// update projection matrix for proper view frustum culling
  850. if(cameras.length===2){setProjectionFromUnion(cameraVR,cameraL,cameraR);}else {// assume single camera setup (AR)
  851. cameraVR.projectionMatrix.copy(cameraL.projectionMatrix);}return cameraVR;};// Animation Loop
  852. var onAnimationFrameCallback=null;function onAnimationFrame(time,frame){pose=frame.getViewerPose(referenceSpace);if(pose!==null){var views=pose.views;var baseLayer=session.renderState.baseLayer;renderer.setFramebuffer(baseLayer.framebuffer);var cameraVRNeedsUpdate=false;// check if it's necessary to rebuild cameraVR's camera list
  853. if(views.length!==cameraVR.cameras.length){cameraVR.cameras.length=0;cameraVRNeedsUpdate=true;}for(var _i122=0;_i122<views.length;_i122++){var view=views[_i122];var viewport=baseLayer.getViewport(view);var camera=cameras[_i122];camera.matrix.fromArray(view.transform.matrix);camera.projectionMatrix.fromArray(view.projectionMatrix);camera.viewport.set(viewport.x,viewport.y,viewport.width,viewport.height);if(_i122===0){cameraVR.matrix.copy(camera.matrix);}if(cameraVRNeedsUpdate===true){cameraVR.cameras.push(camera);}}}//
  854. var inputSources=session.inputSources;for(var _i123=0;_i123<controllers.length;_i123++){var controller=controllers[_i123];var inputSource=inputSources[_i123];controller.update(inputSource,frame,referenceSpace);}if(onAnimationFrameCallback)onAnimationFrameCallback(time,frame);}var animation=new WebGLAnimation();animation.setAnimationLoop(onAnimationFrame);this.setAnimationLoop=function(callback){onAnimationFrameCallback=callback;};this.dispose=function(){};}Object.assign(WebXRManager.prototype,EventDispatcher.prototype);function WebGLMaterials(properties){function refreshFogUniforms(uniforms,fog){uniforms.fogColor.value.copy(fog.color);if(fog.isFog){uniforms.fogNear.value=fog.near;uniforms.fogFar.value=fog.far;}else if(fog.isFogExp2){uniforms.fogDensity.value=fog.density;}}function refreshMaterialUniforms(uniforms,material,pixelRatio,height){if(material.isMeshBasicMaterial){refreshUniformsCommon(uniforms,material);}else if(material.isMeshLambertMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsLambert(uniforms,material);}else if(material.isMeshToonMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsToon(uniforms,material);}else if(material.isMeshPhongMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsPhong(uniforms,material);}else if(material.isMeshStandardMaterial){refreshUniformsCommon(uniforms,material);if(material.isMeshPhysicalMaterial){refreshUniformsPhysical(uniforms,material);}else {refreshUniformsStandard(uniforms,material);}}else if(material.isMeshMatcapMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsMatcap(uniforms,material);}else if(material.isMeshDepthMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsDepth(uniforms,material);}else if(material.isMeshDistanceMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsDistance(uniforms,material);}else if(material.isMeshNormalMaterial){refreshUniformsCommon(uniforms,material);refreshUniformsNormal(uniforms,material);}else if(material.isLineBasicMaterial){refreshUniformsLine(uniforms,material);if(material.isLineDashedMaterial){refreshUniformsDash(uniforms,material);}}else if(material.isPointsMaterial){refreshUniformsPoints(uniforms,material,pixelRatio,height);}else if(material.isSpriteMaterial){refreshUniformsSprites(uniforms,material);}else if(material.isShadowMaterial){uniforms.color.value.copy(material.color);uniforms.opacity.value=material.opacity;}else if(material.isShaderMaterial){material.uniformsNeedUpdate=false;// #15581
  855. }}function refreshUniformsCommon(uniforms,material){uniforms.opacity.value=material.opacity;if(material.color){uniforms.diffuse.value.copy(material.color);}if(material.emissive){uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity);}if(material.map){uniforms.map.value=material.map;}if(material.alphaMap){uniforms.alphaMap.value=material.alphaMap;}if(material.specularMap){uniforms.specularMap.value=material.specularMap;}var envMap=properties.get(material).envMap;if(envMap){uniforms.envMap.value=envMap;uniforms.flipEnvMap.value=envMap.isCubeTexture&&envMap._needsFlipEnvMap?-1:1;uniforms.reflectivity.value=material.reflectivity;uniforms.refractionRatio.value=material.refractionRatio;var maxMipLevel=properties.get(envMap).__maxMipLevel;if(maxMipLevel!==undefined){uniforms.maxMipLevel.value=maxMipLevel;}}if(material.lightMap){uniforms.lightMap.value=material.lightMap;uniforms.lightMapIntensity.value=material.lightMapIntensity;}if(material.aoMap){uniforms.aoMap.value=material.aoMap;uniforms.aoMapIntensity.value=material.aoMapIntensity;}// uv repeat and offset setting priorities
  856. // 1. color map
  857. // 2. specular map
  858. // 3. displacementMap map
  859. // 4. normal map
  860. // 5. bump map
  861. // 6. roughnessMap map
  862. // 7. metalnessMap map
  863. // 8. alphaMap map
  864. // 9. emissiveMap map
  865. // 10. clearcoat map
  866. // 11. clearcoat normal map
  867. // 12. clearcoat roughnessMap map
  868. var uvScaleMap;if(material.map){uvScaleMap=material.map;}else if(material.specularMap){uvScaleMap=material.specularMap;}else if(material.displacementMap){uvScaleMap=material.displacementMap;}else if(material.normalMap){uvScaleMap=material.normalMap;}else if(material.bumpMap){uvScaleMap=material.bumpMap;}else if(material.roughnessMap){uvScaleMap=material.roughnessMap;}else if(material.metalnessMap){uvScaleMap=material.metalnessMap;}else if(material.alphaMap){uvScaleMap=material.alphaMap;}else if(material.emissiveMap){uvScaleMap=material.emissiveMap;}else if(material.clearcoatMap){uvScaleMap=material.clearcoatMap;}else if(material.clearcoatNormalMap){uvScaleMap=material.clearcoatNormalMap;}else if(material.clearcoatRoughnessMap){uvScaleMap=material.clearcoatRoughnessMap;}if(uvScaleMap!==undefined){// backwards compatibility
  869. if(uvScaleMap.isWebGLRenderTarget){uvScaleMap=uvScaleMap.texture;}if(uvScaleMap.matrixAutoUpdate===true){uvScaleMap.updateMatrix();}uniforms.uvTransform.value.copy(uvScaleMap.matrix);}// uv repeat and offset setting priorities for uv2
  870. // 1. ao map
  871. // 2. light map
  872. var uv2ScaleMap;if(material.aoMap){uv2ScaleMap=material.aoMap;}else if(material.lightMap){uv2ScaleMap=material.lightMap;}if(uv2ScaleMap!==undefined){// backwards compatibility
  873. if(uv2ScaleMap.isWebGLRenderTarget){uv2ScaleMap=uv2ScaleMap.texture;}if(uv2ScaleMap.matrixAutoUpdate===true){uv2ScaleMap.updateMatrix();}uniforms.uv2Transform.value.copy(uv2ScaleMap.matrix);}}function refreshUniformsLine(uniforms,material){uniforms.diffuse.value.copy(material.color);uniforms.opacity.value=material.opacity;}function refreshUniformsDash(uniforms,material){uniforms.dashSize.value=material.dashSize;uniforms.totalSize.value=material.dashSize+material.gapSize;uniforms.scale.value=material.scale;}function refreshUniformsPoints(uniforms,material,pixelRatio,height){uniforms.diffuse.value.copy(material.color);uniforms.opacity.value=material.opacity;uniforms.size.value=material.size*pixelRatio;uniforms.scale.value=height*0.5;if(material.map){uniforms.map.value=material.map;}if(material.alphaMap){uniforms.alphaMap.value=material.alphaMap;}// uv repeat and offset setting priorities
  874. // 1. color map
  875. // 2. alpha map
  876. var uvScaleMap;if(material.map){uvScaleMap=material.map;}else if(material.alphaMap){uvScaleMap=material.alphaMap;}if(uvScaleMap!==undefined){if(uvScaleMap.matrixAutoUpdate===true){uvScaleMap.updateMatrix();}uniforms.uvTransform.value.copy(uvScaleMap.matrix);}}function refreshUniformsSprites(uniforms,material){uniforms.diffuse.value.copy(material.color);uniforms.opacity.value=material.opacity;uniforms.rotation.value=material.rotation;if(material.map){uniforms.map.value=material.map;}if(material.alphaMap){uniforms.alphaMap.value=material.alphaMap;}// uv repeat and offset setting priorities
  877. // 1. color map
  878. // 2. alpha map
  879. var uvScaleMap;if(material.map){uvScaleMap=material.map;}else if(material.alphaMap){uvScaleMap=material.alphaMap;}if(uvScaleMap!==undefined){if(uvScaleMap.matrixAutoUpdate===true){uvScaleMap.updateMatrix();}uniforms.uvTransform.value.copy(uvScaleMap.matrix);}}function refreshUniformsLambert(uniforms,material){if(material.emissiveMap){uniforms.emissiveMap.value=material.emissiveMap;}}function refreshUniformsPhong(uniforms,material){uniforms.specular.value.copy(material.specular);uniforms.shininess.value=Math.max(material.shininess,1e-4);// to prevent pow( 0.0, 0.0 )
  880. if(material.emissiveMap){uniforms.emissiveMap.value=material.emissiveMap;}if(material.bumpMap){uniforms.bumpMap.value=material.bumpMap;uniforms.bumpScale.value=material.bumpScale;if(material.side===BackSide)uniforms.bumpScale.value*=-1;}if(material.normalMap){uniforms.normalMap.value=material.normalMap;uniforms.normalScale.value.copy(material.normalScale);if(material.side===BackSide)uniforms.normalScale.value.negate();}if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}}function refreshUniformsToon(uniforms,material){if(material.gradientMap){uniforms.gradientMap.value=material.gradientMap;}if(material.emissiveMap){uniforms.emissiveMap.value=material.emissiveMap;}if(material.bumpMap){uniforms.bumpMap.value=material.bumpMap;uniforms.bumpScale.value=material.bumpScale;if(material.side===BackSide)uniforms.bumpScale.value*=-1;}if(material.normalMap){uniforms.normalMap.value=material.normalMap;uniforms.normalScale.value.copy(material.normalScale);if(material.side===BackSide)uniforms.normalScale.value.negate();}if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}}function refreshUniformsStandard(uniforms,material){uniforms.roughness.value=material.roughness;uniforms.metalness.value=material.metalness;if(material.roughnessMap){uniforms.roughnessMap.value=material.roughnessMap;}if(material.metalnessMap){uniforms.metalnessMap.value=material.metalnessMap;}if(material.emissiveMap){uniforms.emissiveMap.value=material.emissiveMap;}if(material.bumpMap){uniforms.bumpMap.value=material.bumpMap;uniforms.bumpScale.value=material.bumpScale;if(material.side===BackSide)uniforms.bumpScale.value*=-1;}if(material.normalMap){uniforms.normalMap.value=material.normalMap;uniforms.normalScale.value.copy(material.normalScale);if(material.side===BackSide)uniforms.normalScale.value.negate();}if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}var envMap=properties.get(material).envMap;if(envMap){//uniforms.envMap.value = material.envMap; // part of uniforms common
  881. uniforms.envMapIntensity.value=material.envMapIntensity;}}function refreshUniformsPhysical(uniforms,material){refreshUniformsStandard(uniforms,material);uniforms.reflectivity.value=material.reflectivity;// also part of uniforms common
  882. uniforms.clearcoat.value=material.clearcoat;uniforms.clearcoatRoughness.value=material.clearcoatRoughness;if(material.sheen)uniforms.sheen.value.copy(material.sheen);if(material.clearcoatMap){uniforms.clearcoatMap.value=material.clearcoatMap;}if(material.clearcoatRoughnessMap){uniforms.clearcoatRoughnessMap.value=material.clearcoatRoughnessMap;}if(material.clearcoatNormalMap){uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale);uniforms.clearcoatNormalMap.value=material.clearcoatNormalMap;if(material.side===BackSide){uniforms.clearcoatNormalScale.value.negate();}}uniforms.transmission.value=material.transmission;if(material.transmissionMap){uniforms.transmissionMap.value=material.transmissionMap;}}function refreshUniformsMatcap(uniforms,material){if(material.matcap){uniforms.matcap.value=material.matcap;}if(material.bumpMap){uniforms.bumpMap.value=material.bumpMap;uniforms.bumpScale.value=material.bumpScale;if(material.side===BackSide)uniforms.bumpScale.value*=-1;}if(material.normalMap){uniforms.normalMap.value=material.normalMap;uniforms.normalScale.value.copy(material.normalScale);if(material.side===BackSide)uniforms.normalScale.value.negate();}if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}}function refreshUniformsDepth(uniforms,material){if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}}function refreshUniformsDistance(uniforms,material){if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}uniforms.referencePosition.value.copy(material.referencePosition);uniforms.nearDistance.value=material.nearDistance;uniforms.farDistance.value=material.farDistance;}function refreshUniformsNormal(uniforms,material){if(material.bumpMap){uniforms.bumpMap.value=material.bumpMap;uniforms.bumpScale.value=material.bumpScale;if(material.side===BackSide)uniforms.bumpScale.value*=-1;}if(material.normalMap){uniforms.normalMap.value=material.normalMap;uniforms.normalScale.value.copy(material.normalScale);if(material.side===BackSide)uniforms.normalScale.value.negate();}if(material.displacementMap){uniforms.displacementMap.value=material.displacementMap;uniforms.displacementScale.value=material.displacementScale;uniforms.displacementBias.value=material.displacementBias;}}return {refreshFogUniforms:refreshFogUniforms,refreshMaterialUniforms:refreshMaterialUniforms};}function createCanvasElement(){var canvas=document.createElementNS('http://www.w3.org/1999/xhtml','canvas');canvas.style.display='block';return canvas;}function WebGLRenderer(parameters){parameters=parameters||{};var _canvas=parameters.canvas!==undefined?parameters.canvas:createCanvasElement(),_context=parameters.context!==undefined?parameters.context:null,_alpha=parameters.alpha!==undefined?parameters.alpha:false,_depth=parameters.depth!==undefined?parameters.depth:true,_stencil=parameters.stencil!==undefined?parameters.stencil:true,_antialias=parameters.antialias!==undefined?parameters.antialias:false,_premultipliedAlpha=parameters.premultipliedAlpha!==undefined?parameters.premultipliedAlpha:true,_preserveDrawingBuffer=parameters.preserveDrawingBuffer!==undefined?parameters.preserveDrawingBuffer:false,_powerPreference=parameters.powerPreference!==undefined?parameters.powerPreference:'default',_failIfMajorPerformanceCaveat=parameters.failIfMajorPerformanceCaveat!==undefined?parameters.failIfMajorPerformanceCaveat:false;var currentRenderList=null;var currentRenderState=null;// render() can be called from within a callback triggered by another render.
  883. // We track this so that the nested render call gets its state isolated from the parent render call.
  884. var renderStateStack=[];// public properties
  885. this.domElement=_canvas;// Debug configuration container
  886. this.debug={/**
  887. * Enables error checking and reporting when shader programs are being compiled
  888. * @type {boolean}
  889. */checkShaderErrors:true};// clearing
  890. this.autoClear=true;this.autoClearColor=true;this.autoClearDepth=true;this.autoClearStencil=true;// scene graph
  891. this.sortObjects=true;// user-defined clipping
  892. this.clippingPlanes=[];this.localClippingEnabled=false;// physically based shading
  893. this.gammaFactor=2.0;// for backwards compatibility
  894. this.outputEncoding=LinearEncoding;// physical lights
  895. this.physicallyCorrectLights=false;// tone mapping
  896. this.toneMapping=NoToneMapping;this.toneMappingExposure=1.0;// morphs
  897. this.maxMorphTargets=8;this.maxMorphNormals=4;// internal properties
  898. var _this=this;var _isContextLost=false;// internal state cache
  899. var _framebuffer=null;var _currentActiveCubeFace=0;var _currentActiveMipmapLevel=0;var _currentRenderTarget=null;var _currentFramebuffer=null;var _currentMaterialId=-1;var _currentCamera=null;var _currentViewport=new Vector4();var _currentScissor=new Vector4();var _currentScissorTest=null;//
  900. var _width=_canvas.width;var _height=_canvas.height;var _pixelRatio=1;var _opaqueSort=null;var _transparentSort=null;var _viewport=new Vector4(0,0,_width,_height);var _scissor=new Vector4(0,0,_width,_height);var _scissorTest=false;// frustum
  901. var _frustum=new Frustum();// clipping
  902. var _clippingEnabled=false;var _localClippingEnabled=false;// camera matrices cache
  903. var _projScreenMatrix=new Matrix4();var _vector3=new Vector3();var _emptyScene={background:null,fog:null,environment:null,overrideMaterial:null,isScene:true};function getTargetPixelRatio(){return _currentRenderTarget===null?_pixelRatio:1;}// initialize
  904. var _gl=_context;function getContext(contextNames,contextAttributes){for(var _i124=0;_i124<contextNames.length;_i124++){var contextName=contextNames[_i124];var context=_canvas.getContext(contextName,contextAttributes);if(context!==null)return context;}return null;}try{var contextAttributes={alpha:_alpha,depth:_depth,stencil:_stencil,antialias:_antialias,premultipliedAlpha:_premultipliedAlpha,preserveDrawingBuffer:_preserveDrawingBuffer,powerPreference:_powerPreference,failIfMajorPerformanceCaveat:_failIfMajorPerformanceCaveat};// event listeners must be registered before WebGL context is created, see #12753
  905. _canvas.addEventListener('webglcontextlost',onContextLost,false);_canvas.addEventListener('webglcontextrestored',onContextRestore,false);if(_gl===null){var contextNames=['webgl2','webgl','experimental-webgl'];if(_this.isWebGL1Renderer===true){contextNames.shift();}_gl=getContext(contextNames,contextAttributes);if(_gl===null){if(getContext(contextNames)){throw new Error('Error creating WebGL context with your selected attributes.');}else {throw new Error('Error creating WebGL context.');}}}// Some experimental-webgl implementations do not have getShaderPrecisionFormat
  906. if(_gl.getShaderPrecisionFormat===undefined){_gl.getShaderPrecisionFormat=function(){return {'rangeMin':1,'rangeMax':1,'precision':1};};}}catch(error){console.error('THREE.WebGLRenderer: '+error.message);throw error;}var extensions,capabilities,state,info;var properties,textures,cubemaps,attributes,geometries,objects;var programCache,materials,renderLists,renderStates,clipping;var background,morphtargets,bufferRenderer,indexedBufferRenderer;var utils,bindingStates;function initGLContext(){extensions=new WebGLExtensions(_gl);capabilities=new WebGLCapabilities(_gl,extensions,parameters);if(capabilities.isWebGL2===false){extensions.get('WEBGL_depth_texture');extensions.get('OES_texture_float');extensions.get('OES_texture_half_float');extensions.get('OES_texture_half_float_linear');extensions.get('OES_standard_derivatives');extensions.get('OES_element_index_uint');extensions.get('OES_vertex_array_object');extensions.get('ANGLE_instanced_arrays');}extensions.get('OES_texture_float_linear');utils=new WebGLUtils(_gl,extensions,capabilities);state=new WebGLState(_gl,extensions,capabilities);state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor());state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor());info=new WebGLInfo(_gl);properties=new WebGLProperties();textures=new WebGLTextures(_gl,extensions,state,properties,capabilities,utils,info);cubemaps=new WebGLCubeMaps(_this);attributes=new WebGLAttributes(_gl,capabilities);bindingStates=new WebGLBindingStates(_gl,extensions,attributes,capabilities);geometries=new WebGLGeometries(_gl,attributes,info,bindingStates);objects=new WebGLObjects(_gl,geometries,attributes,info);morphtargets=new WebGLMorphtargets(_gl);clipping=new WebGLClipping(properties);programCache=new WebGLPrograms(_this,cubemaps,extensions,capabilities,bindingStates,clipping);materials=new WebGLMaterials(properties);renderLists=new WebGLRenderLists(properties);renderStates=new WebGLRenderStates(extensions,capabilities);background=new WebGLBackground(_this,cubemaps,state,objects,_premultipliedAlpha);bufferRenderer=new WebGLBufferRenderer(_gl,extensions,info,capabilities);indexedBufferRenderer=new WebGLIndexedBufferRenderer(_gl,extensions,info,capabilities);info.programs=programCache.programs;_this.capabilities=capabilities;_this.extensions=extensions;_this.properties=properties;_this.renderLists=renderLists;_this.state=state;_this.info=info;_this._textures=textures;//xzw add
  907. }initGLContext();// xr
  908. var xr=new WebXRManager(_this,_gl);this.xr=xr;// shadow map
  909. var shadowMap=new WebGLShadowMap(_this,objects,capabilities.maxTextureSize);this.shadowMap=shadowMap;// API
  910. this.getContext=function(){return _gl;};this.getContextAttributes=function(){return _gl.getContextAttributes();};this.forceContextLoss=function(){var extension=extensions.get('WEBGL_lose_context');if(extension)extension.loseContext();};this.forceContextRestore=function(){var extension=extensions.get('WEBGL_lose_context');if(extension)extension.restoreContext();};this.getPixelRatio=function(){return _pixelRatio;};this.setPixelRatio=function(value){if(value===undefined)return;_pixelRatio=value;this.setSize(_width,_height,false);};this.getSize=function(target){if(target===undefined){console.warn('WebGLRenderer: .getsize() now requires a Vector2 as an argument');target=new Vector2();}return target.set(_width,_height);};this.setSize=function(width,height,updateStyle){if(xr.isPresenting){console.warn('THREE.WebGLRenderer: Can\'t change size while VR device is presenting.');return;}_width=width;_height=height;_canvas.width=Math.floor(width*_pixelRatio);_canvas.height=Math.floor(height*_pixelRatio);if(updateStyle!==false){_canvas.style.width=width+'px';_canvas.style.height=height+'px';}this.setViewport(0,0,width,height);};this.getDrawingBufferSize=function(target){if(target===undefined){console.warn('WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument');target=new Vector2();}return target.set(_width*_pixelRatio,_height*_pixelRatio).floor();};this.setDrawingBufferSize=function(width,height,pixelRatio){_width=width;_height=height;_pixelRatio=pixelRatio;_canvas.width=Math.floor(width*pixelRatio);_canvas.height=Math.floor(height*pixelRatio);this.setViewport(0,0,width,height);};this.getCurrentViewport=function(target){if(target===undefined){console.warn('WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument');target=new Vector4();}return target.copy(_currentViewport);};this.getViewport=function(target){return target.copy(_viewport);};this.setViewport=function(x,y,width,height){if(x.isVector4){_viewport.set(x.x,x.y,x.z,x.w);}else {_viewport.set(x,y,width,height);}state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor());};this.getScissor=function(target){return target.copy(_scissor);};this.setScissor=function(x,y,width,height){if(x.isVector4){_scissor.set(x.x,x.y,x.z,x.w);}else {_scissor.set(x,y,width,height);}state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor());};this.getScissorTest=function(){return _scissorTest;};this.setScissorTest=function(boolean){state.setScissorTest(_scissorTest=boolean);};this.setOpaqueSort=function(method){_opaqueSort=method;};this.setTransparentSort=function(method){_transparentSort=method;};// Clearing
  911. this.getClearColor=function(target){if(target===undefined){console.warn('WebGLRenderer: .getClearColor() now requires a Color as an argument');target=new Color();}return target.copy(background.getClearColor());};this.setClearColor=function(){background.setClearColor.apply(background,arguments);};this.getClearAlpha=function(){return background.getClearAlpha();};this.setClearAlpha=function(){background.setClearAlpha.apply(background,arguments);};this.clear=function(color,depth,stencil){var bits=0;if(color===undefined||color)bits|=16384;if(depth===undefined||depth)bits|=256;if(stencil===undefined||stencil)bits|=1024;_gl.clear(bits);};this.clearColor=function(){this.clear(true,false,false);};this.clearDepth=function(){this.clear(false,true,false);};this.clearStencil=function(){this.clear(false,false,true);};//
  912. this.dispose=function(){_canvas.removeEventListener('webglcontextlost',onContextLost,false);_canvas.removeEventListener('webglcontextrestored',onContextRestore,false);renderLists.dispose();renderStates.dispose();properties.dispose();cubemaps.dispose();objects.dispose();bindingStates.dispose();xr.dispose();animation.stop();};// Events
  913. function onContextLost(event){event.preventDefault();console.log('THREE.WebGLRenderer: Context Lost.');_isContextLost=true;}function onContextRestore(/* event */){console.log('THREE.WebGLRenderer: Context Restored.');_isContextLost=false;initGLContext();}function onMaterialDispose(event){var material=event.target;material.removeEventListener('dispose',onMaterialDispose);deallocateMaterial(material);}// Buffer deallocation
  914. function deallocateMaterial(material){releaseMaterialProgramReference(material);properties.remove(material);}function releaseMaterialProgramReference(material){var programInfo=properties.get(material).program;if(programInfo!==undefined){programCache.releaseProgram(programInfo);}}// Buffer rendering
  915. function renderObjectImmediate(object,program){object.render(function(object){_this.renderBufferImmediate(object,program);});}this.renderBufferImmediate=function(object,program){bindingStates.initAttributes();var buffers=properties.get(object);if(object.hasPositions&&!buffers.position)buffers.position=_gl.createBuffer();if(object.hasNormals&&!buffers.normal)buffers.normal=_gl.createBuffer();if(object.hasUvs&&!buffers.uv)buffers.uv=_gl.createBuffer();if(object.hasColors&&!buffers.color)buffers.color=_gl.createBuffer();var programAttributes=program.getAttributes();if(object.hasPositions){_gl.bindBuffer(34962,buffers.position);_gl.bufferData(34962,object.positionArray,35048);bindingStates.enableAttribute(programAttributes.position);_gl.vertexAttribPointer(programAttributes.position,3,5126,false,0,0);}if(object.hasNormals){_gl.bindBuffer(34962,buffers.normal);_gl.bufferData(34962,object.normalArray,35048);bindingStates.enableAttribute(programAttributes.normal);_gl.vertexAttribPointer(programAttributes.normal,3,5126,false,0,0);}if(object.hasUvs){_gl.bindBuffer(34962,buffers.uv);_gl.bufferData(34962,object.uvArray,35048);bindingStates.enableAttribute(programAttributes.uv);_gl.vertexAttribPointer(programAttributes.uv,2,5126,false,0,0);}if(object.hasColors){_gl.bindBuffer(34962,buffers.color);_gl.bufferData(34962,object.colorArray,35048);bindingStates.enableAttribute(programAttributes.color);_gl.vertexAttribPointer(programAttributes.color,3,5126,false,0,0);}bindingStates.disableUnusedAttributes();_gl.drawArrays(4,0,object.count);object.count=0;};this.renderBufferDirect=function(camera,scene,geometry,material,object,group){if(scene===null)scene=_emptyScene;// renderBufferDirect second parameter used to be fog (could be null)
  916. var frontFaceCW=object.isMesh&&object.matrixWorld.determinant()<0;var program=setProgram(camera,scene,material,object);state.setMaterial(material,frontFaceCW);//
  917. var index=geometry.index;var position=geometry.attributes.position;//
  918. if(index===null){if(position===undefined||position.count===0)return;}else if(index.count===0){return;}//
  919. var rangeFactor=1;if(material.wireframe===true){index=geometries.getWireframeAttribute(geometry);rangeFactor=2;}if(material.morphTargets||material.morphNormals){morphtargets.update(object,geometry,material,program);}bindingStates.setup(object,material,program,geometry,index);var attribute;var renderer=bufferRenderer;if(index!==null){attribute=attributes.get(index);renderer=indexedBufferRenderer;renderer.setIndex(attribute);}//
  920. var dataCount=index!==null?index.count:position.count;var rangeStart=geometry.drawRange.start*rangeFactor;var rangeCount=geometry.drawRange.count*rangeFactor;var groupStart=group!==null?group.start*rangeFactor:0;var groupCount=group!==null?group.count*rangeFactor:Infinity;var drawStart=Math.max(rangeStart,groupStart);var drawEnd=Math.min(dataCount,rangeStart+rangeCount,groupStart+groupCount)-1;var drawCount=Math.max(0,drawEnd-drawStart+1);if(drawCount===0)return;//
  921. if(object.isMesh){if(material.wireframe===true){state.setLineWidth(material.wireframeLinewidth*getTargetPixelRatio());renderer.setMode(1);}else {renderer.setMode(4);}}else if(object.isLine){var lineWidth=material.linewidth;if(lineWidth===undefined)lineWidth=1;// Not using Line*Material
  922. state.setLineWidth(lineWidth*getTargetPixelRatio());if(object.isLineSegments){renderer.setMode(1);}else if(object.isLineLoop){renderer.setMode(2);}else {renderer.setMode(3);}}else if(object.isPoints){renderer.setMode(0);}else if(object.isSprite){renderer.setMode(4);}if(object.isInstancedMesh){renderer.renderInstances(drawStart,drawCount,object.count);}else if(geometry.isInstancedBufferGeometry){var instanceCount=Math.min(geometry.instanceCount,geometry._maxInstanceCount);renderer.renderInstances(drawStart,drawCount,instanceCount);}else {renderer.render(drawStart,drawCount);}};// Compile
  923. this.compile=function(scene,camera){currentRenderState=renderStates.get(scene);currentRenderState.init();scene.traverseVisible(function(object){if(object.isLight&&object.layers.test(camera.layers)){currentRenderState.pushLight(object);if(object.castShadow){currentRenderState.pushShadow(object);}}});currentRenderState.setupLights();var compiled=new WeakMap();scene.traverse(function(object){var material=object.material;if(material){if(Array.isArray(material)){for(var _i125=0;_i125<material.length;_i125++){var material2=material[_i125];if(compiled.has(material2)===false){initMaterial(material2,scene,object);compiled.set(material2);}}}else if(compiled.has(material)===false){initMaterial(material,scene,object);compiled.set(material);}}});};// Animation Loop
  924. var onAnimationFrameCallback=null;function onAnimationFrame(time){if(xr.isPresenting)return;if(onAnimationFrameCallback)onAnimationFrameCallback(time);}var animation=new WebGLAnimation();animation.setAnimationLoop(onAnimationFrame);if(typeof window!=='undefined')animation.setContext(window);this.setAnimationLoop=function(callback){onAnimationFrameCallback=callback;xr.setAnimationLoop(callback);callback===null?animation.stop():animation.start();};// Rendering
  925. this.render=function(scene,camera){var renderTarget,forceClear;if(arguments[2]!==undefined){console.warn('THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.');renderTarget=arguments[2];}if(arguments[3]!==undefined){console.warn('THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.');forceClear=arguments[3];}if(camera!==undefined&&camera.isCamera!==true){console.error('THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.');return;}if(_isContextLost===true)return;// reset caching for this frame
  926. bindingStates.resetDefaultState();_currentMaterialId=-1;_currentCamera=null;// update scene graph
  927. if(scene.autoUpdate===true)scene.updateMatrixWorld();// update camera matrices and frustum
  928. if(camera.parent===null)camera.updateMatrixWorld();if(xr.enabled===true&&xr.isPresenting===true){camera=xr.getCamera(camera);}//
  929. if(scene.isScene===true)scene.onBeforeRender(_this,scene,camera,renderTarget||_currentRenderTarget);currentRenderState=renderStates.get(scene,renderStateStack.length);currentRenderState.init();renderStateStack.push(currentRenderState);_projScreenMatrix.multiplyMatrices(camera.projectionMatrix,camera.matrixWorldInverse);_frustum.setFromProjectionMatrix(_projScreenMatrix);_localClippingEnabled=this.localClippingEnabled;_clippingEnabled=clipping.init(this.clippingPlanes,_localClippingEnabled,camera);currentRenderList=renderLists.get(scene,camera);currentRenderList.init();projectObject(scene,camera,0,_this.sortObjects);currentRenderList.finish();if(_this.sortObjects===true){currentRenderList.sort(_opaqueSort,_transparentSort);}//
  930. if(_clippingEnabled===true)clipping.beginShadows();var shadowsArray=currentRenderState.state.shadowsArray;shadowMap.render(shadowsArray,scene,camera);currentRenderState.setupLights();currentRenderState.setupLightsView(camera);if(_clippingEnabled===true)clipping.endShadows();//
  931. if(this.info.autoReset===true)this.info.reset();if(renderTarget!==undefined){this.setRenderTarget(renderTarget);}//
  932. background.render(currentRenderList,scene,camera,forceClear);// render scene
  933. var opaqueObjects=currentRenderList.opaque;var transparentObjects=currentRenderList.transparent;if(opaqueObjects.length>0)renderObjects(opaqueObjects,scene,camera);if(transparentObjects.length>0)renderObjects(transparentObjects,scene,camera);//
  934. if(scene.isScene===true)scene.onAfterRender(_this,scene,camera);//
  935. if(_currentRenderTarget!==null){// Generate mipmap if we're using any kind of mipmap filtering
  936. textures.updateRenderTargetMipmap(_currentRenderTarget);// resolve multisample renderbuffers to a single-sample texture if necessary
  937. textures.updateMultisampleRenderTarget(_currentRenderTarget);}// Ensure depth buffer writing is enabled so it can be cleared on next render
  938. state.buffers.depth.setTest(true);state.buffers.depth.setMask(true);state.buffers.color.setMask(true);state.setPolygonOffset(false);// _gl.finish();
  939. renderStateStack.pop();if(renderStateStack.length>0){currentRenderState=renderStateStack[renderStateStack.length-1];}else {currentRenderState=null;}currentRenderList=null;};function projectObject(object,camera,groupOrder,sortObjects){if(object.visible===false)return;var visible=object.layers.test(camera.layers);if(visible){if(object.isGroup){groupOrder=object.renderOrder;}else if(object.isLOD){if(object.autoUpdate===true)object.update(camera);}else if(object.isLight){currentRenderState.pushLight(object);if(object.castShadow){currentRenderState.pushShadow(object);}}else if(object.isSprite){if(!object.frustumCulled||_frustum.intersectsSprite(object)){if(sortObjects){_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);}var geometry=objects.update(object);var material=object.material;if(material.visible){currentRenderList.push(object,geometry,material,groupOrder,_vector3.z,null);}}}else if(object.isImmediateRenderObject){if(sortObjects){_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);}currentRenderList.push(object,null,object.material,groupOrder,_vector3.z,null);}else if(object.isMesh||object.isLine||object.isPoints){if(object.isSkinnedMesh){// update skeleton only once in a frame
  940. if(object.skeleton.frame!==info.render.frame){object.skeleton.update();object.skeleton.frame=info.render.frame;}}if(!object.frustumCulled||_frustum.intersectsObject(object)){if(sortObjects){_vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix);}var _geometry2=objects.update(object);var _material=object.material;if(Array.isArray(_material)){var groups=_geometry2.groups;for(var _i126=0,l=groups.length;_i126<l;_i126++){var group=groups[_i126];var groupMaterial=_material[group.materialIndex];if(groupMaterial&&groupMaterial.visible){currentRenderList.push(object,_geometry2,groupMaterial,groupOrder,_vector3.z,group);}}}else if(_material.visible){currentRenderList.push(object,_geometry2,_material,groupOrder,_vector3.z,null);}}}}var children=object.children;for(var _i127=0,_l5=children.length;_i127<_l5;_i127++){projectObject(children[_i127],camera,groupOrder,sortObjects);}}function renderObjects(renderList,scene,camera){var overrideMaterial=scene.isScene===true?scene.overrideMaterial:null;for(var _i128=0,l=renderList.length;_i128<l;_i128++){var renderItem=renderList[_i128];var object=renderItem.object;var geometry=renderItem.geometry;var material=overrideMaterial===null?renderItem.material:overrideMaterial;var group=renderItem.group;if(camera.isArrayCamera){var cameras=camera.cameras;for(var j=0,jl=cameras.length;j<jl;j++){var camera2=cameras[j];if(object.layers.test(camera2.layers)){state.viewport(_currentViewport.copy(camera2.viewport));currentRenderState.setupLightsView(camera2);renderObject(object,scene,camera2,geometry,material,group);}}}else {renderObject(object,scene,camera,geometry,material,group);}}}function renderObject(object,scene,camera,geometry,material,group){object.onBeforeRender(_this,scene,camera,geometry,material,group);object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse,object.matrixWorld);object.normalMatrix.getNormalMatrix(object.modelViewMatrix);if(object.isImmediateRenderObject){var program=setProgram(camera,scene,material,object);state.setMaterial(material);bindingStates.reset();renderObjectImmediate(object,program);}else {_this.renderBufferDirect(camera,scene,geometry,material,object,group);}object.onAfterRender(_this,scene,camera,geometry,material,group);}function initMaterial(material,scene,object){if(scene.isScene!==true)scene=_emptyScene;// scene could be a Mesh, Line, Points, ...
  941. var materialProperties=properties.get(material);var lights=currentRenderState.state.lights;var shadowsArray=currentRenderState.state.shadowsArray;var lightsStateVersion=lights.state.version;var parameters=programCache.getParameters(material,lights.state,shadowsArray,scene,object);var programCacheKey=programCache.getProgramCacheKey(parameters);var program=materialProperties.program;var programChange=true;if(program===undefined){// new material
  942. material.addEventListener('dispose',onMaterialDispose);}else if(program.cacheKey!==programCacheKey){// changed glsl or parameters
  943. releaseMaterialProgramReference(material);}else if(materialProperties.lightsStateVersion!==lightsStateVersion){programChange=false;}else if(parameters.shaderID!==undefined){// same glsl and uniform list, envMap still needs the update here to avoid a frame-late effect
  944. var environment=material.isMeshStandardMaterial?scene.environment:null;materialProperties.envMap=cubemaps.get(material.envMap||environment);return;}else {// only rebuild uniform list
  945. programChange=false;}if(programChange){parameters.uniforms=programCache.getUniforms(material);material.onBeforeCompile(parameters,_this);program=programCache.acquireProgram(parameters,programCacheKey);materialProperties.program=program;materialProperties.uniforms=parameters.uniforms;materialProperties.outputEncoding=parameters.outputEncoding;}var uniforms=materialProperties.uniforms;if(!material.isShaderMaterial&&!material.isRawShaderMaterial||material.clipping===true){materialProperties.numClippingPlanes=clipping.numPlanes;materialProperties.numIntersection=clipping.numIntersection;uniforms.clippingPlanes=clipping.uniform;}materialProperties.environment=material.isMeshStandardMaterial?scene.environment:null;materialProperties.fog=scene.fog;materialProperties.envMap=cubemaps.get(material.envMap||materialProperties.environment);// store the light setup it was created for
  946. materialProperties.needsLights=materialNeedsLights(material);materialProperties.lightsStateVersion=lightsStateVersion;if(materialProperties.needsLights){// wire up the material to this renderer's lighting state
  947. uniforms.ambientLightColor.value=lights.state.ambient;uniforms.lightProbe.value=lights.state.probe;uniforms.directionalLights.value=lights.state.directional;uniforms.directionalLightShadows.value=lights.state.directionalShadow;uniforms.spotLights.value=lights.state.spot;uniforms.spotLightShadows.value=lights.state.spotShadow;uniforms.rectAreaLights.value=lights.state.rectArea;uniforms.ltc_1.value=lights.state.rectAreaLTC1;uniforms.ltc_2.value=lights.state.rectAreaLTC2;uniforms.pointLights.value=lights.state.point;uniforms.pointLightShadows.value=lights.state.pointShadow;uniforms.hemisphereLights.value=lights.state.hemi;uniforms.directionalShadowMap.value=lights.state.directionalShadowMap;uniforms.directionalShadowMatrix.value=lights.state.directionalShadowMatrix;uniforms.spotShadowMap.value=lights.state.spotShadowMap;uniforms.spotShadowMatrix.value=lights.state.spotShadowMatrix;uniforms.pointShadowMap.value=lights.state.pointShadowMap;uniforms.pointShadowMatrix.value=lights.state.pointShadowMatrix;// TODO (abelnation): add area lights shadow info to uniforms
  948. }var progUniforms=materialProperties.program.getUniforms();var uniformsList=WebGLUniforms.seqWithValue(progUniforms.seq,uniforms);materialProperties.uniformsList=uniformsList;}function setProgram(camera,scene,material,object){if(scene.isScene!==true)scene=_emptyScene;// scene could be a Mesh, Line, Points, ...
  949. textures.resetTextureUnits();var fog=scene.fog;var environment=material.isMeshStandardMaterial?scene.environment:null;var encoding=_currentRenderTarget===null?_this.outputEncoding:_currentRenderTarget.texture.encoding;var envMap=cubemaps.get(material.envMap||environment);var materialProperties=properties.get(material);var lights=currentRenderState.state.lights;if(_clippingEnabled===true){if(_localClippingEnabled===true||camera!==_currentCamera){var useCache=camera===_currentCamera&&material.id===_currentMaterialId;// we might want to call this function with some ClippingGroup
  950. // object instead of the material, once it becomes feasible
  951. // (#8465, #8379)
  952. clipping.setState(material,camera,useCache);}}if(material.version===materialProperties.__version){if(material.fog&&materialProperties.fog!==fog){initMaterial(material,scene,object);}else if(materialProperties.environment!==environment){initMaterial(material,scene,object);}else if(materialProperties.needsLights&&materialProperties.lightsStateVersion!==lights.state.version){initMaterial(material,scene,object);}else if(materialProperties.numClippingPlanes!==undefined&&(materialProperties.numClippingPlanes!==clipping.numPlanes||materialProperties.numIntersection!==clipping.numIntersection)){initMaterial(material,scene,object);}else if(materialProperties.outputEncoding!==encoding){initMaterial(material,scene,object);}else if(materialProperties.envMap!==envMap){initMaterial(material,scene,object);}}else {initMaterial(material,scene,object);materialProperties.__version=material.version;}var refreshProgram=false;var refreshMaterial=false;var refreshLights=false;var program=materialProperties.program,p_uniforms=program.getUniforms(),m_uniforms=materialProperties.uniforms;if(state.useProgram(program.program)){refreshProgram=true;refreshMaterial=true;refreshLights=true;}if(material.id!==_currentMaterialId){_currentMaterialId=material.id;refreshMaterial=true;}if(refreshProgram||_currentCamera!==camera){p_uniforms.setValue(_gl,'projectionMatrix',camera.projectionMatrix);if(capabilities.logarithmicDepthBuffer){p_uniforms.setValue(_gl,'logDepthBufFC',2.0/(Math.log(camera.far+1.0)/Math.LN2));}if(_currentCamera!==camera){_currentCamera=camera;// lighting uniforms depend on the camera so enforce an update
  953. // now, in case this material supports lights - or later, when
  954. // the next material that does gets activated:
  955. refreshMaterial=true;// set to true on material change
  956. refreshLights=true;// remains set until update done
  957. }// load material specific uniforms
  958. // (shader material also gets them for the sake of genericity)
  959. if(material.isShaderMaterial||material.isMeshPhongMaterial||material.isMeshToonMaterial||material.isMeshStandardMaterial||material.envMap){var uCamPos=p_uniforms.map.cameraPosition;if(uCamPos!==undefined){uCamPos.setValue(_gl,_vector3.setFromMatrixPosition(camera.matrixWorld));}}if(material.isMeshPhongMaterial||material.isMeshToonMaterial||material.isMeshLambertMaterial||material.isMeshBasicMaterial||material.isMeshStandardMaterial||material.isShaderMaterial){p_uniforms.setValue(_gl,'isOrthographic',camera.isOrthographicCamera===true);}if(material.isMeshPhongMaterial||material.isMeshToonMaterial||material.isMeshLambertMaterial||material.isMeshBasicMaterial||material.isMeshStandardMaterial||material.isShaderMaterial||material.isShadowMaterial||material.skinning){p_uniforms.setValue(_gl,'viewMatrix',camera.matrixWorldInverse);}}// skinning uniforms must be set even if material didn't change
  960. // auto-setting of texture unit for bone texture must go before other textures
  961. // otherwise textures used for skinning can take over texture units reserved for other material textures
  962. if(material.skinning){p_uniforms.setOptional(_gl,object,'bindMatrix');p_uniforms.setOptional(_gl,object,'bindMatrixInverse');var skeleton=object.skeleton;if(skeleton){var bones=skeleton.bones;if(capabilities.floatVertexTextures){if(skeleton.boneTexture===null){// layout (1 matrix = 4 pixels)
  963. // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
  964. // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
  965. // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
  966. // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
  967. // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
  968. var size=Math.sqrt(bones.length*4);// 4 pixels needed for 1 matrix
  969. size=MathUtils.ceilPowerOfTwo(size);size=Math.max(size,4);var boneMatrices=new Float32Array(size*size*4);// 4 floats per RGBA pixel
  970. boneMatrices.set(skeleton.boneMatrices);// copy current values
  971. var boneTexture=new DataTexture(boneMatrices,size,size,RGBAFormat,FloatType);skeleton.boneMatrices=boneMatrices;skeleton.boneTexture=boneTexture;skeleton.boneTextureSize=size;}p_uniforms.setValue(_gl,'boneTexture',skeleton.boneTexture,textures);p_uniforms.setValue(_gl,'boneTextureSize',skeleton.boneTextureSize);}else {p_uniforms.setOptional(_gl,skeleton,'boneMatrices');}}}if(refreshMaterial||materialProperties.receiveShadow!==object.receiveShadow){materialProperties.receiveShadow=object.receiveShadow;p_uniforms.setValue(_gl,'receiveShadow',object.receiveShadow);}if(refreshMaterial){p_uniforms.setValue(_gl,'toneMappingExposure',_this.toneMappingExposure);if(materialProperties.needsLights){// the current material requires lighting info
  972. // note: all lighting uniforms are always set correctly
  973. // they simply reference the renderer's state for their
  974. // values
  975. //
  976. // use the current material's .needsUpdate flags to set
  977. // the GL state when required
  978. markUniformsLightsNeedsUpdate(m_uniforms,refreshLights);}// refresh uniforms common to several materials
  979. if(fog&&material.fog){materials.refreshFogUniforms(m_uniforms,fog);}materials.refreshMaterialUniforms(m_uniforms,material,_pixelRatio,_height);WebGLUniforms.upload(_gl,materialProperties.uniformsList,m_uniforms,textures);}if(material.isShaderMaterial&&material.uniformsNeedUpdate===true){WebGLUniforms.upload(_gl,materialProperties.uniformsList,m_uniforms,textures);material.uniformsNeedUpdate=false;}if(material.isSpriteMaterial){p_uniforms.setValue(_gl,'center',object.center);}// common matrices
  980. p_uniforms.setValue(_gl,'modelViewMatrix',object.modelViewMatrix);p_uniforms.setValue(_gl,'normalMatrix',object.normalMatrix);p_uniforms.setValue(_gl,'modelMatrix',object.matrixWorld);return program;}// If uniforms are marked as clean, they don't need to be loaded to the GPU.
  981. function markUniformsLightsNeedsUpdate(uniforms,value){uniforms.ambientLightColor.needsUpdate=value;uniforms.lightProbe.needsUpdate=value;uniforms.directionalLights.needsUpdate=value;uniforms.directionalLightShadows.needsUpdate=value;uniforms.pointLights.needsUpdate=value;uniforms.pointLightShadows.needsUpdate=value;uniforms.spotLights.needsUpdate=value;uniforms.spotLightShadows.needsUpdate=value;uniforms.rectAreaLights.needsUpdate=value;uniforms.hemisphereLights.needsUpdate=value;}function materialNeedsLights(material){return material.isMeshLambertMaterial||material.isMeshToonMaterial||material.isMeshPhongMaterial||material.isMeshStandardMaterial||material.isShadowMaterial||material.isShaderMaterial&&material.lights===true;}//
  982. this.setFramebuffer=function(value){if(_framebuffer!==value&&_currentRenderTarget===null)_gl.bindFramebuffer(36160,value);_framebuffer=value;};this.getActiveCubeFace=function(){return _currentActiveCubeFace;};this.getActiveMipmapLevel=function(){return _currentActiveMipmapLevel;};this.getRenderList=function(){return currentRenderList;};this.setRenderList=function(renderList){currentRenderList=renderList;};this.getRenderTarget=function(){return _currentRenderTarget;};this.setRenderTarget=function(renderTarget){var activeCubeFace=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var activeMipmapLevel=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;_currentRenderTarget=renderTarget;_currentActiveCubeFace=activeCubeFace;_currentActiveMipmapLevel=activeMipmapLevel;if(renderTarget&&properties.get(renderTarget).__webglFramebuffer===undefined){textures.setupRenderTarget(renderTarget);}var framebuffer=_framebuffer;var isCube=false;if(renderTarget){var __webglFramebuffer=properties.get(renderTarget).__webglFramebuffer;if(renderTarget.isWebGLCubeRenderTarget){framebuffer=__webglFramebuffer[activeCubeFace];isCube=true;}else if(renderTarget.isWebGLMultisampleRenderTarget){framebuffer=properties.get(renderTarget).__webglMultisampledFramebuffer;}else {framebuffer=__webglFramebuffer;}_currentViewport.copy(renderTarget.viewport);_currentScissor.copy(renderTarget.scissor);_currentScissorTest=renderTarget.scissorTest;}else {_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor();_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor();_currentScissorTest=_scissorTest;}if(_currentFramebuffer!==framebuffer){_gl.bindFramebuffer(36160,framebuffer);_currentFramebuffer=framebuffer;}state.viewport(_currentViewport);state.scissor(_currentScissor);state.setScissorTest(_currentScissorTest);if(isCube){var textureProperties=properties.get(renderTarget.texture);_gl.framebufferTexture2D(36160,36064,34069+activeCubeFace,textureProperties.__webglTexture,activeMipmapLevel);}};this.readRenderTargetPixels=function(renderTarget,x,y,width,height,buffer,activeCubeFaceIndex){if(!(renderTarget&&renderTarget.isWebGLRenderTarget)){console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.');return;}var framebuffer=properties.get(renderTarget).__webglFramebuffer;if(renderTarget.isWebGLCubeRenderTarget&&activeCubeFaceIndex!==undefined){framebuffer=framebuffer[activeCubeFaceIndex];}if(framebuffer){var restore=false;if(framebuffer!==_currentFramebuffer){_gl.bindFramebuffer(36160,framebuffer);restore=true;}try{var texture=renderTarget.texture;var textureFormat=texture.format;var textureType=texture.type;if(textureFormat!==RGBAFormat&&utils.convert(textureFormat)!==_gl.getParameter(35739)){console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.');return;}if(textureType!==UnsignedByteType&&utils.convert(textureType)!==_gl.getParameter(35738)&&// IE11, Edge and Chrome Mac < 52 (#9513)
  983. !(textureType===FloatType&&(capabilities.isWebGL2||extensions.get('OES_texture_float')||extensions.get('WEBGL_color_buffer_float')))&&// Chrome Mac >= 52 and Firefox
  984. !(textureType===HalfFloatType&&(capabilities.isWebGL2?extensions.get('EXT_color_buffer_float'):extensions.get('EXT_color_buffer_half_float')))){console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.');return;}if(_gl.checkFramebufferStatus(36160)===36053){// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
  985. if(x>=0&&x<=renderTarget.width-width&&y>=0&&y<=renderTarget.height-height){_gl.readPixels(x,y,width,height,utils.convert(textureFormat),utils.convert(textureType),buffer);}}else {console.error('THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.');}}finally{if(restore){_gl.bindFramebuffer(36160,_currentFramebuffer);}}}};this.copyFramebufferToTexture=function(position,texture){var level=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var levelScale=Math.pow(2,-level);var width=Math.floor(texture.image.width*levelScale);var height=Math.floor(texture.image.height*levelScale);var glFormat=utils.convert(texture.format);textures.setTexture2D(texture,0);_gl.copyTexImage2D(3553,level,glFormat,position.x,position.y,width,height,0);state.unbindTexture();};this.copyTextureToTexture=function(position,srcTexture,dstTexture){var level=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0;var width=srcTexture.image.width;var height=srcTexture.image.height;var glFormat=utils.convert(dstTexture.format);var glType=utils.convert(dstTexture.type);textures.setTexture2D(dstTexture,0);// As another texture upload may have changed pixelStorei
  986. // parameters, make sure they are correct for the dstTexture
  987. _gl.pixelStorei(37440,dstTexture.flipY);_gl.pixelStorei(37441,dstTexture.premultiplyAlpha);_gl.pixelStorei(3317,dstTexture.unpackAlignment);if(srcTexture.isDataTexture){_gl.texSubImage2D(3553,level,position.x,position.y,width,height,glFormat,glType,srcTexture.image.data);}else {if(srcTexture.isCompressedTexture){_gl.compressedTexSubImage2D(3553,level,position.x,position.y,srcTexture.mipmaps[0].width,srcTexture.mipmaps[0].height,glFormat,srcTexture.mipmaps[0].data);}else {_gl.texSubImage2D(3553,level,position.x,position.y,glFormat,glType,srcTexture.image);}}// Generate mipmaps only when copying level 0
  988. if(level===0&&dstTexture.generateMipmaps)_gl.generateMipmap(3553);state.unbindTexture();};this.initTexture=function(texture){textures.setTexture2D(texture,0);state.unbindTexture();};this.resetState=function(){state.reset();bindingStates.reset();};if(typeof __THREE_DEVTOOLS__!=='undefined'){__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe',{detail:this}));// eslint-disable-line no-undef
  989. }}function WebGL1Renderer(parameters){WebGLRenderer.call(this,parameters);}WebGL1Renderer.prototype=Object.assign(Object.create(WebGLRenderer.prototype),{constructor:WebGL1Renderer,isWebGL1Renderer:true});class FogExp2{constructor(color,density){Object.defineProperty(this,'isFogExp2',{value:true});this.name='';this.color=new Color(color);this.density=density!==undefined?density:0.00025;}clone(){return new FogExp2(this.color,this.density);}toJSON(/* meta */){return {type:'FogExp2',color:this.color.getHex(),density:this.density};}}class Fog{constructor(color,near,far){Object.defineProperty(this,'isFog',{value:true});this.name='';this.color=new Color(color);this.near=near!==undefined?near:1;this.far=far!==undefined?far:1000;}clone(){return new Fog(this.color,this.near,this.far);}toJSON(/* meta */){return {type:'Fog',color:this.color.getHex(),near:this.near,far:this.far};}}class Scene extends Object3D{constructor(){super();Object.defineProperty(this,'isScene',{value:true});this.type='Scene';this.background=null;this.environment=null;this.fog=null;this.overrideMaterial=null;this.autoUpdate=true;// checked by the renderer
  990. if(typeof __THREE_DEVTOOLS__!=='undefined'){__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe',{detail:this}));// eslint-disable-line no-undef
  991. }}copy(source,recursive){super.copy(source,recursive);if(source.background!==null)this.background=source.background.clone();if(source.environment!==null)this.environment=source.environment.clone();if(source.fog!==null)this.fog=source.fog.clone();if(source.overrideMaterial!==null)this.overrideMaterial=source.overrideMaterial.clone();this.autoUpdate=source.autoUpdate;this.matrixAutoUpdate=source.matrixAutoUpdate;return this;}toJSON(meta){var data=super.toJSON(meta);if(this.background!==null)data.object.background=this.background.toJSON(meta);if(this.environment!==null)data.object.environment=this.environment.toJSON(meta);if(this.fog!==null)data.object.fog=this.fog.toJSON();return data;}}function InterleavedBuffer(array,stride){this.array=array;this.stride=stride;this.count=array!==undefined?array.length/stride:0;this.usage=StaticDrawUsage;this.updateRange={offset:0,count:-1};this.version=0;this.uuid=MathUtils.generateUUID();}Object.defineProperty(InterleavedBuffer.prototype,'needsUpdate',{set:function set(value){if(value===true)this.version++;}});Object.assign(InterleavedBuffer.prototype,{isInterleavedBuffer:true,onUploadCallback:function onUploadCallback(){},setUsage:function setUsage(value){this.usage=value;return this;},copy:function copy(source){this.array=new source.array.constructor(source.array);this.count=source.count;this.stride=source.stride;this.usage=source.usage;return this;},copyAt:function copyAt(index1,attribute,index2){index1*=this.stride;index2*=attribute.stride;for(var _i129=0,l=this.stride;_i129<l;_i129++){this.array[index1+_i129]=attribute.array[index2+_i129];}return this;},set:function set(value){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.array.set(value,offset);return this;},clone:function clone(data){if(data.arrayBuffers===undefined){data.arrayBuffers={};}if(this.array.buffer._uuid===undefined){this.array.buffer._uuid=MathUtils.generateUUID();}if(data.arrayBuffers[this.array.buffer._uuid]===undefined){data.arrayBuffers[this.array.buffer._uuid]=this.array.slice(0).buffer;}var array=new this.array.constructor(data.arrayBuffers[this.array.buffer._uuid]);var ib=new InterleavedBuffer(array,this.stride);ib.setUsage(this.usage);return ib;},onUpload:function onUpload(callback){this.onUploadCallback=callback;return this;},toJSON:function toJSON(data){if(data.arrayBuffers===undefined){data.arrayBuffers={};}// generate UUID for array buffer if necessary
  992. if(this.array.buffer._uuid===undefined){this.array.buffer._uuid=MathUtils.generateUUID();}if(data.arrayBuffers[this.array.buffer._uuid]===undefined){data.arrayBuffers[this.array.buffer._uuid]=Array.prototype.slice.call(new Uint32Array(this.array.buffer));}//
  993. return {uuid:this.uuid,buffer:this.array.buffer._uuid,type:this.array.constructor.name,stride:this.stride};}});var _vector$6=new Vector3();function InterleavedBufferAttribute(interleavedBuffer,itemSize,offset,normalized){this.name='';this.data=interleavedBuffer;this.itemSize=itemSize;this.offset=offset;this.normalized=normalized===true;}Object.defineProperties(InterleavedBufferAttribute.prototype,{count:{get:function get(){return this.data.count;}},array:{get:function get(){return this.data.array;}},needsUpdate:{set:function set(value){this.data.needsUpdate=value;}}});Object.assign(InterleavedBufferAttribute.prototype,{isInterleavedBufferAttribute:true,applyMatrix4:function applyMatrix4(m){for(var _i130=0,l=this.data.count;_i130<l;_i130++){_vector$6.x=this.getX(_i130);_vector$6.y=this.getY(_i130);_vector$6.z=this.getZ(_i130);_vector$6.applyMatrix4(m);this.setXYZ(_i130,_vector$6.x,_vector$6.y,_vector$6.z);}return this;},setX:function setX(index,x){this.data.array[index*this.data.stride+this.offset]=x;return this;},setY:function setY(index,y){this.data.array[index*this.data.stride+this.offset+1]=y;return this;},setZ:function setZ(index,z){this.data.array[index*this.data.stride+this.offset+2]=z;return this;},setW:function setW(index,w){this.data.array[index*this.data.stride+this.offset+3]=w;return this;},getX:function getX(index){return this.data.array[index*this.data.stride+this.offset];},getY:function getY(index){return this.data.array[index*this.data.stride+this.offset+1];},getZ:function getZ(index){return this.data.array[index*this.data.stride+this.offset+2];},getW:function getW(index){return this.data.array[index*this.data.stride+this.offset+3];},setXY:function setXY(index,x,y){index=index*this.data.stride+this.offset;this.data.array[index+0]=x;this.data.array[index+1]=y;return this;},setXYZ:function setXYZ(index,x,y,z){index=index*this.data.stride+this.offset;this.data.array[index+0]=x;this.data.array[index+1]=y;this.data.array[index+2]=z;return this;},setXYZW:function setXYZW(index,x,y,z,w){index=index*this.data.stride+this.offset;this.data.array[index+0]=x;this.data.array[index+1]=y;this.data.array[index+2]=z;this.data.array[index+3]=w;return this;},clone:function clone(data){if(data===undefined){console.log('THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.');var array=[];for(var _i131=0;_i131<this.count;_i131++){var index=_i131*this.data.stride+this.offset;for(var j=0;j<this.itemSize;j++){array.push(this.data.array[index+j]);}}return new BufferAttribute(new this.array.constructor(array),this.itemSize,this.normalized);}else {if(data.interleavedBuffers===undefined){data.interleavedBuffers={};}if(data.interleavedBuffers[this.data.uuid]===undefined){data.interleavedBuffers[this.data.uuid]=this.data.clone(data);}return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid],this.itemSize,this.offset,this.normalized);}},toJSON:function toJSON(data){if(data===undefined){console.log('THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.');var array=[];for(var _i132=0;_i132<this.count;_i132++){var index=_i132*this.data.stride+this.offset;for(var j=0;j<this.itemSize;j++){array.push(this.data.array[index+j]);}}// deinterleave data and save it as an ordinary buffer attribute for now
  994. return {itemSize:this.itemSize,type:this.array.constructor.name,array:array,normalized:this.normalized};}else {// save as true interlaved attribtue
  995. if(data.interleavedBuffers===undefined){data.interleavedBuffers={};}if(data.interleavedBuffers[this.data.uuid]===undefined){data.interleavedBuffers[this.data.uuid]=this.data.toJSON(data);}return {isInterleavedBufferAttribute:true,itemSize:this.itemSize,data:this.data.uuid,offset:this.offset,normalized:this.normalized};}}});/**
  996. * parameters = {
  997. * color: <hex>,
  998. * map: new THREE.Texture( <Image> ),
  999. * alphaMap: new THREE.Texture( <Image> ),
  1000. * rotation: <float>,
  1001. * sizeAttenuation: <bool>
  1002. * }
  1003. */function SpriteMaterial(parameters){Material.call(this);this.type='SpriteMaterial';this.color=new Color(0xffffff);this.map=null;this.alphaMap=null;this.rotation=0;this.sizeAttenuation=true;this.transparent=true;this.setValues(parameters);}SpriteMaterial.prototype=Object.create(Material.prototype);SpriteMaterial.prototype.constructor=SpriteMaterial;SpriteMaterial.prototype.isSpriteMaterial=true;SpriteMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.map=source.map;this.alphaMap=source.alphaMap;this.rotation=source.rotation;this.sizeAttenuation=source.sizeAttenuation;return this;};var _geometry;var _intersectPoint=new Vector3();var _worldScale=new Vector3();var _mvPosition=new Vector3();var _alignedPosition=new Vector2();var _rotatedPosition=new Vector2();var _viewWorldMatrix=new Matrix4();var _vA$1=new Vector3();var _vB$1=new Vector3();var _vC$1=new Vector3();var _uvA$1=new Vector2();var _uvB$1=new Vector2();var _uvC$1=new Vector2();function Sprite$1(material){Object3D.call(this);this.type='Sprite';if(_geometry===undefined){_geometry=new BufferGeometry();var float32Array=new Float32Array([-0.5,-0.5,0,0,0,0.5,-0.5,0,1,0,0.5,0.5,0,1,1,-0.5,0.5,0,0,1]);var interleavedBuffer=new InterleavedBuffer(float32Array,5);_geometry.setIndex([0,1,2,0,2,3]);_geometry.setAttribute('position',new InterleavedBufferAttribute(interleavedBuffer,3,0,false));_geometry.setAttribute('uv',new InterleavedBufferAttribute(interleavedBuffer,2,3,false));}this.geometry=_geometry;this.material=material!==undefined?material:new SpriteMaterial();this.center=new Vector2(0.5,0.5);}Sprite$1.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Sprite$1,isSprite:true,raycast:function raycast(raycaster,intersects){if(raycaster.camera===null){console.error('THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.');}_worldScale.setFromMatrixScale(this.matrixWorld);_viewWorldMatrix.copy(raycaster.camera.matrixWorld);this.modelViewMatrix.multiplyMatrices(raycaster.camera.matrixWorldInverse,this.matrixWorld);_mvPosition.setFromMatrixPosition(this.modelViewMatrix);if(raycaster.camera.isPerspectiveCamera&&this.material.sizeAttenuation===false){_worldScale.multiplyScalar(-_mvPosition.z);}var rotation=this.material.rotation;var sin,cos;if(rotation!==0){cos=Math.cos(rotation);sin=Math.sin(rotation);}var center=this.center;transformVertex(_vA$1.set(-0.5,-0.5,0),_mvPosition,center,_worldScale,sin,cos);transformVertex(_vB$1.set(0.5,-0.5,0),_mvPosition,center,_worldScale,sin,cos);transformVertex(_vC$1.set(0.5,0.5,0),_mvPosition,center,_worldScale,sin,cos);_uvA$1.set(0,0);_uvB$1.set(1,0);_uvC$1.set(1,1);// check first triangle
  1004. var intersect=raycaster.ray.intersectTriangle(_vA$1,_vB$1,_vC$1,false,_intersectPoint);if(intersect===null){// check second triangle
  1005. transformVertex(_vB$1.set(-0.5,0.5,0),_mvPosition,center,_worldScale,sin,cos);_uvB$1.set(0,1);intersect=raycaster.ray.intersectTriangle(_vA$1,_vC$1,_vB$1,false,_intersectPoint);if(intersect===null){return;}}var distance=raycaster.ray.origin.distanceTo(_intersectPoint);if(distance<raycaster.near||distance>raycaster.far)return;intersects.push({distance:distance,point:_intersectPoint.clone(),uv:Triangle.getUV(_intersectPoint,_vA$1,_vB$1,_vC$1,_uvA$1,_uvB$1,_uvC$1,new Vector2()),face:null,object:this});},copy:function copy(source){Object3D.prototype.copy.call(this,source);if(source.center!==undefined)this.center.copy(source.center);this.material=source.material;return this;}});function transformVertex(vertexPosition,mvPosition,center,scale,sin,cos){// compute position in camera space
  1006. _alignedPosition.subVectors(vertexPosition,center).addScalar(0.5).multiply(scale);// to check if rotation is not zero
  1007. if(sin!==undefined){_rotatedPosition.x=cos*_alignedPosition.x-sin*_alignedPosition.y;_rotatedPosition.y=sin*_alignedPosition.x+cos*_alignedPosition.y;}else {_rotatedPosition.copy(_alignedPosition);}vertexPosition.copy(mvPosition);vertexPosition.x+=_rotatedPosition.x;vertexPosition.y+=_rotatedPosition.y;// transform to world space
  1008. vertexPosition.applyMatrix4(_viewWorldMatrix);}var _v1$4=new Vector3();var _v2$2=new Vector3();function LOD(){Object3D.call(this);this._currentLevel=0;this.type='LOD';Object.defineProperties(this,{levels:{enumerable:true,value:[]}});this.autoUpdate=true;}LOD.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:LOD,isLOD:true,copy:function copy(source){Object3D.prototype.copy.call(this,source,false);var levels=source.levels;for(var _i133=0,l=levels.length;_i133<l;_i133++){var level=levels[_i133];this.addLevel(level.object.clone(),level.distance);}this.autoUpdate=source.autoUpdate;return this;},addLevel:function addLevel(object){var distance=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;distance=Math.abs(distance);var levels=this.levels;var l;for(l=0;l<levels.length;l++){if(distance<levels[l].distance){break;}}levels.splice(l,0,{distance:distance,object:object});this.add(object);return this;},getCurrentLevel:function getCurrentLevel(){return this._currentLevel;},getObjectForDistance:function getObjectForDistance(distance){var levels=this.levels;if(levels.length>0){var _i134,l;for(_i134=1,l=levels.length;_i134<l;_i134++){if(distance<levels[_i134].distance){break;}}return levels[_i134-1].object;}return null;},raycast:function raycast(raycaster,intersects){var levels=this.levels;if(levels.length>0){_v1$4.setFromMatrixPosition(this.matrixWorld);var distance=raycaster.ray.origin.distanceTo(_v1$4);this.getObjectForDistance(distance).raycast(raycaster,intersects);}},update:function update(camera){var levels=this.levels;if(levels.length>1){_v1$4.setFromMatrixPosition(camera.matrixWorld);_v2$2.setFromMatrixPosition(this.matrixWorld);var distance=_v1$4.distanceTo(_v2$2)/camera.zoom;levels[0].object.visible=true;var _i135,l;for(_i135=1,l=levels.length;_i135<l;_i135++){if(distance>=levels[_i135].distance){levels[_i135-1].object.visible=false;levels[_i135].object.visible=true;}else {break;}}this._currentLevel=_i135-1;for(;_i135<l;_i135++){levels[_i135].object.visible=false;}}},toJSON:function toJSON(meta){var data=Object3D.prototype.toJSON.call(this,meta);if(this.autoUpdate===false)data.object.autoUpdate=false;data.object.levels=[];var levels=this.levels;for(var _i136=0,l=levels.length;_i136<l;_i136++){var level=levels[_i136];data.object.levels.push({object:level.object.uuid,distance:level.distance});}return data;}});var _basePosition=new Vector3();var _skinIndex=new Vector4();var _skinWeight=new Vector4();var _vector$7=new Vector3();var _matrix$1=new Matrix4();function SkinnedMesh(geometry,material){if(geometry&&geometry.isGeometry){console.error('THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.');}Mesh.call(this,geometry,material);this.type='SkinnedMesh';this.bindMode='attached';this.bindMatrix=new Matrix4();this.bindMatrixInverse=new Matrix4();}SkinnedMesh.prototype=Object.assign(Object.create(Mesh.prototype),{constructor:SkinnedMesh,isSkinnedMesh:true,copy:function copy(source){Mesh.prototype.copy.call(this,source);this.bindMode=source.bindMode;this.bindMatrix.copy(source.bindMatrix);this.bindMatrixInverse.copy(source.bindMatrixInverse);this.skeleton=source.skeleton;return this;},bind:function bind(skeleton,bindMatrix){this.skeleton=skeleton;if(bindMatrix===undefined){this.updateMatrixWorld(true);this.skeleton.calculateInverses();bindMatrix=this.matrixWorld;}this.bindMatrix.copy(bindMatrix);this.bindMatrixInverse.copy(bindMatrix).invert();},pose:function pose(){this.skeleton.pose();},normalizeSkinWeights:function normalizeSkinWeights(){var vector=new Vector4();var skinWeight=this.geometry.attributes.skinWeight;for(var _i137=0,l=skinWeight.count;_i137<l;_i137++){vector.x=skinWeight.getX(_i137);vector.y=skinWeight.getY(_i137);vector.z=skinWeight.getZ(_i137);vector.w=skinWeight.getW(_i137);var scale=1.0/vector.manhattanLength();if(scale!==Infinity){vector.multiplyScalar(scale);}else {vector.set(1,0,0,0);// do something reasonable
  1009. }skinWeight.setXYZW(_i137,vector.x,vector.y,vector.z,vector.w);}},updateMatrixWorld:function updateMatrixWorld(force){Mesh.prototype.updateMatrixWorld.call(this,force);if(this.bindMode==='attached'){this.bindMatrixInverse.copy(this.matrixWorld).invert();}else if(this.bindMode==='detached'){this.bindMatrixInverse.copy(this.bindMatrix).invert();}else {console.warn('THREE.SkinnedMesh: Unrecognized bindMode: '+this.bindMode);}},boneTransform:function boneTransform(index,target){var skeleton=this.skeleton;var geometry=this.geometry;_skinIndex.fromBufferAttribute(geometry.attributes.skinIndex,index);_skinWeight.fromBufferAttribute(geometry.attributes.skinWeight,index);_basePosition.fromBufferAttribute(geometry.attributes.position,index).applyMatrix4(this.bindMatrix);target.set(0,0,0);for(var _i138=0;_i138<4;_i138++){var weight=_skinWeight.getComponent(_i138);if(weight!==0){var boneIndex=_skinIndex.getComponent(_i138);_matrix$1.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld,skeleton.boneInverses[boneIndex]);target.addScaledVector(_vector$7.copy(_basePosition).applyMatrix4(_matrix$1),weight);}}return target.applyMatrix4(this.bindMatrixInverse);}});function Bone(){Object3D.call(this);this.type='Bone';}Bone.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Bone,isBone:true});var _offsetMatrix=new Matrix4();var _identityMatrix=new Matrix4();function Skeleton(){var bones=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var boneInverses=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[];this.uuid=MathUtils.generateUUID();this.bones=bones.slice(0);this.boneInverses=boneInverses;this.boneMatrices=null;this.boneTexture=null;this.boneTextureSize=0;this.frame=-1;this.init();}Object.assign(Skeleton.prototype,{init:function init(){var bones=this.bones;var boneInverses=this.boneInverses;this.boneMatrices=new Float32Array(bones.length*16);// calculate inverse bone matrices if necessary
  1010. if(boneInverses.length===0){this.calculateInverses();}else {// handle special case
  1011. if(bones.length!==boneInverses.length){console.warn('THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.');this.boneInverses=[];for(var _i139=0,il=this.bones.length;_i139<il;_i139++){this.boneInverses.push(new Matrix4());}}}},calculateInverses:function calculateInverses(){this.boneInverses.length=0;for(var _i140=0,il=this.bones.length;_i140<il;_i140++){var inverse=new Matrix4();if(this.bones[_i140]){inverse.copy(this.bones[_i140].matrixWorld).invert();}this.boneInverses.push(inverse);}},pose:function pose(){// recover the bind-time world matrices
  1012. for(var _i141=0,il=this.bones.length;_i141<il;_i141++){var bone=this.bones[_i141];if(bone){bone.matrixWorld.copy(this.boneInverses[_i141]).invert();}}// compute the local matrices, positions, rotations and scales
  1013. for(var _i142=0,_il11=this.bones.length;_i142<_il11;_i142++){var _bone=this.bones[_i142];if(_bone){if(_bone.parent&&_bone.parent.isBone){_bone.matrix.copy(_bone.parent.matrixWorld).invert();_bone.matrix.multiply(_bone.matrixWorld);}else {_bone.matrix.copy(_bone.matrixWorld);}_bone.matrix.decompose(_bone.position,_bone.quaternion,_bone.scale);}}},update:function update(){var bones=this.bones;var boneInverses=this.boneInverses;var boneMatrices=this.boneMatrices;var boneTexture=this.boneTexture;// flatten bone matrices to array
  1014. for(var _i143=0,il=bones.length;_i143<il;_i143++){// compute the offset between the current and the original transform
  1015. var matrix=bones[_i143]?bones[_i143].matrixWorld:_identityMatrix;_offsetMatrix.multiplyMatrices(matrix,boneInverses[_i143]);_offsetMatrix.toArray(boneMatrices,_i143*16);}if(boneTexture!==null){boneTexture.needsUpdate=true;}},clone:function clone(){return new Skeleton(this.bones,this.boneInverses);},getBoneByName:function getBoneByName(name){for(var _i144=0,il=this.bones.length;_i144<il;_i144++){var bone=this.bones[_i144];if(bone.name===name){return bone;}}return undefined;},dispose:function dispose(){if(this.boneTexture!==null){this.boneTexture.dispose();this.boneTexture=null;}},fromJSON:function fromJSON(json,bones){this.uuid=json.uuid;for(var _i145=0,l=json.bones.length;_i145<l;_i145++){var uuid=json.bones[_i145];var bone=bones[uuid];if(bone===undefined){console.warn('THREE.Skeleton: No bone found with UUID:',uuid);bone=new Bone();}this.bones.push(bone);this.boneInverses.push(new Matrix4().fromArray(json.boneInverses[_i145]));}this.init();return this;},toJSON:function toJSON(){var data={metadata:{version:4.5,type:'Skeleton',generator:'Skeleton.toJSON'},bones:[],boneInverses:[]};data.uuid=this.uuid;var bones=this.bones;var boneInverses=this.boneInverses;for(var _i146=0,l=bones.length;_i146<l;_i146++){var bone=bones[_i146];data.bones.push(bone.uuid);var boneInverse=boneInverses[_i146];data.boneInverses.push(boneInverse.toArray());}return data;}});var _instanceLocalMatrix=new Matrix4();var _instanceWorldMatrix=new Matrix4();var _instanceIntersects=[];var _mesh=new Mesh();function InstancedMesh(geometry,material,count){Mesh.call(this,geometry,material);this.instanceMatrix=new BufferAttribute(new Float32Array(count*16),16);this.instanceColor=null;this.count=count;this.frustumCulled=false;}InstancedMesh.prototype=Object.assign(Object.create(Mesh.prototype),{constructor:InstancedMesh,isInstancedMesh:true,copy:function copy(source){Mesh.prototype.copy.call(this,source);this.instanceMatrix.copy(source.instanceMatrix);this.count=source.count;return this;},getColorAt:function getColorAt(index,color){color.fromArray(this.instanceColor.array,index*3);},getMatrixAt:function getMatrixAt(index,matrix){matrix.fromArray(this.instanceMatrix.array,index*16);},raycast:function raycast(raycaster,intersects){var matrixWorld=this.matrixWorld;var raycastTimes=this.count;_mesh.geometry=this.geometry;_mesh.material=this.material;if(_mesh.material===undefined)return;for(var instanceId=0;instanceId<raycastTimes;instanceId++){// calculate the world matrix for each instance
  1016. this.getMatrixAt(instanceId,_instanceLocalMatrix);_instanceWorldMatrix.multiplyMatrices(matrixWorld,_instanceLocalMatrix);// the mesh represents this single instance
  1017. _mesh.matrixWorld=_instanceWorldMatrix;_mesh.raycast(raycaster,_instanceIntersects);// process the result of raycast
  1018. for(var _i147=0,l=_instanceIntersects.length;_i147<l;_i147++){var intersect=_instanceIntersects[_i147];intersect.instanceId=instanceId;intersect.object=this;intersects.push(intersect);}_instanceIntersects.length=0;}},setColorAt:function setColorAt(index,color){if(this.instanceColor===null){this.instanceColor=new BufferAttribute(new Float32Array(this.count*3),3);}color.toArray(this.instanceColor.array,index*3);},setMatrixAt:function setMatrixAt(index,matrix){matrix.toArray(this.instanceMatrix.array,index*16);},updateMorphTargets:function updateMorphTargets(){},dispose:function dispose(){this.dispatchEvent({type:'dispose'});}});/**
  1019. * parameters = {
  1020. * color: <hex>,
  1021. * opacity: <float>,
  1022. *
  1023. * linewidth: <float>,
  1024. * linecap: "round",
  1025. * linejoin: "round"
  1026. * }
  1027. */function LineBasicMaterial(parameters){Material.call(this);this.type='LineBasicMaterial';this.color=new Color(0xffffff);this.linewidth=1;this.linecap='round';this.linejoin='round';this.morphTargets=false;this.setValues(parameters);}LineBasicMaterial.prototype=Object.create(Material.prototype);LineBasicMaterial.prototype.constructor=LineBasicMaterial;LineBasicMaterial.prototype.isLineBasicMaterial=true;LineBasicMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.linewidth=source.linewidth;this.linecap=source.linecap;this.linejoin=source.linejoin;this.morphTargets=source.morphTargets;return this;};var _start=new Vector3();var _end=new Vector3();var _inverseMatrix$1=new Matrix4();var _ray$1=new Ray();var _sphere$2=new Sphere();function Line(){var geometry=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new BufferGeometry();var material=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new LineBasicMaterial();Object3D.call(this);this.type='Line';this.geometry=geometry;this.material=material;this.updateMorphTargets();}Line.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Line,isLine:true,copy:function copy(source){Object3D.prototype.copy.call(this,source);this.material=source.material;this.geometry=source.geometry;return this;},computeLineDistances:function computeLineDistances(){var geometry=this.geometry;if(geometry.isBufferGeometry){// we assume non-indexed geometry
  1028. if(geometry.index===null){var positionAttribute=geometry.attributes.position;var lineDistances=[0];for(var _i148=1,l=positionAttribute.count;_i148<l;_i148++){_start.fromBufferAttribute(positionAttribute,_i148-1);_end.fromBufferAttribute(positionAttribute,_i148);lineDistances[_i148]=lineDistances[_i148-1];lineDistances[_i148]+=_start.distanceTo(_end);}geometry.setAttribute('lineDistance',new Float32BufferAttribute(lineDistances,1));}else {console.warn('THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');}}else if(geometry.isGeometry){var vertices=geometry.vertices;var _lineDistances=geometry.lineDistances;_lineDistances[0]=0;for(var _i149=1,_l6=vertices.length;_i149<_l6;_i149++){_lineDistances[_i149]=_lineDistances[_i149-1];_lineDistances[_i149]+=vertices[_i149-1].distanceTo(vertices[_i149]);}}return this;},raycast:function raycast(raycaster,intersects){var geometry=this.geometry;var matrixWorld=this.matrixWorld;var threshold=raycaster.params.Line.threshold;// Checking boundingSphere distance to ray
  1029. if(geometry.boundingSphere===null)geometry.computeBoundingSphere();_sphere$2.copy(geometry.boundingSphere);_sphere$2.applyMatrix4(matrixWorld);_sphere$2.radius+=threshold;if(raycaster.ray.intersectsSphere(_sphere$2)===false)return;//
  1030. _inverseMatrix$1.copy(matrixWorld).invert();_ray$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$1);var localThreshold=threshold/((this.scale.x+this.scale.y+this.scale.z)/3);var localThresholdSq=localThreshold*localThreshold;var vStart=new Vector3();var vEnd=new Vector3();var interSegment=new Vector3();var interRay=new Vector3();var step=this.isLineSegments?2:1;if(geometry.isBufferGeometry){var index=geometry.index;var attributes=geometry.attributes;var positionAttribute=attributes.position;if(index!==null){var indices=index.array;for(var _i150=0,l=indices.length-1;_i150<l;_i150+=step){var a=indices[_i150];var b=indices[_i150+1];vStart.fromBufferAttribute(positionAttribute,a);vEnd.fromBufferAttribute(positionAttribute,b);var distSq=_ray$1.distanceSqToSegment(vStart,vEnd,interRay,interSegment);if(distSq>localThresholdSq)continue;interRay.applyMatrix4(this.matrixWorld);//Move back to world space for distance calculation
  1031. var distance=raycaster.ray.origin.distanceTo(interRay);if(distance<raycaster.near||distance>raycaster.far)continue;intersects.push({distance:distance,// What do we want? intersection point on the ray or on the segment??
  1032. // point: raycaster.ray.at( distance ),
  1033. point:interSegment.clone().applyMatrix4(this.matrixWorld),index:_i150,face:null,faceIndex:null,object:this});}}else {for(var _i151=0,_l7=positionAttribute.count-1;_i151<_l7;_i151+=step){vStart.fromBufferAttribute(positionAttribute,_i151);vEnd.fromBufferAttribute(positionAttribute,_i151+1);var _distSq=_ray$1.distanceSqToSegment(vStart,vEnd,interRay,interSegment);if(_distSq>localThresholdSq)continue;interRay.applyMatrix4(this.matrixWorld);//Move back to world space for distance calculation
  1034. var _distance=raycaster.ray.origin.distanceTo(interRay);if(_distance<raycaster.near||_distance>raycaster.far)continue;intersects.push({distance:_distance,// What do we want? intersection point on the ray or on the segment??
  1035. // point: raycaster.ray.at( distance ),
  1036. point:interSegment.clone().applyMatrix4(this.matrixWorld),index:_i151,face:null,faceIndex:null,object:this});}}}else if(geometry.isGeometry){var vertices=geometry.vertices;var nbVertices=vertices.length;for(var _i152=0;_i152<nbVertices-1;_i152+=step){var _distSq2=_ray$1.distanceSqToSegment(vertices[_i152],vertices[_i152+1],interRay,interSegment);if(_distSq2>localThresholdSq)continue;interRay.applyMatrix4(this.matrixWorld);//Move back to world space for distance calculation
  1037. var _distance2=raycaster.ray.origin.distanceTo(interRay);if(_distance2<raycaster.near||_distance2>raycaster.far)continue;intersects.push({distance:_distance2,// What do we want? intersection point on the ray or on the segment??
  1038. // point: raycaster.ray.at( distance ),
  1039. point:interSegment.clone().applyMatrix4(this.matrixWorld),index:_i152,face:null,faceIndex:null,object:this});}}},updateMorphTargets:function updateMorphTargets(){var geometry=this.geometry;if(geometry.isBufferGeometry){var morphAttributes=geometry.morphAttributes;var keys=Object.keys(morphAttributes);if(keys.length>0){var morphAttribute=morphAttributes[keys[0]];if(morphAttribute!==undefined){this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var m=0,ml=morphAttribute.length;m<ml;m++){var name=morphAttribute[m].name||String(m);this.morphTargetInfluences.push(0);this.morphTargetDictionary[name]=m;}}}}else {var morphTargets=geometry.morphTargets;if(morphTargets!==undefined&&morphTargets.length>0){console.error('THREE.Line.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.');}}}});var _start$1=new Vector3();var _end$1=new Vector3();function LineSegments(geometry,material){Line.call(this,geometry,material);this.type='LineSegments';}LineSegments.prototype=Object.assign(Object.create(Line.prototype),{constructor:LineSegments,isLineSegments:true,computeLineDistances:function computeLineDistances(){var geometry=this.geometry;if(geometry.isBufferGeometry){// we assume non-indexed geometry
  1040. if(geometry.index===null){var positionAttribute=geometry.attributes.position;var lineDistances=[];for(var _i153=0,l=positionAttribute.count;_i153<l;_i153+=2){_start$1.fromBufferAttribute(positionAttribute,_i153);_end$1.fromBufferAttribute(positionAttribute,_i153+1);lineDistances[_i153]=_i153===0?0:lineDistances[_i153-1];lineDistances[_i153+1]=lineDistances[_i153]+_start$1.distanceTo(_end$1);}geometry.setAttribute('lineDistance',new Float32BufferAttribute(lineDistances,1));}else {console.warn('THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');}}else if(geometry.isGeometry){var vertices=geometry.vertices;var _lineDistances2=geometry.lineDistances;for(var _i154=0,_l8=vertices.length;_i154<_l8;_i154+=2){_start$1.copy(vertices[_i154]);_end$1.copy(vertices[_i154+1]);_lineDistances2[_i154]=_i154===0?0:_lineDistances2[_i154-1];_lineDistances2[_i154+1]=_lineDistances2[_i154]+_start$1.distanceTo(_end$1);}}return this;}});function LineLoop(geometry,material){Line.call(this,geometry,material);this.type='LineLoop';}LineLoop.prototype=Object.assign(Object.create(Line.prototype),{constructor:LineLoop,isLineLoop:true});/**
  1041. * parameters = {
  1042. * color: <hex>,
  1043. * opacity: <float>,
  1044. * map: new THREE.Texture( <Image> ),
  1045. * alphaMap: new THREE.Texture( <Image> ),
  1046. *
  1047. * size: <float>,
  1048. * sizeAttenuation: <bool>
  1049. *
  1050. * morphTargets: <bool>
  1051. * }
  1052. */function PointsMaterial(parameters){Material.call(this);this.type='PointsMaterial';this.color=new Color(0xffffff);this.map=null;this.alphaMap=null;this.size=1;this.sizeAttenuation=true;this.morphTargets=false;this.setValues(parameters);}PointsMaterial.prototype=Object.create(Material.prototype);PointsMaterial.prototype.constructor=PointsMaterial;PointsMaterial.prototype.isPointsMaterial=true;PointsMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.map=source.map;this.alphaMap=source.alphaMap;this.size=source.size;this.sizeAttenuation=source.sizeAttenuation;this.morphTargets=source.morphTargets;return this;};var _inverseMatrix$2=new Matrix4();var _ray$2=new Ray();var _sphere$3=new Sphere();var _position$1=new Vector3();function Points(){var geometry=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new BufferGeometry();var material=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new PointsMaterial();Object3D.call(this);this.type='Points';this.geometry=geometry;this.material=material;this.updateMorphTargets();}Points.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Points,isPoints:true,copy:function copy(source){Object3D.prototype.copy.call(this,source);this.material=source.material;this.geometry=source.geometry;return this;},raycast:function raycast(raycaster,intersects){var geometry=this.geometry;var matrixWorld=this.matrixWorld;var threshold=raycaster.params.Points.threshold;// Checking boundingSphere distance to ray
  1053. if(geometry.boundingSphere===null)geometry.computeBoundingSphere();_sphere$3.copy(geometry.boundingSphere);_sphere$3.applyMatrix4(matrixWorld);_sphere$3.radius+=threshold;if(raycaster.ray.intersectsSphere(_sphere$3)===false)return;//
  1054. _inverseMatrix$2.copy(matrixWorld).invert();_ray$2.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2);var localThreshold=threshold/((this.scale.x+this.scale.y+this.scale.z)/3);var localThresholdSq=localThreshold*localThreshold;if(geometry.isBufferGeometry){var index=geometry.index;var attributes=geometry.attributes;var positionAttribute=attributes.position;if(index!==null){var indices=index.array;for(var _i155=0,il=indices.length;_i155<il;_i155++){var a=indices[_i155];_position$1.fromBufferAttribute(positionAttribute,a);testPoint(_position$1,a,localThresholdSq,matrixWorld,raycaster,intersects,this);}}else {for(var _i156=0,l=positionAttribute.count;_i156<l;_i156++){_position$1.fromBufferAttribute(positionAttribute,_i156);testPoint(_position$1,_i156,localThresholdSq,matrixWorld,raycaster,intersects,this);}}}else {var vertices=geometry.vertices;for(var _i157=0,_l9=vertices.length;_i157<_l9;_i157++){testPoint(vertices[_i157],_i157,localThresholdSq,matrixWorld,raycaster,intersects,this);}}},updateMorphTargets:function updateMorphTargets(){var geometry=this.geometry;if(geometry.isBufferGeometry){var morphAttributes=geometry.morphAttributes;var keys=Object.keys(morphAttributes);if(keys.length>0){var morphAttribute=morphAttributes[keys[0]];if(morphAttribute!==undefined){this.morphTargetInfluences=[];this.morphTargetDictionary={};for(var m=0,ml=morphAttribute.length;m<ml;m++){var name=morphAttribute[m].name||String(m);this.morphTargetInfluences.push(0);this.morphTargetDictionary[name]=m;}}}}else {var morphTargets=geometry.morphTargets;if(morphTargets!==undefined&&morphTargets.length>0){console.error('THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.');}}}});function testPoint(point,index,localThresholdSq,matrixWorld,raycaster,intersects,object){var rayPointDistanceSq=_ray$2.distanceSqToPoint(point);if(rayPointDistanceSq<localThresholdSq){var intersectPoint=new Vector3();_ray$2.closestPointToPoint(point,intersectPoint);intersectPoint.applyMatrix4(matrixWorld);var distance=raycaster.ray.origin.distanceTo(intersectPoint);if(distance<raycaster.near||distance>raycaster.far)return;intersects.push({distance:distance,distanceToRay:Math.sqrt(rayPointDistanceSq),point:intersectPoint,index:index,face:null,object:object});}}function VideoTexture(video,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy){Texture.call(this,video,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy);this.format=format!==undefined?format:RGBFormat;this.minFilter=minFilter!==undefined?minFilter:LinearFilter;this.magFilter=magFilter!==undefined?magFilter:LinearFilter;this.generateMipmaps=false;var scope=this;function updateVideo(){scope.needsUpdate=true;video.requestVideoFrameCallback(updateVideo);}if('requestVideoFrameCallback'in video){video.requestVideoFrameCallback(updateVideo);}}VideoTexture.prototype=Object.assign(Object.create(Texture.prototype),{constructor:VideoTexture,clone:function clone(){return new this.constructor(this.image).copy(this);},isVideoTexture:true,update:function update(){var video=this.image;var hasVideoFrameCallback='requestVideoFrameCallback'in video;if(hasVideoFrameCallback===false&&video.readyState>=video.HAVE_CURRENT_DATA){this.needsUpdate=true;}}});function CompressedTexture(mipmaps,width,height,format,type,mapping,wrapS,wrapT,magFilter,minFilter,anisotropy,encoding){Texture.call(this,null,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy,encoding);this.image={width:width,height:height};this.mipmaps=mipmaps;// no flipping for cube textures
  1055. // (also flipping doesn't work for compressed textures )
  1056. this.flipY=false;// can't generate mipmaps for compressed textures
  1057. // mips must be embedded in DDS files
  1058. this.generateMipmaps=false;}CompressedTexture.prototype=Object.create(Texture.prototype);CompressedTexture.prototype.constructor=CompressedTexture;CompressedTexture.prototype.isCompressedTexture=true;function CanvasTexture(canvas,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy){Texture.call(this,canvas,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy);this.needsUpdate=true;}CanvasTexture.prototype=Object.create(Texture.prototype);CanvasTexture.prototype.constructor=CanvasTexture;CanvasTexture.prototype.isCanvasTexture=true;function DepthTexture(width,height,type,mapping,wrapS,wrapT,magFilter,minFilter,anisotropy,format){format=format!==undefined?format:DepthFormat;if(format!==DepthFormat&&format!==DepthStencilFormat){throw new Error('DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat');}if(type===undefined&&format===DepthFormat)type=UnsignedShortType;if(type===undefined&&format===DepthStencilFormat)type=UnsignedInt248Type$1;Texture.call(this,null,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy);this.image={width:width,height:height};this.magFilter=magFilter!==undefined?magFilter:NearestFilter;this.minFilter=minFilter!==undefined?minFilter:NearestFilter;this.flipY=false;this.generateMipmaps=false;}DepthTexture.prototype=Object.create(Texture.prototype);DepthTexture.prototype.constructor=DepthTexture;DepthTexture.prototype.isDepthTexture=true;var _geometryId=0;// Geometry uses even numbers as Id
  1059. var _m1$3=new Matrix4();var _obj$1=new Object3D();var _offset$1=new Vector3();function Geometry(){Object.defineProperty(this,'id',{value:_geometryId+=2});this.uuid=MathUtils.generateUUID();this.name='';this.type='Geometry';this.vertices=[];this.colors=[];this.faces=[];this.faceVertexUvs=[[]];this.morphTargets=[];this.morphNormals=[];this.skinWeights=[];this.skinIndices=[];this.lineDistances=[];this.boundingBox=null;this.boundingSphere=null;// update flags
  1060. this.elementsNeedUpdate=false;this.verticesNeedUpdate=false;this.uvsNeedUpdate=false;this.normalsNeedUpdate=false;this.colorsNeedUpdate=false;this.lineDistancesNeedUpdate=false;this.groupsNeedUpdate=false;}Geometry.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:Geometry,isGeometry:true,applyMatrix4:function applyMatrix4(matrix){var normalMatrix=new Matrix3().getNormalMatrix(matrix);for(var _i158=0,il=this.vertices.length;_i158<il;_i158++){var vertex=this.vertices[_i158];vertex.applyMatrix4(matrix);}for(var _i159=0,_il12=this.faces.length;_i159<_il12;_i159++){var face=this.faces[_i159];face.normal.applyMatrix3(normalMatrix).normalize();for(var j=0,jl=face.vertexNormals.length;j<jl;j++){face.vertexNormals[j].applyMatrix3(normalMatrix).normalize();}}if(this.boundingBox!==null){this.computeBoundingBox();}if(this.boundingSphere!==null){this.computeBoundingSphere();}this.verticesNeedUpdate=true;this.normalsNeedUpdate=true;return this;},rotateX:function rotateX(angle){// rotate geometry around world x-axis
  1061. _m1$3.makeRotationX(angle);this.applyMatrix4(_m1$3);return this;},rotateY:function rotateY(angle){// rotate geometry around world y-axis
  1062. _m1$3.makeRotationY(angle);this.applyMatrix4(_m1$3);return this;},rotateZ:function rotateZ(angle){// rotate geometry around world z-axis
  1063. _m1$3.makeRotationZ(angle);this.applyMatrix4(_m1$3);return this;},translate:function translate(x,y,z){// translate geometry
  1064. _m1$3.makeTranslation(x,y,z);this.applyMatrix4(_m1$3);return this;},scale:function scale(x,y,z){// scale geometry
  1065. _m1$3.makeScale(x,y,z);this.applyMatrix4(_m1$3);return this;},lookAt:function lookAt(vector){_obj$1.lookAt(vector);_obj$1.updateMatrix();this.applyMatrix4(_obj$1.matrix);return this;},fromBufferGeometry:function fromBufferGeometry(geometry){var scope=this;var index=geometry.index!==null?geometry.index:undefined;var attributes=geometry.attributes;if(attributes.position===undefined){console.error('THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.');return this;}var position=attributes.position;var normal=attributes.normal;var color=attributes.color;var uv=attributes.uv;var uv2=attributes.uv2;if(uv2!==undefined)this.faceVertexUvs[1]=[];for(var _i160=0;_i160<position.count;_i160++){scope.vertices.push(new Vector3().fromBufferAttribute(position,_i160));if(color!==undefined){scope.colors.push(new Color().fromBufferAttribute(color,_i160));}}function addFace(a,b,c,materialIndex){var vertexColors=color===undefined?[]:[scope.colors[a].clone(),scope.colors[b].clone(),scope.colors[c].clone()];var vertexNormals=normal===undefined?[]:[new Vector3().fromBufferAttribute(normal,a),new Vector3().fromBufferAttribute(normal,b),new Vector3().fromBufferAttribute(normal,c)];var face=new Face3(a,b,c,vertexNormals,vertexColors,materialIndex);scope.faces.push(face);if(uv!==undefined){scope.faceVertexUvs[0].push([new Vector2().fromBufferAttribute(uv,a),new Vector2().fromBufferAttribute(uv,b),new Vector2().fromBufferAttribute(uv,c)]);}if(uv2!==undefined){scope.faceVertexUvs[1].push([new Vector2().fromBufferAttribute(uv2,a),new Vector2().fromBufferAttribute(uv2,b),new Vector2().fromBufferAttribute(uv2,c)]);}}var groups=geometry.groups;if(groups.length>0){for(var _i161=0;_i161<groups.length;_i161++){var group=groups[_i161];var start=group.start;var count=group.count;for(var j=start,jl=start+count;j<jl;j+=3){if(index!==undefined){addFace(index.getX(j),index.getX(j+1),index.getX(j+2),group.materialIndex);}else {addFace(j,j+1,j+2,group.materialIndex);}}}}else {if(index!==undefined){for(var _i162=0;_i162<index.count;_i162+=3){addFace(index.getX(_i162),index.getX(_i162+1),index.getX(_i162+2));}}else {for(var _i163=0;_i163<position.count;_i163+=3){addFace(_i163,_i163+1,_i163+2);}}}this.computeFaceNormals();if(geometry.boundingBox!==null){this.boundingBox=geometry.boundingBox.clone();}if(geometry.boundingSphere!==null){this.boundingSphere=geometry.boundingSphere.clone();}return this;},center:function center(){this.computeBoundingBox();this.boundingBox.getCenter(_offset$1).negate();this.translate(_offset$1.x,_offset$1.y,_offset$1.z);return this;},normalize:function normalize(){this.computeBoundingSphere();var center=this.boundingSphere.center;var radius=this.boundingSphere.radius;var s=radius===0?1:1.0/radius;var matrix=new Matrix4();matrix.set(s,0,0,-s*center.x,0,s,0,-s*center.y,0,0,s,-s*center.z,0,0,0,1);this.applyMatrix4(matrix);return this;},computeFaceNormals:function computeFaceNormals(){var cb=new Vector3(),ab=new Vector3();for(var f=0,fl=this.faces.length;f<fl;f++){var face=this.faces[f];var vA=this.vertices[face.a];var vB=this.vertices[face.b];var vC=this.vertices[face.c];cb.subVectors(vC,vB);ab.subVectors(vA,vB);cb.cross(ab);cb.normalize();face.normal.copy(cb);}},computeVertexNormals:function computeVertexNormals(){var areaWeighted=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;var vertices=new Array(this.vertices.length);for(var v=0,vl=this.vertices.length;v<vl;v++){vertices[v]=new Vector3();}if(areaWeighted){// vertex normals weighted by triangle areas
  1066. // http://www.iquilezles.org/www/articles/normals/normals.htm
  1067. var cb=new Vector3(),ab=new Vector3();for(var f=0,fl=this.faces.length;f<fl;f++){var face=this.faces[f];var vA=this.vertices[face.a];var vB=this.vertices[face.b];var vC=this.vertices[face.c];cb.subVectors(vC,vB);ab.subVectors(vA,vB);cb.cross(ab);vertices[face.a].add(cb);vertices[face.b].add(cb);vertices[face.c].add(cb);}}else {this.computeFaceNormals();for(var _f=0,_fl=this.faces.length;_f<_fl;_f++){var _face=this.faces[_f];vertices[_face.a].add(_face.normal);vertices[_face.b].add(_face.normal);vertices[_face.c].add(_face.normal);}}for(var _v=0,_vl=this.vertices.length;_v<_vl;_v++){vertices[_v].normalize();}for(var _f3=0,_fl2=this.faces.length;_f3<_fl2;_f3++){var _face2=this.faces[_f3];var vertexNormals=_face2.vertexNormals;if(vertexNormals.length===3){vertexNormals[0].copy(vertices[_face2.a]);vertexNormals[1].copy(vertices[_face2.b]);vertexNormals[2].copy(vertices[_face2.c]);}else {vertexNormals[0]=vertices[_face2.a].clone();vertexNormals[1]=vertices[_face2.b].clone();vertexNormals[2]=vertices[_face2.c].clone();}}if(this.faces.length>0){this.normalsNeedUpdate=true;}},computeFlatVertexNormals:function computeFlatVertexNormals(){this.computeFaceNormals();for(var f=0,fl=this.faces.length;f<fl;f++){var face=this.faces[f];var vertexNormals=face.vertexNormals;if(vertexNormals.length===3){vertexNormals[0].copy(face.normal);vertexNormals[1].copy(face.normal);vertexNormals[2].copy(face.normal);}else {vertexNormals[0]=face.normal.clone();vertexNormals[1]=face.normal.clone();vertexNormals[2]=face.normal.clone();}}if(this.faces.length>0){this.normalsNeedUpdate=true;}},computeMorphNormals:function computeMorphNormals(){// save original normals
  1068. // - create temp variables on first access
  1069. // otherwise just copy (for faster repeated calls)
  1070. for(var f=0,fl=this.faces.length;f<fl;f++){var face=this.faces[f];if(!face.__originalFaceNormal){face.__originalFaceNormal=face.normal.clone();}else {face.__originalFaceNormal.copy(face.normal);}if(!face.__originalVertexNormals)face.__originalVertexNormals=[];for(var _i164=0,il=face.vertexNormals.length;_i164<il;_i164++){if(!face.__originalVertexNormals[_i164]){face.__originalVertexNormals[_i164]=face.vertexNormals[_i164].clone();}else {face.__originalVertexNormals[_i164].copy(face.vertexNormals[_i164]);}}}// use temp geometry to compute face and vertex normals for each morph
  1071. var tmpGeo=new Geometry();tmpGeo.faces=this.faces;for(var _i165=0,_il13=this.morphTargets.length;_i165<_il13;_i165++){// create on first access
  1072. if(!this.morphNormals[_i165]){this.morphNormals[_i165]={};this.morphNormals[_i165].faceNormals=[];this.morphNormals[_i165].vertexNormals=[];var dstNormalsFace=this.morphNormals[_i165].faceNormals;var dstNormalsVertex=this.morphNormals[_i165].vertexNormals;for(var _f4=0,_fl3=this.faces.length;_f4<_fl3;_f4++){var faceNormal=new Vector3();var vertexNormals={a:new Vector3(),b:new Vector3(),c:new Vector3()};dstNormalsFace.push(faceNormal);dstNormalsVertex.push(vertexNormals);}}var morphNormals=this.morphNormals[_i165];// set vertices to morph target
  1073. tmpGeo.vertices=this.morphTargets[_i165].vertices;// compute morph normals
  1074. tmpGeo.computeFaceNormals();tmpGeo.computeVertexNormals();// store morph normals
  1075. for(var _f5=0,_fl4=this.faces.length;_f5<_fl4;_f5++){var _face3=this.faces[_f5];var _faceNormal=morphNormals.faceNormals[_f5];var _vertexNormals=morphNormals.vertexNormals[_f5];_faceNormal.copy(_face3.normal);_vertexNormals.a.copy(_face3.vertexNormals[0]);_vertexNormals.b.copy(_face3.vertexNormals[1]);_vertexNormals.c.copy(_face3.vertexNormals[2]);}}// restore original normals
  1076. for(var _f6=0,_fl5=this.faces.length;_f6<_fl5;_f6++){var _face4=this.faces[_f6];_face4.normal=_face4.__originalFaceNormal;_face4.vertexNormals=_face4.__originalVertexNormals;}},computeBoundingBox:function computeBoundingBox(){if(this.boundingBox===null){this.boundingBox=new Box3();}this.boundingBox.setFromPoints(this.vertices);},computeBoundingSphere:function computeBoundingSphere(){if(this.boundingSphere===null){this.boundingSphere=new Sphere();}this.boundingSphere.setFromPoints(this.vertices);},merge:function merge(geometry,matrix){var materialIndexOffset=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;if(!(geometry&&geometry.isGeometry)){console.error('THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.',geometry);return;}var normalMatrix;var vertexOffset=this.vertices.length,vertices1=this.vertices,vertices2=geometry.vertices,faces1=this.faces,faces2=geometry.faces,colors1=this.colors,colors2=geometry.colors;if(matrix!==undefined){normalMatrix=new Matrix3().getNormalMatrix(matrix);}// vertices
  1077. for(var _i166=0,il=vertices2.length;_i166<il;_i166++){var vertex=vertices2[_i166];var vertexCopy=vertex.clone();if(matrix!==undefined)vertexCopy.applyMatrix4(matrix);vertices1.push(vertexCopy);}// colors
  1078. for(var _i167=0,_il14=colors2.length;_i167<_il14;_i167++){colors1.push(colors2[_i167].clone());}// faces
  1079. for(var _i168=0,_il15=faces2.length;_i168<_il15;_i168++){var face=faces2[_i168];var normal=void 0,color=void 0;var faceVertexNormals=face.vertexNormals,faceVertexColors=face.vertexColors;var faceCopy=new Face3(face.a+vertexOffset,face.b+vertexOffset,face.c+vertexOffset);faceCopy.normal.copy(face.normal);if(normalMatrix!==undefined){faceCopy.normal.applyMatrix3(normalMatrix).normalize();}for(var j=0,jl=faceVertexNormals.length;j<jl;j++){normal=faceVertexNormals[j].clone();if(normalMatrix!==undefined){normal.applyMatrix3(normalMatrix).normalize();}faceCopy.vertexNormals.push(normal);}faceCopy.color.copy(face.color);for(var _j5=0,_jl2=faceVertexColors.length;_j5<_jl2;_j5++){color=faceVertexColors[_j5];faceCopy.vertexColors.push(color.clone());}faceCopy.materialIndex=face.materialIndex+materialIndexOffset;faces1.push(faceCopy);}// uvs
  1080. for(var _i169=0,_il16=geometry.faceVertexUvs.length;_i169<_il16;_i169++){var faceVertexUvs2=geometry.faceVertexUvs[_i169];if(this.faceVertexUvs[_i169]===undefined)this.faceVertexUvs[_i169]=[];for(var _j6=0,_jl3=faceVertexUvs2.length;_j6<_jl3;_j6++){var uvs2=faceVertexUvs2[_j6],uvsCopy=[];for(var k=0,kl=uvs2.length;k<kl;k++){uvsCopy.push(uvs2[k].clone());}this.faceVertexUvs[_i169].push(uvsCopy);}}},mergeMesh:function mergeMesh(mesh){if(!(mesh&&mesh.isMesh)){console.error('THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.',mesh);return;}if(mesh.matrixAutoUpdate)mesh.updateMatrix();this.merge(mesh.geometry,mesh.matrix);},/*
  1081. * Checks for duplicate vertices with hashmap.
  1082. * Duplicated vertices are removed
  1083. * and faces' vertices are updated.
  1084. */mergeVertices:function mergeVertices(){var precisionPoints=arguments.length>0&&arguments[0]!==undefined?arguments[0]:4;var verticesMap={};// Hashmap for looking up vertices by position coordinates (and making sure they are unique)
  1085. var unique=[],changes=[];var precision=Math.pow(10,precisionPoints);for(var _i170=0,il=this.vertices.length;_i170<il;_i170++){var v=this.vertices[_i170];var key=Math.round(v.x*precision)+'_'+Math.round(v.y*precision)+'_'+Math.round(v.z*precision);if(verticesMap[key]===undefined){verticesMap[key]=_i170;unique.push(this.vertices[_i170]);changes[_i170]=unique.length-1;}else {//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  1086. changes[_i170]=changes[verticesMap[key]];}}// if faces are completely degenerate after merging vertices, we
  1087. // have to remove them from the geometry.
  1088. var faceIndicesToRemove=[];for(var _i171=0,_il17=this.faces.length;_i171<_il17;_i171++){var face=this.faces[_i171];face.a=changes[face.a];face.b=changes[face.b];face.c=changes[face.c];var indices=[face.a,face.b,face.c];// if any duplicate vertices are found in a Face3
  1089. // we have to remove the face as nothing can be saved
  1090. for(var n=0;n<3;n++){if(indices[n]===indices[(n+1)%3]){faceIndicesToRemove.push(_i171);break;}}}for(var _i172=faceIndicesToRemove.length-1;_i172>=0;_i172--){var idx=faceIndicesToRemove[_i172];this.faces.splice(idx,1);for(var j=0,jl=this.faceVertexUvs.length;j<jl;j++){this.faceVertexUvs[j].splice(idx,1);}}// Use unique set of vertices
  1091. var diff=this.vertices.length-unique.length;this.vertices=unique;return diff;},setFromPoints:function setFromPoints(points){this.vertices=[];for(var _i173=0,l=points.length;_i173<l;_i173++){var point=points[_i173];this.vertices.push(new Vector3(point.x,point.y,point.z||0));}return this;},sortFacesByMaterialIndex:function sortFacesByMaterialIndex(){var faces=this.faces;var length=faces.length;// tag faces
  1092. for(var _i174=0;_i174<length;_i174++){faces[_i174]._id=_i174;}// sort faces
  1093. function materialIndexSort(a,b){return a.materialIndex-b.materialIndex;}faces.sort(materialIndexSort);// sort uvs
  1094. var uvs1=this.faceVertexUvs[0];var uvs2=this.faceVertexUvs[1];var newUvs1,newUvs2;if(uvs1&&uvs1.length===length)newUvs1=[];if(uvs2&&uvs2.length===length)newUvs2=[];for(var _i175=0;_i175<length;_i175++){var id=faces[_i175]._id;if(newUvs1)newUvs1.push(uvs1[id]);if(newUvs2)newUvs2.push(uvs2[id]);}if(newUvs1)this.faceVertexUvs[0]=newUvs1;if(newUvs2)this.faceVertexUvs[1]=newUvs2;},toJSON:function toJSON(){var data={metadata:{version:4.5,type:'Geometry',generator:'Geometry.toJSON'}};// standard Geometry serialization
  1095. data.uuid=this.uuid;data.type=this.type;if(this.name!=='')data.name=this.name;if(this.parameters!==undefined){var parameters=this.parameters;for(var key in parameters){if(parameters[key]!==undefined)data[key]=parameters[key];}return data;}var vertices=[];for(var _i176=0;_i176<this.vertices.length;_i176++){var vertex=this.vertices[_i176];vertices.push(vertex.x,vertex.y,vertex.z);}var faces=[];var normals=[];var normalsHash={};var colors=[];var colorsHash={};var uvs=[];var uvsHash={};for(var _i177=0;_i177<this.faces.length;_i177++){var face=this.faces[_i177];var hasMaterial=true;var hasFaceUv=false;// deprecated
  1096. var hasFaceVertexUv=this.faceVertexUvs[0][_i177]!==undefined;var hasFaceNormal=face.normal.length()>0;var hasFaceVertexNormal=face.vertexNormals.length>0;var hasFaceColor=face.color.r!==1||face.color.g!==1||face.color.b!==1;var hasFaceVertexColor=face.vertexColors.length>0;var faceType=0;faceType=setBit(faceType,0,0);// isQuad
  1097. faceType=setBit(faceType,1,hasMaterial);faceType=setBit(faceType,2,hasFaceUv);faceType=setBit(faceType,3,hasFaceVertexUv);faceType=setBit(faceType,4,hasFaceNormal);faceType=setBit(faceType,5,hasFaceVertexNormal);faceType=setBit(faceType,6,hasFaceColor);faceType=setBit(faceType,7,hasFaceVertexColor);faces.push(faceType);faces.push(face.a,face.b,face.c);faces.push(face.materialIndex);if(hasFaceVertexUv){var faceVertexUvs=this.faceVertexUvs[0][_i177];faces.push(getUvIndex(faceVertexUvs[0]),getUvIndex(faceVertexUvs[1]),getUvIndex(faceVertexUvs[2]));}if(hasFaceNormal){faces.push(getNormalIndex(face.normal));}if(hasFaceVertexNormal){var vertexNormals=face.vertexNormals;faces.push(getNormalIndex(vertexNormals[0]),getNormalIndex(vertexNormals[1]),getNormalIndex(vertexNormals[2]));}if(hasFaceColor){faces.push(getColorIndex(face.color));}if(hasFaceVertexColor){var vertexColors=face.vertexColors;faces.push(getColorIndex(vertexColors[0]),getColorIndex(vertexColors[1]),getColorIndex(vertexColors[2]));}}function setBit(value,position,enabled){return enabled?value|1<<position:value&~(1<<position);}function getNormalIndex(normal){var hash=normal.x.toString()+normal.y.toString()+normal.z.toString();if(normalsHash[hash]!==undefined){return normalsHash[hash];}normalsHash[hash]=normals.length/3;normals.push(normal.x,normal.y,normal.z);return normalsHash[hash];}function getColorIndex(color){var hash=color.r.toString()+color.g.toString()+color.b.toString();if(colorsHash[hash]!==undefined){return colorsHash[hash];}colorsHash[hash]=colors.length;colors.push(color.getHex());return colorsHash[hash];}function getUvIndex(uv){var hash=uv.x.toString()+uv.y.toString();if(uvsHash[hash]!==undefined){return uvsHash[hash];}uvsHash[hash]=uvs.length/2;uvs.push(uv.x,uv.y);return uvsHash[hash];}data.data={};data.data.vertices=vertices;data.data.normals=normals;if(colors.length>0)data.data.colors=colors;if(uvs.length>0)data.data.uvs=[uvs];// temporal backward compatibility
  1098. data.data.faces=faces;return data;},clone:function clone(){/*
  1099. // Handle primitives
  1100. const parameters = this.parameters;
  1101. if ( parameters !== undefined ) {
  1102. const values = [];
  1103. for ( const key in parameters ) {
  1104. values.push( parameters[ key ] );
  1105. }
  1106. const geometry = Object.create( this.constructor.prototype );
  1107. this.constructor.apply( geometry, values );
  1108. return geometry;
  1109. }
  1110. return new this.constructor().copy( this );
  1111. */return new Geometry().copy(this);},copy:function copy(source){// reset
  1112. this.vertices=[];this.colors=[];this.faces=[];this.faceVertexUvs=[[]];this.morphTargets=[];this.morphNormals=[];this.skinWeights=[];this.skinIndices=[];this.lineDistances=[];this.boundingBox=null;this.boundingSphere=null;// name
  1113. this.name=source.name;// vertices
  1114. var vertices=source.vertices;for(var _i178=0,il=vertices.length;_i178<il;_i178++){this.vertices.push(vertices[_i178].clone());}// colors
  1115. var colors=source.colors;for(var _i179=0,_il18=colors.length;_i179<_il18;_i179++){this.colors.push(colors[_i179].clone());}// faces
  1116. var faces=source.faces;for(var _i180=0,_il19=faces.length;_i180<_il19;_i180++){this.faces.push(faces[_i180].clone());}// face vertex uvs
  1117. for(var _i181=0,_il20=source.faceVertexUvs.length;_i181<_il20;_i181++){var faceVertexUvs=source.faceVertexUvs[_i181];if(this.faceVertexUvs[_i181]===undefined){this.faceVertexUvs[_i181]=[];}for(var j=0,jl=faceVertexUvs.length;j<jl;j++){var uvs=faceVertexUvs[j],uvsCopy=[];for(var k=0,kl=uvs.length;k<kl;k++){var uv=uvs[k];uvsCopy.push(uv.clone());}this.faceVertexUvs[_i181].push(uvsCopy);}}// morph targets
  1118. var morphTargets=source.morphTargets;for(var _i182=0,_il21=morphTargets.length;_i182<_il21;_i182++){var morphTarget={};morphTarget.name=morphTargets[_i182].name;// vertices
  1119. if(morphTargets[_i182].vertices!==undefined){morphTarget.vertices=[];for(var _j7=0,_jl4=morphTargets[_i182].vertices.length;_j7<_jl4;_j7++){morphTarget.vertices.push(morphTargets[_i182].vertices[_j7].clone());}}// normals
  1120. if(morphTargets[_i182].normals!==undefined){morphTarget.normals=[];for(var _j8=0,_jl5=morphTargets[_i182].normals.length;_j8<_jl5;_j8++){morphTarget.normals.push(morphTargets[_i182].normals[_j8].clone());}}this.morphTargets.push(morphTarget);}// morph normals
  1121. var morphNormals=source.morphNormals;for(var _i183=0,_il22=morphNormals.length;_i183<_il22;_i183++){var morphNormal={};// vertex normals
  1122. if(morphNormals[_i183].vertexNormals!==undefined){morphNormal.vertexNormals=[];for(var _j9=0,_jl6=morphNormals[_i183].vertexNormals.length;_j9<_jl6;_j9++){var srcVertexNormal=morphNormals[_i183].vertexNormals[_j9];var destVertexNormal={};destVertexNormal.a=srcVertexNormal.a.clone();destVertexNormal.b=srcVertexNormal.b.clone();destVertexNormal.c=srcVertexNormal.c.clone();morphNormal.vertexNormals.push(destVertexNormal);}}// face normals
  1123. if(morphNormals[_i183].faceNormals!==undefined){morphNormal.faceNormals=[];for(var _j10=0,_jl7=morphNormals[_i183].faceNormals.length;_j10<_jl7;_j10++){morphNormal.faceNormals.push(morphNormals[_i183].faceNormals[_j10].clone());}}this.morphNormals.push(morphNormal);}// skin weights
  1124. var skinWeights=source.skinWeights;for(var _i184=0,_il23=skinWeights.length;_i184<_il23;_i184++){this.skinWeights.push(skinWeights[_i184].clone());}// skin indices
  1125. var skinIndices=source.skinIndices;for(var _i185=0,_il24=skinIndices.length;_i185<_il24;_i185++){this.skinIndices.push(skinIndices[_i185].clone());}// line distances
  1126. var lineDistances=source.lineDistances;for(var _i186=0,_il25=lineDistances.length;_i186<_il25;_i186++){this.lineDistances.push(lineDistances[_i186]);}// bounding box
  1127. var boundingBox=source.boundingBox;if(boundingBox!==null){this.boundingBox=boundingBox.clone();}// bounding sphere
  1128. var boundingSphere=source.boundingSphere;if(boundingSphere!==null){this.boundingSphere=boundingSphere.clone();}// update flags
  1129. this.elementsNeedUpdate=source.elementsNeedUpdate;this.verticesNeedUpdate=source.verticesNeedUpdate;this.uvsNeedUpdate=source.uvsNeedUpdate;this.normalsNeedUpdate=source.normalsNeedUpdate;this.colorsNeedUpdate=source.colorsNeedUpdate;this.lineDistancesNeedUpdate=source.lineDistancesNeedUpdate;this.groupsNeedUpdate=source.groupsNeedUpdate;return this;},dispose:function dispose(){this.dispatchEvent({type:'dispose'});}});class BoxGeometry extends Geometry{constructor(width,height,depth,widthSegments,heightSegments,depthSegments){super();this.type='BoxGeometry';this.parameters={width:width,height:height,depth:depth,widthSegments:widthSegments,heightSegments:heightSegments,depthSegments:depthSegments};this.fromBufferGeometry(new BoxBufferGeometry(width,height,depth,widthSegments,heightSegments,depthSegments));this.mergeVertices();}}class CircleBufferGeometry extends BufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var segments=arguments.length>1&&arguments[1]!==undefined?arguments[1]:8;var thetaStart=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var thetaLength=arguments.length>3&&arguments[3]!==undefined?arguments[3]:Math.PI*2;super();this.type='CircleBufferGeometry';this.parameters={radius:radius,segments:segments,thetaStart:thetaStart,thetaLength:thetaLength};segments=Math.max(3,segments);// buffers
  1130. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  1131. var vertex=new Vector3();var uv=new Vector2();// center point
  1132. vertices.push(0,0,0);normals.push(0,0,1);uvs.push(0.5,0.5);for(var s=0,_i187=3;s<=segments;s++,_i187+=3){var segment=thetaStart+s/segments*thetaLength;// vertex
  1133. vertex.x=radius*Math.cos(segment);vertex.y=radius*Math.sin(segment);vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1134. normals.push(0,0,1);// uvs
  1135. uv.x=(vertices[_i187]/radius+1)/2;uv.y=(vertices[_i187+1]/radius+1)/2;uvs.push(uv.x,uv.y);}// indices
  1136. for(var _i188=1;_i188<=segments;_i188++){indices.push(_i188,_i188+1,0);}// build geometry
  1137. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}}class CircleGeometry extends Geometry{constructor(radius,segments,thetaStart,thetaLength){super();this.type='CircleGeometry';this.parameters={radius:radius,segments:segments,thetaStart:thetaStart,thetaLength:thetaLength};this.fromBufferGeometry(new CircleBufferGeometry(radius,segments,thetaStart,thetaLength));this.mergeVertices();}}class CylinderBufferGeometry extends BufferGeometry{constructor(){var radiusTop=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var radiusBottom=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var height=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var radialSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:8;var heightSegments=arguments.length>4&&arguments[4]!==undefined?arguments[4]:1;var openEnded=arguments.length>5&&arguments[5]!==undefined?arguments[5]:false;var thetaStart=arguments.length>6&&arguments[6]!==undefined?arguments[6]:0;var thetaLength=arguments.length>7&&arguments[7]!==undefined?arguments[7]:Math.PI*2;super();this.type='CylinderBufferGeometry';this.parameters={radiusTop:radiusTop,radiusBottom:radiusBottom,height:height,radialSegments:radialSegments,heightSegments:heightSegments,openEnded:openEnded,thetaStart:thetaStart,thetaLength:thetaLength};var scope=this;radialSegments=Math.floor(radialSegments);heightSegments=Math.floor(heightSegments);// buffers
  1138. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  1139. var index=0;var indexArray=[];var halfHeight=height/2;var groupStart=0;// generate geometry
  1140. generateTorso();if(openEnded===false){if(radiusTop>0)generateCap(true);if(radiusBottom>0)generateCap(false);}// build geometry
  1141. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));function generateTorso(){var normal=new Vector3();var vertex=new Vector3();var groupCount=0;// this will be used to calculate the normal
  1142. var slope=(radiusBottom-radiusTop)/height;// generate vertices, normals and uvs
  1143. for(var y=0;y<=heightSegments;y++){var indexRow=[];var v=y/heightSegments;// calculate the radius of the current row
  1144. var radius=v*(radiusBottom-radiusTop)+radiusTop;for(var x=0;x<=radialSegments;x++){var u=x/radialSegments;var theta=u*thetaLength+thetaStart;var sinTheta=Math.sin(theta);var cosTheta=Math.cos(theta);// vertex
  1145. vertex.x=radius*sinTheta;vertex.y=-v*height+halfHeight;vertex.z=radius*cosTheta;vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1146. normal.set(sinTheta,slope,cosTheta).normalize();normals.push(normal.x,normal.y,normal.z);// uv
  1147. uvs.push(u,1-v);// save index of vertex in respective row
  1148. indexRow.push(index++);}// now save vertices of the row in our index array
  1149. indexArray.push(indexRow);}// generate indices
  1150. for(var _x2=0;_x2<radialSegments;_x2++){for(var _y2=0;_y2<heightSegments;_y2++){// we use the index array to access the correct indices
  1151. var a=indexArray[_y2][_x2];var b=indexArray[_y2+1][_x2];var c=indexArray[_y2+1][_x2+1];var d=indexArray[_y2][_x2+1];// faces
  1152. indices.push(a,b,d);indices.push(b,c,d);// update group counter
  1153. groupCount+=6;}}// add a group to the geometry. this will ensure multi material support
  1154. scope.addGroup(groupStart,groupCount,0);// calculate new start value for groups
  1155. groupStart+=groupCount;}function generateCap(top){// save the index of the first center vertex
  1156. var centerIndexStart=index;var uv=new Vector2();var vertex=new Vector3();var groupCount=0;var radius=top===true?radiusTop:radiusBottom;var sign=top===true?1:-1;// first we generate the center vertex data of the cap.
  1157. // because the geometry needs one set of uvs per face,
  1158. // we must generate a center vertex per face/segment
  1159. for(var x=1;x<=radialSegments;x++){// vertex
  1160. vertices.push(0,halfHeight*sign,0);// normal
  1161. normals.push(0,sign,0);// uv
  1162. uvs.push(0.5,0.5);// increase index
  1163. index++;}// save the index of the last center vertex
  1164. var centerIndexEnd=index;// now we generate the surrounding vertices, normals and uvs
  1165. for(var _x3=0;_x3<=radialSegments;_x3++){var u=_x3/radialSegments;var theta=u*thetaLength+thetaStart;var cosTheta=Math.cos(theta);var sinTheta=Math.sin(theta);// vertex
  1166. vertex.x=radius*sinTheta;vertex.y=halfHeight*sign;vertex.z=radius*cosTheta;vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1167. normals.push(0,sign,0);// uv
  1168. uv.x=cosTheta*0.5+0.5;uv.y=sinTheta*0.5*sign+0.5;uvs.push(uv.x,uv.y);// increase index
  1169. index++;}// generate indices
  1170. for(var _x4=0;_x4<radialSegments;_x4++){var c=centerIndexStart+_x4;var _i189=centerIndexEnd+_x4;if(top===true){// face top
  1171. indices.push(_i189,_i189+1,c);}else {// face bottom
  1172. indices.push(_i189+1,_i189,c);}groupCount+=3;}// add a group to the geometry. this will ensure multi material support
  1173. scope.addGroup(groupStart,groupCount,top===true?1:2);// calculate new start value for groups
  1174. groupStart+=groupCount;}}}class CylinderGeometry extends Geometry{constructor(radiusTop,radiusBottom,height,radialSegments,heightSegments,openEnded,thetaStart,thetaLength){super();this.type='CylinderGeometry';this.parameters={radiusTop:radiusTop,radiusBottom:radiusBottom,height:height,radialSegments:radialSegments,heightSegments:heightSegments,openEnded:openEnded,thetaStart:thetaStart,thetaLength:thetaLength};this.fromBufferGeometry(new CylinderBufferGeometry(radiusTop,radiusBottom,height,radialSegments,heightSegments,openEnded,thetaStart,thetaLength));this.mergeVertices();}}class ConeGeometry extends CylinderGeometry{constructor(radius,height,radialSegments,heightSegments,openEnded,thetaStart,thetaLength){super(0,radius,height,radialSegments,heightSegments,openEnded,thetaStart,thetaLength);this.type='ConeGeometry';this.parameters={radius:radius,height:height,radialSegments:radialSegments,heightSegments:heightSegments,openEnded:openEnded,thetaStart:thetaStart,thetaLength:thetaLength};}}class ConeBufferGeometry extends CylinderBufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var height=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var radialSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:8;var heightSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;var openEnded=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;var thetaStart=arguments.length>5&&arguments[5]!==undefined?arguments[5]:0;var thetaLength=arguments.length>6&&arguments[6]!==undefined?arguments[6]:Math.PI*2;super(0,radius,height,radialSegments,heightSegments,openEnded,thetaStart,thetaLength);this.type='ConeBufferGeometry';this.parameters={radius:radius,height:height,radialSegments:radialSegments,heightSegments:heightSegments,openEnded:openEnded,thetaStart:thetaStart,thetaLength:thetaLength};}}class PolyhedronBufferGeometry extends BufferGeometry{constructor(vertices,indices){var radius=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var detail=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0;super();this.type='PolyhedronBufferGeometry';this.parameters={vertices:vertices,indices:indices,radius:radius,detail:detail};// default buffer data
  1175. var vertexBuffer=[];var uvBuffer=[];// the subdivision creates the vertex buffer data
  1176. subdivide(detail);// all vertices should lie on a conceptual sphere with a given radius
  1177. applyRadius(radius);// finally, create the uv data
  1178. generateUVs();// build non-indexed geometry
  1179. this.setAttribute('position',new Float32BufferAttribute(vertexBuffer,3));this.setAttribute('normal',new Float32BufferAttribute(vertexBuffer.slice(),3));this.setAttribute('uv',new Float32BufferAttribute(uvBuffer,2));if(detail===0){this.computeVertexNormals();// flat normals
  1180. }else {this.normalizeNormals();// smooth normals
  1181. }// helper functions
  1182. function subdivide(detail){var a=new Vector3();var b=new Vector3();var c=new Vector3();// iterate over all faces and apply a subdivison with the given detail value
  1183. for(var _i190=0;_i190<indices.length;_i190+=3){// get the vertices of the face
  1184. getVertexByIndex(indices[_i190+0],a);getVertexByIndex(indices[_i190+1],b);getVertexByIndex(indices[_i190+2],c);// perform subdivision
  1185. subdivideFace(a,b,c,detail);}}function subdivideFace(a,b,c,detail){var cols=detail+1;// we use this multidimensional array as a data structure for creating the subdivision
  1186. var v=[];// construct all of the vertices for this subdivision
  1187. for(var _i191=0;_i191<=cols;_i191++){v[_i191]=[];var aj=a.clone().lerp(c,_i191/cols);var bj=b.clone().lerp(c,_i191/cols);var rows=cols-_i191;for(var j=0;j<=rows;j++){if(j===0&&_i191===cols){v[_i191][j]=aj;}else {v[_i191][j]=aj.clone().lerp(bj,j/rows);}}}// construct all of the faces
  1188. for(var _i192=0;_i192<cols;_i192++){for(var _j11=0;_j11<2*(cols-_i192)-1;_j11++){var k=Math.floor(_j11/2);if(_j11%2===0){pushVertex(v[_i192][k+1]);pushVertex(v[_i192+1][k]);pushVertex(v[_i192][k]);}else {pushVertex(v[_i192][k+1]);pushVertex(v[_i192+1][k+1]);pushVertex(v[_i192+1][k]);}}}}function applyRadius(radius){var vertex=new Vector3();// iterate over the entire buffer and apply the radius to each vertex
  1189. for(var _i193=0;_i193<vertexBuffer.length;_i193+=3){vertex.x=vertexBuffer[_i193+0];vertex.y=vertexBuffer[_i193+1];vertex.z=vertexBuffer[_i193+2];vertex.normalize().multiplyScalar(radius);vertexBuffer[_i193+0]=vertex.x;vertexBuffer[_i193+1]=vertex.y;vertexBuffer[_i193+2]=vertex.z;}}function generateUVs(){var vertex=new Vector3();for(var _i194=0;_i194<vertexBuffer.length;_i194+=3){vertex.x=vertexBuffer[_i194+0];vertex.y=vertexBuffer[_i194+1];vertex.z=vertexBuffer[_i194+2];var u=azimuth(vertex)/2/Math.PI+0.5;var v=inclination(vertex)/Math.PI+0.5;uvBuffer.push(u,1-v);}correctUVs();correctSeam();}function correctSeam(){// handle case when face straddles the seam, see #3269
  1190. for(var _i195=0;_i195<uvBuffer.length;_i195+=6){// uv data of a single face
  1191. var x0=uvBuffer[_i195+0];var x1=uvBuffer[_i195+2];var x2=uvBuffer[_i195+4];var max=Math.max(x0,x1,x2);var min=Math.min(x0,x1,x2);// 0.9 is somewhat arbitrary
  1192. if(max>0.9&&min<0.1){if(x0<0.2)uvBuffer[_i195+0]+=1;if(x1<0.2)uvBuffer[_i195+2]+=1;if(x2<0.2)uvBuffer[_i195+4]+=1;}}}function pushVertex(vertex){vertexBuffer.push(vertex.x,vertex.y,vertex.z);}function getVertexByIndex(index,vertex){var stride=index*3;vertex.x=vertices[stride+0];vertex.y=vertices[stride+1];vertex.z=vertices[stride+2];}function correctUVs(){var a=new Vector3();var b=new Vector3();var c=new Vector3();var centroid=new Vector3();var uvA=new Vector2();var uvB=new Vector2();var uvC=new Vector2();for(var _i196=0,j=0;_i196<vertexBuffer.length;_i196+=9,j+=6){a.set(vertexBuffer[_i196+0],vertexBuffer[_i196+1],vertexBuffer[_i196+2]);b.set(vertexBuffer[_i196+3],vertexBuffer[_i196+4],vertexBuffer[_i196+5]);c.set(vertexBuffer[_i196+6],vertexBuffer[_i196+7],vertexBuffer[_i196+8]);uvA.set(uvBuffer[j+0],uvBuffer[j+1]);uvB.set(uvBuffer[j+2],uvBuffer[j+3]);uvC.set(uvBuffer[j+4],uvBuffer[j+5]);centroid.copy(a).add(b).add(c).divideScalar(3);var azi=azimuth(centroid);correctUV(uvA,j+0,a,azi);correctUV(uvB,j+2,b,azi);correctUV(uvC,j+4,c,azi);}}function correctUV(uv,stride,vector,azimuth){if(azimuth<0&&uv.x===1){uvBuffer[stride]=uv.x-1;}if(vector.x===0&&vector.z===0){uvBuffer[stride]=azimuth/2/Math.PI+0.5;}}// Angle around the Y axis, counter-clockwise when looking from above.
  1193. function azimuth(vector){return Math.atan2(vector.z,-vector.x);}// Angle above the XZ plane.
  1194. function inclination(vector){return Math.atan2(-vector.y,Math.sqrt(vector.x*vector.x+vector.z*vector.z));}}}class DodecahedronBufferGeometry extends PolyhedronBufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var detail=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var t=(1+Math.sqrt(5))/2;var r=1/t;var vertices=[// (±1, ±1, ±1)
  1195. -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, ±1/φ, ±φ)
  1196. 0,-r,-t,0,-r,t,0,r,-t,0,r,t,// (±1/φ, ±φ, 0)
  1197. -r,-t,0,-r,t,0,r,-t,0,r,t,0,// (±φ, 0, ±1/φ)
  1198. -t,0,-r,t,0,-r,-t,0,r,t,0,r];var indices=[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9];super(vertices,indices,radius,detail);this.type='DodecahedronBufferGeometry';this.parameters={radius:radius,detail:detail};}}class DodecahedronGeometry extends Geometry{constructor(radius,detail){super();this.type='DodecahedronGeometry';this.parameters={radius:radius,detail:detail};this.fromBufferGeometry(new DodecahedronBufferGeometry(radius,detail));this.mergeVertices();}}var _v0$2=new Vector3();var _v1$5=new Vector3();var _normal$1=new Vector3();var _triangle=new Triangle();class EdgesGeometry extends BufferGeometry{constructor(geometry,thresholdAngle){super();this.type='EdgesGeometry';this.parameters={thresholdAngle:thresholdAngle};thresholdAngle=thresholdAngle!==undefined?thresholdAngle:1;if(geometry.isGeometry){geometry=new BufferGeometry().fromGeometry(geometry);}var precisionPoints=4;var precision=Math.pow(10,precisionPoints);var thresholdDot=Math.cos(MathUtils.DEG2RAD*thresholdAngle);var indexAttr=geometry.getIndex();var positionAttr=geometry.getAttribute('position');var indexCount=indexAttr?indexAttr.count:positionAttr.count;var indexArr=[0,0,0];var vertKeys=['a','b','c'];var hashes=new Array(3);var edgeData={};var vertices=[];for(var _i197=0;_i197<indexCount;_i197+=3){if(indexAttr){indexArr[0]=indexAttr.getX(_i197);indexArr[1]=indexAttr.getX(_i197+1);indexArr[2]=indexAttr.getX(_i197+2);}else {indexArr[0]=_i197;indexArr[1]=_i197+1;indexArr[2]=_i197+2;}var{a,b,c}=_triangle;a.fromBufferAttribute(positionAttr,indexArr[0]);b.fromBufferAttribute(positionAttr,indexArr[1]);c.fromBufferAttribute(positionAttr,indexArr[2]);_triangle.getNormal(_normal$1);// create hashes for the edge from the vertices
  1199. hashes[0]="".concat(Math.round(a.x*precision),",").concat(Math.round(a.y*precision),",").concat(Math.round(a.z*precision));hashes[1]="".concat(Math.round(b.x*precision),",").concat(Math.round(b.y*precision),",").concat(Math.round(b.z*precision));hashes[2]="".concat(Math.round(c.x*precision),",").concat(Math.round(c.y*precision),",").concat(Math.round(c.z*precision));// skip degenerate triangles
  1200. if(hashes[0]===hashes[1]||hashes[1]===hashes[2]||hashes[2]===hashes[0]){continue;}// iterate over every edge
  1201. for(var j=0;j<3;j++){// get the first and next vertex making up the edge
  1202. var jNext=(j+1)%3;var vecHash0=hashes[j];var vecHash1=hashes[jNext];var v0=_triangle[vertKeys[j]];var v1=_triangle[vertKeys[jNext]];var hash="".concat(vecHash0,"_").concat(vecHash1);var reverseHash="".concat(vecHash1,"_").concat(vecHash0);if(reverseHash in edgeData&&edgeData[reverseHash]){// if we found a sibling edge add it into the vertex array if
  1203. // it meets the angle threshold and delete the edge from the map.
  1204. if(_normal$1.dot(edgeData[reverseHash].normal)<=thresholdDot){vertices.push(v0.x,v0.y,v0.z);vertices.push(v1.x,v1.y,v1.z);}edgeData[reverseHash]=null;}else if(!(hash in edgeData)){// if we've already got an edge here then skip adding a new one
  1205. edgeData[hash]={index0:indexArr[j],index1:indexArr[jNext],normal:_normal$1.clone()};}}}// iterate over all remaining, unmatched edges and add them to the vertex array
  1206. for(var key in edgeData){if(edgeData[key]){var{index0,index1}=edgeData[key];_v0$2.fromBufferAttribute(positionAttr,index0);_v1$5.fromBufferAttribute(positionAttr,index1);vertices.push(_v0$2.x,_v0$2.y,_v0$2.z);vertices.push(_v1$5.x,_v1$5.y,_v1$5.z);}}this.setAttribute('position',new Float32BufferAttribute(vertices,3));}}/**
  1207. * Port from https://github.com/mapbox/earcut (v2.2.2)
  1208. */var Earcut={triangulate:function triangulate(data,holeIndices,dim){dim=dim||2;var hasHoles=holeIndices&&holeIndices.length;var outerLen=hasHoles?holeIndices[0]*dim:data.length;var outerNode=linkedList(data,0,outerLen,dim,true);var triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;var minX,minY,maxX,maxY,x,y,invSize;if(hasHoles)outerNode=eliminateHoles(data,holeIndices,outerNode,dim);// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  1209. if(data.length>80*dim){minX=maxX=data[0];minY=maxY=data[1];for(var _i198=dim;_i198<outerLen;_i198+=dim){x=data[_i198];y=data[_i198+1];if(x<minX)minX=x;if(y<minY)minY=y;if(x>maxX)maxX=x;if(y>maxY)maxY=y;}// minX, minY and invSize are later used to transform coords into integers for z-order calculation
  1210. invSize=Math.max(maxX-minX,maxY-minY);invSize=invSize!==0?1/invSize:0;}earcutLinked(outerNode,triangles,dim,minX,minY,invSize);return triangles;}};// create a circular doubly linked list from polygon points in the specified winding order
  1211. function linkedList(data,start,end,dim,clockwise){var i,last;if(clockwise===signedArea(data,start,end,dim)>0){for(i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);}else {for(i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);}if(last&&equals(last,last.next)){removeNode(last);last=last.next;}return last;}// eliminate colinear or duplicate points
  1212. function filterPoints(start,end){if(!start)return start;if(!end)end=start;var p=start,again;do{again=false;if(!p.steiner&&(equals(p,p.next)||area(p.prev,p,p.next)===0)){removeNode(p);p=end=p.prev;if(p===p.next)break;again=true;}else {p=p.next;}}while(again||p!==end);return end;}// main ear slicing loop which triangulates a polygon (given as a linked list)
  1213. function earcutLinked(ear,triangles,dim,minX,minY,invSize,pass){if(!ear)return;// interlink polygon nodes in z-order
  1214. if(!pass&&invSize)indexCurve(ear,minX,minY,invSize);var stop=ear,prev,next;// iterate through ears, slicing them one by one
  1215. while(ear.prev!==ear.next){prev=ear.prev;next=ear.next;if(invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear)){// cut off the triangle
  1216. triangles.push(prev.i/dim);triangles.push(ear.i/dim);triangles.push(next.i/dim);removeNode(ear);// skipping the next vertex leads to less sliver triangles
  1217. ear=next.next;stop=next.next;continue;}ear=next;// if we looped through the whole remaining polygon and can't find any more ears
  1218. if(ear===stop){// try filtering points and slicing again
  1219. if(!pass){earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);// if this didn't work, try curing all small self-intersections locally
  1220. }else if(pass===1){ear=cureLocalIntersections(filterPoints(ear),triangles,dim);earcutLinked(ear,triangles,dim,minX,minY,invSize,2);// as a last resort, try splitting the remaining polygon into two
  1221. }else if(pass===2){splitEarcut(ear,triangles,dim,minX,minY,invSize);}break;}}}// check whether a polygon node forms a valid ear with adjacent nodes
  1222. function isEar(ear){var a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return false;// reflex, can't be an ear
  1223. // now make sure we don't have other points inside the potential ear
  1224. var p=ear.next.next;while(p!==ear.prev){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return false;p=p.next;}return true;}function isEarHashed(ear,minX,minY,invSize){var a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return false;// reflex, can't be an ear
  1225. // triangle bbox; min & max are calculated like this for speed
  1226. var minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y;// z-order range for the current triangle bbox;
  1227. var minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);var p=ear.prevZ,n=ear.nextZ;// look for points inside the triangle in both directions
  1228. while(p&&p.z>=minZ&&n&&n.z<=maxZ){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return false;p=p.prevZ;if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return false;n=n.nextZ;}// look for remaining points in decreasing z-order
  1229. while(p&&p.z>=minZ){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return false;p=p.prevZ;}// look for remaining points in increasing z-order
  1230. while(n&&n.z<=maxZ){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return false;n=n.nextZ;}return true;}// go through all polygon nodes and cure small local self-intersections
  1231. function cureLocalIntersections(start,triangles,dim){var p=start;do{var a=p.prev,b=p.next.next;if(!equals(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)){triangles.push(a.i/dim);triangles.push(p.i/dim);triangles.push(b.i/dim);// remove two nodes involved
  1232. removeNode(p);removeNode(p.next);p=start=b;}p=p.next;}while(p!==start);return filterPoints(p);}// try splitting polygon into two and triangulate them independently
  1233. function splitEarcut(start,triangles,dim,minX,minY,invSize){// look for a valid diagonal that divides the polygon into two
  1234. var a=start;do{var b=a.next.next;while(b!==a.prev){if(a.i!==b.i&&isValidDiagonal(a,b)){// split the polygon in two by the diagonal
  1235. var c=splitPolygon(a,b);// filter colinear points around the cuts
  1236. a=filterPoints(a,a.next);c=filterPoints(c,c.next);// run earcut on each half
  1237. earcutLinked(a,triangles,dim,minX,minY,invSize);earcutLinked(c,triangles,dim,minX,minY,invSize);return;}b=b.next;}a=a.next;}while(a!==start);}// link every hole into the outer loop, producing a single-ring polygon without holes
  1238. function eliminateHoles(data,holeIndices,outerNode,dim){var queue=[];var i,len,start,end,list;for(i=0,len=holeIndices.length;i<len;i++){start=holeIndices[i]*dim;end=i<len-1?holeIndices[i+1]*dim:data.length;list=linkedList(data,start,end,dim,false);if(list===list.next)list.steiner=true;queue.push(getLeftmost(list));}queue.sort(compareX);// process holes from left to right
  1239. for(i=0;i<queue.length;i++){eliminateHole(queue[i],outerNode);outerNode=filterPoints(outerNode,outerNode.next);}return outerNode;}function compareX(a,b){return a.x-b.x;}// find a bridge between vertices that connects hole with an outer ring and and link it
  1240. function eliminateHole(hole,outerNode){outerNode=findHoleBridge(hole,outerNode);if(outerNode){var b=splitPolygon(outerNode,hole);// filter collinear points around the cuts
  1241. filterPoints(outerNode,outerNode.next);filterPoints(b,b.next);}}// David Eberly's algorithm for finding a bridge between hole and outer polygon
  1242. function findHoleBridge(hole,outerNode){var p=outerNode;var hx=hole.x;var hy=hole.y;var qx=-Infinity,m;// find a segment intersected by a ray from the hole's leftmost point to the left;
  1243. // segment's endpoint with lesser x will be potential connection point
  1244. do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){var x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){qx=x;if(x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next;}m=p.x<p.next.x?p:p.next;}}p=p.next;}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;// hole touches outer segment; pick leftmost endpoint
  1245. // look for points inside the triangle of hole point, segment intersection and endpoint;
  1246. // if there are no points found, we have a valid connection;
  1247. // otherwise choose the point of the minimum angle with the ray as connection point
  1248. var stop=m,mx=m.x,my=m.y;var tanMin=Infinity,tan;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){tan=Math.abs(hy-p.y)/(hx-p.x);// tangential
  1249. if(locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))){m=p;tanMin=tan;}}p=p.next;}while(p!==stop);return m;}// whether sector in vertex m contains sector in vertex p in the same coordinates
  1250. function sectorContainsSector(m,p){return area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0;}// interlink polygon nodes in z-order
  1251. function indexCurve(start,minX,minY,invSize){var p=start;do{if(p.z===null)p.z=zOrder(p.x,p.y,minX,minY,invSize);p.prevZ=p.prev;p.nextZ=p.next;p=p.next;}while(p!==start);p.prevZ.nextZ=null;p.prevZ=null;sortLinked(p);}// Simon Tatham's linked list merge sort algorithm
  1252. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  1253. function sortLinked(list){var i,p,q,e,tail,numMerges,pSize,qSize,inSize=1;do{p=list;list=null;tail=null;numMerges=0;while(p){numMerges++;q=p;pSize=0;for(i=0;i<inSize;i++){pSize++;q=q.nextZ;if(!q)break;}qSize=inSize;while(pSize>0||qSize>0&&q){if(pSize!==0&&(qSize===0||!q||p.z<=q.z)){e=p;p=p.nextZ;pSize--;}else {e=q;q=q.nextZ;qSize--;}if(tail)tail.nextZ=e;else list=e;e.prevZ=tail;tail=e;}p=q;}tail.nextZ=null;inSize*=2;}while(numMerges>1);return list;}// z-order of a point given coords and inverse of the longer side of data bbox
  1254. function zOrder(x,y,minX,minY,invSize){// coords are transformed into non-negative 15-bit integer range
  1255. x=32767*(x-minX)*invSize;y=32767*(y-minY)*invSize;x=(x|x<<8)&0x00FF00FF;x=(x|x<<4)&0x0F0F0F0F;x=(x|x<<2)&0x33333333;x=(x|x<<1)&0x55555555;y=(y|y<<8)&0x00FF00FF;y=(y|y<<4)&0x0F0F0F0F;y=(y|y<<2)&0x33333333;y=(y|y<<1)&0x55555555;return x|y<<1;}// find the leftmost node of a polygon ring
  1256. function getLeftmost(start){var p=start,leftmost=start;do{if(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)leftmost=p;p=p.next;}while(p!==start);return leftmost;}// check if a point lies within a convex triangle
  1257. function pointInTriangle(ax,ay,bx,by,cx,cy,px,py){return (cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0;}// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  1258. function isValidDiagonal(a,b){return a.next.i!==b.i&&a.prev.i!==b.i&&!intersectsPolygon(a,b)&&(// dones't intersect other edges
  1259. locallyInside(a,b)&&locallyInside(b,a)&&middleInside(a,b)&&(// locally visible
  1260. area(a.prev,a,b.prev)||area(a,b.prev,b))||// does not create opposite-facing sectors
  1261. equals(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0);// special zero-length case
  1262. }// signed area of a triangle
  1263. function area(p,q,r){return (q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y);}// check if two points are equal
  1264. function equals(p1,p2){return p1.x===p2.x&&p1.y===p2.y;}// check if two segments intersect
  1265. function intersects(p1,q1,p2,q2){var o1=sign(area(p1,q1,p2));var o2=sign(area(p1,q1,q2));var o3=sign(area(p2,q2,p1));var o4=sign(area(p2,q2,q1));if(o1!==o2&&o3!==o4)return true;// general case
  1266. if(o1===0&&onSegment(p1,p2,q1))return true;// p1, q1 and p2 are collinear and p2 lies on p1q1
  1267. if(o2===0&&onSegment(p1,q2,q1))return true;// p1, q1 and q2 are collinear and q2 lies on p1q1
  1268. if(o3===0&&onSegment(p2,p1,q2))return true;// p2, q2 and p1 are collinear and p1 lies on p2q2
  1269. if(o4===0&&onSegment(p2,q1,q2))return true;// p2, q2 and q1 are collinear and q1 lies on p2q2
  1270. return false;}// for collinear points p, q, r, check if point q lies on segment pr
  1271. function onSegment(p,q,r){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);}function sign(num){return num>0?1:num<0?-1:0;}// check if a polygon diagonal intersects any polygon segments
  1272. function intersectsPolygon(a,b){var p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return true;p=p.next;}while(p!==a);return false;}// check if a polygon diagonal is locally inside the polygon
  1273. function locallyInside(a,b){return area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0;}// check if the middle point of a polygon diagonal is inside the polygon
  1274. function middleInside(a,b){var p=a,inside=false;var px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{if(p.y>py!==p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x)inside=!inside;p=p.next;}while(p!==a);return inside;}// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  1275. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  1276. function splitPolygon(a,b){var a2=new Node(a.i,a.x,a.y),b2=new Node(b.i,b.x,b.y),an=a.next,bp=b.prev;a.next=b;b.prev=a;a2.next=an;an.prev=a2;b2.next=a2;a2.prev=b2;bp.next=b2;b2.prev=bp;return b2;}// create a node and optionally link it with previous one (in a circular doubly linked list)
  1277. function insertNode(i,x,y,last){var p=new Node(i,x,y);if(!last){p.prev=p;p.next=p;}else {p.next=last.next;p.prev=last;last.next.prev=p;last.next=p;}return p;}function removeNode(p){p.next.prev=p.prev;p.prev.next=p.next;if(p.prevZ)p.prevZ.nextZ=p.nextZ;if(p.nextZ)p.nextZ.prevZ=p.prevZ;}function Node(i,x,y){// vertex index in coordinates array
  1278. this.i=i;// vertex coordinates
  1279. this.x=x;this.y=y;// previous and next vertex nodes in a polygon ring
  1280. this.prev=null;this.next=null;// z-order curve value
  1281. this.z=null;// previous and next nodes in z-order
  1282. this.prevZ=null;this.nextZ=null;// indicates whether this is a steiner point
  1283. this.steiner=false;}function signedArea(data,start,end,dim){var sum=0;for(var _i199=start,j=end-dim;_i199<end;_i199+=dim){sum+=(data[j]-data[_i199])*(data[_i199+1]+data[j+1]);j=_i199;}return sum;}var ShapeUtils={// calculate area of the contour polygon
  1284. area:function area(contour){var n=contour.length;var a=0.0;for(var p=n-1,q=0;q<n;p=q++){a+=contour[p].x*contour[q].y-contour[q].x*contour[p].y;}return a*0.5;},isClockWise:function isClockWise(pts){return ShapeUtils.area(pts)<0;},triangulateShape:function triangulateShape(contour,holes){var vertices=[];// flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
  1285. var holeIndices=[];// array of hole indices
  1286. var faces=[];// final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
  1287. removeDupEndPts(contour);addContour(vertices,contour);//
  1288. var holeIndex=contour.length;holes.forEach(removeDupEndPts);for(var _i200=0;_i200<holes.length;_i200++){holeIndices.push(holeIndex);holeIndex+=holes[_i200].length;addContour(vertices,holes[_i200]);}//
  1289. var triangles=Earcut.triangulate(vertices,holeIndices);//
  1290. for(var _i201=0;_i201<triangles.length;_i201+=3){faces.push(triangles.slice(_i201,_i201+3));}return faces;}};function removeDupEndPts(points){var l=points.length;if(l>2&&points[l-1].equals(points[0])){points.pop();}}function addContour(vertices,contour){for(var _i202=0;_i202<contour.length;_i202++){vertices.push(contour[_i202].x);vertices.push(contour[_i202].y);}}/**
  1291. * Creates extruded geometry from a path shape.
  1292. *
  1293. * parameters = {
  1294. *
  1295. * curveSegments: <int>, // number of points on the curves
  1296. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  1297. * depth: <float>, // Depth to extrude the shape
  1298. *
  1299. * bevelEnabled: <bool>, // turn on bevel
  1300. * bevelThickness: <float>, // how deep into the original shape bevel goes
  1301. * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
  1302. * bevelOffset: <float>, // how far from shape outline does bevel start
  1303. * bevelSegments: <int>, // number of bevel layers
  1304. *
  1305. * extrudePath: <THREE.Curve> // curve to extrude shape along
  1306. *
  1307. * UVGenerator: <Object> // object that provides UV generator functions
  1308. *
  1309. * }
  1310. */class ExtrudeBufferGeometry extends BufferGeometry{constructor(shapes,options){super();this.type='ExtrudeBufferGeometry';this.parameters={shapes:shapes,options:options};shapes=Array.isArray(shapes)?shapes:[shapes];var scope=this;var verticesArray=[];var uvArray=[];for(var _i203=0,l=shapes.length;_i203<l;_i203++){var shape=shapes[_i203];addShape(shape);}// build geometry
  1311. this.setAttribute('position',new Float32BufferAttribute(verticesArray,3));this.setAttribute('uv',new Float32BufferAttribute(uvArray,2));this.computeVertexNormals();// functions
  1312. function addShape(shape){var placeholder=[];// options
  1313. var curveSegments=options.curveSegments!==undefined?options.curveSegments:12;var steps=options.steps!==undefined?options.steps:1;var depth=options.depth!==undefined?options.depth:100;var bevelEnabled=options.bevelEnabled!==undefined?options.bevelEnabled:true;var bevelThickness=options.bevelThickness!==undefined?options.bevelThickness:6;var bevelSize=options.bevelSize!==undefined?options.bevelSize:bevelThickness-2;var bevelOffset=options.bevelOffset!==undefined?options.bevelOffset:0;var bevelSegments=options.bevelSegments!==undefined?options.bevelSegments:3;var extrudePath=options.extrudePath;var uvgen=options.UVGenerator!==undefined?options.UVGenerator:WorldUVGenerator;// deprecated options
  1314. if(options.amount!==undefined){console.warn('THREE.ExtrudeBufferGeometry: amount has been renamed to depth.');depth=options.amount;}//
  1315. var extrudePts,extrudeByPath=false;var splineTube,binormal,normal,position2;if(extrudePath){extrudePts=options.dontSmooth?extrudePath.points.slice():extrudePath.getSpacedPoints(steps);//add!!!!!!!!! 不要平均分,直接用原来的点
  1316. extrudeByPath=true;bevelEnabled=false;// bevels not supported for path extrusion
  1317. // SETUP TNB variables
  1318. // TODO1 - have a .isClosed in spline?
  1319. splineTube=extrudePath.computeFrenetFrames(steps,false,options.dontSmooth);///xzw add true !!!!!
  1320. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  1321. binormal=new Vector3();normal=new Vector3();position2=new Vector3();}// Safeguards if bevels are not enabled
  1322. if(!bevelEnabled){bevelSegments=0;bevelThickness=0;bevelSize=0;bevelOffset=0;}// Variables initialization
  1323. var shapePoints=shape.extractPoints(curveSegments);var vertices=shapePoints.shape;var holes=shapePoints.holes;var reverse=!ShapeUtils.isClockWise(vertices);if(reverse){vertices=vertices.reverse();// Maybe we should also check if holes are in the opposite direction, just to be safe ...
  1324. for(var h=0,hl=holes.length;h<hl;h++){var ahole=holes[h];if(ShapeUtils.isClockWise(ahole)){holes[h]=ahole.reverse();}}}var faces=ShapeUtils.triangulateShape(vertices,holes);/* Vertices */var contour=vertices;// vertices has all points but contour has only points of circumference
  1325. for(var _h=0,_hl=holes.length;_h<_hl;_h++){var _ahole=holes[_h];vertices=vertices.concat(_ahole);}function scalePt2(pt,vec,size){if(!vec)console.error('THREE.ExtrudeGeometry: vec does not exist');return vec.clone().multiplyScalar(size).add(pt);}var vlen=vertices.length,flen=faces.length;// Find directions for point movement
  1326. function getBevelVec(inPt,inPrev,inNext){// computes for inPt the corresponding point inPt' on a new contour
  1327. // shifted by 1 unit (length of normalized vector) to the left
  1328. // if we walk along contour clockwise, this new contour is outside the old one
  1329. //
  1330. // inPt' is the intersection of the two lines parallel to the two
  1331. // adjacent edges of inPt at a distance of 1 unit on the left side.
  1332. var v_trans_x,v_trans_y,shrink_by;// resulting translation vector for inPt
  1333. // good reading for geometry algorithms (here: line-line intersection)
  1334. // http://geomalgorithms.com/a05-_intersect-1.html
  1335. var v_prev_x=inPt.x-inPrev.x,v_prev_y=inPt.y-inPrev.y;var v_next_x=inNext.x-inPt.x,v_next_y=inNext.y-inPt.y;var v_prev_lensq=v_prev_x*v_prev_x+v_prev_y*v_prev_y;// check for collinear edges
  1336. var collinear0=v_prev_x*v_next_y-v_prev_y*v_next_x;if(Math.abs(collinear0)>Number.EPSILON){// not collinear
  1337. // length of vectors for normalizing
  1338. var v_prev_len=Math.sqrt(v_prev_lensq);var v_next_len=Math.sqrt(v_next_x*v_next_x+v_next_y*v_next_y);// shift adjacent points by unit vectors to the left
  1339. var ptPrevShift_x=inPrev.x-v_prev_y/v_prev_len;var ptPrevShift_y=inPrev.y+v_prev_x/v_prev_len;var ptNextShift_x=inNext.x-v_next_y/v_next_len;var ptNextShift_y=inNext.y+v_next_x/v_next_len;// scaling factor for v_prev to intersection point
  1340. var sf=((ptNextShift_x-ptPrevShift_x)*v_next_y-(ptNextShift_y-ptPrevShift_y)*v_next_x)/(v_prev_x*v_next_y-v_prev_y*v_next_x);// vector from inPt to intersection point
  1341. v_trans_x=ptPrevShift_x+v_prev_x*sf-inPt.x;v_trans_y=ptPrevShift_y+v_prev_y*sf-inPt.y;// Don't normalize!, otherwise sharp corners become ugly
  1342. // but prevent crazy spikes
  1343. var v_trans_lensq=v_trans_x*v_trans_x+v_trans_y*v_trans_y;if(v_trans_lensq<=2){return new Vector2(v_trans_x,v_trans_y);}else {shrink_by=Math.sqrt(v_trans_lensq/2);}}else {// handle special case of collinear edges
  1344. var direction_eq=false;// assumes: opposite
  1345. if(v_prev_x>Number.EPSILON){if(v_next_x>Number.EPSILON){direction_eq=true;}}else {if(v_prev_x<-Number.EPSILON){if(v_next_x<-Number.EPSILON){direction_eq=true;}}else {if(Math.sign(v_prev_y)===Math.sign(v_next_y)){direction_eq=true;}}}if(direction_eq){// console.log("Warning: lines are a straight sequence");
  1346. v_trans_x=-v_prev_y;v_trans_y=v_prev_x;shrink_by=Math.sqrt(v_prev_lensq);}else {// console.log("Warning: lines are a straight spike");
  1347. v_trans_x=v_prev_x;v_trans_y=v_prev_y;shrink_by=Math.sqrt(v_prev_lensq/2);}}return new Vector2(v_trans_x/shrink_by,v_trans_y/shrink_by);}var contourMovements=[];for(var _i204=0,il=contour.length,j=il-1,k=_i204+1;_i204<il;_i204++,j++,k++){if(j===il)j=0;if(k===il)k=0;// (j)---(i)---(k)
  1348. // console.log('i,j,k', i, j , k)
  1349. contourMovements[_i204]=getBevelVec(contour[_i204],contour[j],contour[k]);}var holesMovements=[];var oneHoleMovements,verticesMovements=contourMovements.concat();for(var _h2=0,_hl2=holes.length;_h2<_hl2;_h2++){var _ahole2=holes[_h2];oneHoleMovements=[];for(var _i205=0,_il26=_ahole2.length,_j12=_il26-1,_k=_i205+1;_i205<_il26;_i205++,_j12++,_k++){if(_j12===_il26)_j12=0;if(_k===_il26)_k=0;// (j)---(i)---(k)
  1350. oneHoleMovements[_i205]=getBevelVec(_ahole2[_i205],_ahole2[_j12],_ahole2[_k]);}holesMovements.push(oneHoleMovements);verticesMovements=verticesMovements.concat(oneHoleMovements);}// Loop bevelSegments, 1 for the front, 1 for the back
  1351. for(var b=0;b<bevelSegments;b++){//for ( b = bevelSegments; b > 0; b -- ) {
  1352. var t=b/bevelSegments;var z=bevelThickness*Math.cos(t*Math.PI/2);var _bs=bevelSize*Math.sin(t*Math.PI/2)+bevelOffset;// contract shape
  1353. for(var _i206=0,_il27=contour.length;_i206<_il27;_i206++){var vert=scalePt2(contour[_i206],contourMovements[_i206],_bs);v(vert.x,vert.y,-z);}// expand holes
  1354. for(var _h3=0,_hl3=holes.length;_h3<_hl3;_h3++){var _ahole3=holes[_h3];oneHoleMovements=holesMovements[_h3];for(var _i207=0,_il28=_ahole3.length;_i207<_il28;_i207++){var _vert=scalePt2(_ahole3[_i207],oneHoleMovements[_i207],_bs);v(_vert.x,_vert.y,-z);}}}var bs=bevelSize+bevelOffset;// Back facing vertices
  1355. for(var _i208=0;_i208<vlen;_i208++){var _vert2=bevelEnabled?scalePt2(vertices[_i208],verticesMovements[_i208],bs):vertices[_i208];if(!extrudeByPath){v(_vert2.x,_vert2.y,0);}else {// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  1356. normal.copy(splineTube.normals[0]).multiplyScalar(_vert2.x);binormal.copy(splineTube.binormals[0]).multiplyScalar(_vert2.y);position2.copy(extrudePts[0]).add(normal).add(binormal);v(position2.x,position2.y,position2.z);}}// Add stepped vertices...
  1357. // Including front facing vertices
  1358. for(var s=1;s<=steps;s++){for(var _i209=0;_i209<vlen;_i209++){var _vert3=bevelEnabled?scalePt2(vertices[_i209],verticesMovements[_i209],bs):vertices[_i209];if(!extrudeByPath){v(_vert3.x,_vert3.y,depth/steps*s);}else {// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  1359. normal.copy(splineTube.normals[s]).multiplyScalar(_vert3.x);binormal.copy(splineTube.binormals[s]).multiplyScalar(_vert3.y);position2.copy(extrudePts[s]).add(normal).add(binormal);v(position2.x,position2.y,position2.z);}}}// Add bevel segments planes
  1360. //for ( b = 1; b <= bevelSegments; b ++ ) {
  1361. for(var _b5=bevelSegments-1;_b5>=0;_b5--){var _t=_b5/bevelSegments;var _z2=bevelThickness*Math.cos(_t*Math.PI/2);var _bs2=bevelSize*Math.sin(_t*Math.PI/2)+bevelOffset;// contract shape
  1362. for(var _i210=0,_il29=contour.length;_i210<_il29;_i210++){var _vert4=scalePt2(contour[_i210],contourMovements[_i210],_bs2);v(_vert4.x,_vert4.y,depth+_z2);}// expand holes
  1363. for(var _h4=0,_hl4=holes.length;_h4<_hl4;_h4++){var _ahole4=holes[_h4];oneHoleMovements=holesMovements[_h4];for(var _i211=0,_il30=_ahole4.length;_i211<_il30;_i211++){var _vert5=scalePt2(_ahole4[_i211],oneHoleMovements[_i211],_bs2);if(!extrudeByPath){v(_vert5.x,_vert5.y,depth+_z2);}else {v(_vert5.x,_vert5.y+extrudePts[steps-1].y,extrudePts[steps-1].x+_z2);}}}}/* Faces */ // Top and bottom faces
  1364. if(!options.openEnded){//xzw add 可以选择开口,不创建Top and bottom faces
  1365. buildLidFaces();}// Sides faces
  1366. buildSideFaces();///// Internal functions
  1367. function buildLidFaces(){var start=verticesArray.length/3;if(bevelEnabled){var layer=0;// steps + 1
  1368. var offset=vlen*layer;// Bottom faces
  1369. for(var _i212=0;_i212<flen;_i212++){var face=faces[_i212];f3(face[2]+offset,face[1]+offset,face[0]+offset);}layer=steps+bevelSegments*2;offset=vlen*layer;// Top faces
  1370. for(var _i213=0;_i213<flen;_i213++){var _face5=faces[_i213];f3(_face5[0]+offset,_face5[1]+offset,_face5[2]+offset);}}else {// Bottom faces
  1371. for(var _i214=0;_i214<flen;_i214++){var _face6=faces[_i214];f3(_face6[2],_face6[1],_face6[0]);}// Top faces
  1372. for(var _i215=0;_i215<flen;_i215++){var _face7=faces[_i215];f3(_face7[0]+vlen*steps,_face7[1]+vlen*steps,_face7[2]+vlen*steps);}}scope.addGroup(start,verticesArray.length/3-start,0);}// Create faces for the z-sides of the shape
  1373. function buildSideFaces(){var start=verticesArray.length/3;var layeroffset=0;sidewalls(contour,layeroffset);layeroffset+=contour.length;for(var _h5=0,_hl5=holes.length;_h5<_hl5;_h5++){var _ahole5=holes[_h5];sidewalls(_ahole5,layeroffset);//, true
  1374. layeroffset+=_ahole5.length;}scope.addGroup(start,verticesArray.length/3-start,1);}function sidewalls(contour,layeroffset){var i=contour.length;var shapeDontClose=shape.dontClose;//xzw add不闭合
  1375. while(--i>=0){if(shapeDontClose&&i==0)break;//xzw add
  1376. var _j13=i;var _k2=i-1;if(_k2<0)_k2=contour.length-1;//console.log('b', i,j, i-1, k,vertices.length);
  1377. for(var _s4=0,sl=steps+bevelSegments*2;_s4<sl;_s4++){var slen1=vlen*_s4;var slen2=vlen*(_s4+1);var a=layeroffset+_j13+slen1,_b6=layeroffset+_k2+slen1,c=layeroffset+_k2+slen2,d=layeroffset+_j13+slen2;f4(a,_b6,c,d);}}}function v(x,y,z){placeholder.push(x);placeholder.push(y);placeholder.push(z);}function f3(a,b,c){addVertex(a);addVertex(b);addVertex(c);var nextIndex=verticesArray.length/3;var uvs=uvgen.generateTopUV(scope,verticesArray,nextIndex-3,nextIndex-2,nextIndex-1);addUV(uvs[0]);addUV(uvs[1]);addUV(uvs[2]);}function f4(a,b,c,d){addVertex(a);addVertex(b);addVertex(d);addVertex(b);addVertex(c);addVertex(d);var nextIndex=verticesArray.length/3;var uvs=uvgen.generateSideWallUV(scope,verticesArray,nextIndex-6,nextIndex-3,nextIndex-2,nextIndex-1);addUV(uvs[0]);addUV(uvs[1]);addUV(uvs[3]);addUV(uvs[1]);addUV(uvs[2]);addUV(uvs[3]);}function addVertex(index){verticesArray.push(placeholder[index*3+0]);verticesArray.push(placeholder[index*3+1]);verticesArray.push(placeholder[index*3+2]);}function addUV(vector2){uvArray.push(vector2.x);uvArray.push(vector2.y);}}}toJSON(){var data=BufferGeometry.prototype.toJSON.call(this);var shapes=this.parameters.shapes;var options=this.parameters.options;return toJSON(shapes,options,data);}}var WorldUVGenerator={generateTopUV:function generateTopUV(geometry,vertices,indexA,indexB,indexC){var a_x=vertices[indexA*3];var a_y=vertices[indexA*3+1];var b_x=vertices[indexB*3];var b_y=vertices[indexB*3+1];var c_x=vertices[indexC*3];var c_y=vertices[indexC*3+1];return [new Vector2(a_x,a_y),new Vector2(b_x,b_y),new Vector2(c_x,c_y)];},generateSideWallUV:function generateSideWallUV(geometry,vertices,indexA,indexB,indexC,indexD){var a_x=vertices[indexA*3];var a_y=vertices[indexA*3+1];var a_z=vertices[indexA*3+2];var b_x=vertices[indexB*3];var b_y=vertices[indexB*3+1];var b_z=vertices[indexB*3+2];var c_x=vertices[indexC*3];var c_y=vertices[indexC*3+1];var c_z=vertices[indexC*3+2];var d_x=vertices[indexD*3];var d_y=vertices[indexD*3+1];var d_z=vertices[indexD*3+2];if(Math.abs(a_y-b_y)<0.01){return [new Vector2(a_x,1-a_z),new Vector2(b_x,1-b_z),new Vector2(c_x,1-c_z),new Vector2(d_x,1-d_z)];}else {return [new Vector2(a_y,1-a_z),new Vector2(b_y,1-b_z),new Vector2(c_y,1-c_z),new Vector2(d_y,1-d_z)];}}};function toJSON(shapes,options,data){data.shapes=[];if(Array.isArray(shapes)){for(var _i216=0,l=shapes.length;_i216<l;_i216++){var shape=shapes[_i216];data.shapes.push(shape.uuid);}}else {data.shapes.push(shapes.uuid);}if(options.extrudePath!==undefined)data.options.extrudePath=options.extrudePath.toJSON();return data;}/**
  1378. * Creates extruded geometry from a path shape.
  1379. *
  1380. * parameters = {
  1381. *
  1382. * curveSegments: <int>, // number of points on the curves
  1383. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  1384. * depth: <float>, // Depth to extrude the shape
  1385. *
  1386. * bevelEnabled: <bool>, // turn on bevel
  1387. * bevelThickness: <float>, // how deep into the original shape bevel goes
  1388. * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
  1389. * bevelOffset: <float>, // how far from shape outline does bevel start
  1390. * bevelSegments: <int>, // number of bevel layers
  1391. *
  1392. * extrudePath: <THREE.Curve> // curve to extrude shape along
  1393. *
  1394. * UVGenerator: <Object> // object that provides UV generator functions
  1395. *
  1396. * }
  1397. */class ExtrudeGeometry extends Geometry{constructor(shapes,options){super();this.type='ExtrudeGeometry';this.parameters={shapes:shapes,options:options};this.fromBufferGeometry(new ExtrudeBufferGeometry(shapes,options));this.mergeVertices();}toJSON(){var data=super.toJSON();var shapes=this.parameters.shapes;var options=this.parameters.options;return toJSON$1(shapes,options,data);}}function toJSON$1(shapes,options,data){data.shapes=[];if(Array.isArray(shapes)){for(var _i217=0,l=shapes.length;_i217<l;_i217++){var shape=shapes[_i217];data.shapes.push(shape.uuid);}}else {data.shapes.push(shapes.uuid);}if(options.extrudePath!==undefined)data.options.extrudePath=options.extrudePath.toJSON();return data;}class IcosahedronBufferGeometry extends PolyhedronBufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var detail=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var t=(1+Math.sqrt(5))/2;var vertices=[-1,t,0,1,t,0,-1,-t,0,1,-t,0,0,-1,t,0,1,t,0,-1,-t,0,1,-t,t,0,-1,t,0,1,-t,0,-1,-t,0,1];var indices=[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1];super(vertices,indices,radius,detail);this.type='IcosahedronBufferGeometry';this.parameters={radius:radius,detail:detail};}}class IcosahedronGeometry extends Geometry{constructor(radius,detail){super();this.type='IcosahedronGeometry';this.parameters={radius:radius,detail:detail};this.fromBufferGeometry(new IcosahedronBufferGeometry(radius,detail));this.mergeVertices();}}class LatheBufferGeometry extends BufferGeometry{constructor(points){var segments=arguments.length>1&&arguments[1]!==undefined?arguments[1]:12;var phiStart=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var phiLength=arguments.length>3&&arguments[3]!==undefined?arguments[3]:Math.PI*2;super();this.type='LatheBufferGeometry';this.parameters={points:points,segments:segments,phiStart:phiStart,phiLength:phiLength};segments=Math.floor(segments);// clamp phiLength so it's in range of [ 0, 2PI ]
  1398. phiLength=MathUtils.clamp(phiLength,0,Math.PI*2);// buffers
  1399. var indices=[];var vertices=[];var uvs=[];// helper variables
  1400. var inverseSegments=1.0/segments;var vertex=new Vector3();var uv=new Vector2();// generate vertices and uvs
  1401. for(var _i218=0;_i218<=segments;_i218++){var phi=phiStart+_i218*inverseSegments*phiLength;var sin=Math.sin(phi);var cos=Math.cos(phi);for(var j=0;j<=points.length-1;j++){// vertex
  1402. vertex.x=points[j].x*sin;vertex.y=points[j].y;vertex.z=points[j].x*cos;vertices.push(vertex.x,vertex.y,vertex.z);// uv
  1403. uv.x=_i218/segments;uv.y=j/(points.length-1);uvs.push(uv.x,uv.y);}}// indices
  1404. for(var _i219=0;_i219<segments;_i219++){for(var _j14=0;_j14<points.length-1;_j14++){var base=_j14+_i219*points.length;var a=base;var b=base+points.length;var c=base+points.length+1;var d=base+1;// faces
  1405. indices.push(a,b,d);indices.push(b,c,d);}}// build geometry
  1406. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));// generate normals
  1407. this.computeVertexNormals();// if the geometry is closed, we need to average the normals along the seam.
  1408. // because the corresponding vertices are identical (but still have different UVs).
  1409. if(phiLength===Math.PI*2){var normals=this.attributes.normal.array;var n1=new Vector3();var n2=new Vector3();var n=new Vector3();// this is the buffer offset for the last line of vertices
  1410. var _base=segments*points.length*3;for(var _i220=0,_j15=0;_i220<points.length;_i220++,_j15+=3){// select the normal of the vertex in the first line
  1411. n1.x=normals[_j15+0];n1.y=normals[_j15+1];n1.z=normals[_j15+2];// select the normal of the vertex in the last line
  1412. n2.x=normals[_base+_j15+0];n2.y=normals[_base+_j15+1];n2.z=normals[_base+_j15+2];// average normals
  1413. n.addVectors(n1,n2).normalize();// assign the new values to both normals
  1414. normals[_j15+0]=normals[_base+_j15+0]=n.x;normals[_j15+1]=normals[_base+_j15+1]=n.y;normals[_j15+2]=normals[_base+_j15+2]=n.z;}}}}class LatheGeometry extends Geometry{constructor(points,segments,phiStart,phiLength){super();this.type='LatheGeometry';this.parameters={points:points,segments:segments,phiStart:phiStart,phiLength:phiLength};this.fromBufferGeometry(new LatheBufferGeometry(points,segments,phiStart,phiLength));this.mergeVertices();}}class OctahedronBufferGeometry extends PolyhedronBufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var detail=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var vertices=[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1];var indices=[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2];super(vertices,indices,radius,detail);this.type='OctahedronBufferGeometry';this.parameters={radius:radius,detail:detail};}}class OctahedronGeometry extends Geometry{constructor(radius,detail){super();this.type='OctahedronGeometry';this.parameters={radius:radius,detail:detail};this.fromBufferGeometry(new OctahedronBufferGeometry(radius,detail));this.mergeVertices();}}/**
  1415. * Parametric Surfaces Geometry
  1416. * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
  1417. */function ParametricBufferGeometry(func,slices,stacks){BufferGeometry.call(this);this.type='ParametricBufferGeometry';this.parameters={func:func,slices:slices,stacks:stacks};// buffers
  1418. var indices=[];var vertices=[];var normals=[];var uvs=[];var EPS=0.00001;var normal=new Vector3();var p0=new Vector3(),p1=new Vector3();var pu=new Vector3(),pv=new Vector3();if(func.length<3){console.error('THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.');}// generate vertices, normals and uvs
  1419. var sliceCount=slices+1;for(var _i221=0;_i221<=stacks;_i221++){var v=_i221/stacks;for(var j=0;j<=slices;j++){var u=j/slices;// vertex
  1420. func(u,v,p0);vertices.push(p0.x,p0.y,p0.z);// normal
  1421. // approximate tangent vectors via finite differences
  1422. if(u-EPS>=0){func(u-EPS,v,p1);pu.subVectors(p0,p1);}else {func(u+EPS,v,p1);pu.subVectors(p1,p0);}if(v-EPS>=0){func(u,v-EPS,p1);pv.subVectors(p0,p1);}else {func(u,v+EPS,p1);pv.subVectors(p1,p0);}// cross product of tangent vectors returns surface normal
  1423. normal.crossVectors(pu,pv).normalize();normals.push(normal.x,normal.y,normal.z);// uv
  1424. uvs.push(u,v);}}// generate indices
  1425. for(var _i222=0;_i222<stacks;_i222++){for(var _j16=0;_j16<slices;_j16++){var a=_i222*sliceCount+_j16;var b=_i222*sliceCount+_j16+1;var c=(_i222+1)*sliceCount+_j16+1;var d=(_i222+1)*sliceCount+_j16;// faces one and two
  1426. indices.push(a,b,d);indices.push(b,c,d);}}// build geometry
  1427. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}ParametricBufferGeometry.prototype=Object.create(BufferGeometry.prototype);ParametricBufferGeometry.prototype.constructor=ParametricBufferGeometry;/**
  1428. * Parametric Surfaces Geometry
  1429. * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
  1430. */function ParametricGeometry(func,slices,stacks){Geometry.call(this);this.type='ParametricGeometry';this.parameters={func:func,slices:slices,stacks:stacks};this.fromBufferGeometry(new ParametricBufferGeometry(func,slices,stacks));this.mergeVertices();}ParametricGeometry.prototype=Object.create(Geometry.prototype);ParametricGeometry.prototype.constructor=ParametricGeometry;class PlaneGeometry extends Geometry{constructor(width,height,widthSegments,heightSegments){super();this.type='PlaneGeometry';this.parameters={width:width,height:height,widthSegments:widthSegments,heightSegments:heightSegments};this.fromBufferGeometry(new PlaneBufferGeometry(width,height,widthSegments,heightSegments));this.mergeVertices();}}class PolyhedronGeometry extends Geometry{constructor(vertices,indices,radius,detail){super();this.type='PolyhedronGeometry';this.parameters={vertices:vertices,indices:indices,radius:radius,detail:detail};this.fromBufferGeometry(new PolyhedronBufferGeometry(vertices,indices,radius,detail));this.mergeVertices();}}class RingBufferGeometry extends BufferGeometry{constructor(){var innerRadius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0.5;var outerRadius=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var thetaSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:8;var phiSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;var thetaStart=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0;var thetaLength=arguments.length>5&&arguments[5]!==undefined?arguments[5]:Math.PI*2;super();this.type='RingBufferGeometry';this.parameters={innerRadius:innerRadius,outerRadius:outerRadius,thetaSegments:thetaSegments,phiSegments:phiSegments,thetaStart:thetaStart,thetaLength:thetaLength};thetaSegments=Math.max(3,thetaSegments);phiSegments=Math.max(1,phiSegments);// buffers
  1431. var indices=[];var vertices=[];var normals=[];var uvs=[];// some helper variables
  1432. var radius=innerRadius;var radiusStep=(outerRadius-innerRadius)/phiSegments;var vertex=new Vector3();var uv=new Vector2();// generate vertices, normals and uvs
  1433. for(var j=0;j<=phiSegments;j++){for(var _i223=0;_i223<=thetaSegments;_i223++){// values are generate from the inside of the ring to the outside
  1434. var segment=thetaStart+_i223/thetaSegments*thetaLength;// vertex
  1435. vertex.x=radius*Math.cos(segment);vertex.y=radius*Math.sin(segment);vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1436. normals.push(0,0,1);// uv
  1437. uv.x=(vertex.x/outerRadius+1)/2;uv.y=(vertex.y/outerRadius+1)/2;uvs.push(uv.x,uv.y);}// increase the radius for next row of vertices
  1438. radius+=radiusStep;}// indices
  1439. for(var _j17=0;_j17<phiSegments;_j17++){var thetaSegmentLevel=_j17*(thetaSegments+1);for(var _i224=0;_i224<thetaSegments;_i224++){var _segment=_i224+thetaSegmentLevel;var a=_segment;var b=_segment+thetaSegments+1;var c=_segment+thetaSegments+2;var d=_segment+1;// faces
  1440. indices.push(a,b,d);indices.push(b,c,d);}}// build geometry
  1441. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}}class RingGeometry extends Geometry{constructor(innerRadius,outerRadius,thetaSegments,phiSegments,thetaStart,thetaLength){super();this.type='RingGeometry';this.parameters={innerRadius:innerRadius,outerRadius:outerRadius,thetaSegments:thetaSegments,phiSegments:phiSegments,thetaStart:thetaStart,thetaLength:thetaLength};this.fromBufferGeometry(new RingBufferGeometry(innerRadius,outerRadius,thetaSegments,phiSegments,thetaStart,thetaLength));this.mergeVertices();}}class ShapeBufferGeometry extends BufferGeometry{constructor(shapes){var curveSegments=arguments.length>1&&arguments[1]!==undefined?arguments[1]:12;super();this.type='ShapeBufferGeometry';this.parameters={shapes:shapes,curveSegments:curveSegments};// buffers
  1442. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  1443. var groupStart=0;var groupCount=0;// allow single and array values for "shapes" parameter
  1444. if(Array.isArray(shapes)===false){addShape(shapes);}else {for(var _i225=0;_i225<shapes.length;_i225++){addShape(shapes[_i225]);this.addGroup(groupStart,groupCount,_i225);// enables MultiMaterial support
  1445. groupStart+=groupCount;groupCount=0;}}// build geometry
  1446. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));// helper functions
  1447. function addShape(shape){var indexOffset=vertices.length/3;var points=shape.extractPoints(curveSegments);var shapeVertices=points.shape;var shapeHoles=points.holes;// check direction of vertices
  1448. if(ShapeUtils.isClockWise(shapeVertices)===false){shapeVertices=shapeVertices.reverse();}for(var _i226=0,l=shapeHoles.length;_i226<l;_i226++){var shapeHole=shapeHoles[_i226];if(ShapeUtils.isClockWise(shapeHole)===true){shapeHoles[_i226]=shapeHole.reverse();}}var faces=ShapeUtils.triangulateShape(shapeVertices,shapeHoles);// join vertices of inner and outer paths to a single array
  1449. for(var _i227=0,_l10=shapeHoles.length;_i227<_l10;_i227++){var _shapeHole=shapeHoles[_i227];shapeVertices=shapeVertices.concat(_shapeHole);}// vertices, normals, uvs
  1450. for(var _i228=0,_l11=shapeVertices.length;_i228<_l11;_i228++){var vertex=shapeVertices[_i228];vertices.push(vertex.x,vertex.y,0);normals.push(0,0,1);uvs.push(vertex.x,vertex.y);// world uvs
  1451. }// incides
  1452. for(var _i229=0,_l12=faces.length;_i229<_l12;_i229++){var face=faces[_i229];var a=face[0]+indexOffset;var b=face[1]+indexOffset;var c=face[2]+indexOffset;indices.push(a,b,c);groupCount+=3;}}}toJSON(){var data=BufferGeometry.prototype.toJSON.call(this);var shapes=this.parameters.shapes;return toJSON$2(shapes,data);}}function toJSON$2(shapes,data){data.shapes=[];if(Array.isArray(shapes)){for(var _i230=0,l=shapes.length;_i230<l;_i230++){var shape=shapes[_i230];data.shapes.push(shape.uuid);}}else {data.shapes.push(shapes.uuid);}return data;}class ShapeGeometry extends Geometry{constructor(shapes,curveSegments){super();this.type='ShapeGeometry';if(typeof curveSegments==='object'){console.warn('THREE.ShapeGeometry: Options parameter has been removed.');curveSegments=curveSegments.curveSegments;}this.parameters={shapes:shapes,curveSegments:curveSegments};this.fromBufferGeometry(new ShapeBufferGeometry(shapes,curveSegments));this.mergeVertices();}toJSON(){var data=Geometry.prototype.toJSON.call(this);var shapes=this.parameters.shapes;return toJSON$3(shapes,data);}}function toJSON$3(shapes,data){data.shapes=[];if(Array.isArray(shapes)){for(var _i231=0,l=shapes.length;_i231<l;_i231++){var shape=shapes[_i231];data.shapes.push(shape.uuid);}}else {data.shapes.push(shapes.uuid);}return data;}class SphereBufferGeometry extends BufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var widthSegments=arguments.length>1&&arguments[1]!==undefined?arguments[1]:8;var heightSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:6;var phiStart=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0;var phiLength=arguments.length>4&&arguments[4]!==undefined?arguments[4]:Math.PI*2;var thetaStart=arguments.length>5&&arguments[5]!==undefined?arguments[5]:0;var thetaLength=arguments.length>6&&arguments[6]!==undefined?arguments[6]:Math.PI;super();this.type='SphereBufferGeometry';this.parameters={radius:radius,widthSegments:widthSegments,heightSegments:heightSegments,phiStart:phiStart,phiLength:phiLength,thetaStart:thetaStart,thetaLength:thetaLength};widthSegments=Math.max(3,Math.floor(widthSegments));heightSegments=Math.max(2,Math.floor(heightSegments));var thetaEnd=Math.min(thetaStart+thetaLength,Math.PI);var index=0;var grid=[];var vertex=new Vector3();var normal=new Vector3();// buffers
  1453. var indices=[];var vertices=[];var normals=[];var uvs=[];// generate vertices, normals and uvs
  1454. for(var iy=0;iy<=heightSegments;iy++){var verticesRow=[];var v=iy/heightSegments;// special case for the poles
  1455. var uOffset=0;if(iy==0&&thetaStart==0){uOffset=0.5/widthSegments;}else if(iy==heightSegments&&thetaEnd==Math.PI){uOffset=-0.5/widthSegments;}for(var ix=0;ix<=widthSegments;ix++){var u=ix/widthSegments;// vertex
  1456. vertex.x=-radius*Math.cos(phiStart+u*phiLength)*Math.sin(thetaStart+v*thetaLength);vertex.y=radius*Math.cos(thetaStart+v*thetaLength);vertex.z=radius*Math.sin(phiStart+u*phiLength)*Math.sin(thetaStart+v*thetaLength);vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1457. normal.copy(vertex).normalize();normals.push(normal.x,normal.y,normal.z);// uv
  1458. uvs.push(u+uOffset,1-v);verticesRow.push(index++);}grid.push(verticesRow);}// indices
  1459. for(var _iy3=0;_iy3<heightSegments;_iy3++){for(var _ix3=0;_ix3<widthSegments;_ix3++){var a=grid[_iy3][_ix3+1];var b=grid[_iy3][_ix3];var c=grid[_iy3+1][_ix3];var d=grid[_iy3+1][_ix3+1];if(_iy3!==0||thetaStart>0)indices.push(a,b,d);if(_iy3!==heightSegments-1||thetaEnd<Math.PI)indices.push(b,c,d);}}// build geometry
  1460. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}}class SphereGeometry extends Geometry{constructor(radius,widthSegments,heightSegments,phiStart,phiLength,thetaStart,thetaLength){super();this.type='SphereGeometry';this.parameters={radius:radius,widthSegments:widthSegments,heightSegments:heightSegments,phiStart:phiStart,phiLength:phiLength,thetaStart:thetaStart,thetaLength:thetaLength};this.fromBufferGeometry(new SphereBufferGeometry(radius,widthSegments,heightSegments,phiStart,phiLength,thetaStart,thetaLength));this.mergeVertices();}}class TetrahedronBufferGeometry extends PolyhedronBufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var detail=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var vertices=[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1];var indices=[2,1,0,0,3,2,1,3,0,2,3,1];super(vertices,indices,radius,detail);this.type='TetrahedronBufferGeometry';this.parameters={radius:radius,detail:detail};}}class TetrahedronGeometry extends Geometry{constructor(radius,detail){super();this.type='TetrahedronGeometry';this.parameters={radius:radius,detail:detail};this.fromBufferGeometry(new TetrahedronBufferGeometry(radius,detail));this.mergeVertices();}}/**
  1461. * Text = 3D Text
  1462. *
  1463. * parameters = {
  1464. * font: <THREE.Font>, // font
  1465. *
  1466. * size: <float>, // size of the text
  1467. * height: <float>, // thickness to extrude text
  1468. * curveSegments: <int>, // number of points on the curves
  1469. *
  1470. * bevelEnabled: <bool>, // turn on bevel
  1471. * bevelThickness: <float>, // how deep into text bevel goes
  1472. * bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
  1473. * bevelOffset: <float> // how far from text outline does bevel start
  1474. * }
  1475. */class TextBufferGeometry extends ExtrudeBufferGeometry{constructor(text){var parameters=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var font=parameters.font;if(!(font&&font.isFont)){console.error('THREE.TextGeometry: font parameter is not an instance of THREE.Font.');return new BufferGeometry();}var shapes=font.generateShapes(text,parameters.size);// translate parameters to ExtrudeGeometry API
  1476. parameters.depth=parameters.height!==undefined?parameters.height:50;// defaults
  1477. if(parameters.bevelThickness===undefined)parameters.bevelThickness=10;if(parameters.bevelSize===undefined)parameters.bevelSize=8;if(parameters.bevelEnabled===undefined)parameters.bevelEnabled=false;super(shapes,parameters);this.type='TextBufferGeometry';}}/**
  1478. * Text = 3D Text
  1479. *
  1480. * parameters = {
  1481. * font: <THREE.Font>, // font
  1482. *
  1483. * size: <float>, // size of the text
  1484. * height: <float>, // thickness to extrude text
  1485. * curveSegments: <int>, // number of points on the curves
  1486. *
  1487. * bevelEnabled: <bool>, // turn on bevel
  1488. * bevelThickness: <float>, // how deep into text bevel goes
  1489. * bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
  1490. * bevelOffset: <float> // how far from text outline does bevel start
  1491. * }
  1492. */class TextGeometry extends Geometry{constructor(text,parameters){super();this.type='TextGeometry';this.parameters={text:text,parameters:parameters};this.fromBufferGeometry(new TextBufferGeometry(text,parameters));this.mergeVertices();}}class TorusBufferGeometry extends BufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var tube=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0.4;var radialSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:8;var tubularSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:6;var arc=arguments.length>4&&arguments[4]!==undefined?arguments[4]:Math.PI*2;super();this.type='TorusBufferGeometry';this.parameters={radius:radius,tube:tube,radialSegments:radialSegments,tubularSegments:tubularSegments,arc:arc};radialSegments=Math.floor(radialSegments);tubularSegments=Math.floor(tubularSegments);// buffers
  1493. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  1494. var center=new Vector3();var vertex=new Vector3();var normal=new Vector3();// generate vertices, normals and uvs
  1495. for(var j=0;j<=radialSegments;j++){for(var _i232=0;_i232<=tubularSegments;_i232++){var u=_i232/tubularSegments*arc;var v=j/radialSegments*Math.PI*2;// vertex
  1496. vertex.x=(radius+tube*Math.cos(v))*Math.cos(u);vertex.y=(radius+tube*Math.cos(v))*Math.sin(u);vertex.z=tube*Math.sin(v);vertices.push(vertex.x,vertex.y,vertex.z);// normal
  1497. center.x=radius*Math.cos(u);center.y=radius*Math.sin(u);normal.subVectors(vertex,center).normalize();normals.push(normal.x,normal.y,normal.z);// uv
  1498. uvs.push(_i232/tubularSegments);uvs.push(j/radialSegments);}}// generate indices
  1499. for(var _j18=1;_j18<=radialSegments;_j18++){for(var _i233=1;_i233<=tubularSegments;_i233++){// indices
  1500. var a=(tubularSegments+1)*_j18+_i233-1;var b=(tubularSegments+1)*(_j18-1)+_i233-1;var c=(tubularSegments+1)*(_j18-1)+_i233;var d=(tubularSegments+1)*_j18+_i233;// faces
  1501. indices.push(a,b,d);indices.push(b,c,d);}}// build geometry
  1502. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));}}class TorusGeometry extends Geometry{constructor(radius,tube,radialSegments,tubularSegments,arc){super();this.type='TorusGeometry';this.parameters={radius:radius,tube:tube,radialSegments:radialSegments,tubularSegments:tubularSegments,arc:arc};this.fromBufferGeometry(new TorusBufferGeometry(radius,tube,radialSegments,tubularSegments,arc));this.mergeVertices();}}class TorusKnotBufferGeometry extends BufferGeometry{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var tube=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0.4;var tubularSegments=arguments.length>2&&arguments[2]!==undefined?arguments[2]:64;var radialSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:8;var p=arguments.length>4&&arguments[4]!==undefined?arguments[4]:2;var q=arguments.length>5&&arguments[5]!==undefined?arguments[5]:3;super();this.type='TorusKnotBufferGeometry';this.parameters={radius:radius,tube:tube,tubularSegments:tubularSegments,radialSegments:radialSegments,p:p,q:q};tubularSegments=Math.floor(tubularSegments);radialSegments=Math.floor(radialSegments);// buffers
  1503. var indices=[];var vertices=[];var normals=[];var uvs=[];// helper variables
  1504. var vertex=new Vector3();var normal=new Vector3();var P1=new Vector3();var P2=new Vector3();var B=new Vector3();var T=new Vector3();var N=new Vector3();// generate vertices, normals and uvs
  1505. for(var _i234=0;_i234<=tubularSegments;++_i234){// the radian "u" is used to calculate the position on the torus curve of the current tubular segement
  1506. var u=_i234/tubularSegments*p*Math.PI*2;// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
  1507. // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
  1508. calculatePositionOnCurve(u,p,q,radius,P1);calculatePositionOnCurve(u+0.01,p,q,radius,P2);// calculate orthonormal basis
  1509. T.subVectors(P2,P1);N.addVectors(P2,P1);B.crossVectors(T,N);N.crossVectors(B,T);// normalize B, N. T can be ignored, we don't use it
  1510. B.normalize();N.normalize();for(var j=0;j<=radialSegments;++j){// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
  1511. // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
  1512. var v=j/radialSegments*Math.PI*2;var cx=-tube*Math.cos(v);var cy=tube*Math.sin(v);// now calculate the final vertex position.
  1513. // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
  1514. vertex.x=P1.x+(cx*N.x+cy*B.x);vertex.y=P1.y+(cx*N.y+cy*B.y);vertex.z=P1.z+(cx*N.z+cy*B.z);vertices.push(vertex.x,vertex.y,vertex.z);// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
  1515. normal.subVectors(vertex,P1).normalize();normals.push(normal.x,normal.y,normal.z);// uv
  1516. uvs.push(_i234/tubularSegments);uvs.push(j/radialSegments);}}// generate indices
  1517. for(var _j19=1;_j19<=tubularSegments;_j19++){for(var _i235=1;_i235<=radialSegments;_i235++){// indices
  1518. var a=(radialSegments+1)*(_j19-1)+(_i235-1);var b=(radialSegments+1)*_j19+(_i235-1);var c=(radialSegments+1)*_j19+_i235;var d=(radialSegments+1)*(_j19-1)+_i235;// faces
  1519. indices.push(a,b,d);indices.push(b,c,d);}}// build geometry
  1520. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));// this function calculates the current position on the torus curve
  1521. function calculatePositionOnCurve(u,p,q,radius,position){var cu=Math.cos(u);var su=Math.sin(u);var quOverP=q/p*u;var cs=Math.cos(quOverP);position.x=radius*(2+cs)*0.5*cu;position.y=radius*(2+cs)*su*0.5;position.z=radius*Math.sin(quOverP)*0.5;}}}class TorusKnotGeometry extends Geometry{constructor(radius,tube,tubularSegments,radialSegments,p,q,heightScale){super();this.type='TorusKnotGeometry';this.parameters={radius:radius,tube:tube,tubularSegments:tubularSegments,radialSegments:radialSegments,p:p,q:q};if(heightScale!==undefined)console.warn('THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.');this.fromBufferGeometry(new TorusKnotBufferGeometry(radius,tube,tubularSegments,radialSegments,p,q));this.mergeVertices();}}class TubeBufferGeometry extends BufferGeometry{constructor(path){var tubularSegments=arguments.length>1&&arguments[1]!==undefined?arguments[1]:64;var radius=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var radialSegments=arguments.length>3&&arguments[3]!==undefined?arguments[3]:8;var closed=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;super();this.type='TubeBufferGeometry';this.parameters={path:path,tubularSegments:tubularSegments,radius:radius,radialSegments:radialSegments,closed:closed};var frames=path.computeFrenetFrames(tubularSegments,closed);// expose internals
  1522. this.tangents=frames.tangents;this.normals=frames.normals;this.binormals=frames.binormals;// helper variables
  1523. var vertex=new Vector3();var normal=new Vector3();var uv=new Vector2();var P=new Vector3();// buffer
  1524. var vertices=[];var normals=[];var uvs=[];var indices=[];// create buffer data
  1525. generateBufferData();// build geometry
  1526. this.setIndex(indices);this.setAttribute('position',new Float32BufferAttribute(vertices,3));this.setAttribute('normal',new Float32BufferAttribute(normals,3));this.setAttribute('uv',new Float32BufferAttribute(uvs,2));// functions
  1527. function generateBufferData(){for(var _i236=0;_i236<tubularSegments;_i236++){generateSegment(_i236);}// if the geometry is not closed, generate the last row of vertices and normals
  1528. // at the regular position on the given path
  1529. //
  1530. // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
  1531. generateSegment(closed===false?tubularSegments:0);// uvs are generated in a separate function.
  1532. // this makes it easy compute correct values for closed geometries
  1533. generateUVs();// finally create faces
  1534. generateIndices();}function generateSegment(i){// we use getPointAt to sample evenly distributed points from the given path
  1535. P=path.getPointAt(i/tubularSegments,P);// retrieve corresponding normal and binormal
  1536. var N=frames.normals[i];var B=frames.binormals[i];// generate normals and vertices for the current segment
  1537. for(var j=0;j<=radialSegments;j++){var v=j/radialSegments*Math.PI*2;var sin=Math.sin(v);var cos=-Math.cos(v);// normal
  1538. normal.x=cos*N.x+sin*B.x;normal.y=cos*N.y+sin*B.y;normal.z=cos*N.z+sin*B.z;normal.normalize();normals.push(normal.x,normal.y,normal.z);// vertex
  1539. vertex.x=P.x+radius*normal.x;vertex.y=P.y+radius*normal.y;vertex.z=P.z+radius*normal.z;vertices.push(vertex.x,vertex.y,vertex.z);}}function generateIndices(){for(var j=1;j<=tubularSegments;j++){for(var _i237=1;_i237<=radialSegments;_i237++){var a=(radialSegments+1)*(j-1)+(_i237-1);var b=(radialSegments+1)*j+(_i237-1);var c=(radialSegments+1)*j+_i237;var d=(radialSegments+1)*(j-1)+_i237;// faces
  1540. indices.push(a,b,d);indices.push(b,c,d);}}}function generateUVs(){for(var _i238=0;_i238<=tubularSegments;_i238++){for(var j=0;j<=radialSegments;j++){uv.x=_i238/tubularSegments;uv.y=j/radialSegments;uvs.push(uv.x,uv.y);}}}}toJSON(){var data=BufferGeometry.prototype.toJSON.call(this);data.path=this.parameters.path.toJSON();return data;}}class TubeGeometry extends Geometry{constructor(path,tubularSegments,radius,radialSegments,closed,taper){super();this.type='TubeGeometry';this.parameters={path:path,tubularSegments:tubularSegments,radius:radius,radialSegments:radialSegments,closed:closed};if(taper!==undefined)console.warn('THREE.TubeGeometry: taper has been removed.');var bufferGeometry=new TubeBufferGeometry(path,tubularSegments,radius,radialSegments,closed);// expose internals
  1541. this.tangents=bufferGeometry.tangents;this.normals=bufferGeometry.normals;this.binormals=bufferGeometry.binormals;// create geometry
  1542. this.fromBufferGeometry(bufferGeometry);this.mergeVertices();}}class WireframeGeometry extends BufferGeometry{constructor(geometry){super();this.type='WireframeGeometry';// buffer
  1543. var vertices=[];// helper variables
  1544. var edge=[0,0],edges={};var keys=['a','b','c'];// different logic for Geometry and BufferGeometry
  1545. if(geometry&&geometry.isGeometry){// create a data structure that contains all edges without duplicates
  1546. var faces=geometry.faces;for(var _i239=0,l=faces.length;_i239<l;_i239++){var face=faces[_i239];for(var j=0;j<3;j++){var edge1=face[keys[j]];var edge2=face[keys[(j+1)%3]];edge[0]=Math.min(edge1,edge2);// sorting prevents duplicates
  1547. edge[1]=Math.max(edge1,edge2);var key=edge[0]+','+edge[1];if(edges[key]===undefined){edges[key]={index1:edge[0],index2:edge[1]};}}}// generate vertices
  1548. for(var _key3 in edges){var e=edges[_key3];var vertex=geometry.vertices[e.index1];vertices.push(vertex.x,vertex.y,vertex.z);vertex=geometry.vertices[e.index2];vertices.push(vertex.x,vertex.y,vertex.z);}}else if(geometry&&geometry.isBufferGeometry){var _vertex=new Vector3();if(geometry.index!==null){// indexed BufferGeometry
  1549. var position=geometry.attributes.position;var indices=geometry.index;var groups=geometry.groups;if(groups.length===0){groups=[{start:0,count:indices.count,materialIndex:0}];}// create a data structure that contains all eges without duplicates
  1550. for(var o=0,ol=groups.length;o<ol;++o){var group=groups[o];var start=group.start;var count=group.count;for(var _i240=start,_l13=start+count;_i240<_l13;_i240+=3){for(var _j20=0;_j20<3;_j20++){var _edge=indices.getX(_i240+_j20);var _edge3=indices.getX(_i240+(_j20+1)%3);edge[0]=Math.min(_edge,_edge3);// sorting prevents duplicates
  1551. edge[1]=Math.max(_edge,_edge3);var _key4=edge[0]+','+edge[1];if(edges[_key4]===undefined){edges[_key4]={index1:edge[0],index2:edge[1]};}}}}// generate vertices
  1552. for(var _key5 in edges){var _e=edges[_key5];_vertex.fromBufferAttribute(position,_e.index1);vertices.push(_vertex.x,_vertex.y,_vertex.z);_vertex.fromBufferAttribute(position,_e.index2);vertices.push(_vertex.x,_vertex.y,_vertex.z);}}else {// non-indexed BufferGeometry
  1553. var _position2=geometry.attributes.position;for(var _i241=0,_l14=_position2.count/3;_i241<_l14;_i241++){for(var _j21=0;_j21<3;_j21++){// three edges per triangle, an edge is represented as (index1, index2)
  1554. // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
  1555. var index1=3*_i241+_j21;_vertex.fromBufferAttribute(_position2,index1);vertices.push(_vertex.x,_vertex.y,_vertex.z);var index2=3*_i241+(_j21+1)%3;_vertex.fromBufferAttribute(_position2,index2);vertices.push(_vertex.x,_vertex.y,_vertex.z);}}}}// build geometry
  1556. this.setAttribute('position',new Float32BufferAttribute(vertices,3));}}var Geometries=/*#__PURE__*/Object.freeze({__proto__:null,BoxGeometry:BoxGeometry,BoxBufferGeometry:BoxBufferGeometry,CircleGeometry:CircleGeometry,CircleBufferGeometry:CircleBufferGeometry,ConeGeometry:ConeGeometry,ConeBufferGeometry:ConeBufferGeometry,CylinderGeometry:CylinderGeometry,CylinderBufferGeometry:CylinderBufferGeometry,DodecahedronGeometry:DodecahedronGeometry,DodecahedronBufferGeometry:DodecahedronBufferGeometry,EdgesGeometry:EdgesGeometry,ExtrudeGeometry:ExtrudeGeometry,ExtrudeBufferGeometry:ExtrudeBufferGeometry,IcosahedronGeometry:IcosahedronGeometry,IcosahedronBufferGeometry:IcosahedronBufferGeometry,LatheGeometry:LatheGeometry,LatheBufferGeometry:LatheBufferGeometry,OctahedronGeometry:OctahedronGeometry,OctahedronBufferGeometry:OctahedronBufferGeometry,ParametricGeometry:ParametricGeometry,ParametricBufferGeometry:ParametricBufferGeometry,PlaneGeometry:PlaneGeometry,PlaneBufferGeometry:PlaneBufferGeometry,PolyhedronGeometry:PolyhedronGeometry,PolyhedronBufferGeometry:PolyhedronBufferGeometry,RingGeometry:RingGeometry,RingBufferGeometry:RingBufferGeometry,ShapeGeometry:ShapeGeometry,ShapeBufferGeometry:ShapeBufferGeometry,SphereGeometry:SphereGeometry,SphereBufferGeometry:SphereBufferGeometry,TetrahedronGeometry:TetrahedronGeometry,TetrahedronBufferGeometry:TetrahedronBufferGeometry,TextGeometry:TextGeometry,TextBufferGeometry:TextBufferGeometry,TorusGeometry:TorusGeometry,TorusBufferGeometry:TorusBufferGeometry,TorusKnotGeometry:TorusKnotGeometry,TorusKnotBufferGeometry:TorusKnotBufferGeometry,TubeGeometry:TubeGeometry,TubeBufferGeometry:TubeBufferGeometry,WireframeGeometry:WireframeGeometry});/**
  1557. * parameters = {
  1558. * color: <THREE.Color>
  1559. * }
  1560. */function ShadowMaterial(parameters){Material.call(this);this.type='ShadowMaterial';this.color=new Color(0x000000);this.transparent=true;this.setValues(parameters);}ShadowMaterial.prototype=Object.create(Material.prototype);ShadowMaterial.prototype.constructor=ShadowMaterial;ShadowMaterial.prototype.isShadowMaterial=true;ShadowMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);return this;};function RawShaderMaterial(parameters){ShaderMaterial.call(this,parameters);this.type='RawShaderMaterial';}RawShaderMaterial.prototype=Object.create(ShaderMaterial.prototype);RawShaderMaterial.prototype.constructor=RawShaderMaterial;RawShaderMaterial.prototype.isRawShaderMaterial=true;/**
  1561. * parameters = {
  1562. * color: <hex>,
  1563. * roughness: <float>,
  1564. * metalness: <float>,
  1565. * opacity: <float>,
  1566. *
  1567. * map: new THREE.Texture( <Image> ),
  1568. *
  1569. * lightMap: new THREE.Texture( <Image> ),
  1570. * lightMapIntensity: <float>
  1571. *
  1572. * aoMap: new THREE.Texture( <Image> ),
  1573. * aoMapIntensity: <float>
  1574. *
  1575. * emissive: <hex>,
  1576. * emissiveIntensity: <float>
  1577. * emissiveMap: new THREE.Texture( <Image> ),
  1578. *
  1579. * bumpMap: new THREE.Texture( <Image> ),
  1580. * bumpScale: <float>,
  1581. *
  1582. * normalMap: new THREE.Texture( <Image> ),
  1583. * normalMapType: THREE.TangentSpaceNormalMap,
  1584. * normalScale: <Vector2>,
  1585. *
  1586. * displacementMap: new THREE.Texture( <Image> ),
  1587. * displacementScale: <float>,
  1588. * displacementBias: <float>,
  1589. *
  1590. * roughnessMap: new THREE.Texture( <Image> ),
  1591. *
  1592. * metalnessMap: new THREE.Texture( <Image> ),
  1593. *
  1594. * alphaMap: new THREE.Texture( <Image> ),
  1595. *
  1596. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  1597. * envMapIntensity: <float>
  1598. *
  1599. * refractionRatio: <float>,
  1600. *
  1601. * wireframe: <boolean>,
  1602. * wireframeLinewidth: <float>,
  1603. *
  1604. * skinning: <bool>,
  1605. * morphTargets: <bool>,
  1606. * morphNormals: <bool>
  1607. * }
  1608. */function MeshStandardMaterial(parameters){Material.call(this);this.defines={'STANDARD':''};this.type='MeshStandardMaterial';this.color=new Color(0xffffff);// diffuse
  1609. this.roughness=1.0;this.metalness=0.0;this.map=null;this.lightMap=null;this.lightMapIntensity=1.0;this.aoMap=null;this.aoMapIntensity=1.0;this.emissive=new Color(0x000000);this.emissiveIntensity=1.0;this.emissiveMap=null;this.bumpMap=null;this.bumpScale=1;this.normalMap=null;this.normalMapType=TangentSpaceNormalMap;this.normalScale=new Vector2(1,1);this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.roughnessMap=null;this.metalnessMap=null;this.alphaMap=null;this.envMap=null;this.envMapIntensity=1.0;this.refractionRatio=0.98;this.wireframe=false;this.wireframeLinewidth=1;this.wireframeLinecap='round';this.wireframeLinejoin='round';this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.vertexTangents=false;this.setValues(parameters);}MeshStandardMaterial.prototype=Object.create(Material.prototype);MeshStandardMaterial.prototype.constructor=MeshStandardMaterial;MeshStandardMaterial.prototype.isMeshStandardMaterial=true;MeshStandardMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.defines={'STANDARD':''};this.color.copy(source.color);this.roughness=source.roughness;this.metalness=source.metalness;this.map=source.map;this.lightMap=source.lightMap;this.lightMapIntensity=source.lightMapIntensity;this.aoMap=source.aoMap;this.aoMapIntensity=source.aoMapIntensity;this.emissive.copy(source.emissive);this.emissiveMap=source.emissiveMap;this.emissiveIntensity=source.emissiveIntensity;this.bumpMap=source.bumpMap;this.bumpScale=source.bumpScale;this.normalMap=source.normalMap;this.normalMapType=source.normalMapType;this.normalScale.copy(source.normalScale);this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.roughnessMap=source.roughnessMap;this.metalnessMap=source.metalnessMap;this.alphaMap=source.alphaMap;this.envMap=source.envMap;this.envMapIntensity=source.envMapIntensity;this.refractionRatio=source.refractionRatio;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.wireframeLinecap=source.wireframeLinecap;this.wireframeLinejoin=source.wireframeLinejoin;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;this.vertexTangents=source.vertexTangents;return this;};/**
  1610. * parameters = {
  1611. * clearcoat: <float>,
  1612. * clearcoatMap: new THREE.Texture( <Image> ),
  1613. * clearcoatRoughness: <float>,
  1614. * clearcoatRoughnessMap: new THREE.Texture( <Image> ),
  1615. * clearcoatNormalScale: <Vector2>,
  1616. * clearcoatNormalMap: new THREE.Texture( <Image> ),
  1617. *
  1618. * reflectivity: <float>,
  1619. * ior: <float>,
  1620. *
  1621. * sheen: <Color>,
  1622. *
  1623. * transmission: <float>,
  1624. * transmissionMap: new THREE.Texture( <Image> )
  1625. * }
  1626. */function MeshPhysicalMaterial(parameters){MeshStandardMaterial.call(this);this.defines={'STANDARD':'','PHYSICAL':''};this.type='MeshPhysicalMaterial';this.clearcoat=0.0;this.clearcoatMap=null;this.clearcoatRoughness=0.0;this.clearcoatRoughnessMap=null;this.clearcoatNormalScale=new Vector2(1,1);this.clearcoatNormalMap=null;this.reflectivity=0.5;// maps to F0 = 0.04
  1627. Object.defineProperty(this,'ior',{get:function get(){return (1+0.4*this.reflectivity)/(1-0.4*this.reflectivity);},set:function set(ior){this.reflectivity=MathUtils.clamp(2.5*(ior-1)/(ior+1),0,1);}});this.sheen=null;// null will disable sheen bsdf
  1628. this.transmission=0.0;this.transmissionMap=null;this.setValues(parameters);}MeshPhysicalMaterial.prototype=Object.create(MeshStandardMaterial.prototype);MeshPhysicalMaterial.prototype.constructor=MeshPhysicalMaterial;MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial=true;MeshPhysicalMaterial.prototype.copy=function(source){MeshStandardMaterial.prototype.copy.call(this,source);this.defines={'STANDARD':'','PHYSICAL':''};this.clearcoat=source.clearcoat;this.clearcoatMap=source.clearcoatMap;this.clearcoatRoughness=source.clearcoatRoughness;this.clearcoatRoughnessMap=source.clearcoatRoughnessMap;this.clearcoatNormalMap=source.clearcoatNormalMap;this.clearcoatNormalScale.copy(source.clearcoatNormalScale);this.reflectivity=source.reflectivity;if(source.sheen){this.sheen=(this.sheen||new Color()).copy(source.sheen);}else {this.sheen=null;}this.transmission=source.transmission;this.transmissionMap=source.transmissionMap;return this;};/**
  1629. * parameters = {
  1630. * color: <hex>,
  1631. * specular: <hex>,
  1632. * shininess: <float>,
  1633. * opacity: <float>,
  1634. *
  1635. * map: new THREE.Texture( <Image> ),
  1636. *
  1637. * lightMap: new THREE.Texture( <Image> ),
  1638. * lightMapIntensity: <float>
  1639. *
  1640. * aoMap: new THREE.Texture( <Image> ),
  1641. * aoMapIntensity: <float>
  1642. *
  1643. * emissive: <hex>,
  1644. * emissiveIntensity: <float>
  1645. * emissiveMap: new THREE.Texture( <Image> ),
  1646. *
  1647. * bumpMap: new THREE.Texture( <Image> ),
  1648. * bumpScale: <float>,
  1649. *
  1650. * normalMap: new THREE.Texture( <Image> ),
  1651. * normalMapType: THREE.TangentSpaceNormalMap,
  1652. * normalScale: <Vector2>,
  1653. *
  1654. * displacementMap: new THREE.Texture( <Image> ),
  1655. * displacementScale: <float>,
  1656. * displacementBias: <float>,
  1657. *
  1658. * specularMap: new THREE.Texture( <Image> ),
  1659. *
  1660. * alphaMap: new THREE.Texture( <Image> ),
  1661. *
  1662. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  1663. * combine: THREE.MultiplyOperation,
  1664. * reflectivity: <float>,
  1665. * refractionRatio: <float>,
  1666. *
  1667. * wireframe: <boolean>,
  1668. * wireframeLinewidth: <float>,
  1669. *
  1670. * skinning: <bool>,
  1671. * morphTargets: <bool>,
  1672. * morphNormals: <bool>
  1673. * }
  1674. */function MeshPhongMaterial(parameters){Material.call(this);this.type='MeshPhongMaterial';this.color=new Color(0xffffff);// diffuse
  1675. this.specular=new Color(0x111111);this.shininess=30;this.map=null;this.lightMap=null;this.lightMapIntensity=1.0;this.aoMap=null;this.aoMapIntensity=1.0;this.emissive=new Color(0x000000);this.emissiveIntensity=1.0;this.emissiveMap=null;this.bumpMap=null;this.bumpScale=1;this.normalMap=null;this.normalMapType=TangentSpaceNormalMap;this.normalScale=new Vector2(1,1);this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.specularMap=null;this.alphaMap=null;this.envMap=null;this.combine=MultiplyOperation;this.reflectivity=1;this.refractionRatio=0.98;this.wireframe=false;this.wireframeLinewidth=1;this.wireframeLinecap='round';this.wireframeLinejoin='round';this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.setValues(parameters);}MeshPhongMaterial.prototype=Object.create(Material.prototype);MeshPhongMaterial.prototype.constructor=MeshPhongMaterial;MeshPhongMaterial.prototype.isMeshPhongMaterial=true;MeshPhongMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.specular.copy(source.specular);this.shininess=source.shininess;this.map=source.map;this.lightMap=source.lightMap;this.lightMapIntensity=source.lightMapIntensity;this.aoMap=source.aoMap;this.aoMapIntensity=source.aoMapIntensity;this.emissive.copy(source.emissive);this.emissiveMap=source.emissiveMap;this.emissiveIntensity=source.emissiveIntensity;this.bumpMap=source.bumpMap;this.bumpScale=source.bumpScale;this.normalMap=source.normalMap;this.normalMapType=source.normalMapType;this.normalScale.copy(source.normalScale);this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.specularMap=source.specularMap;this.alphaMap=source.alphaMap;this.envMap=source.envMap;this.combine=source.combine;this.reflectivity=source.reflectivity;this.refractionRatio=source.refractionRatio;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.wireframeLinecap=source.wireframeLinecap;this.wireframeLinejoin=source.wireframeLinejoin;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;return this;};/**
  1676. * parameters = {
  1677. * color: <hex>,
  1678. *
  1679. * map: new THREE.Texture( <Image> ),
  1680. * gradientMap: new THREE.Texture( <Image> ),
  1681. *
  1682. * lightMap: new THREE.Texture( <Image> ),
  1683. * lightMapIntensity: <float>
  1684. *
  1685. * aoMap: new THREE.Texture( <Image> ),
  1686. * aoMapIntensity: <float>
  1687. *
  1688. * emissive: <hex>,
  1689. * emissiveIntensity: <float>
  1690. * emissiveMap: new THREE.Texture( <Image> ),
  1691. *
  1692. * bumpMap: new THREE.Texture( <Image> ),
  1693. * bumpScale: <float>,
  1694. *
  1695. * normalMap: new THREE.Texture( <Image> ),
  1696. * normalMapType: THREE.TangentSpaceNormalMap,
  1697. * normalScale: <Vector2>,
  1698. *
  1699. * displacementMap: new THREE.Texture( <Image> ),
  1700. * displacementScale: <float>,
  1701. * displacementBias: <float>,
  1702. *
  1703. * alphaMap: new THREE.Texture( <Image> ),
  1704. *
  1705. * wireframe: <boolean>,
  1706. * wireframeLinewidth: <float>,
  1707. *
  1708. * skinning: <bool>,
  1709. * morphTargets: <bool>,
  1710. * morphNormals: <bool>
  1711. * }
  1712. */function MeshToonMaterial(parameters){Material.call(this);this.defines={'TOON':''};this.type='MeshToonMaterial';this.color=new Color(0xffffff);this.map=null;this.gradientMap=null;this.lightMap=null;this.lightMapIntensity=1.0;this.aoMap=null;this.aoMapIntensity=1.0;this.emissive=new Color(0x000000);this.emissiveIntensity=1.0;this.emissiveMap=null;this.bumpMap=null;this.bumpScale=1;this.normalMap=null;this.normalMapType=TangentSpaceNormalMap;this.normalScale=new Vector2(1,1);this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.alphaMap=null;this.wireframe=false;this.wireframeLinewidth=1;this.wireframeLinecap='round';this.wireframeLinejoin='round';this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.setValues(parameters);}MeshToonMaterial.prototype=Object.create(Material.prototype);MeshToonMaterial.prototype.constructor=MeshToonMaterial;MeshToonMaterial.prototype.isMeshToonMaterial=true;MeshToonMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.map=source.map;this.gradientMap=source.gradientMap;this.lightMap=source.lightMap;this.lightMapIntensity=source.lightMapIntensity;this.aoMap=source.aoMap;this.aoMapIntensity=source.aoMapIntensity;this.emissive.copy(source.emissive);this.emissiveMap=source.emissiveMap;this.emissiveIntensity=source.emissiveIntensity;this.bumpMap=source.bumpMap;this.bumpScale=source.bumpScale;this.normalMap=source.normalMap;this.normalMapType=source.normalMapType;this.normalScale.copy(source.normalScale);this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.alphaMap=source.alphaMap;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.wireframeLinecap=source.wireframeLinecap;this.wireframeLinejoin=source.wireframeLinejoin;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;return this;};/**
  1713. * parameters = {
  1714. * opacity: <float>,
  1715. *
  1716. * bumpMap: new THREE.Texture( <Image> ),
  1717. * bumpScale: <float>,
  1718. *
  1719. * normalMap: new THREE.Texture( <Image> ),
  1720. * normalMapType: THREE.TangentSpaceNormalMap,
  1721. * normalScale: <Vector2>,
  1722. *
  1723. * displacementMap: new THREE.Texture( <Image> ),
  1724. * displacementScale: <float>,
  1725. * displacementBias: <float>,
  1726. *
  1727. * wireframe: <boolean>,
  1728. * wireframeLinewidth: <float>
  1729. *
  1730. * skinning: <bool>,
  1731. * morphTargets: <bool>,
  1732. * morphNormals: <bool>
  1733. * }
  1734. */function MeshNormalMaterial(parameters){Material.call(this);this.type='MeshNormalMaterial';this.bumpMap=null;this.bumpScale=1;this.normalMap=null;this.normalMapType=TangentSpaceNormalMap;this.normalScale=new Vector2(1,1);this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.wireframe=false;this.wireframeLinewidth=1;this.fog=false;this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.setValues(parameters);}MeshNormalMaterial.prototype=Object.create(Material.prototype);MeshNormalMaterial.prototype.constructor=MeshNormalMaterial;MeshNormalMaterial.prototype.isMeshNormalMaterial=true;MeshNormalMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.bumpMap=source.bumpMap;this.bumpScale=source.bumpScale;this.normalMap=source.normalMap;this.normalMapType=source.normalMapType;this.normalScale.copy(source.normalScale);this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;return this;};/**
  1735. * parameters = {
  1736. * color: <hex>,
  1737. * opacity: <float>,
  1738. *
  1739. * map: new THREE.Texture( <Image> ),
  1740. *
  1741. * lightMap: new THREE.Texture( <Image> ),
  1742. * lightMapIntensity: <float>
  1743. *
  1744. * aoMap: new THREE.Texture( <Image> ),
  1745. * aoMapIntensity: <float>
  1746. *
  1747. * emissive: <hex>,
  1748. * emissiveIntensity: <float>
  1749. * emissiveMap: new THREE.Texture( <Image> ),
  1750. *
  1751. * specularMap: new THREE.Texture( <Image> ),
  1752. *
  1753. * alphaMap: new THREE.Texture( <Image> ),
  1754. *
  1755. * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
  1756. * combine: THREE.Multiply,
  1757. * reflectivity: <float>,
  1758. * refractionRatio: <float>,
  1759. *
  1760. * wireframe: <boolean>,
  1761. * wireframeLinewidth: <float>,
  1762. *
  1763. * skinning: <bool>,
  1764. * morphTargets: <bool>,
  1765. * morphNormals: <bool>
  1766. * }
  1767. */function MeshLambertMaterial(parameters){Material.call(this);this.type='MeshLambertMaterial';this.color=new Color(0xffffff);// diffuse
  1768. this.map=null;this.lightMap=null;this.lightMapIntensity=1.0;this.aoMap=null;this.aoMapIntensity=1.0;this.emissive=new Color(0x000000);this.emissiveIntensity=1.0;this.emissiveMap=null;this.specularMap=null;this.alphaMap=null;this.envMap=null;this.combine=MultiplyOperation;this.reflectivity=1;this.refractionRatio=0.98;this.wireframe=false;this.wireframeLinewidth=1;this.wireframeLinecap='round';this.wireframeLinejoin='round';this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.setValues(parameters);}MeshLambertMaterial.prototype=Object.create(Material.prototype);MeshLambertMaterial.prototype.constructor=MeshLambertMaterial;MeshLambertMaterial.prototype.isMeshLambertMaterial=true;MeshLambertMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.color.copy(source.color);this.map=source.map;this.lightMap=source.lightMap;this.lightMapIntensity=source.lightMapIntensity;this.aoMap=source.aoMap;this.aoMapIntensity=source.aoMapIntensity;this.emissive.copy(source.emissive);this.emissiveMap=source.emissiveMap;this.emissiveIntensity=source.emissiveIntensity;this.specularMap=source.specularMap;this.alphaMap=source.alphaMap;this.envMap=source.envMap;this.combine=source.combine;this.reflectivity=source.reflectivity;this.refractionRatio=source.refractionRatio;this.wireframe=source.wireframe;this.wireframeLinewidth=source.wireframeLinewidth;this.wireframeLinecap=source.wireframeLinecap;this.wireframeLinejoin=source.wireframeLinejoin;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;return this;};/**
  1769. * parameters = {
  1770. * color: <hex>,
  1771. * opacity: <float>,
  1772. *
  1773. * matcap: new THREE.Texture( <Image> ),
  1774. *
  1775. * map: new THREE.Texture( <Image> ),
  1776. *
  1777. * bumpMap: new THREE.Texture( <Image> ),
  1778. * bumpScale: <float>,
  1779. *
  1780. * normalMap: new THREE.Texture( <Image> ),
  1781. * normalMapType: THREE.TangentSpaceNormalMap,
  1782. * normalScale: <Vector2>,
  1783. *
  1784. * displacementMap: new THREE.Texture( <Image> ),
  1785. * displacementScale: <float>,
  1786. * displacementBias: <float>,
  1787. *
  1788. * alphaMap: new THREE.Texture( <Image> ),
  1789. *
  1790. * skinning: <bool>,
  1791. * morphTargets: <bool>,
  1792. * morphNormals: <bool>
  1793. * }
  1794. */function MeshMatcapMaterial(parameters){Material.call(this);this.defines={'MATCAP':''};this.type='MeshMatcapMaterial';this.color=new Color(0xffffff);// diffuse
  1795. this.matcap=null;this.map=null;this.bumpMap=null;this.bumpScale=1;this.normalMap=null;this.normalMapType=TangentSpaceNormalMap;this.normalScale=new Vector2(1,1);this.displacementMap=null;this.displacementScale=1;this.displacementBias=0;this.alphaMap=null;this.skinning=false;this.morphTargets=false;this.morphNormals=false;this.setValues(parameters);}MeshMatcapMaterial.prototype=Object.create(Material.prototype);MeshMatcapMaterial.prototype.constructor=MeshMatcapMaterial;MeshMatcapMaterial.prototype.isMeshMatcapMaterial=true;MeshMatcapMaterial.prototype.copy=function(source){Material.prototype.copy.call(this,source);this.defines={'MATCAP':''};this.color.copy(source.color);this.matcap=source.matcap;this.map=source.map;this.bumpMap=source.bumpMap;this.bumpScale=source.bumpScale;this.normalMap=source.normalMap;this.normalMapType=source.normalMapType;this.normalScale.copy(source.normalScale);this.displacementMap=source.displacementMap;this.displacementScale=source.displacementScale;this.displacementBias=source.displacementBias;this.alphaMap=source.alphaMap;this.skinning=source.skinning;this.morphTargets=source.morphTargets;this.morphNormals=source.morphNormals;return this;};/**
  1796. * parameters = {
  1797. * color: <hex>,
  1798. * opacity: <float>,
  1799. *
  1800. * linewidth: <float>,
  1801. *
  1802. * scale: <float>,
  1803. * dashSize: <float>,
  1804. * gapSize: <float>
  1805. * }
  1806. */function LineDashedMaterial(parameters){LineBasicMaterial.call(this);this.type='LineDashedMaterial';this.scale=1;this.dashSize=3;this.gapSize=1;this.setValues(parameters);}LineDashedMaterial.prototype=Object.create(LineBasicMaterial.prototype);LineDashedMaterial.prototype.constructor=LineDashedMaterial;LineDashedMaterial.prototype.isLineDashedMaterial=true;LineDashedMaterial.prototype.copy=function(source){LineBasicMaterial.prototype.copy.call(this,source);this.scale=source.scale;this.dashSize=source.dashSize;this.gapSize=source.gapSize;return this;};var Materials=/*#__PURE__*/Object.freeze({__proto__:null,ShadowMaterial:ShadowMaterial,SpriteMaterial:SpriteMaterial,RawShaderMaterial:RawShaderMaterial,ShaderMaterial:ShaderMaterial,PointsMaterial:PointsMaterial,MeshPhysicalMaterial:MeshPhysicalMaterial,MeshStandardMaterial:MeshStandardMaterial,MeshPhongMaterial:MeshPhongMaterial,MeshToonMaterial:MeshToonMaterial,MeshNormalMaterial:MeshNormalMaterial,MeshLambertMaterial:MeshLambertMaterial,MeshDepthMaterial:MeshDepthMaterial,MeshDistanceMaterial:MeshDistanceMaterial,MeshBasicMaterial:MeshBasicMaterial,MeshMatcapMaterial:MeshMatcapMaterial,LineDashedMaterial:LineDashedMaterial,LineBasicMaterial:LineBasicMaterial,Material:Material});var AnimationUtils={// same as Array.prototype.slice, but also works on typed arrays
  1807. arraySlice:function arraySlice(array,from,to){if(AnimationUtils.isTypedArray(array)){// in ios9 array.subarray(from, undefined) will return empty array
  1808. // but array.subarray(from) or array.subarray(from, len) is correct
  1809. return new array.constructor(array.subarray(from,to!==undefined?to:array.length));}return array.slice(from,to);},// converts an array to a specific type
  1810. convertArray:function convertArray(array,type,forceClone){if(!array||// let 'undefined' and 'null' pass
  1811. !forceClone&&array.constructor===type)return array;if(typeof type.BYTES_PER_ELEMENT==='number'){return new type(array);// create typed array
  1812. }return Array.prototype.slice.call(array);// create Array
  1813. },isTypedArray:function isTypedArray(object){return ArrayBuffer.isView(object)&&!(object instanceof DataView);},// returns an array by which times and values can be sorted
  1814. getKeyframeOrder:function getKeyframeOrder(times){function compareTime(i,j){return times[i]-times[j];}var n=times.length;var result=new Array(n);for(var _i242=0;_i242!==n;++_i242)result[_i242]=_i242;result.sort(compareTime);return result;},// uses the array previously returned by 'getKeyframeOrder' to sort data
  1815. sortedArray:function sortedArray(values,stride,order){var nValues=values.length;var result=new values.constructor(nValues);for(var _i243=0,dstOffset=0;dstOffset!==nValues;++_i243){var srcOffset=order[_i243]*stride;for(var j=0;j!==stride;++j){result[dstOffset++]=values[srcOffset+j];}}return result;},// function for parsing AOS keyframe formats
  1816. flattenJSON:function flattenJSON(jsonKeys,times,values,valuePropertyName){var i=1,key=jsonKeys[0];while(key!==undefined&&key[valuePropertyName]===undefined){key=jsonKeys[i++];}if(key===undefined)return;// no data
  1817. var value=key[valuePropertyName];if(value===undefined)return;// no data
  1818. if(Array.isArray(value)){do{value=key[valuePropertyName];if(value!==undefined){times.push(key.time);values.push.apply(values,value);// push all elements
  1819. }key=jsonKeys[i++];}while(key!==undefined);}else if(value.toArray!==undefined){// ...assume THREE.Math-ish
  1820. do{value=key[valuePropertyName];if(value!==undefined){times.push(key.time);value.toArray(values,values.length);}key=jsonKeys[i++];}while(key!==undefined);}else {// otherwise push as-is
  1821. do{value=key[valuePropertyName];if(value!==undefined){times.push(key.time);values.push(value);}key=jsonKeys[i++];}while(key!==undefined);}},subclip:function subclip(sourceClip,name,startFrame,endFrame){var fps=arguments.length>4&&arguments[4]!==undefined?arguments[4]:30;var clip=sourceClip.clone();clip.name=name;var tracks=[];for(var _i244=0;_i244<clip.tracks.length;++_i244){var track=clip.tracks[_i244];var valueSize=track.getValueSize();var times=[];var values=[];for(var j=0;j<track.times.length;++j){var frame=track.times[j]*fps;if(frame<startFrame||frame>=endFrame)continue;times.push(track.times[j]);for(var k=0;k<valueSize;++k){values.push(track.values[j*valueSize+k]);}}if(times.length===0)continue;track.times=AnimationUtils.convertArray(times,track.times.constructor);track.values=AnimationUtils.convertArray(values,track.values.constructor);tracks.push(track);}clip.tracks=tracks;// find minimum .times value across all tracks in the trimmed clip
  1822. var minStartTime=Infinity;for(var _i245=0;_i245<clip.tracks.length;++_i245){if(minStartTime>clip.tracks[_i245].times[0]){minStartTime=clip.tracks[_i245].times[0];}}// shift all tracks such that clip begins at t=0
  1823. for(var _i246=0;_i246<clip.tracks.length;++_i246){clip.tracks[_i246].shift(-1*minStartTime);}clip.resetDuration();return clip;},makeClipAdditive:function makeClipAdditive(targetClip){var referenceFrame=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var referenceClip=arguments.length>2&&arguments[2]!==undefined?arguments[2]:targetClip;var fps=arguments.length>3&&arguments[3]!==undefined?arguments[3]:30;if(fps<=0)fps=30;var numTracks=referenceClip.tracks.length;var referenceTime=referenceFrame/fps;// Make each track's values relative to the values at the reference frame
  1824. var _loop=function _loop(){var referenceTrack=referenceClip.tracks[_i247];var referenceTrackType=referenceTrack.ValueTypeName;// Skip this track if it's non-numeric
  1825. if(referenceTrackType==='bool'||referenceTrackType==='string')return 0;// continue
  1826. // Find the track in the target clip whose name and type matches the reference track
  1827. var targetTrack=targetClip.tracks.find(function(track){return track.name===referenceTrack.name&&track.ValueTypeName===referenceTrackType;});if(targetTrack===undefined)return 0;// continue
  1828. var referenceOffset=0;var referenceValueSize=referenceTrack.getValueSize();if(referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline){referenceOffset=referenceValueSize/3;}var targetOffset=0;var targetValueSize=targetTrack.getValueSize();if(targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline){targetOffset=targetValueSize/3;}var lastIndex=referenceTrack.times.length-1;var referenceValue;// Find the value to subtract out of the track
  1829. if(referenceTime<=referenceTrack.times[0]){// Reference frame is earlier than the first keyframe, so just use the first keyframe
  1830. var startIndex=referenceOffset;var endIndex=referenceValueSize-referenceOffset;referenceValue=AnimationUtils.arraySlice(referenceTrack.values,startIndex,endIndex);}else if(referenceTime>=referenceTrack.times[lastIndex]){// Reference frame is after the last keyframe, so just use the last keyframe
  1831. var _startIndex=lastIndex*referenceValueSize+referenceOffset;var _endIndex=_startIndex+referenceValueSize-referenceOffset;referenceValue=AnimationUtils.arraySlice(referenceTrack.values,_startIndex,_endIndex);}else {// Interpolate to the reference value
  1832. var interpolant=referenceTrack.createInterpolant();var _startIndex2=referenceOffset;var _endIndex2=referenceValueSize-referenceOffset;interpolant.evaluate(referenceTime);referenceValue=AnimationUtils.arraySlice(interpolant.resultBuffer,_startIndex2,_endIndex2);}// Conjugate the quaternion
  1833. if(referenceTrackType==='quaternion'){var referenceQuat=new Quaternion().fromArray(referenceValue).normalize().conjugate();referenceQuat.toArray(referenceValue);}// Subtract the reference value from all of the track values
  1834. var numTimes=targetTrack.times.length;for(var j=0;j<numTimes;++j){var valueStart=j*targetValueSize+targetOffset;if(referenceTrackType==='quaternion'){// Multiply the conjugate for quaternion track types
  1835. Quaternion.multiplyQuaternionsFlat(targetTrack.values,valueStart,referenceValue,0,targetTrack.values,valueStart);}else {var valueEnd=targetValueSize-targetOffset*2;// Subtract each value for all other numeric track types
  1836. for(var k=0;k<valueEnd;++k){targetTrack.values[valueStart+k]-=referenceValue[k];}}}},_ret;for(var _i247=0;_i247<numTracks;++_i247){_ret=_loop();if(_ret===0)continue;}targetClip.blendMode=AdditiveAnimationBlendMode;return targetClip;}};/**
  1837. * Abstract base class of interpolants over parametric samples.
  1838. *
  1839. * The parameter domain is one dimensional, typically the time or a path
  1840. * along a curve defined by the data.
  1841. *
  1842. * The sample values can have any dimensionality and derived classes may
  1843. * apply special interpretations to the data.
  1844. *
  1845. * This class provides the interval seek in a Template Method, deferring
  1846. * the actual interpolation to derived classes.
  1847. *
  1848. * Time complexity is O(1) for linear access crossing at most two points
  1849. * and O(log N) for random access, where N is the number of positions.
  1850. *
  1851. * References:
  1852. *
  1853. * http://www.oodesign.com/template-method-pattern.html
  1854. *
  1855. */function Interpolant(parameterPositions,sampleValues,sampleSize,resultBuffer){this.parameterPositions=parameterPositions;this._cachedIndex=0;this.resultBuffer=resultBuffer!==undefined?resultBuffer:new sampleValues.constructor(sampleSize);this.sampleValues=sampleValues;this.valueSize=sampleSize;}Object.assign(Interpolant.prototype,{evaluate:function evaluate(t){var pp=this.parameterPositions;var i1=this._cachedIndex,t1=pp[i1],t0=pp[i1-1];validate_interval:{seek:{var right;linear_scan:{//- See http://jsperf.com/comparison-to-undefined/3
  1856. //- slower code:
  1857. //-
  1858. //- if ( t >= t1 || t1 === undefined ) {
  1859. forward_scan:if(!(t<t1)){for(var giveUpAt=i1+2;;){if(t1===undefined){if(t<t0)break forward_scan;// after end
  1860. i1=pp.length;this._cachedIndex=i1;return this.afterEnd_(i1-1,t,t0);}if(i1===giveUpAt)break;// this loop
  1861. t0=t1;t1=pp[++i1];if(t<t1){// we have arrived at the sought interval
  1862. break seek;}}// prepare binary search on the right side of the index
  1863. right=pp.length;break linear_scan;}//- slower code:
  1864. //- if ( t < t0 || t0 === undefined ) {
  1865. if(!(t>=t0)){// looping?
  1866. var t1global=pp[1];if(t<t1global){i1=2;// + 1, using the scan for the details
  1867. t0=t1global;}// linear reverse scan
  1868. for(var _giveUpAt=i1-2;;){if(t0===undefined){// before start
  1869. this._cachedIndex=0;return this.beforeStart_(0,t,t1);}if(i1===_giveUpAt)break;// this loop
  1870. t1=t0;t0=pp[--i1-1];if(t>=t0){// we have arrived at the sought interval
  1871. break seek;}}// prepare binary search on the left side of the index
  1872. right=i1;i1=0;break linear_scan;}// the interval is valid
  1873. break validate_interval;}// linear scan
  1874. // binary search
  1875. while(i1<right){var mid=i1+right>>>1;if(t<pp[mid]){right=mid;}else {i1=mid+1;}}t1=pp[i1];t0=pp[i1-1];// check boundary cases, again
  1876. if(t0===undefined){this._cachedIndex=0;return this.beforeStart_(0,t,t1);}if(t1===undefined){i1=pp.length;this._cachedIndex=i1;return this.afterEnd_(i1-1,t0,t);}}// seek
  1877. this._cachedIndex=i1;this.intervalChanged_(i1,t0,t1);}// validate_interval
  1878. return this.interpolate_(i1,t0,t,t1);},settings:null,// optional, subclass-specific settings structure
  1879. // Note: The indirection allows central control of many interpolants.
  1880. // --- Protected interface
  1881. DefaultSettings_:{},getSettings_:function getSettings_(){return this.settings||this.DefaultSettings_;},copySampleValue_:function copySampleValue_(index){// copies a sample value to the result buffer
  1882. var result=this.resultBuffer,values=this.sampleValues,stride=this.valueSize,offset=index*stride;for(var _i248=0;_i248!==stride;++_i248){result[_i248]=values[offset+_i248];}return result;},// Template methods for derived classes:
  1883. interpolate_:function interpolate_(/* i1, t0, t, t1 */){throw new Error('call to abstract method');// implementations shall return this.resultBuffer
  1884. },intervalChanged_:function intervalChanged_(/* i1, t0, t1 */){// empty
  1885. }});// DECLARE ALIAS AFTER assign prototype
  1886. Object.assign(Interpolant.prototype,{//( 0, t, t0 ), returns this.resultBuffer
  1887. beforeStart_:Interpolant.prototype.copySampleValue_,//( N-1, tN-1, t ), returns this.resultBuffer
  1888. afterEnd_:Interpolant.prototype.copySampleValue_});/**
  1889. * Fast and simple cubic spline interpolant.
  1890. *
  1891. * It was derived from a Hermitian construction setting the first derivative
  1892. * at each sample position to the linear slope between neighboring positions
  1893. * over their parameter interval.
  1894. */function CubicInterpolant(parameterPositions,sampleValues,sampleSize,resultBuffer){Interpolant.call(this,parameterPositions,sampleValues,sampleSize,resultBuffer);this._weightPrev=-0;this._offsetPrev=-0;this._weightNext=-0;this._offsetNext=-0;}CubicInterpolant.prototype=Object.assign(Object.create(Interpolant.prototype),{constructor:CubicInterpolant,DefaultSettings_:{endingStart:ZeroCurvatureEnding,endingEnd:ZeroCurvatureEnding},intervalChanged_:function intervalChanged_(i1,t0,t1){var pp=this.parameterPositions;var iPrev=i1-2,iNext=i1+1,tPrev=pp[iPrev],tNext=pp[iNext];if(tPrev===undefined){switch(this.getSettings_().endingStart){case ZeroSlopeEnding:// f'(t0) = 0
  1895. iPrev=i1;tPrev=2*t0-t1;break;case WrapAroundEnding:// use the other end of the curve
  1896. iPrev=pp.length-2;tPrev=t0+pp[iPrev]-pp[iPrev+1];break;default:// ZeroCurvatureEnding
  1897. // f''(t0) = 0 a.k.a. Natural Spline
  1898. iPrev=i1;tPrev=t1;}}if(tNext===undefined){switch(this.getSettings_().endingEnd){case ZeroSlopeEnding:// f'(tN) = 0
  1899. iNext=i1;tNext=2*t1-t0;break;case WrapAroundEnding:// use the other end of the curve
  1900. iNext=1;tNext=t1+pp[1]-pp[0];break;default:// ZeroCurvatureEnding
  1901. // f''(tN) = 0, a.k.a. Natural Spline
  1902. iNext=i1-1;tNext=t0;}}var halfDt=(t1-t0)*0.5,stride=this.valueSize;this._weightPrev=halfDt/(t0-tPrev);this._weightNext=halfDt/(tNext-t1);this._offsetPrev=iPrev*stride;this._offsetNext=iNext*stride;},interpolate_:function interpolate_(i1,t0,t,t1){var result=this.resultBuffer,values=this.sampleValues,stride=this.valueSize,o1=i1*stride,o0=o1-stride,oP=this._offsetPrev,oN=this._offsetNext,wP=this._weightPrev,wN=this._weightNext,p=(t-t0)/(t1-t0),pp=p*p,ppp=pp*p;// evaluate polynomials
  1903. var sP=-wP*ppp+2*wP*pp-wP*p;var s0=(1+wP)*ppp+(-1.5-2*wP)*pp+(-0.5+wP)*p+1;var s1=(-1-wN)*ppp+(1.5+wN)*pp+0.5*p;var sN=wN*ppp-wN*pp;// combine data linearly
  1904. for(var _i249=0;_i249!==stride;++_i249){result[_i249]=sP*values[oP+_i249]+s0*values[o0+_i249]+s1*values[o1+_i249]+sN*values[oN+_i249];}return result;}});function LinearInterpolant(parameterPositions,sampleValues,sampleSize,resultBuffer){Interpolant.call(this,parameterPositions,sampleValues,sampleSize,resultBuffer);}LinearInterpolant.prototype=Object.assign(Object.create(Interpolant.prototype),{constructor:LinearInterpolant,interpolate_:function interpolate_(i1,t0,t,t1){var result=this.resultBuffer,values=this.sampleValues,stride=this.valueSize,offset1=i1*stride,offset0=offset1-stride,weight1=(t-t0)/(t1-t0),weight0=1-weight1;for(var _i250=0;_i250!==stride;++_i250){result[_i250]=values[offset0+_i250]*weight0+values[offset1+_i250]*weight1;}return result;}});/**
  1905. *
  1906. * Interpolant that evaluates to the sample value at the position preceeding
  1907. * the parameter.
  1908. */function DiscreteInterpolant(parameterPositions,sampleValues,sampleSize,resultBuffer){Interpolant.call(this,parameterPositions,sampleValues,sampleSize,resultBuffer);}DiscreteInterpolant.prototype=Object.assign(Object.create(Interpolant.prototype),{constructor:DiscreteInterpolant,interpolate_:function interpolate_(i1/*, t0, t, t1 */){return this.copySampleValue_(i1-1);}});function KeyframeTrack(name,times,values,interpolation){if(name===undefined)throw new Error('THREE.KeyframeTrack: track name is undefined');if(times===undefined||times.length===0)throw new Error('THREE.KeyframeTrack: no keyframes in track named '+name);this.name=name;this.times=AnimationUtils.convertArray(times,this.TimeBufferType);this.values=AnimationUtils.convertArray(values,this.ValueBufferType);this.setInterpolation(interpolation||this.DefaultInterpolation);}// Static methods
  1909. Object.assign(KeyframeTrack,{// Serialization (in static context, because of constructor invocation
  1910. // and automatic invocation of .toJSON):
  1911. toJSON:function toJSON(track){var trackType=track.constructor;var json;// derived classes can define a static toJSON method
  1912. if(trackType.toJSON!==undefined){json=trackType.toJSON(track);}else {// by default, we assume the data can be serialized as-is
  1913. json={'name':track.name,'times':AnimationUtils.convertArray(track.times,Array),'values':AnimationUtils.convertArray(track.values,Array)};var interpolation=track.getInterpolation();if(interpolation!==track.DefaultInterpolation){json.interpolation=interpolation;}}json.type=track.ValueTypeName;// mandatory
  1914. return json;}});Object.assign(KeyframeTrack.prototype,{constructor:KeyframeTrack,TimeBufferType:Float32Array,ValueBufferType:Float32Array,DefaultInterpolation:InterpolateLinear,InterpolantFactoryMethodDiscrete:function InterpolantFactoryMethodDiscrete(result){return new DiscreteInterpolant(this.times,this.values,this.getValueSize(),result);},InterpolantFactoryMethodLinear:function InterpolantFactoryMethodLinear(result){return new LinearInterpolant(this.times,this.values,this.getValueSize(),result);},InterpolantFactoryMethodSmooth:function InterpolantFactoryMethodSmooth(result){return new CubicInterpolant(this.times,this.values,this.getValueSize(),result);},setInterpolation:function setInterpolation(interpolation){var factoryMethod;switch(interpolation){case InterpolateDiscrete:factoryMethod=this.InterpolantFactoryMethodDiscrete;break;case InterpolateLinear:factoryMethod=this.InterpolantFactoryMethodLinear;break;case InterpolateSmooth:factoryMethod=this.InterpolantFactoryMethodSmooth;break;}if(factoryMethod===undefined){var message='unsupported interpolation for '+this.ValueTypeName+' keyframe track named '+this.name;if(this.createInterpolant===undefined){// fall back to default, unless the default itself is messed up
  1915. if(interpolation!==this.DefaultInterpolation){this.setInterpolation(this.DefaultInterpolation);}else {throw new Error(message);// fatal, in this case
  1916. }}console.warn('THREE.KeyframeTrack:',message);return this;}this.createInterpolant=factoryMethod;return this;},getInterpolation:function getInterpolation(){switch(this.createInterpolant){case this.InterpolantFactoryMethodDiscrete:return InterpolateDiscrete;case this.InterpolantFactoryMethodLinear:return InterpolateLinear;case this.InterpolantFactoryMethodSmooth:return InterpolateSmooth;}},getValueSize:function getValueSize(){return this.values.length/this.times.length;},// move all keyframes either forwards or backwards in time
  1917. shift:function shift(timeOffset){if(timeOffset!==0.0){var times=this.times;for(var _i251=0,n=times.length;_i251!==n;++_i251){times[_i251]+=timeOffset;}}return this;},// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
  1918. scale:function scale(timeScale){if(timeScale!==1.0){var times=this.times;for(var _i252=0,n=times.length;_i252!==n;++_i252){times[_i252]*=timeScale;}}return this;},// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
  1919. // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
  1920. trim:function trim(startTime,endTime){var times=this.times,nKeys=times.length;var from=0,to=nKeys-1;while(from!==nKeys&&times[from]<startTime){++from;}while(to!==-1&&times[to]>endTime){--to;}++to;// inclusive -> exclusive bound
  1921. if(from!==0||to!==nKeys){// empty tracks are forbidden, so keep at least one keyframe
  1922. if(from>=to){to=Math.max(to,1);from=to-1;}var stride=this.getValueSize();this.times=AnimationUtils.arraySlice(times,from,to);this.values=AnimationUtils.arraySlice(this.values,from*stride,to*stride);}return this;},// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
  1923. validate:function validate(){var valid=true;var valueSize=this.getValueSize();if(valueSize-Math.floor(valueSize)!==0){console.error('THREE.KeyframeTrack: Invalid value size in track.',this);valid=false;}var times=this.times,values=this.values,nKeys=times.length;if(nKeys===0){console.error('THREE.KeyframeTrack: Track is empty.',this);valid=false;}var prevTime=null;for(var _i253=0;_i253!==nKeys;_i253++){var currTime=times[_i253];if(typeof currTime==='number'&&isNaN(currTime)){console.error('THREE.KeyframeTrack: Time is not a valid number.',this,_i253,currTime);valid=false;break;}if(prevTime!==null&&prevTime>currTime){console.error('THREE.KeyframeTrack: Out of order keys.',this,_i253,currTime,prevTime);valid=false;break;}prevTime=currTime;}if(values!==undefined){if(AnimationUtils.isTypedArray(values)){for(var _i254=0,n=values.length;_i254!==n;++_i254){var value=values[_i254];if(isNaN(value)){console.error('THREE.KeyframeTrack: Value is not a valid number.',this,_i254,value);valid=false;break;}}}}return valid;},// removes equivalent sequential keys as common in morph target sequences
  1924. // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
  1925. optimize:function optimize(){// times or values may be shared with other tracks, so overwriting is unsafe
  1926. var times=AnimationUtils.arraySlice(this.times),values=AnimationUtils.arraySlice(this.values),stride=this.getValueSize(),smoothInterpolation=this.getInterpolation()===InterpolateSmooth,lastIndex=times.length-1;var writeIndex=1;for(var _i255=1;_i255<lastIndex;++_i255){var keep=false;var time=times[_i255];var timeNext=times[_i255+1];// remove adjacent keyframes scheduled at the same time
  1927. if(time!==timeNext&&(_i255!==1||time!==time[0])){if(!smoothInterpolation){// remove unnecessary keyframes same as their neighbors
  1928. var offset=_i255*stride,offsetP=offset-stride,offsetN=offset+stride;for(var j=0;j!==stride;++j){var value=values[offset+j];if(value!==values[offsetP+j]||value!==values[offsetN+j]){keep=true;break;}}}else {keep=true;}}// in-place compaction
  1929. if(keep){if(_i255!==writeIndex){times[writeIndex]=times[_i255];var readOffset=_i255*stride,writeOffset=writeIndex*stride;for(var _j22=0;_j22!==stride;++_j22){values[writeOffset+_j22]=values[readOffset+_j22];}}++writeIndex;}}// flush last keyframe (compaction looks ahead)
  1930. if(lastIndex>0){times[writeIndex]=times[lastIndex];for(var _readOffset=lastIndex*stride,_writeOffset=writeIndex*stride,_j23=0;_j23!==stride;++_j23){values[_writeOffset+_j23]=values[_readOffset+_j23];}++writeIndex;}if(writeIndex!==times.length){this.times=AnimationUtils.arraySlice(times,0,writeIndex);this.values=AnimationUtils.arraySlice(values,0,writeIndex*stride);}else {this.times=times;this.values=values;}return this;},clone:function clone(){var times=AnimationUtils.arraySlice(this.times,0);var values=AnimationUtils.arraySlice(this.values,0);var TypedKeyframeTrack=this.constructor;var track=new TypedKeyframeTrack(this.name,times,values);// Interpolant argument to constructor is not saved, so copy the factory method directly.
  1931. track.createInterpolant=this.createInterpolant;return track;}});/**
  1932. * A Track of Boolean keyframe values.
  1933. */function BooleanKeyframeTrack(name,times,values){KeyframeTrack.call(this,name,times,values);}BooleanKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:BooleanKeyframeTrack,ValueTypeName:'bool',ValueBufferType:Array,DefaultInterpolation:InterpolateDiscrete,InterpolantFactoryMethodLinear:undefined,InterpolantFactoryMethodSmooth:undefined// Note: Actually this track could have a optimized / compressed
  1934. // representation of a single value and a custom interpolant that
  1935. // computes "firstValue ^ isOdd( index )".
  1936. });/**
  1937. * A Track of keyframe values that represent color.
  1938. */function ColorKeyframeTrack(name,times,values,interpolation){KeyframeTrack.call(this,name,times,values,interpolation);}ColorKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:ColorKeyframeTrack,ValueTypeName:'color'// ValueBufferType is inherited
  1939. // DefaultInterpolation is inherited
  1940. // Note: Very basic implementation and nothing special yet.
  1941. // However, this is the place for color space parameterization.
  1942. });/**
  1943. * A Track of numeric keyframe values.
  1944. */function NumberKeyframeTrack(name,times,values,interpolation){KeyframeTrack.call(this,name,times,values,interpolation);}NumberKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:NumberKeyframeTrack,ValueTypeName:'number'// ValueBufferType is inherited
  1945. // DefaultInterpolation is inherited
  1946. });/**
  1947. * Spherical linear unit quaternion interpolant.
  1948. */function QuaternionLinearInterpolant(parameterPositions,sampleValues,sampleSize,resultBuffer){Interpolant.call(this,parameterPositions,sampleValues,sampleSize,resultBuffer);}QuaternionLinearInterpolant.prototype=Object.assign(Object.create(Interpolant.prototype),{constructor:QuaternionLinearInterpolant,interpolate_:function interpolate_(i1,t0,t,t1){var result=this.resultBuffer,values=this.sampleValues,stride=this.valueSize,alpha=(t-t0)/(t1-t0);var offset=i1*stride;for(var end=offset+stride;offset!==end;offset+=4){Quaternion.slerpFlat(result,0,values,offset-stride,values,offset,alpha);}return result;}});/**
  1949. * A Track of quaternion keyframe values.
  1950. */function QuaternionKeyframeTrack(name,times,values,interpolation){KeyframeTrack.call(this,name,times,values,interpolation);}QuaternionKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:QuaternionKeyframeTrack,ValueTypeName:'quaternion',// ValueBufferType is inherited
  1951. DefaultInterpolation:InterpolateLinear,InterpolantFactoryMethodLinear:function InterpolantFactoryMethodLinear(result){return new QuaternionLinearInterpolant(this.times,this.values,this.getValueSize(),result);},InterpolantFactoryMethodSmooth:undefined// not yet implemented
  1952. });/**
  1953. * A Track that interpolates Strings
  1954. */function StringKeyframeTrack(name,times,values,interpolation){KeyframeTrack.call(this,name,times,values,interpolation);}StringKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:StringKeyframeTrack,ValueTypeName:'string',ValueBufferType:Array,DefaultInterpolation:InterpolateDiscrete,InterpolantFactoryMethodLinear:undefined,InterpolantFactoryMethodSmooth:undefined});/**
  1955. * A Track of vectored keyframe values.
  1956. */function VectorKeyframeTrack(name,times,values,interpolation){KeyframeTrack.call(this,name,times,values,interpolation);}VectorKeyframeTrack.prototype=Object.assign(Object.create(KeyframeTrack.prototype),{constructor:VectorKeyframeTrack,ValueTypeName:'vector'// ValueBufferType is inherited
  1957. // DefaultInterpolation is inherited
  1958. });function AnimationClip(name){var duration=arguments.length>1&&arguments[1]!==undefined?arguments[1]:-1;var tracks=arguments.length>2?arguments[2]:undefined;var blendMode=arguments.length>3&&arguments[3]!==undefined?arguments[3]:NormalAnimationBlendMode;this.name=name;this.tracks=tracks;this.duration=duration;this.blendMode=blendMode;this.uuid=MathUtils.generateUUID();// this means it should figure out its duration by scanning the tracks
  1959. if(this.duration<0){this.resetDuration();}}function getTrackTypeForValueTypeName(typeName){switch(typeName.toLowerCase()){case'scalar':case'double':case'float':case'number':case'integer':return NumberKeyframeTrack;case'vector':case'vector2':case'vector3':case'vector4':return VectorKeyframeTrack;case'color':return ColorKeyframeTrack;case'quaternion':return QuaternionKeyframeTrack;case'bool':case'boolean':return BooleanKeyframeTrack;case'string':return StringKeyframeTrack;}throw new Error('THREE.KeyframeTrack: Unsupported typeName: '+typeName);}function parseKeyframeTrack(json){if(json.type===undefined){throw new Error('THREE.KeyframeTrack: track type undefined, can not parse');}var trackType=getTrackTypeForValueTypeName(json.type);if(json.times===undefined){var times=[],values=[];AnimationUtils.flattenJSON(json.keys,times,values,'value');json.times=times;json.values=values;}// derived classes can define a static parse method
  1960. if(trackType.parse!==undefined){return trackType.parse(json);}else {// by default, we assume a constructor compatible with the base
  1961. return new trackType(json.name,json.times,json.values,json.interpolation);}}Object.assign(AnimationClip,{parse:function parse(json){var tracks=[],jsonTracks=json.tracks,frameTime=1.0/(json.fps||1.0);for(var _i256=0,n=jsonTracks.length;_i256!==n;++_i256){tracks.push(parseKeyframeTrack(jsonTracks[_i256]).scale(frameTime));}var clip=new AnimationClip(json.name,json.duration,tracks,json.blendMode);clip.uuid=json.uuid;return clip;},toJSON:function toJSON(clip){var tracks=[],clipTracks=clip.tracks;var json={'name':clip.name,'duration':clip.duration,'tracks':tracks,'uuid':clip.uuid,'blendMode':clip.blendMode};for(var _i257=0,n=clipTracks.length;_i257!==n;++_i257){tracks.push(KeyframeTrack.toJSON(clipTracks[_i257]));}return json;},CreateFromMorphTargetSequence:function CreateFromMorphTargetSequence(name,morphTargetSequence,fps,noLoop){var numMorphTargets=morphTargetSequence.length;var tracks=[];for(var _i258=0;_i258<numMorphTargets;_i258++){var times=[];var values=[];times.push((_i258+numMorphTargets-1)%numMorphTargets,_i258,(_i258+1)%numMorphTargets);values.push(0,1,0);var order=AnimationUtils.getKeyframeOrder(times);times=AnimationUtils.sortedArray(times,1,order);values=AnimationUtils.sortedArray(values,1,order);// if there is a key at the first frame, duplicate it as the
  1962. // last frame as well for perfect loop.
  1963. if(!noLoop&&times[0]===0){times.push(numMorphTargets);values.push(values[0]);}tracks.push(new NumberKeyframeTrack('.morphTargetInfluences['+morphTargetSequence[_i258].name+']',times,values).scale(1.0/fps));}return new AnimationClip(name,-1,tracks);},findByName:function findByName(objectOrClipArray,name){var clipArray=objectOrClipArray;if(!Array.isArray(objectOrClipArray)){var o=objectOrClipArray;clipArray=o.geometry&&o.geometry.animations||o.animations;}for(var _i259=0;_i259<clipArray.length;_i259++){if(clipArray[_i259].name===name){return clipArray[_i259];}}return null;},CreateClipsFromMorphTargetSequences:function CreateClipsFromMorphTargetSequences(morphTargets,fps,noLoop){var animationToMorphTargets={};// tested with https://regex101.com/ on trick sequences
  1964. // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
  1965. var pattern=/^([\w-]*?)([\d]+)$/;// sort morph target names into animation groups based
  1966. // patterns like Walk_001, Walk_002, Run_001, Run_002
  1967. for(var _i260=0,il=morphTargets.length;_i260<il;_i260++){var morphTarget=morphTargets[_i260];var parts=morphTarget.name.match(pattern);if(parts&&parts.length>1){var name=parts[1];var animationMorphTargets=animationToMorphTargets[name];if(!animationMorphTargets){animationToMorphTargets[name]=animationMorphTargets=[];}animationMorphTargets.push(morphTarget);}}var clips=[];for(var _name4 in animationToMorphTargets){clips.push(AnimationClip.CreateFromMorphTargetSequence(_name4,animationToMorphTargets[_name4],fps,noLoop));}return clips;},// parse the animation.hierarchy format
  1968. parseAnimation:function parseAnimation(animation,bones){if(!animation){console.error('THREE.AnimationClip: No animation in JSONLoader data.');return null;}var addNonemptyTrack=function addNonemptyTrack(trackType,trackName,animationKeys,propertyName,destTracks){// only return track if there are actually keys.
  1969. if(animationKeys.length!==0){var times=[];var values=[];AnimationUtils.flattenJSON(animationKeys,times,values,propertyName);// empty keys are filtered out, so check again
  1970. if(times.length!==0){destTracks.push(new trackType(trackName,times,values));}}};var tracks=[];var clipName=animation.name||'default';var fps=animation.fps||30;var blendMode=animation.blendMode;// automatic length determination in AnimationClip.
  1971. var duration=animation.length||-1;var hierarchyTracks=animation.hierarchy||[];for(var h=0;h<hierarchyTracks.length;h++){var animationKeys=hierarchyTracks[h].keys;// skip empty tracks
  1972. if(!animationKeys||animationKeys.length===0)continue;// process morph targets
  1973. if(animationKeys[0].morphTargets){// figure out all morph targets used in this track
  1974. var morphTargetNames={};var k=void 0;for(k=0;k<animationKeys.length;k++){if(animationKeys[k].morphTargets){for(var m=0;m<animationKeys[k].morphTargets.length;m++){morphTargetNames[animationKeys[k].morphTargets[m]]=-1;}}}// create a track for each morph target with all zero
  1975. // morphTargetInfluences except for the keys in which
  1976. // the morphTarget is named.
  1977. for(var morphTargetName in morphTargetNames){var times=[];var values=[];for(var _m=0;_m!==animationKeys[k].morphTargets.length;++_m){var animationKey=animationKeys[k];times.push(animationKey.time);values.push(animationKey.morphTarget===morphTargetName?1:0);}tracks.push(new NumberKeyframeTrack('.morphTargetInfluence['+morphTargetName+']',times,values));}duration=morphTargetNames.length*(fps||1.0);}else {// ...assume skeletal animation
  1978. var boneName='.bones['+bones[h].name+']';addNonemptyTrack(VectorKeyframeTrack,boneName+'.position',animationKeys,'pos',tracks);addNonemptyTrack(QuaternionKeyframeTrack,boneName+'.quaternion',animationKeys,'rot',tracks);addNonemptyTrack(VectorKeyframeTrack,boneName+'.scale',animationKeys,'scl',tracks);}}if(tracks.length===0){return null;}var clip=new AnimationClip(clipName,duration,tracks,blendMode);return clip;}});Object.assign(AnimationClip.prototype,{resetDuration:function resetDuration(){var tracks=this.tracks;var duration=0;for(var _i261=0,n=tracks.length;_i261!==n;++_i261){var track=this.tracks[_i261];duration=Math.max(duration,track.times[track.times.length-1]);}this.duration=duration;return this;},trim:function trim(){for(var _i262=0;_i262<this.tracks.length;_i262++){this.tracks[_i262].trim(0,this.duration);}return this;},validate:function validate(){var valid=true;for(var _i263=0;_i263<this.tracks.length;_i263++){valid=valid&&this.tracks[_i263].validate();}return valid;},optimize:function optimize(){for(var _i264=0;_i264<this.tracks.length;_i264++){this.tracks[_i264].optimize();}return this;},clone:function clone(){var tracks=[];for(var _i265=0;_i265<this.tracks.length;_i265++){tracks.push(this.tracks[_i265].clone());}return new AnimationClip(this.name,this.duration,tracks,this.blendMode);},toJSON:function toJSON(){return AnimationClip.toJSON(this);}});var Cache={enabled:false,files:{},add:function add(key,file){if(this.enabled===false)return;// console.log( 'THREE.Cache', 'Adding key:', key );
  1979. this.files[key]=file;},get:function get(key){if(this.enabled===false)return;// console.log( 'THREE.Cache', 'Checking key:', key );
  1980. return this.files[key];},remove:function remove(key){delete this.files[key];},clear:function clear(){this.files={};}};function LoadingManager(onLoad,onProgress,onError){var scope=this;var isLoading=false;var itemsLoaded=0;var itemsTotal=0;var urlModifier=undefined;var handlers=[];// Refer to #5689 for the reason why we don't set .onStart
  1981. // in the constructor
  1982. this.onStart=undefined;this.onLoad=onLoad;this.onProgress=onProgress;this.onError=onError;this.itemStart=function(url){itemsTotal++;if(isLoading===false){if(scope.onStart!==undefined){scope.onStart(url,itemsLoaded,itemsTotal);}}isLoading=true;};this.itemEnd=function(url){itemsLoaded++;if(scope.onProgress!==undefined){scope.onProgress(url,itemsLoaded,itemsTotal);}if(itemsLoaded===itemsTotal){isLoading=false;if(scope.onLoad!==undefined){scope.onLoad();}}};this.itemError=function(url){if(scope.onError!==undefined){scope.onError(url);}};this.resolveURL=function(url){if(urlModifier){return urlModifier(url);}return url;};this.setURLModifier=function(transform){urlModifier=transform;return this;};this.addHandler=function(regex,loader){handlers.push(regex,loader);return this;};this.removeHandler=function(regex){var index=handlers.indexOf(regex);if(index!==-1){handlers.splice(index,2);}return this;};this.getHandler=function(file){for(var _i266=0,l=handlers.length;_i266<l;_i266+=2){var regex=handlers[_i266];var loader=handlers[_i266+1];if(regex.global)regex.lastIndex=0;// see #17920
  1983. if(regex.test(file)){return loader;}}return null;};}var DefaultLoadingManager=new LoadingManager();function Loader(manager){this.manager=manager!==undefined?manager:DefaultLoadingManager;this.crossOrigin='anonymous';this.withCredentials=false;this.path='';this.resourcePath='';this.requestHeader={};}Object.assign(Loader.prototype,{load:function load(/* url, onLoad, onProgress, onError */){},loadAsync:function loadAsync(url,onProgress){var scope=this;return new Promise(function(resolve,reject){scope.load(url,resolve,onProgress,reject);});},parse:function parse(/* data */){},setCrossOrigin:function setCrossOrigin(crossOrigin){this.crossOrigin=crossOrigin;return this;},setWithCredentials:function setWithCredentials(value){this.withCredentials=value;return this;},setPath:function setPath(path){this.path=path;return this;},setResourcePath:function setResourcePath(resourcePath){this.resourcePath=resourcePath;return this;},setRequestHeader:function setRequestHeader(requestHeader){this.requestHeader=requestHeader;return this;}});var loading={};function FileLoader(manager){Loader.call(this,manager);}FileLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:FileLoader,load:function load(url,onLoad,onProgress,onError){if(url===undefined)url='';if(this.path!==undefined)url=this.path+url;url=this.manager.resolveURL(url);var scope=this;var cached=Cache.get(url);if(cached!==undefined){scope.manager.itemStart(url);setTimeout(function(){if(onLoad)onLoad(cached);scope.manager.itemEnd(url);},0);return cached;}// Check if request is duplicate
  1984. if(loading[url]!==undefined){loading[url].push({onLoad:onLoad,onProgress:onProgress,onError:onError});return;}// Check for data: URI
  1985. var dataUriRegex=/^data:(.*?)(;base64)?,(.*)$/;var dataUriRegexResult=url.match(dataUriRegex);var request;// Safari can not handle Data URIs through XMLHttpRequest so process manually
  1986. if(dataUriRegexResult){var mimeType=dataUriRegexResult[1];var isBase64=!!dataUriRegexResult[2];var data=dataUriRegexResult[3];data=decodeURIComponent(data);if(isBase64)data=atob(data);try{var response;var responseType=(this.responseType||'').toLowerCase();switch(responseType){case'arraybuffer':case'blob':var view=new Uint8Array(data.length);for(var _i267=0;_i267<data.length;_i267++){view[_i267]=data.charCodeAt(_i267);}if(responseType==='blob'){response=new Blob([view.buffer],{type:mimeType});}else {response=view.buffer;}break;case'document':var parser=new DOMParser();response=parser.parseFromString(data,mimeType);break;case'json':response=JSON.parse(data);break;default:// 'text' or other
  1987. response=data;break;}// Wait for next browser tick like standard XMLHttpRequest event dispatching does
  1988. setTimeout(function(){if(onLoad)onLoad(response);scope.manager.itemEnd(url);},0);}catch(error){// Wait for next browser tick like standard XMLHttpRequest event dispatching does
  1989. setTimeout(function(){if(onError)onError(error);scope.manager.itemError(url);scope.manager.itemEnd(url);},0);}}else {// Initialise array for duplicate requests
  1990. loading[url]=[];loading[url].push({onLoad:onLoad,onProgress:onProgress,onError:onError});request=new XMLHttpRequest();request.open('GET',url,true);request.addEventListener('load',function(event){var response=this.response;var callbacks=loading[url];delete loading[url];if(this.status===200||this.status===0){// Some browsers return HTTP Status 0 when using non-http protocol
  1991. // e.g. 'file://' or 'data://'. Handle as success.
  1992. if(this.status===0)console.warn('THREE.FileLoader: HTTP Status 0 received.');// Add to cache only on HTTP success, so that we do not cache
  1993. // error response bodies as proper responses to requests.
  1994. Cache.add(url,response);for(var _i268=0,il=callbacks.length;_i268<il;_i268++){var callback=callbacks[_i268];if(callback.onLoad)callback.onLoad(response);}scope.manager.itemEnd(url);}else {for(var _i269=0,_il31=callbacks.length;_i269<_il31;_i269++){var _callback=callbacks[_i269];if(_callback.onError)_callback.onError(event);}scope.manager.itemError(url);scope.manager.itemEnd(url);}},false);request.addEventListener('progress',function(event){var callbacks=loading[url];for(var _i270=0,il=callbacks.length;_i270<il;_i270++){var callback=callbacks[_i270];if(callback.onProgress)callback.onProgress(event);}},false);request.addEventListener('error',function(event){var callbacks=loading[url];delete loading[url];for(var _i271=0,il=callbacks.length;_i271<il;_i271++){var callback=callbacks[_i271];if(callback.onError)callback.onError(event);}scope.manager.itemError(url);scope.manager.itemEnd(url);},false);request.addEventListener('abort',function(event){var callbacks=loading[url];delete loading[url];for(var _i272=0,il=callbacks.length;_i272<il;_i272++){var callback=callbacks[_i272];if(callback.onError)callback.onError(event);}scope.manager.itemError(url);scope.manager.itemEnd(url);},false);if(this.responseType!==undefined)request.responseType=this.responseType;if(this.withCredentials!==undefined)request.withCredentials=this.withCredentials;if(request.overrideMimeType)request.overrideMimeType(this.mimeType!==undefined?this.mimeType:'text/plain');for(var header in this.requestHeader){request.setRequestHeader(header,this.requestHeader[header]);}request.send(null);}scope.manager.itemStart(url);return request;},setResponseType:function setResponseType(value){this.responseType=value;return this;},setMimeType:function setMimeType(value){this.mimeType=value;return this;}});function AnimationLoader(manager){Loader.call(this,manager);}AnimationLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:AnimationLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var loader=new FileLoader(scope.manager);loader.setPath(scope.path);loader.setRequestHeader(scope.requestHeader);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(text){try{onLoad(scope.parse(JSON.parse(text)));}catch(e){if(onError){onError(e);}else {console.error(e);}scope.manager.itemError(url);}},onProgress,onError);},parse:function parse(json){var animations=[];for(var _i273=0;_i273<json.length;_i273++){var clip=AnimationClip.parse(json[_i273]);animations.push(clip);}return animations;}});/**
  1995. * Abstract Base class to block based textures loader (dds, pvr, ...)
  1996. *
  1997. * Sub classes have to implement the parse() method which will be used in load().
  1998. */function CompressedTextureLoader(manager){Loader.call(this,manager);}CompressedTextureLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:CompressedTextureLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var images=[];var texture=new CompressedTexture();var loader=new FileLoader(this.manager);loader.setPath(this.path);loader.setResponseType('arraybuffer');loader.setRequestHeader(this.requestHeader);loader.setWithCredentials(scope.withCredentials);var loaded=0;function loadTexture(i){loader.load(url[i],function(buffer){var texDatas=scope.parse(buffer,true);images[i]={width:texDatas.width,height:texDatas.height,format:texDatas.format,mipmaps:texDatas.mipmaps};loaded+=1;if(loaded===6){if(texDatas.mipmapCount===1)texture.minFilter=LinearFilter;texture.image=images;texture.format=texDatas.format;texture.needsUpdate=true;if(onLoad)onLoad(texture);}},onProgress,onError);}if(Array.isArray(url)){for(var _i274=0,il=url.length;_i274<il;++_i274){loadTexture(_i274);}}else {// compressed cubemap texture stored in a single DDS file
  1999. loader.load(url,function(buffer){var texDatas=scope.parse(buffer,true);if(texDatas.isCubemap){var faces=texDatas.mipmaps.length/texDatas.mipmapCount;for(var f=0;f<faces;f++){images[f]={mipmaps:[]};for(var _i275=0;_i275<texDatas.mipmapCount;_i275++){images[f].mipmaps.push(texDatas.mipmaps[f*texDatas.mipmapCount+_i275]);images[f].format=texDatas.format;images[f].width=texDatas.width;images[f].height=texDatas.height;}}texture.image=images;}else {texture.image.width=texDatas.width;texture.image.height=texDatas.height;texture.mipmaps=texDatas.mipmaps;}if(texDatas.mipmapCount===1){texture.minFilter=LinearFilter;}texture.format=texDatas.format;texture.needsUpdate=true;if(onLoad)onLoad(texture);},onProgress,onError);}return texture;}});function ImageLoader(manager){Loader.call(this,manager);}ImageLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:ImageLoader,load:function load(url,onLoad,onProgress,onError){if(this.path!==undefined)url=this.path+url;url=this.manager.resolveURL(url);var scope=this;var cached=Cache.get(url);if(cached!==undefined){scope.manager.itemStart(url);setTimeout(function(){if(onLoad)onLoad(cached);scope.manager.itemEnd(url);},0);return cached;}var image=document.createElementNS('http://www.w3.org/1999/xhtml','img');function onImageLoad(){image.removeEventListener('load',onImageLoad,false);image.removeEventListener('error',onImageError,false);Cache.add(url,this);if(onLoad)onLoad(this);scope.manager.itemEnd(url);}function onImageError(event){image.removeEventListener('load',onImageLoad,false);image.removeEventListener('error',onImageError,false);if(onError)onError(event);scope.manager.itemError(url);scope.manager.itemEnd(url);}image.addEventListener('load',onImageLoad,false);image.addEventListener('error',onImageError,false);if(url.substr(0,5)!=='data:'){if(this.crossOrigin!==undefined)image.crossOrigin=this.crossOrigin;}scope.manager.itemStart(url);image.src=url;return image;}});function CubeTextureLoader(manager){Loader.call(this,manager);}CubeTextureLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:CubeTextureLoader,load:function load(urls,onLoad,onProgress,onError){var texture=new CubeTexture();var loader=new ImageLoader(this.manager);loader.setCrossOrigin(this.crossOrigin);loader.setPath(this.path);var loaded=0;function loadTexture(i){loader.load(urls[i],function(image){texture.images[i]=image;loaded++;if(loaded===6){texture.needsUpdate=true;if(onLoad)onLoad(texture);}},undefined,onError);}for(var _i276=0;_i276<urls.length;++_i276){loadTexture(_i276);}return texture;}});/**
  2000. * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
  2001. *
  2002. * Sub classes have to implement the parse() method which will be used in load().
  2003. */function DataTextureLoader(manager){Loader.call(this,manager);}DataTextureLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:DataTextureLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var texture=new DataTexture();var loader=new FileLoader(this.manager);loader.setResponseType('arraybuffer');loader.setRequestHeader(this.requestHeader);loader.setPath(this.path);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(buffer){var texData=scope.parse(buffer);if(!texData)return;if(texData.image!==undefined){texture.image=texData.image;}else if(texData.data!==undefined){texture.image.width=texData.width;texture.image.height=texData.height;texture.image.data=texData.data;}texture.wrapS=texData.wrapS!==undefined?texData.wrapS:ClampToEdgeWrapping;texture.wrapT=texData.wrapT!==undefined?texData.wrapT:ClampToEdgeWrapping;texture.magFilter=texData.magFilter!==undefined?texData.magFilter:LinearFilter;texture.minFilter=texData.minFilter!==undefined?texData.minFilter:LinearFilter;texture.anisotropy=texData.anisotropy!==undefined?texData.anisotropy:1;if(texData.format!==undefined){texture.format=texData.format;}if(texData.type!==undefined){texture.type=texData.type;}if(texData.mipmaps!==undefined){texture.mipmaps=texData.mipmaps;texture.minFilter=LinearMipmapLinearFilter;// presumably...
  2004. }if(texData.mipmapCount===1){texture.minFilter=LinearFilter;}texture.needsUpdate=true;if(onLoad)onLoad(texture,texData);},onProgress,onError);return texture;}});function TextureLoader(manager){Loader.call(this,manager);}TextureLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:TextureLoader,load:function load(url,onLoad,onProgress,onError){var texture=new Texture();var loader=new ImageLoader(this.manager);loader.setCrossOrigin(this.crossOrigin);loader.setPath(this.path);loader.load(url,function(image){texture.image=image;// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
  2005. var isJPEG=url.search(/\.jpe?g($|\?)/i)>0||url.search(/^data\:image\/jpeg/)===0;texture.format=isJPEG?RGBFormat:RGBAFormat;texture.needsUpdate=true;if(onLoad!==undefined){onLoad(texture);}},onProgress,onError);return texture;}});/**
  2006. * Extensible curve object.
  2007. *
  2008. * Some common of curve methods:
  2009. * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
  2010. * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
  2011. * .getPoints(), .getSpacedPoints()
  2012. * .getLength()
  2013. * .updateArcLengths()
  2014. *
  2015. * This following curves inherit from THREE.Curve:
  2016. *
  2017. * -- 2D curves --
  2018. * THREE.ArcCurve
  2019. * THREE.CubicBezierCurve
  2020. * THREE.EllipseCurve
  2021. * THREE.LineCurve
  2022. * THREE.QuadraticBezierCurve
  2023. * THREE.SplineCurve
  2024. *
  2025. * -- 3D curves --
  2026. * THREE.CatmullRomCurve3
  2027. * THREE.CubicBezierCurve3
  2028. * THREE.LineCurve3
  2029. * THREE.QuadraticBezierCurve3
  2030. *
  2031. * A series of curves can be represented as a THREE.CurvePath.
  2032. *
  2033. **/function Curve(){this.type='Curve';this.arcLengthDivisions=200;}Object.assign(Curve.prototype,{// Virtual base class method to overwrite and implement in subclasses
  2034. // - t [0 .. 1]
  2035. getPoint:function getPoint(/* t, optionalTarget */){console.warn('THREE.Curve: .getPoint() not implemented.');return null;},// Get point at relative position in curve according to arc length
  2036. // - u [0 .. 1]
  2037. getPointAt:function getPointAt(u,optionalTarget){var t=this.getUtoTmapping(u);return this.getPoint(t,optionalTarget);},// Get sequence of points using getPoint( t )
  2038. getPoints:function getPoints(){var divisions=arguments.length>0&&arguments[0]!==undefined?arguments[0]:5;var points=[];for(var d=0;d<=divisions;d++){points.push(this.getPoint(d/divisions));}return points;},// Get sequence of points using getPointAt( u )
  2039. getSpacedPoints:function getSpacedPoints(){var divisions=arguments.length>0&&arguments[0]!==undefined?arguments[0]:5;var points=[];for(var d=0;d<=divisions;d++){points.push(this.getPointAt(d/divisions));}return points;},// Get total curve arc length
  2040. getLength:function getLength(){var lengths=this.getLengths();return lengths[lengths.length-1];},// Get list of cumulative segment lengths
  2041. getLengths:function getLengths(divisions){if(divisions===undefined)divisions=this.arcLengthDivisions;if(this.cacheArcLengths&&this.cacheArcLengths.length===divisions+1&&!this.needsUpdate){return this.cacheArcLengths;}this.needsUpdate=false;var cache=[];var current,last=this.getPoint(0);var sum=0;cache.push(0);for(var p=1;p<=divisions;p++){current=this.getPoint(p/divisions);sum+=current.distanceTo(last);cache.push(sum);last=current;}this.cacheArcLengths=cache;return cache;// { sums: cache, sum: sum }; Sum is in the last element.
  2042. },updateArcLengths:function updateArcLengths(){this.needsUpdate=true;this.getLengths();},// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
  2043. getUtoTmapping:function getUtoTmapping(u,distance){var arcLengths=this.getLengths();var i=0;var il=arcLengths.length;var targetArcLength;// The targeted u distance value to get
  2044. if(distance){targetArcLength=distance;}else {targetArcLength=u*arcLengths[il-1];}// binary search for the index with largest value smaller than target u distance
  2045. var low=0,high=il-1,comparison;while(low<=high){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
  2046. comparison=arcLengths[i]-targetArcLength;if(comparison<0){low=i+1;}else if(comparison>0){high=i-1;}else {high=i;break;// DONE
  2047. }}i=high;if(arcLengths[i]===targetArcLength){return i/(il-1);}// we could get finer grain at lengths, or use simple interpolation between two points
  2048. var lengthBefore=arcLengths[i];var lengthAfter=arcLengths[i+1];var segmentLength=lengthAfter-lengthBefore;// determine where we are between the 'before' and 'after' points
  2049. var segmentFraction=(targetArcLength-lengthBefore)/segmentLength;// add that fractional amount to t
  2050. var t=(i+segmentFraction)/(il-1);return t;},// Returns a unit vector tangent at t
  2051. // In case any sub curve does not implement its tangent derivation,
  2052. // 2 points a small delta apart will be used to find its gradient
  2053. // which seems to give a reasonable approximation
  2054. getTangent:function getTangent(t,optionalTarget){var delta=0.0001;var t1=t-delta;var t2=t+delta;// Capping in case of danger
  2055. if(t1<0)t1=0;if(t2>1)t2=1;var pt1=this.getPoint(t1);var pt2=this.getPoint(t2);var tangent=optionalTarget||(pt1.isVector2?new Vector2():new Vector3());tangent.copy(pt2).sub(pt1).normalize();return tangent;},getTangentAt:function getTangentAt(u,optionalTarget){var t=this.getUtoTmapping(u);return this.getTangent(t,optionalTarget);},computeFrenetFrames:function computeFrenetFrames(segments,closed,getCtrlPointsDirect){//xzw add getCtrlPointsDirect
  2056. // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
  2057. var normal=new Vector3();var tangents=[];var normals=[];var binormals=[];var vec=new Vector3();var mat=new Matrix4();// compute the tangent vectors for each segment on the curve
  2058. if(getCtrlPointsDirect){//xzw 直接返回控制点所在的
  2059. this.getCurveLengths();segments=this.cacheLengths.length;var lengthSum=this.cacheLengths[this.cacheLengths.length-1];//xzw add 计算控制点处所在处的比例
  2060. for(var _i277=0;_i277<=segments;_i277++){var u=_i277==0?0:this.cacheLengths[_i277-1]/lengthSum;tangents[_i277]=this.getTangentAt(u,new Vector3());tangents[_i277].normalize();}}else {for(var _i278=0;_i278<=segments;_i278++){//这是平均分线长度
  2061. var _u=_i278/segments;tangents[_i278]=this.getTangentAt(_u,new Vector3());tangents[_i278].normalize();}}// select an initial normal vector perpendicular to the first tangent vector,
  2062. // and in the direction of the minimum tangent xyz component
  2063. normals[0]=new Vector3();binormals[0]=new Vector3();var min=Number.MAX_VALUE;var tx=Math.abs(tangents[0].x);var ty=Math.abs(tangents[0].y);var tz=Math.abs(tangents[0].z);if(tx<=min){min=tx;normal.set(1,0,0);}if(ty<=min){min=ty;normal.set(0,1,0);}if(tz<=min){normal.set(0,0,1);}vec.crossVectors(tangents[0],normal).normalize();normals[0].crossVectors(tangents[0],vec);binormals[0].crossVectors(tangents[0],normals[0]);// compute the slowly-varying normal and binormal vectors for each segment on the curve
  2064. for(var _i279=1;_i279<=segments;_i279++){normals[_i279]=normals[_i279-1].clone();binormals[_i279]=binormals[_i279-1].clone();vec.crossVectors(tangents[_i279-1],tangents[_i279]);if(vec.length()>Number.EPSILON){vec.normalize();var theta=Math.acos(MathUtils.clamp(tangents[_i279-1].dot(tangents[_i279]),-1,1));// clamp for floating pt errors
  2065. normals[_i279].applyMatrix4(mat.makeRotationAxis(vec,theta));}binormals[_i279].crossVectors(tangents[_i279],normals[_i279]);}// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
  2066. if(closed===true){var _theta=Math.acos(MathUtils.clamp(normals[0].dot(normals[segments]),-1,1));_theta/=segments;if(tangents[0].dot(vec.crossVectors(normals[0],normals[segments]))>0){_theta=-_theta;}for(var _i280=1;_i280<=segments;_i280++){// twist a little...
  2067. normals[_i280].applyMatrix4(mat.makeRotationAxis(tangents[_i280],_theta*_i280));binormals[_i280].crossVectors(tangents[_i280],normals[_i280]);}}return {tangents:tangents,normals:normals,binormals:binormals};},clone:function clone(){return new this.constructor().copy(this);},copy:function copy(source){this.arcLengthDivisions=source.arcLengthDivisions;return this;},toJSON:function toJSON(){var data={metadata:{version:4.5,type:'Curve',generator:'Curve.toJSON'}};data.arcLengthDivisions=this.arcLengthDivisions;data.type=this.type;return data;},fromJSON:function fromJSON(json){this.arcLengthDivisions=json.arcLengthDivisions;return this;}});function EllipseCurve(aX,aY,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise,aRotation){Curve.call(this);this.type='EllipseCurve';this.aX=aX||0;this.aY=aY||0;this.xRadius=xRadius||1;this.yRadius=yRadius||1;this.aStartAngle=aStartAngle||0;this.aEndAngle=aEndAngle||2*Math.PI;this.aClockwise=aClockwise||false;this.aRotation=aRotation||0;}EllipseCurve.prototype=Object.create(Curve.prototype);EllipseCurve.prototype.constructor=EllipseCurve;EllipseCurve.prototype.isEllipseCurve=true;EllipseCurve.prototype.getPoint=function(t,optionalTarget){var point=optionalTarget||new Vector2();var twoPi=Math.PI*2;var deltaAngle=this.aEndAngle-this.aStartAngle;var samePoints=Math.abs(deltaAngle)<Number.EPSILON;// ensures that deltaAngle is 0 .. 2 PI
  2068. while(deltaAngle<0)deltaAngle+=twoPi;while(deltaAngle>twoPi)deltaAngle-=twoPi;if(deltaAngle<Number.EPSILON){if(samePoints){deltaAngle=0;}else {deltaAngle=twoPi;}}if(this.aClockwise===true&&!samePoints){if(deltaAngle===twoPi){deltaAngle=-twoPi;}else {deltaAngle=deltaAngle-twoPi;}}var angle=this.aStartAngle+t*deltaAngle;var x=this.aX+this.xRadius*Math.cos(angle);var y=this.aY+this.yRadius*Math.sin(angle);if(this.aRotation!==0){var cos=Math.cos(this.aRotation);var sin=Math.sin(this.aRotation);var tx=x-this.aX;var ty=y-this.aY;// Rotate the point about the center of the ellipse.
  2069. x=tx*cos-ty*sin+this.aX;y=tx*sin+ty*cos+this.aY;}return point.set(x,y);};EllipseCurve.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.aX=source.aX;this.aY=source.aY;this.xRadius=source.xRadius;this.yRadius=source.yRadius;this.aStartAngle=source.aStartAngle;this.aEndAngle=source.aEndAngle;this.aClockwise=source.aClockwise;this.aRotation=source.aRotation;return this;};EllipseCurve.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.aX=this.aX;data.aY=this.aY;data.xRadius=this.xRadius;data.yRadius=this.yRadius;data.aStartAngle=this.aStartAngle;data.aEndAngle=this.aEndAngle;data.aClockwise=this.aClockwise;data.aRotation=this.aRotation;return data;};EllipseCurve.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.aX=json.aX;this.aY=json.aY;this.xRadius=json.xRadius;this.yRadius=json.yRadius;this.aStartAngle=json.aStartAngle;this.aEndAngle=json.aEndAngle;this.aClockwise=json.aClockwise;this.aRotation=json.aRotation;return this;};function ArcCurve(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){EllipseCurve.call(this,aX,aY,aRadius,aRadius,aStartAngle,aEndAngle,aClockwise);this.type='ArcCurve';}ArcCurve.prototype=Object.create(EllipseCurve.prototype);ArcCurve.prototype.constructor=ArcCurve;ArcCurve.prototype.isArcCurve=true;/**
  2070. * Centripetal CatmullRom Curve - which is useful for avoiding
  2071. * cusps and self-intersections in non-uniform catmull rom curves.
  2072. * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
  2073. *
  2074. * curve.type accepts centripetal(default), chordal and catmullrom
  2075. * curve.tension is used for catmullrom which defaults to 0.5
  2076. */ /*
  2077. Based on an optimized c++ solution in
  2078. - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
  2079. - http://ideone.com/NoEbVM
  2080. This CubicPoly class could be used for reusing some variables and calculations,
  2081. but for three.js curve use, it could be possible inlined and flatten into a single function call
  2082. which can be placed in CurveUtils.
  2083. */function CubicPoly(){var c0=0,c1=0,c2=0,c3=0;/*
  2084. * Compute coefficients for a cubic polynomial
  2085. * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
  2086. * such that
  2087. * p(0) = x0, p(1) = x1
  2088. * and
  2089. * p'(0) = t0, p'(1) = t1.
  2090. */function init(x0,x1,t0,t1){c0=x0;c1=t0;c2=-3*x0+3*x1-2*t0-t1;c3=2*x0-2*x1+t0+t1;}return {initCatmullRom:function initCatmullRom(x0,x1,x2,x3,tension){init(x1,x2,tension*(x2-x0),tension*(x3-x1));},initNonuniformCatmullRom:function initNonuniformCatmullRom(x0,x1,x2,x3,dt0,dt1,dt2){// compute tangents when parameterized in [t1,t2]
  2091. var t1=(x1-x0)/dt0-(x2-x0)/(dt0+dt1)+(x2-x1)/dt1;var t2=(x2-x1)/dt1-(x3-x1)/(dt1+dt2)+(x3-x2)/dt2;// rescale tangents for parametrization in [0,1]
  2092. t1*=dt1;t2*=dt1;init(x1,x2,t1,t2);},calc:function calc(t){var t2=t*t;var t3=t2*t;return c0+c1*t+c2*t2+c3*t3;}};}//
  2093. var tmp=new Vector3();var px=new CubicPoly(),py=new CubicPoly(),pz=new CubicPoly();function CatmullRomCurve3(){var points=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var closed=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var curveType=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'centripetal';var tension=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0.5;Curve.call(this);this.type='CatmullRomCurve3';this.points=points;this.closed=closed;this.curveType=curveType;this.tension=tension;}CatmullRomCurve3.prototype=Object.create(Curve.prototype);CatmullRomCurve3.prototype.constructor=CatmullRomCurve3;CatmullRomCurve3.prototype.isCatmullRomCurve3=true;CatmullRomCurve3.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var point=optionalTarget;var points=this.points;var l=points.length;var p=(l-(this.closed?0:1))*t;var intPoint=Math.floor(p);var weight=p-intPoint;if(this.closed){intPoint+=intPoint>0?0:(Math.floor(Math.abs(intPoint)/l)+1)*l;}else if(weight===0&&intPoint===l-1){intPoint=l-2;weight=1;}var p0,p3;// 4 points (p1 & p2 defined below)
  2094. if(this.closed||intPoint>0){p0=points[(intPoint-1)%l];}else {// extrapolate first point
  2095. tmp.subVectors(points[0],points[1]).add(points[0]);p0=tmp;}var p1=points[intPoint%l];var p2=points[(intPoint+1)%l];if(this.closed||intPoint+2<l){p3=points[(intPoint+2)%l];}else {// extrapolate last point
  2096. tmp.subVectors(points[l-1],points[l-2]).add(points[l-1]);p3=tmp;}if(this.curveType==='centripetal'||this.curveType==='chordal'){// init Centripetal / Chordal Catmull-Rom
  2097. var pow=this.curveType==='chordal'?0.5:0.25;var dt0=Math.pow(p0.distanceToSquared(p1),pow);var dt1=Math.pow(p1.distanceToSquared(p2),pow);var dt2=Math.pow(p2.distanceToSquared(p3),pow);// safety check for repeated points
  2098. if(dt1<1e-4)dt1=1.0;if(dt0<1e-4)dt0=dt1;if(dt2<1e-4)dt2=dt1;px.initNonuniformCatmullRom(p0.x,p1.x,p2.x,p3.x,dt0,dt1,dt2);py.initNonuniformCatmullRom(p0.y,p1.y,p2.y,p3.y,dt0,dt1,dt2);pz.initNonuniformCatmullRom(p0.z,p1.z,p2.z,p3.z,dt0,dt1,dt2);}else if(this.curveType==='catmullrom'){px.initCatmullRom(p0.x,p1.x,p2.x,p3.x,this.tension);py.initCatmullRom(p0.y,p1.y,p2.y,p3.y,this.tension);pz.initCatmullRom(p0.z,p1.z,p2.z,p3.z,this.tension);}point.set(px.calc(weight),py.calc(weight),pz.calc(weight));return point;};CatmullRomCurve3.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.points=[];for(var _i281=0,l=source.points.length;_i281<l;_i281++){var point=source.points[_i281];this.points.push(point.clone());}this.closed=source.closed;this.curveType=source.curveType;this.tension=source.tension;return this;};CatmullRomCurve3.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.points=[];for(var _i282=0,l=this.points.length;_i282<l;_i282++){var point=this.points[_i282];data.points.push(point.toArray());}data.closed=this.closed;data.curveType=this.curveType;data.tension=this.tension;return data;};CatmullRomCurve3.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.points=[];for(var _i283=0,l=json.points.length;_i283<l;_i283++){var point=json.points[_i283];this.points.push(new Vector3().fromArray(point));}this.closed=json.closed;this.curveType=json.curveType;this.tension=json.tension;return this;};/**
  2099. * Bezier Curves formulas obtained from
  2100. * http://en.wikipedia.org/wiki/Bézier_curve
  2101. */function CatmullRom(t,p0,p1,p2,p3){var v0=(p2-p0)*0.5;var v1=(p3-p1)*0.5;var t2=t*t;var t3=t*t2;return (2*p1-2*p2+v0+v1)*t3+(-3*p1+3*p2-2*v0-v1)*t2+v0*t+p1;}//
  2102. function QuadraticBezierP0(t,p){var k=1-t;return k*k*p;}function QuadraticBezierP1(t,p){return 2*(1-t)*t*p;}function QuadraticBezierP2(t,p){return t*t*p;}function QuadraticBezier(t,p0,p1,p2){return QuadraticBezierP0(t,p0)+QuadraticBezierP1(t,p1)+QuadraticBezierP2(t,p2);}//
  2103. function CubicBezierP0(t,p){var k=1-t;return k*k*k*p;}function CubicBezierP1(t,p){var k=1-t;return 3*k*k*t*p;}function CubicBezierP2(t,p){return 3*(1-t)*t*t*p;}function CubicBezierP3(t,p){return t*t*t*p;}function CubicBezier(t,p0,p1,p2,p3){return CubicBezierP0(t,p0)+CubicBezierP1(t,p1)+CubicBezierP2(t,p2)+CubicBezierP3(t,p3);}function CubicBezierCurve(){var v0=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector2();var v1=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var v2=arguments.length>2&&arguments[2]!==undefined?arguments[2]:new Vector2();var v3=arguments.length>3&&arguments[3]!==undefined?arguments[3]:new Vector2();Curve.call(this);this.type='CubicBezierCurve';this.v0=v0;this.v1=v1;this.v2=v2;this.v3=v3;}CubicBezierCurve.prototype=Object.create(Curve.prototype);CubicBezierCurve.prototype.constructor=CubicBezierCurve;CubicBezierCurve.prototype.isCubicBezierCurve=true;CubicBezierCurve.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var point=optionalTarget;var v0=this.v0,v1=this.v1,v2=this.v2,v3=this.v3;point.set(CubicBezier(t,v0.x,v1.x,v2.x,v3.x),CubicBezier(t,v0.y,v1.y,v2.y,v3.y));return point;};CubicBezierCurve.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v0.copy(source.v0);this.v1.copy(source.v1);this.v2.copy(source.v2);this.v3.copy(source.v3);return this;};CubicBezierCurve.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v0=this.v0.toArray();data.v1=this.v1.toArray();data.v2=this.v2.toArray();data.v3=this.v3.toArray();return data;};CubicBezierCurve.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v0.fromArray(json.v0);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);this.v3.fromArray(json.v3);return this;};function CubicBezierCurve3(){var v0=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector3();var v1=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var v2=arguments.length>2&&arguments[2]!==undefined?arguments[2]:new Vector3();var v3=arguments.length>3&&arguments[3]!==undefined?arguments[3]:new Vector3();Curve.call(this);this.type='CubicBezierCurve3';this.v0=v0;this.v1=v1;this.v2=v2;this.v3=v3;}CubicBezierCurve3.prototype=Object.create(Curve.prototype);CubicBezierCurve3.prototype.constructor=CubicBezierCurve3;CubicBezierCurve3.prototype.isCubicBezierCurve3=true;CubicBezierCurve3.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var point=optionalTarget;var v0=this.v0,v1=this.v1,v2=this.v2,v3=this.v3;point.set(CubicBezier(t,v0.x,v1.x,v2.x,v3.x),CubicBezier(t,v0.y,v1.y,v2.y,v3.y),CubicBezier(t,v0.z,v1.z,v2.z,v3.z));return point;};CubicBezierCurve3.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v0.copy(source.v0);this.v1.copy(source.v1);this.v2.copy(source.v2);this.v3.copy(source.v3);return this;};CubicBezierCurve3.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v0=this.v0.toArray();data.v1=this.v1.toArray();data.v2=this.v2.toArray();data.v3=this.v3.toArray();return data;};CubicBezierCurve3.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v0.fromArray(json.v0);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);this.v3.fromArray(json.v3);return this;};function LineCurve(){var v1=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector2();var v2=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();Curve.call(this);this.type='LineCurve';this.v1=v1;this.v2=v2;}LineCurve.prototype=Object.create(Curve.prototype);LineCurve.prototype.constructor=LineCurve;LineCurve.prototype.isLineCurve=true;LineCurve.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var point=optionalTarget;if(t===1){point.copy(this.v2);}else {point.copy(this.v2).sub(this.v1);point.multiplyScalar(t).add(this.v1);}return point;};// Line curve is linear, so we can overwrite default getPointAt
  2104. LineCurve.prototype.getPointAt=function(u,optionalTarget){return this.getPoint(u,optionalTarget);};LineCurve.prototype.getTangent=function(t,optionalTarget){var tangent=optionalTarget||new Vector2();tangent.copy(this.v2).sub(this.v1).normalize();return tangent;};LineCurve.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v1.copy(source.v1);this.v2.copy(source.v2);return this;};LineCurve.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v1=this.v1.toArray();data.v2=this.v2.toArray();return data;};LineCurve.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);return this;};function LineCurve3(){var v1=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector3();var v2=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();Curve.call(this);this.type='LineCurve3';this.v1=v1;this.v2=v2;}LineCurve3.prototype=Object.create(Curve.prototype);LineCurve3.prototype.constructor=LineCurve3;LineCurve3.prototype.isLineCurve3=true;LineCurve3.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var point=optionalTarget;if(t===1){point.copy(this.v2);}else {point.copy(this.v2).sub(this.v1);point.multiplyScalar(t).add(this.v1);}return point;};// Line curve is linear, so we can overwrite default getPointAt
  2105. LineCurve3.prototype.getPointAt=function(u,optionalTarget){return this.getPoint(u,optionalTarget);};LineCurve3.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v1.copy(source.v1);this.v2.copy(source.v2);return this;};LineCurve3.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v1=this.v1.toArray();data.v2=this.v2.toArray();return data;};LineCurve3.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);return this;};function QuadraticBezierCurve(){var v0=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector2();var v1=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var v2=arguments.length>2&&arguments[2]!==undefined?arguments[2]:new Vector2();Curve.call(this);this.type='QuadraticBezierCurve';this.v0=v0;this.v1=v1;this.v2=v2;}QuadraticBezierCurve.prototype=Object.create(Curve.prototype);QuadraticBezierCurve.prototype.constructor=QuadraticBezierCurve;QuadraticBezierCurve.prototype.isQuadraticBezierCurve=true;QuadraticBezierCurve.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var point=optionalTarget;var v0=this.v0,v1=this.v1,v2=this.v2;point.set(QuadraticBezier(t,v0.x,v1.x,v2.x),QuadraticBezier(t,v0.y,v1.y,v2.y));return point;};QuadraticBezierCurve.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v0.copy(source.v0);this.v1.copy(source.v1);this.v2.copy(source.v2);return this;};QuadraticBezierCurve.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v0=this.v0.toArray();data.v1=this.v1.toArray();data.v2=this.v2.toArray();return data;};QuadraticBezierCurve.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v0.fromArray(json.v0);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);return this;};function QuadraticBezierCurve3(){var v0=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Vector3();var v1=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var v2=arguments.length>2&&arguments[2]!==undefined?arguments[2]:new Vector3();Curve.call(this);this.type='QuadraticBezierCurve3';this.v0=v0;this.v1=v1;this.v2=v2;}QuadraticBezierCurve3.prototype=Object.create(Curve.prototype);QuadraticBezierCurve3.prototype.constructor=QuadraticBezierCurve3;QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3=true;QuadraticBezierCurve3.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector3();var point=optionalTarget;var v0=this.v0,v1=this.v1,v2=this.v2;point.set(QuadraticBezier(t,v0.x,v1.x,v2.x),QuadraticBezier(t,v0.y,v1.y,v2.y),QuadraticBezier(t,v0.z,v1.z,v2.z));return point;};QuadraticBezierCurve3.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.v0.copy(source.v0);this.v1.copy(source.v1);this.v2.copy(source.v2);return this;};QuadraticBezierCurve3.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.v0=this.v0.toArray();data.v1=this.v1.toArray();data.v2=this.v2.toArray();return data;};QuadraticBezierCurve3.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.v0.fromArray(json.v0);this.v1.fromArray(json.v1);this.v2.fromArray(json.v2);return this;};function SplineCurve(){var points=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];Curve.call(this);this.type='SplineCurve';this.points=points;}SplineCurve.prototype=Object.create(Curve.prototype);SplineCurve.prototype.constructor=SplineCurve;SplineCurve.prototype.isSplineCurve=true;SplineCurve.prototype.getPoint=function(t){var optionalTarget=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Vector2();var point=optionalTarget;var points=this.points;var p=(points.length-1)*t;var intPoint=Math.floor(p);var weight=p-intPoint;var p0=points[intPoint===0?intPoint:intPoint-1];var p1=points[intPoint];var p2=points[intPoint>points.length-2?points.length-1:intPoint+1];var p3=points[intPoint>points.length-3?points.length-1:intPoint+2];point.set(CatmullRom(weight,p0.x,p1.x,p2.x,p3.x),CatmullRom(weight,p0.y,p1.y,p2.y,p3.y));return point;};SplineCurve.prototype.copy=function(source){Curve.prototype.copy.call(this,source);this.points=[];for(var _i284=0,l=source.points.length;_i284<l;_i284++){var point=source.points[_i284];this.points.push(point.clone());}return this;};SplineCurve.prototype.toJSON=function(){var data=Curve.prototype.toJSON.call(this);data.points=[];for(var _i285=0,l=this.points.length;_i285<l;_i285++){var point=this.points[_i285];data.points.push(point.toArray());}return data;};SplineCurve.prototype.fromJSON=function(json){Curve.prototype.fromJSON.call(this,json);this.points=[];for(var _i286=0,l=json.points.length;_i286<l;_i286++){var point=json.points[_i286];this.points.push(new Vector2().fromArray(point));}return this;};var Curves=/*#__PURE__*/Object.freeze({__proto__:null,ArcCurve:ArcCurve,CatmullRomCurve3:CatmullRomCurve3,CubicBezierCurve:CubicBezierCurve,CubicBezierCurve3:CubicBezierCurve3,EllipseCurve:EllipseCurve,LineCurve:LineCurve,LineCurve3:LineCurve3,QuadraticBezierCurve:QuadraticBezierCurve,QuadraticBezierCurve3:QuadraticBezierCurve3,SplineCurve:SplineCurve});/**************************************************************
  2106. * Curved Path - a curve path is simply a array of connected
  2107. * curves, but retains the api of a curve
  2108. **************************************************************/function CurvePath(){Curve.call(this);this.type='CurvePath';this.curves=[];this.autoClose=false;// Automatically closes the path
  2109. }CurvePath.prototype=Object.assign(Object.create(Curve.prototype),{constructor:CurvePath,add:function add(curve){this.curves.push(curve);},closePath:function closePath(){// Add a line curve if start and end of lines are not connected
  2110. var startPoint=this.curves[0].getPoint(0);var endPoint=this.curves[this.curves.length-1].getPoint(1);if(!startPoint.equals(endPoint)){this.curves.push(new LineCurve(endPoint,startPoint));}},// To get accurate point with reference to
  2111. // entire path distance at time t,
  2112. // following has to be done:
  2113. // 1. Length of each sub path have to be known
  2114. // 2. Locate and identify type of curve
  2115. // 3. Get t for the curve
  2116. // 4. Return curve.getPointAt(t')
  2117. getPoint:function getPoint(t){var d=t*this.getLength();var curveLengths=this.getCurveLengths();var i=0;// To think about boundaries points.
  2118. while(i<curveLengths.length){if(curveLengths[i]>=d){var diff=curveLengths[i]-d;var curve=this.curves[i];var segmentLength=curve.getLength();var u=segmentLength===0?0:1-diff/segmentLength;return curve.getPointAt(u);}i++;}return null;// loop where sum != 0, sum > d , sum+1 <d
  2119. },// We cannot use the default THREE.Curve getPoint() with getLength() because in
  2120. // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
  2121. // getPoint() depends on getLength
  2122. getLength:function getLength(){var lens=this.getCurveLengths();return lens[lens.length-1];},// cacheLengths must be recalculated.
  2123. updateArcLengths:function updateArcLengths(){this.needsUpdate=true;this.cacheLengths=null;this.getCurveLengths();},// Compute lengths and cache them
  2124. // We cannot overwrite getLengths() because UtoT mapping uses it.
  2125. getCurveLengths:function getCurveLengths(){// We use cache values if curves and cache array are same length
  2126. if(this.cacheLengths&&this.cacheLengths.length===this.curves.length){return this.cacheLengths;}// Get length of sub-curve
  2127. // Push sums into cached array
  2128. var lengths=[];var sums=0;for(var _i287=0,l=this.curves.length;_i287<l;_i287++){sums+=this.curves[_i287].getLength();lengths.push(sums);}this.cacheLengths=lengths;return lengths;},getSpacedPoints:function getSpacedPoints(){var divisions=arguments.length>0&&arguments[0]!==undefined?arguments[0]:40;var points=[];for(var _i288=0;_i288<=divisions;_i288++){points.push(this.getPoint(_i288/divisions));}if(this.autoClose){points.push(points[0]);}return points;},getPoints:function getPoints(){var divisions=arguments.length>0&&arguments[0]!==undefined?arguments[0]:12;var points=[];var last;for(var _i289=0,curves=this.curves;_i289<curves.length;_i289++){var curve=curves[_i289];var resolution=curve&&curve.isEllipseCurve?divisions*2:curve&&(curve.isLineCurve||curve.isLineCurve3)?1:curve&&curve.isSplineCurve?divisions*curve.points.length:divisions;var pts=curve.getPoints(resolution);for(var j=0;j<pts.length;j++){var point=pts[j];if(last&&last.equals(point))continue;// ensures no consecutive points are duplicates
  2129. points.push(point);last=point;}}if(this.autoClose&&points.length>1&&!points[points.length-1].equals(points[0])){points.push(points[0]);}return points;},copy:function copy(source){Curve.prototype.copy.call(this,source);this.curves=[];for(var _i290=0,l=source.curves.length;_i290<l;_i290++){var curve=source.curves[_i290];this.curves.push(curve.clone());}this.autoClose=source.autoClose;return this;},toJSON:function toJSON(){var data=Curve.prototype.toJSON.call(this);data.autoClose=this.autoClose;data.curves=[];for(var _i291=0,l=this.curves.length;_i291<l;_i291++){var curve=this.curves[_i291];data.curves.push(curve.toJSON());}return data;},fromJSON:function fromJSON(json){Curve.prototype.fromJSON.call(this,json);this.autoClose=json.autoClose;this.curves=[];for(var _i292=0,l=json.curves.length;_i292<l;_i292++){var curve=json.curves[_i292];this.curves.push(new Curves[curve.type]().fromJSON(curve));}return this;}});function Path(points){CurvePath.call(this);this.type='Path';this.currentPoint=new Vector2();if(points){this.setFromPoints(points);}}Path.prototype=Object.assign(Object.create(CurvePath.prototype),{constructor:Path,setFromPoints:function setFromPoints(points){this.moveTo(points[0].x,points[0].y);for(var _i293=1,l=points.length;_i293<l;_i293++){this.lineTo(points[_i293].x,points[_i293].y);}return this;},moveTo:function moveTo(x,y){this.currentPoint.set(x,y);// TODO consider referencing vectors instead of copying?
  2130. return this;},lineTo:function lineTo(x,y){var curve=new LineCurve(this.currentPoint.clone(),new Vector2(x,y));this.curves.push(curve);this.currentPoint.set(x,y);return this;},quadraticCurveTo:function quadraticCurveTo(aCPx,aCPy,aX,aY){var curve=new QuadraticBezierCurve(this.currentPoint.clone(),new Vector2(aCPx,aCPy),new Vector2(aX,aY));this.curves.push(curve);this.currentPoint.set(aX,aY);return this;},bezierCurveTo:function bezierCurveTo(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY){var curve=new CubicBezierCurve(this.currentPoint.clone(),new Vector2(aCP1x,aCP1y),new Vector2(aCP2x,aCP2y),new Vector2(aX,aY));this.curves.push(curve);this.currentPoint.set(aX,aY);return this;},splineThru:function splineThru(pts/*Array of Vector*/){var npts=[this.currentPoint.clone()].concat(pts);var curve=new SplineCurve(npts);this.curves.push(curve);this.currentPoint.copy(pts[pts.length-1]);return this;},arc:function arc(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){var x0=this.currentPoint.x;var y0=this.currentPoint.y;this.absarc(aX+x0,aY+y0,aRadius,aStartAngle,aEndAngle,aClockwise);return this;},absarc:function absarc(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){this.absellipse(aX,aY,aRadius,aRadius,aStartAngle,aEndAngle,aClockwise);return this;},ellipse:function ellipse(aX,aY,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise,aRotation){var x0=this.currentPoint.x;var y0=this.currentPoint.y;this.absellipse(aX+x0,aY+y0,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise,aRotation);return this;},absellipse:function absellipse(aX,aY,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise,aRotation){var curve=new EllipseCurve(aX,aY,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise,aRotation);if(this.curves.length>0){// if a previous curve is present, attempt to join
  2131. var firstPoint=curve.getPoint(0);if(!firstPoint.equals(this.currentPoint)){this.lineTo(firstPoint.x,firstPoint.y);}}this.curves.push(curve);var lastPoint=curve.getPoint(1);this.currentPoint.copy(lastPoint);return this;},copy:function copy(source){CurvePath.prototype.copy.call(this,source);this.currentPoint.copy(source.currentPoint);return this;},toJSON:function toJSON(){var data=CurvePath.prototype.toJSON.call(this);data.currentPoint=this.currentPoint.toArray();return data;},fromJSON:function fromJSON(json){CurvePath.prototype.fromJSON.call(this,json);this.currentPoint.fromArray(json.currentPoint);return this;}});function Shape(points){Path.call(this,points);this.uuid=MathUtils.generateUUID();this.type='Shape';this.holes=[];}Shape.prototype=Object.assign(Object.create(Path.prototype),{constructor:Shape,getPointsHoles:function getPointsHoles(divisions){var holesPts=[];for(var _i294=0,l=this.holes.length;_i294<l;_i294++){holesPts[_i294]=this.holes[_i294].getPoints(divisions);}return holesPts;},// get points of shape and holes (keypoints based on segments parameter)
  2132. extractPoints:function extractPoints(divisions){return {shape:this.getPoints(divisions),holes:this.getPointsHoles(divisions)};},copy:function copy(source){Path.prototype.copy.call(this,source);this.holes=[];for(var _i295=0,l=source.holes.length;_i295<l;_i295++){var hole=source.holes[_i295];this.holes.push(hole.clone());}return this;},toJSON:function toJSON(){var data=Path.prototype.toJSON.call(this);data.uuid=this.uuid;data.holes=[];for(var _i296=0,l=this.holes.length;_i296<l;_i296++){var hole=this.holes[_i296];data.holes.push(hole.toJSON());}return data;},fromJSON:function fromJSON(json){Path.prototype.fromJSON.call(this,json);this.uuid=json.uuid;this.holes=[];for(var _i297=0,l=json.holes.length;_i297<l;_i297++){var hole=json.holes[_i297];this.holes.push(new Path().fromJSON(hole));}return this;}});function Light(color){var intensity=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;Object3D.call(this);this.type='Light';this.color=new Color(color);this.intensity=intensity;}Light.prototype=Object.assign(Object.create(Object3D.prototype),{constructor:Light,isLight:true,copy:function copy(source){Object3D.prototype.copy.call(this,source);this.color.copy(source.color);this.intensity=source.intensity;return this;},toJSON:function toJSON(meta){var data=Object3D.prototype.toJSON.call(this,meta);data.object.color=this.color.getHex();data.object.intensity=this.intensity;if(this.groundColor!==undefined)data.object.groundColor=this.groundColor.getHex();if(this.distance!==undefined)data.object.distance=this.distance;if(this.angle!==undefined)data.object.angle=this.angle;if(this.decay!==undefined)data.object.decay=this.decay;if(this.penumbra!==undefined)data.object.penumbra=this.penumbra;if(this.shadow!==undefined)data.object.shadow=this.shadow.toJSON();return data;}});function HemisphereLight(skyColor,groundColor,intensity){Light.call(this,skyColor,intensity);this.type='HemisphereLight';this.position.copy(Object3D.DefaultUp);this.updateMatrix();this.groundColor=new Color(groundColor);}HemisphereLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:HemisphereLight,isHemisphereLight:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.groundColor.copy(source.groundColor);return this;}});function LightShadow(camera){this.camera=camera;this.bias=0;this.normalBias=0;this.radius=1;this.mapSize=new Vector2(512,512);this.map=null;this.mapPass=null;this.matrix=new Matrix4();this.autoUpdate=true;this.needsUpdate=false;this._frustum=new Frustum();this._frameExtents=new Vector2(1,1);this._viewportCount=1;this._viewports=[new Vector4(0,0,1,1)];}Object.assign(LightShadow.prototype,{_projScreenMatrix:new Matrix4(),_lightPositionWorld:new Vector3(),_lookTarget:new Vector3(),getViewportCount:function getViewportCount(){return this._viewportCount;},getFrustum:function getFrustum(){return this._frustum;},updateMatrices:function updateMatrices(light){var shadowCamera=this.camera,shadowMatrix=this.matrix,projScreenMatrix=this._projScreenMatrix,lookTarget=this._lookTarget,lightPositionWorld=this._lightPositionWorld;lightPositionWorld.setFromMatrixPosition(light.matrixWorld);shadowCamera.position.copy(lightPositionWorld);lookTarget.setFromMatrixPosition(light.target.matrixWorld);shadowCamera.lookAt(lookTarget);shadowCamera.updateMatrixWorld();projScreenMatrix.multiplyMatrices(shadowCamera.projectionMatrix,shadowCamera.matrixWorldInverse);this._frustum.setFromProjectionMatrix(projScreenMatrix);shadowMatrix.set(0.5,0.0,0.0,0.5,0.0,0.5,0.0,0.5,0.0,0.0,0.5,0.5,0.0,0.0,0.0,1.0);shadowMatrix.multiply(shadowCamera.projectionMatrix);shadowMatrix.multiply(shadowCamera.matrixWorldInverse);},getViewport:function getViewport(viewportIndex){return this._viewports[viewportIndex];},getFrameExtents:function getFrameExtents(){return this._frameExtents;},copy:function copy(source){this.camera=source.camera.clone();this.bias=source.bias;this.radius=source.radius;this.mapSize.copy(source.mapSize);return this;},clone:function clone(){return new this.constructor().copy(this);},toJSON:function toJSON(){var object={};if(this.bias!==0)object.bias=this.bias;if(this.normalBias!==0)object.normalBias=this.normalBias;if(this.radius!==1)object.radius=this.radius;if(this.mapSize.x!==512||this.mapSize.y!==512)object.mapSize=this.mapSize.toArray();object.camera=this.camera.toJSON(false).object;delete object.camera.matrix;return object;}});function SpotLightShadow(){LightShadow.call(this,new PerspectiveCamera(50,1,0.5,500));this.focus=1;}SpotLightShadow.prototype=Object.assign(Object.create(LightShadow.prototype),{constructor:SpotLightShadow,isSpotLightShadow:true,updateMatrices:function updateMatrices(light){var camera=this.camera;var fov=MathUtils.RAD2DEG*2*light.angle*this.focus;var aspect=this.mapSize.width/this.mapSize.height;var far=light.distance||camera.far;if(fov!==camera.fov||aspect!==camera.aspect||far!==camera.far){camera.fov=fov;camera.aspect=aspect;camera.far=far;camera.updateProjectionMatrix();}LightShadow.prototype.updateMatrices.call(this,light);}});function SpotLight(color,intensity,distance,angle,penumbra,decay){Light.call(this,color,intensity);this.type='SpotLight';this.position.copy(Object3D.DefaultUp);this.updateMatrix();this.target=new Object3D();Object.defineProperty(this,'power',{get:function get(){// intensity = power per solid angle.
  2133. // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  2134. return this.intensity*Math.PI;},set:function set(power){// intensity = power per solid angle.
  2135. // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  2136. this.intensity=power/Math.PI;}});this.distance=distance!==undefined?distance:0;this.angle=angle!==undefined?angle:Math.PI/3;this.penumbra=penumbra!==undefined?penumbra:0;this.decay=decay!==undefined?decay:1;// for physically correct lights, should be 2.
  2137. this.shadow=new SpotLightShadow();}SpotLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:SpotLight,isSpotLight:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.distance=source.distance;this.angle=source.angle;this.penumbra=source.penumbra;this.decay=source.decay;this.target=source.target.clone();this.shadow=source.shadow.clone();return this;}});function PointLightShadow(){LightShadow.call(this,new PerspectiveCamera(90,1,0.5,500));this._frameExtents=new Vector2(4,2);this._viewportCount=6;this._viewports=[// These viewports map a cube-map onto a 2D texture with the
  2138. // following orientation:
  2139. //
  2140. // xzXZ
  2141. // y Y
  2142. //
  2143. // X - Positive x direction
  2144. // x - Negative x direction
  2145. // Y - Positive y direction
  2146. // y - Negative y direction
  2147. // Z - Positive z direction
  2148. // z - Negative z direction
  2149. // positive X
  2150. new Vector4(2,1,1,1),// negative X
  2151. new Vector4(0,1,1,1),// positive Z
  2152. new Vector4(3,1,1,1),// negative Z
  2153. new Vector4(1,1,1,1),// positive Y
  2154. new Vector4(3,0,1,1),// negative Y
  2155. new Vector4(1,0,1,1)];this._cubeDirections=[new Vector3(1,0,0),new Vector3(-1,0,0),new Vector3(0,0,1),new Vector3(0,0,-1),new Vector3(0,1,0),new Vector3(0,-1,0)];this._cubeUps=[new Vector3(0,1,0),new Vector3(0,1,0),new Vector3(0,1,0),new Vector3(0,1,0),new Vector3(0,0,1),new Vector3(0,0,-1)];}PointLightShadow.prototype=Object.assign(Object.create(LightShadow.prototype),{constructor:PointLightShadow,isPointLightShadow:true,updateMatrices:function updateMatrices(light){var viewportIndex=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var camera=this.camera,shadowMatrix=this.matrix,lightPositionWorld=this._lightPositionWorld,lookTarget=this._lookTarget,projScreenMatrix=this._projScreenMatrix;lightPositionWorld.setFromMatrixPosition(light.matrixWorld);camera.position.copy(lightPositionWorld);lookTarget.copy(camera.position);lookTarget.add(this._cubeDirections[viewportIndex]);camera.up.copy(this._cubeUps[viewportIndex]);camera.lookAt(lookTarget);camera.updateMatrixWorld();shadowMatrix.makeTranslation(-lightPositionWorld.x,-lightPositionWorld.y,-lightPositionWorld.z);projScreenMatrix.multiplyMatrices(camera.projectionMatrix,camera.matrixWorldInverse);this._frustum.setFromProjectionMatrix(projScreenMatrix);}});function PointLight(color,intensity,distance,decay){Light.call(this,color,intensity);this.type='PointLight';Object.defineProperty(this,'power',{get:function get(){// intensity = power per solid angle.
  2156. // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  2157. return this.intensity*4*Math.PI;},set:function set(power){// intensity = power per solid angle.
  2158. // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  2159. this.intensity=power/(4*Math.PI);}});this.distance=distance!==undefined?distance:0;this.decay=decay!==undefined?decay:1;// for physically correct lights, should be 2.
  2160. this.shadow=new PointLightShadow();}PointLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:PointLight,isPointLight:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.distance=source.distance;this.decay=source.decay;this.shadow=source.shadow.clone();return this;}});function OrthographicCamera(){var left=arguments.length>0&&arguments[0]!==undefined?arguments[0]:-1;var right=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var top=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var bottom=arguments.length>3&&arguments[3]!==undefined?arguments[3]:-1;var near=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0.1;var far=arguments.length>5&&arguments[5]!==undefined?arguments[5]:2000;Camera.call(this);this.type='OrthographicCamera';this.zoom=1;this.view=null;this.left=left;this.right=right;this.top=top;this.bottom=bottom;this.near=near;this.far=far;this.updateProjectionMatrix();}OrthographicCamera.prototype=Object.assign(Object.create(Camera.prototype),{constructor:OrthographicCamera,isOrthographicCamera:true,copy:function copy(source,recursive){Camera.prototype.copy.call(this,source,recursive);this.left=source.left;this.right=source.right;this.top=source.top;this.bottom=source.bottom;this.near=source.near;this.far=source.far;this.zoom=source.zoom;this.view=source.view===null?null:Object.assign({},source.view);return this;},setViewOffset:function setViewOffset(fullWidth,fullHeight,x,y,width,height){if(this.view===null){this.view={enabled:true,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1};}this.view.enabled=true;this.view.fullWidth=fullWidth;this.view.fullHeight=fullHeight;this.view.offsetX=x;this.view.offsetY=y;this.view.width=width;this.view.height=height;this.updateProjectionMatrix();},clearViewOffset:function clearViewOffset(){if(this.view!==null){this.view.enabled=false;}this.updateProjectionMatrix();},updateProjectionMatrix:function updateProjectionMatrix(){var dx=(this.right-this.left)/(2*this.zoom);var dy=(this.top-this.bottom)/(2*this.zoom);var cx=(this.right+this.left)/2;var cy=(this.top+this.bottom)/2;var left=cx-dx;var right=cx+dx;var top=cy+dy;var bottom=cy-dy;if(this.view!==null&&this.view.enabled){var scaleW=(this.right-this.left)/this.view.fullWidth/this.zoom;var scaleH=(this.top-this.bottom)/this.view.fullHeight/this.zoom;left+=scaleW*this.view.offsetX;right=left+scaleW*this.view.width;top-=scaleH*this.view.offsetY;bottom=top-scaleH*this.view.height;}this.projectionMatrix.makeOrthographic(left,right,top,bottom,this.near,this.far);this.projectionMatrixInverse.copy(this.projectionMatrix).invert();},toJSON:function toJSON(meta){var data=Object3D.prototype.toJSON.call(this,meta);data.object.zoom=this.zoom;data.object.left=this.left;data.object.right=this.right;data.object.top=this.top;data.object.bottom=this.bottom;data.object.near=this.near;data.object.far=this.far;if(this.view!==null)data.object.view=Object.assign({},this.view);return data;}});function DirectionalLightShadow(){LightShadow.call(this,new OrthographicCamera(-5,5,5,-5,0.5,500));}DirectionalLightShadow.prototype=Object.assign(Object.create(LightShadow.prototype),{constructor:DirectionalLightShadow,isDirectionalLightShadow:true,updateMatrices:function updateMatrices(light){LightShadow.prototype.updateMatrices.call(this,light);}});function DirectionalLight(color,intensity){Light.call(this,color,intensity);this.type='DirectionalLight';this.position.copy(Object3D.DefaultUp);this.updateMatrix();this.target=new Object3D();this.shadow=new DirectionalLightShadow();}DirectionalLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:DirectionalLight,isDirectionalLight:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.target=source.target.clone();this.shadow=source.shadow.clone();return this;}});function AmbientLight(color,intensity){Light.call(this,color,intensity);this.type='AmbientLight';}AmbientLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:AmbientLight,isAmbientLight:true});function RectAreaLight(color,intensity,width,height){Light.call(this,color,intensity);this.type='RectAreaLight';this.width=width!==undefined?width:10;this.height=height!==undefined?height:10;}RectAreaLight.prototype=Object.assign(Object.create(Light.prototype),{constructor:RectAreaLight,isRectAreaLight:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.width=source.width;this.height=source.height;return this;},toJSON:function toJSON(meta){var data=Light.prototype.toJSON.call(this,meta);data.object.width=this.width;data.object.height=this.height;return data;}});/**
  2161. * Primary reference:
  2162. * https://graphics.stanford.edu/papers/envmap/envmap.pdf
  2163. *
  2164. * Secondary reference:
  2165. * https://www.ppsloan.org/publications/StupidSH36.pdf
  2166. */ // 3-band SH defined by 9 coefficients
  2167. class SphericalHarmonics3{constructor(){Object.defineProperty(this,'isSphericalHarmonics3',{value:true});this.coefficients=[];for(var _i298=0;_i298<9;_i298++){this.coefficients.push(new Vector3());}}set(coefficients){for(var _i299=0;_i299<9;_i299++){this.coefficients[_i299].copy(coefficients[_i299]);}return this;}zero(){for(var _i300=0;_i300<9;_i300++){this.coefficients[_i300].set(0,0,0);}return this;}// get the radiance in the direction of the normal
  2168. // target is a Vector3
  2169. getAt(normal,target){// normal is assumed to be unit length
  2170. var x=normal.x,y=normal.y,z=normal.z;var coeff=this.coefficients;// band 0
  2171. target.copy(coeff[0]).multiplyScalar(0.282095);// band 1
  2172. target.addScaledVector(coeff[1],0.488603*y);target.addScaledVector(coeff[2],0.488603*z);target.addScaledVector(coeff[3],0.488603*x);// band 2
  2173. target.addScaledVector(coeff[4],1.092548*(x*y));target.addScaledVector(coeff[5],1.092548*(y*z));target.addScaledVector(coeff[6],0.315392*(3.0*z*z-1.0));target.addScaledVector(coeff[7],1.092548*(x*z));target.addScaledVector(coeff[8],0.546274*(x*x-y*y));return target;}// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
  2174. // target is a Vector3
  2175. // https://graphics.stanford.edu/papers/envmap/envmap.pdf
  2176. getIrradianceAt(normal,target){// normal is assumed to be unit length
  2177. var x=normal.x,y=normal.y,z=normal.z;var coeff=this.coefficients;// band 0
  2178. target.copy(coeff[0]).multiplyScalar(0.886227);// π * 0.282095
  2179. // band 1
  2180. target.addScaledVector(coeff[1],2.0*0.511664*y);// ( 2 * π / 3 ) * 0.488603
  2181. target.addScaledVector(coeff[2],2.0*0.511664*z);target.addScaledVector(coeff[3],2.0*0.511664*x);// band 2
  2182. target.addScaledVector(coeff[4],2.0*0.429043*x*y);// ( π / 4 ) * 1.092548
  2183. target.addScaledVector(coeff[5],2.0*0.429043*y*z);target.addScaledVector(coeff[6],0.743125*z*z-0.247708);// ( π / 4 ) * 0.315392 * 3
  2184. target.addScaledVector(coeff[7],2.0*0.429043*x*z);target.addScaledVector(coeff[8],0.429043*(x*x-y*y));// ( π / 4 ) * 0.546274
  2185. return target;}add(sh){for(var _i301=0;_i301<9;_i301++){this.coefficients[_i301].add(sh.coefficients[_i301]);}return this;}addScaledSH(sh,s){for(var _i302=0;_i302<9;_i302++){this.coefficients[_i302].addScaledVector(sh.coefficients[_i302],s);}return this;}scale(s){for(var _i303=0;_i303<9;_i303++){this.coefficients[_i303].multiplyScalar(s);}return this;}lerp(sh,alpha){for(var _i304=0;_i304<9;_i304++){this.coefficients[_i304].lerp(sh.coefficients[_i304],alpha);}return this;}equals(sh){for(var _i305=0;_i305<9;_i305++){if(!this.coefficients[_i305].equals(sh.coefficients[_i305])){return false;}}return true;}copy(sh){return this.set(sh.coefficients);}clone(){return new this.constructor().copy(this);}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var coefficients=this.coefficients;for(var _i306=0;_i306<9;_i306++){coefficients[_i306].fromArray(array,offset+_i306*3);}return this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var coefficients=this.coefficients;for(var _i307=0;_i307<9;_i307++){coefficients[_i307].toArray(array,offset+_i307*3);}return array;}// evaluate the basis functions
  2186. // shBasis is an Array[ 9 ]
  2187. static getBasisAt(normal,shBasis){// normal is assumed to be unit length
  2188. var x=normal.x,y=normal.y,z=normal.z;// band 0
  2189. shBasis[0]=0.282095;// band 1
  2190. shBasis[1]=0.488603*y;shBasis[2]=0.488603*z;shBasis[3]=0.488603*x;// band 2
  2191. shBasis[4]=1.092548*x*y;shBasis[5]=1.092548*y*z;shBasis[6]=0.315392*(3*z*z-1);shBasis[7]=1.092548*x*z;shBasis[8]=0.546274*(x*x-y*y);}}function LightProbe(sh,intensity){Light.call(this,undefined,intensity);this.type='LightProbe';this.sh=sh!==undefined?sh:new SphericalHarmonics3();}LightProbe.prototype=Object.assign(Object.create(Light.prototype),{constructor:LightProbe,isLightProbe:true,copy:function copy(source){Light.prototype.copy.call(this,source);this.sh.copy(source.sh);return this;},fromJSON:function fromJSON(json){this.intensity=json.intensity;// TODO: Move this bit to Light.fromJSON();
  2192. this.sh.fromArray(json.sh);return this;},toJSON:function toJSON(meta){var data=Light.prototype.toJSON.call(this,meta);data.object.sh=this.sh.toArray();return data;}});function MaterialLoader(manager){Loader.call(this,manager);this.textures={};}MaterialLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:MaterialLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var loader=new FileLoader(scope.manager);loader.setPath(scope.path);loader.setRequestHeader(scope.requestHeader);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(text){try{onLoad(scope.parse(JSON.parse(text)));}catch(e){if(onError){onError(e);}else {console.error(e);}scope.manager.itemError(url);}},onProgress,onError);},parse:function parse(json){var textures=this.textures;function getTexture(name){if(textures[name]===undefined){console.warn('THREE.MaterialLoader: Undefined texture',name);}return textures[name];}var material=new Materials[json.type]();if(json.uuid!==undefined)material.uuid=json.uuid;if(json.name!==undefined)material.name=json.name;if(json.color!==undefined&&material.color!==undefined)material.color.setHex(json.color);if(json.roughness!==undefined)material.roughness=json.roughness;if(json.metalness!==undefined)material.metalness=json.metalness;if(json.sheen!==undefined)material.sheen=new Color().setHex(json.sheen);if(json.emissive!==undefined&&material.emissive!==undefined)material.emissive.setHex(json.emissive);if(json.specular!==undefined&&material.specular!==undefined)material.specular.setHex(json.specular);if(json.shininess!==undefined)material.shininess=json.shininess;if(json.clearcoat!==undefined)material.clearcoat=json.clearcoat;if(json.clearcoatRoughness!==undefined)material.clearcoatRoughness=json.clearcoatRoughness;if(json.fog!==undefined)material.fog=json.fog;if(json.flatShading!==undefined)material.flatShading=json.flatShading;if(json.blending!==undefined)material.blending=json.blending;if(json.combine!==undefined)material.combine=json.combine;if(json.side!==undefined)material.side=json.side;if(json.opacity!==undefined)material.opacity=json.opacity;if(json.transparent!==undefined)material.transparent=json.transparent;if(json.alphaTest!==undefined)material.alphaTest=json.alphaTest;if(json.depthTest!==undefined)material.depthTest=json.depthTest;if(json.depthWrite!==undefined)material.depthWrite=json.depthWrite;if(json.colorWrite!==undefined)material.colorWrite=json.colorWrite;if(json.stencilWrite!==undefined)material.stencilWrite=json.stencilWrite;if(json.stencilWriteMask!==undefined)material.stencilWriteMask=json.stencilWriteMask;if(json.stencilFunc!==undefined)material.stencilFunc=json.stencilFunc;if(json.stencilRef!==undefined)material.stencilRef=json.stencilRef;if(json.stencilFuncMask!==undefined)material.stencilFuncMask=json.stencilFuncMask;if(json.stencilFail!==undefined)material.stencilFail=json.stencilFail;if(json.stencilZFail!==undefined)material.stencilZFail=json.stencilZFail;if(json.stencilZPass!==undefined)material.stencilZPass=json.stencilZPass;if(json.wireframe!==undefined)material.wireframe=json.wireframe;if(json.wireframeLinewidth!==undefined)material.wireframeLinewidth=json.wireframeLinewidth;if(json.wireframeLinecap!==undefined)material.wireframeLinecap=json.wireframeLinecap;if(json.wireframeLinejoin!==undefined)material.wireframeLinejoin=json.wireframeLinejoin;if(json.rotation!==undefined)material.rotation=json.rotation;if(json.linewidth!==1)material.linewidth=json.linewidth;if(json.dashSize!==undefined)material.dashSize=json.dashSize;if(json.gapSize!==undefined)material.gapSize=json.gapSize;if(json.scale!==undefined)material.scale=json.scale;if(json.polygonOffset!==undefined)material.polygonOffset=json.polygonOffset;if(json.polygonOffsetFactor!==undefined)material.polygonOffsetFactor=json.polygonOffsetFactor;if(json.polygonOffsetUnits!==undefined)material.polygonOffsetUnits=json.polygonOffsetUnits;if(json.skinning!==undefined)material.skinning=json.skinning;if(json.morphTargets!==undefined)material.morphTargets=json.morphTargets;if(json.morphNormals!==undefined)material.morphNormals=json.morphNormals;if(json.dithering!==undefined)material.dithering=json.dithering;if(json.vertexTangents!==undefined)material.vertexTangents=json.vertexTangents;if(json.visible!==undefined)material.visible=json.visible;if(json.toneMapped!==undefined)material.toneMapped=json.toneMapped;if(json.userData!==undefined)material.userData=json.userData;if(json.vertexColors!==undefined){if(typeof json.vertexColors==='number'){material.vertexColors=json.vertexColors>0?true:false;}else {material.vertexColors=json.vertexColors;}}// Shader Material
  2193. if(json.uniforms!==undefined){for(var name in json.uniforms){var uniform=json.uniforms[name];material.uniforms[name]={};switch(uniform.type){case't':material.uniforms[name].value=getTexture(uniform.value);break;case'c':material.uniforms[name].value=new Color().setHex(uniform.value);break;case'v2':material.uniforms[name].value=new Vector2().fromArray(uniform.value);break;case'v3':material.uniforms[name].value=new Vector3().fromArray(uniform.value);break;case'v4':material.uniforms[name].value=new Vector4().fromArray(uniform.value);break;case'm3':material.uniforms[name].value=new Matrix3().fromArray(uniform.value);break;case'm4':material.uniforms[name].value=new Matrix4().fromArray(uniform.value);break;default:material.uniforms[name].value=uniform.value;}}}if(json.defines!==undefined)material.defines=json.defines;if(json.vertexShader!==undefined)material.vertexShader=json.vertexShader;if(json.fragmentShader!==undefined)material.fragmentShader=json.fragmentShader;if(json.extensions!==undefined){for(var key in json.extensions){material.extensions[key]=json.extensions[key];}}// Deprecated
  2194. if(json.shading!==undefined)material.flatShading=json.shading===1;// THREE.FlatShading
  2195. // for PointsMaterial
  2196. if(json.size!==undefined)material.size=json.size;if(json.sizeAttenuation!==undefined)material.sizeAttenuation=json.sizeAttenuation;// maps
  2197. if(json.map!==undefined)material.map=getTexture(json.map);if(json.matcap!==undefined)material.matcap=getTexture(json.matcap);if(json.alphaMap!==undefined)material.alphaMap=getTexture(json.alphaMap);if(json.bumpMap!==undefined)material.bumpMap=getTexture(json.bumpMap);if(json.bumpScale!==undefined)material.bumpScale=json.bumpScale;if(json.normalMap!==undefined)material.normalMap=getTexture(json.normalMap);if(json.normalMapType!==undefined)material.normalMapType=json.normalMapType;if(json.normalScale!==undefined){var normalScale=json.normalScale;if(Array.isArray(normalScale)===false){// Blender exporter used to export a scalar. See #7459
  2198. normalScale=[normalScale,normalScale];}material.normalScale=new Vector2().fromArray(normalScale);}if(json.displacementMap!==undefined)material.displacementMap=getTexture(json.displacementMap);if(json.displacementScale!==undefined)material.displacementScale=json.displacementScale;if(json.displacementBias!==undefined)material.displacementBias=json.displacementBias;if(json.roughnessMap!==undefined)material.roughnessMap=getTexture(json.roughnessMap);if(json.metalnessMap!==undefined)material.metalnessMap=getTexture(json.metalnessMap);if(json.emissiveMap!==undefined)material.emissiveMap=getTexture(json.emissiveMap);if(json.emissiveIntensity!==undefined)material.emissiveIntensity=json.emissiveIntensity;if(json.specularMap!==undefined)material.specularMap=getTexture(json.specularMap);if(json.envMap!==undefined)material.envMap=getTexture(json.envMap);if(json.envMapIntensity!==undefined)material.envMapIntensity=json.envMapIntensity;if(json.reflectivity!==undefined)material.reflectivity=json.reflectivity;if(json.refractionRatio!==undefined)material.refractionRatio=json.refractionRatio;if(json.lightMap!==undefined)material.lightMap=getTexture(json.lightMap);if(json.lightMapIntensity!==undefined)material.lightMapIntensity=json.lightMapIntensity;if(json.aoMap!==undefined)material.aoMap=getTexture(json.aoMap);if(json.aoMapIntensity!==undefined)material.aoMapIntensity=json.aoMapIntensity;if(json.gradientMap!==undefined)material.gradientMap=getTexture(json.gradientMap);if(json.clearcoatMap!==undefined)material.clearcoatMap=getTexture(json.clearcoatMap);if(json.clearcoatRoughnessMap!==undefined)material.clearcoatRoughnessMap=getTexture(json.clearcoatRoughnessMap);if(json.clearcoatNormalMap!==undefined)material.clearcoatNormalMap=getTexture(json.clearcoatNormalMap);if(json.clearcoatNormalScale!==undefined)material.clearcoatNormalScale=new Vector2().fromArray(json.clearcoatNormalScale);if(json.transmission!==undefined)material.transmission=json.transmission;if(json.transmissionMap!==undefined)material.transmissionMap=getTexture(json.transmissionMap);return material;},setTextures:function setTextures(value){this.textures=value;return this;}});var LoaderUtils={decodeText:function decodeText(array){if(typeof TextDecoder!=='undefined'){return new TextDecoder().decode(array);}// Avoid the String.fromCharCode.apply(null, array) shortcut, which
  2199. // throws a "maximum call stack size exceeded" error for large arrays.
  2200. var s='';for(var _i308=0,il=array.length;_i308<il;_i308++){// Implicitly assumes little-endian.
  2201. s+=String.fromCharCode(array[_i308]);}try{// merges multi-byte utf-8 characters.
  2202. return decodeURIComponent(escape(s));}catch(e){// see #16358
  2203. return s;}},extractUrlBase:function extractUrlBase(url){var index=url.lastIndexOf('/');if(index===-1)return './';return url.substr(0,index+1);}};function InstancedBufferGeometry(){BufferGeometry.call(this);this.type='InstancedBufferGeometry';this.instanceCount=Infinity;}InstancedBufferGeometry.prototype=Object.assign(Object.create(BufferGeometry.prototype),{constructor:InstancedBufferGeometry,isInstancedBufferGeometry:true,copy:function copy(source){BufferGeometry.prototype.copy.call(this,source);this.instanceCount=source.instanceCount;return this;},clone:function clone(){return new this.constructor().copy(this);},toJSON:function toJSON(){var data=BufferGeometry.prototype.toJSON.call(this);data.instanceCount=this.instanceCount;data.isInstancedBufferGeometry=true;return data;}});function InstancedBufferAttribute(array,itemSize,normalized,meshPerAttribute){if(typeof normalized==='number'){meshPerAttribute=normalized;normalized=false;console.error('THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.');}BufferAttribute.call(this,array,itemSize,normalized);this.meshPerAttribute=meshPerAttribute||1;}InstancedBufferAttribute.prototype=Object.assign(Object.create(BufferAttribute.prototype),{constructor:InstancedBufferAttribute,isInstancedBufferAttribute:true,copy:function copy(source){BufferAttribute.prototype.copy.call(this,source);this.meshPerAttribute=source.meshPerAttribute;return this;},toJSON:function toJSON(){var data=BufferAttribute.prototype.toJSON.call(this);data.meshPerAttribute=this.meshPerAttribute;data.isInstancedBufferAttribute=true;return data;}});function BufferGeometryLoader(manager){Loader.call(this,manager);}BufferGeometryLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:BufferGeometryLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var loader=new FileLoader(scope.manager);loader.setPath(scope.path);loader.setRequestHeader(scope.requestHeader);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(text){try{onLoad(scope.parse(JSON.parse(text)));}catch(e){if(onError){onError(e);}else {console.error(e);}scope.manager.itemError(url);}},onProgress,onError);},parse:function parse(json){var interleavedBufferMap={};var arrayBufferMap={};function getInterleavedBuffer(json,uuid){if(interleavedBufferMap[uuid]!==undefined)return interleavedBufferMap[uuid];var interleavedBuffers=json.interleavedBuffers;var interleavedBuffer=interleavedBuffers[uuid];var buffer=getArrayBuffer(json,interleavedBuffer.buffer);var array=getTypedArray(interleavedBuffer.type,buffer);var ib=new InterleavedBuffer(array,interleavedBuffer.stride);ib.uuid=interleavedBuffer.uuid;interleavedBufferMap[uuid]=ib;return ib;}function getArrayBuffer(json,uuid){if(arrayBufferMap[uuid]!==undefined)return arrayBufferMap[uuid];var arrayBuffers=json.arrayBuffers;var arrayBuffer=arrayBuffers[uuid];var ab=new Uint32Array(arrayBuffer).buffer;arrayBufferMap[uuid]=ab;return ab;}var geometry=json.isInstancedBufferGeometry?new InstancedBufferGeometry():new BufferGeometry();var index=json.data.index;if(index!==undefined){var typedArray=getTypedArray(index.type,index.array);geometry.setIndex(new BufferAttribute(typedArray,1));}var attributes=json.data.attributes;for(var key in attributes){var attribute=attributes[key];var bufferAttribute=void 0;if(attribute.isInterleavedBufferAttribute){var interleavedBuffer=getInterleavedBuffer(json.data,attribute.data);bufferAttribute=new InterleavedBufferAttribute(interleavedBuffer,attribute.itemSize,attribute.offset,attribute.normalized);}else {var _typedArray=getTypedArray(attribute.type,attribute.array);var bufferAttributeConstr=attribute.isInstancedBufferAttribute?InstancedBufferAttribute:BufferAttribute;bufferAttribute=new bufferAttributeConstr(_typedArray,attribute.itemSize,attribute.normalized);}if(attribute.name!==undefined)bufferAttribute.name=attribute.name;geometry.setAttribute(key,bufferAttribute);}var morphAttributes=json.data.morphAttributes;if(morphAttributes){for(var _key6 in morphAttributes){var attributeArray=morphAttributes[_key6];var array=[];for(var _i309=0,il=attributeArray.length;_i309<il;_i309++){var _attribute9=attributeArray[_i309];var _bufferAttribute=void 0;if(_attribute9.isInterleavedBufferAttribute){var _interleavedBuffer=getInterleavedBuffer(json.data,_attribute9.data);_bufferAttribute=new InterleavedBufferAttribute(_interleavedBuffer,_attribute9.itemSize,_attribute9.offset,_attribute9.normalized);}else {var _typedArray2=getTypedArray(_attribute9.type,_attribute9.array);_bufferAttribute=new BufferAttribute(_typedArray2,_attribute9.itemSize,_attribute9.normalized);}if(_attribute9.name!==undefined)_bufferAttribute.name=_attribute9.name;array.push(_bufferAttribute);}geometry.morphAttributes[_key6]=array;}}var morphTargetsRelative=json.data.morphTargetsRelative;if(morphTargetsRelative){geometry.morphTargetsRelative=true;}var groups=json.data.groups||json.data.drawcalls||json.data.offsets;if(groups!==undefined){for(var _i310=0,n=groups.length;_i310!==n;++_i310){var group=groups[_i310];geometry.addGroup(group.start,group.count,group.materialIndex);}}var boundingSphere=json.data.boundingSphere;if(boundingSphere!==undefined){var center=new Vector3();if(boundingSphere.center!==undefined){center.fromArray(boundingSphere.center);}geometry.boundingSphere=new Sphere(center,boundingSphere.radius);}if(json.name)geometry.name=json.name;if(json.userData)geometry.userData=json.userData;return geometry;}});class ObjectLoader extends Loader{constructor(manager){super(manager);}load(url,onLoad,onProgress,onError){var scope=this;var path=this.path===''?LoaderUtils.extractUrlBase(url):this.path;this.resourcePath=this.resourcePath||path;var loader=new FileLoader(this.manager);loader.setPath(this.path);loader.setRequestHeader(this.requestHeader);loader.setWithCredentials(this.withCredentials);loader.load(url,function(text){var json=null;try{json=JSON.parse(text);}catch(error){if(onError!==undefined)onError(error);console.error('THREE:ObjectLoader: Can\'t parse '+url+'.',error.message);return;}var metadata=json.metadata;if(metadata===undefined||metadata.type===undefined||metadata.type.toLowerCase()==='geometry'){console.error('THREE.ObjectLoader: Can\'t load '+url);return;}scope.parse(json,onLoad);},onProgress,onError);}parse(json,onLoad){var animations=this.parseAnimations(json.animations);var shapes=this.parseShapes(json.shapes);var geometries=this.parseGeometries(json.geometries,shapes);var images=this.parseImages(json.images,function(){if(onLoad!==undefined)onLoad(object);});var textures=this.parseTextures(json.textures,images);var materials=this.parseMaterials(json.materials,textures);var object=this.parseObject(json.object,geometries,materials,animations);var skeletons=this.parseSkeletons(json.skeletons,object);this.bindSkeletons(object,skeletons);//
  2204. if(onLoad!==undefined){var hasImages=false;for(var uuid in images){if(images[uuid]instanceof HTMLImageElement){hasImages=true;break;}}if(hasImages===false)onLoad(object);}return object;}parseShapes(json){var shapes={};if(json!==undefined){for(var _i311=0,l=json.length;_i311<l;_i311++){var shape=new Shape().fromJSON(json[_i311]);shapes[shape.uuid]=shape;}}return shapes;}parseSkeletons(json,object){var skeletons={};var bones={};// generate bone lookup table
  2205. object.traverse(function(child){if(child.isBone)bones[child.uuid]=child;});// create skeletons
  2206. if(json!==undefined){for(var _i312=0,l=json.length;_i312<l;_i312++){var skeleton=new Skeleton().fromJSON(json[_i312],bones);skeletons[skeleton.uuid]=skeleton;}}return skeletons;}parseGeometries(json,shapes){var geometries={};var geometryShapes;if(json!==undefined){var bufferGeometryLoader=new BufferGeometryLoader();for(var _i313=0,l=json.length;_i313<l;_i313++){var geometry=void 0;var data=json[_i313];switch(data.type){case'PlaneGeometry':case'PlaneBufferGeometry':geometry=new Geometries[data.type](data.width,data.height,data.widthSegments,data.heightSegments);break;case'BoxGeometry':case'BoxBufferGeometry':case'CubeGeometry':// backwards compatible
  2207. geometry=new Geometries[data.type](data.width,data.height,data.depth,data.widthSegments,data.heightSegments,data.depthSegments);break;case'CircleGeometry':case'CircleBufferGeometry':geometry=new Geometries[data.type](data.radius,data.segments,data.thetaStart,data.thetaLength);break;case'CylinderGeometry':case'CylinderBufferGeometry':geometry=new Geometries[data.type](data.radiusTop,data.radiusBottom,data.height,data.radialSegments,data.heightSegments,data.openEnded,data.thetaStart,data.thetaLength);break;case'ConeGeometry':case'ConeBufferGeometry':geometry=new Geometries[data.type](data.radius,data.height,data.radialSegments,data.heightSegments,data.openEnded,data.thetaStart,data.thetaLength);break;case'SphereGeometry':case'SphereBufferGeometry':geometry=new Geometries[data.type](data.radius,data.widthSegments,data.heightSegments,data.phiStart,data.phiLength,data.thetaStart,data.thetaLength);break;case'DodecahedronGeometry':case'DodecahedronBufferGeometry':case'IcosahedronGeometry':case'IcosahedronBufferGeometry':case'OctahedronGeometry':case'OctahedronBufferGeometry':case'TetrahedronGeometry':case'TetrahedronBufferGeometry':geometry=new Geometries[data.type](data.radius,data.detail);break;case'RingGeometry':case'RingBufferGeometry':geometry=new Geometries[data.type](data.innerRadius,data.outerRadius,data.thetaSegments,data.phiSegments,data.thetaStart,data.thetaLength);break;case'TorusGeometry':case'TorusBufferGeometry':geometry=new Geometries[data.type](data.radius,data.tube,data.radialSegments,data.tubularSegments,data.arc);break;case'TorusKnotGeometry':case'TorusKnotBufferGeometry':geometry=new Geometries[data.type](data.radius,data.tube,data.tubularSegments,data.radialSegments,data.p,data.q);break;case'TubeGeometry':case'TubeBufferGeometry':// This only works for built-in curves (e.g. CatmullRomCurve3).
  2208. // User defined curves or instances of CurvePath will not be deserialized.
  2209. geometry=new Geometries[data.type](new Curves[data.path.type]().fromJSON(data.path),data.tubularSegments,data.radius,data.radialSegments,data.closed);break;case'LatheGeometry':case'LatheBufferGeometry':geometry=new Geometries[data.type](data.points,data.segments,data.phiStart,data.phiLength);break;case'PolyhedronGeometry':case'PolyhedronBufferGeometry':geometry=new Geometries[data.type](data.vertices,data.indices,data.radius,data.details);break;case'ShapeGeometry':case'ShapeBufferGeometry':geometryShapes=[];for(var j=0,jl=data.shapes.length;j<jl;j++){var shape=shapes[data.shapes[j]];geometryShapes.push(shape);}geometry=new Geometries[data.type](geometryShapes,data.curveSegments);break;case'ExtrudeGeometry':case'ExtrudeBufferGeometry':geometryShapes=[];for(var _j24=0,_jl8=data.shapes.length;_j24<_jl8;_j24++){var _shape=shapes[data.shapes[_j24]];geometryShapes.push(_shape);}var extrudePath=data.options.extrudePath;if(extrudePath!==undefined){data.options.extrudePath=new Curves[extrudePath.type]().fromJSON(extrudePath);}geometry=new Geometries[data.type](geometryShapes,data.options);break;case'BufferGeometry':case'InstancedBufferGeometry':geometry=bufferGeometryLoader.parse(data);break;case'Geometry':console.error('THREE.ObjectLoader: Loading "Geometry" is not supported anymore.');break;default:console.warn('THREE.ObjectLoader: Unsupported geometry type "'+data.type+'"');continue;}geometry.uuid=data.uuid;if(data.name!==undefined)geometry.name=data.name;if(geometry.isBufferGeometry===true&&data.userData!==undefined)geometry.userData=data.userData;geometries[data.uuid]=geometry;}}return geometries;}parseMaterials(json,textures){var cache={};// MultiMaterial
  2210. var materials={};if(json!==undefined){var loader=new MaterialLoader();loader.setTextures(textures);for(var _i314=0,l=json.length;_i314<l;_i314++){var data=json[_i314];if(data.type==='MultiMaterial'){// Deprecated
  2211. var array=[];for(var j=0;j<data.materials.length;j++){var material=data.materials[j];if(cache[material.uuid]===undefined){cache[material.uuid]=loader.parse(material);}array.push(cache[material.uuid]);}materials[data.uuid]=array;}else {if(cache[data.uuid]===undefined){cache[data.uuid]=loader.parse(data);}materials[data.uuid]=cache[data.uuid];}}}return materials;}parseAnimations(json){var animations={};if(json!==undefined){for(var _i315=0;_i315<json.length;_i315++){var data=json[_i315];var clip=AnimationClip.parse(data);animations[clip.uuid]=clip;}}return animations;}parseImages(json,onLoad){var scope=this;var images={};var loader;function loadImage(url){scope.manager.itemStart(url);return loader.load(url,function(){scope.manager.itemEnd(url);},undefined,function(){scope.manager.itemError(url);scope.manager.itemEnd(url);});}function deserializeImage(image){if(typeof image==='string'){var url=image;var path=/^(\/\/)|([a-z]+:(\/\/)?)/i.test(url)?url:scope.resourcePath+url;return loadImage(path);}else {if(image.data){return {data:getTypedArray(image.type,image.data),width:image.width,height:image.height};}else {return null;}}}if(json!==undefined&&json.length>0){var manager=new LoadingManager(onLoad);loader=new ImageLoader(manager);loader.setCrossOrigin(this.crossOrigin);for(var _i316=0,il=json.length;_i316<il;_i316++){var image=json[_i316];var url=image.url;if(Array.isArray(url)){// load array of images e.g CubeTexture
  2212. images[image.uuid]=[];for(var j=0,jl=url.length;j<jl;j++){var currentUrl=url[j];var deserializedImage=deserializeImage(currentUrl);if(deserializedImage!==null){if(deserializedImage instanceof HTMLImageElement){images[image.uuid].push(deserializedImage);}else {// special case: handle array of data textures for cube textures
  2213. images[image.uuid].push(new DataTexture(deserializedImage.data,deserializedImage.width,deserializedImage.height));}}}}else {// load single image
  2214. var _deserializedImage=deserializeImage(image.url);if(_deserializedImage!==null){images[image.uuid]=_deserializedImage;}}}}return images;}parseTextures(json,images){function parseConstant(value,type){if(typeof value==='number')return value;console.warn('THREE.ObjectLoader.parseTexture: Constant should be in numeric form.',value);return type[value];}var textures={};if(json!==undefined){for(var _i317=0,l=json.length;_i317<l;_i317++){var data=json[_i317];if(data.image===undefined){console.warn('THREE.ObjectLoader: No "image" specified for',data.uuid);}if(images[data.image]===undefined){console.warn('THREE.ObjectLoader: Undefined image',data.image);}var texture=void 0;var image=images[data.image];if(Array.isArray(image)){texture=new CubeTexture(image);if(image.length===6)texture.needsUpdate=true;}else {if(image&&image.data){texture=new DataTexture(image.data,image.width,image.height);}else {texture=new Texture(image);}if(image)texture.needsUpdate=true;// textures can have undefined image data
  2215. }texture.uuid=data.uuid;if(data.name!==undefined)texture.name=data.name;if(data.mapping!==undefined)texture.mapping=parseConstant(data.mapping,TEXTURE_MAPPING);if(data.offset!==undefined)texture.offset.fromArray(data.offset);if(data.repeat!==undefined)texture.repeat.fromArray(data.repeat);if(data.center!==undefined)texture.center.fromArray(data.center);if(data.rotation!==undefined)texture.rotation=data.rotation;if(data.wrap!==undefined){texture.wrapS=parseConstant(data.wrap[0],TEXTURE_WRAPPING);texture.wrapT=parseConstant(data.wrap[1],TEXTURE_WRAPPING);}if(data.format!==undefined)texture.format=data.format;if(data.type!==undefined)texture.type=data.type;if(data.encoding!==undefined)texture.encoding=data.encoding;if(data.minFilter!==undefined)texture.minFilter=parseConstant(data.minFilter,TEXTURE_FILTER);if(data.magFilter!==undefined)texture.magFilter=parseConstant(data.magFilter,TEXTURE_FILTER);if(data.anisotropy!==undefined)texture.anisotropy=data.anisotropy;if(data.flipY!==undefined)texture.flipY=data.flipY;if(data.premultiplyAlpha!==undefined)texture.premultiplyAlpha=data.premultiplyAlpha;if(data.unpackAlignment!==undefined)texture.unpackAlignment=data.unpackAlignment;textures[data.uuid]=texture;}}return textures;}parseObject(data,geometries,materials,animations){var object;function getGeometry(name){if(geometries[name]===undefined){console.warn('THREE.ObjectLoader: Undefined geometry',name);}return geometries[name];}function getMaterial(name){if(name===undefined)return undefined;if(Array.isArray(name)){var array=[];for(var _i318=0,l=name.length;_i318<l;_i318++){var uuid=name[_i318];if(materials[uuid]===undefined){console.warn('THREE.ObjectLoader: Undefined material',uuid);}array.push(materials[uuid]);}return array;}if(materials[name]===undefined){console.warn('THREE.ObjectLoader: Undefined material',name);}return materials[name];}var geometry,material;switch(data.type){case'Scene':object=new Scene();if(data.background!==undefined){if(Number.isInteger(data.background)){object.background=new Color(data.background);}}if(data.fog!==undefined){if(data.fog.type==='Fog'){object.fog=new Fog(data.fog.color,data.fog.near,data.fog.far);}else if(data.fog.type==='FogExp2'){object.fog=new FogExp2(data.fog.color,data.fog.density);}}break;case'PerspectiveCamera':object=new PerspectiveCamera(data.fov,data.aspect,data.near,data.far);if(data.focus!==undefined)object.focus=data.focus;if(data.zoom!==undefined)object.zoom=data.zoom;if(data.filmGauge!==undefined)object.filmGauge=data.filmGauge;if(data.filmOffset!==undefined)object.filmOffset=data.filmOffset;if(data.view!==undefined)object.view=Object.assign({},data.view);break;case'OrthographicCamera':object=new OrthographicCamera(data.left,data.right,data.top,data.bottom,data.near,data.far);if(data.zoom!==undefined)object.zoom=data.zoom;if(data.view!==undefined)object.view=Object.assign({},data.view);break;case'AmbientLight':object=new AmbientLight(data.color,data.intensity);break;case'DirectionalLight':object=new DirectionalLight(data.color,data.intensity);break;case'PointLight':object=new PointLight(data.color,data.intensity,data.distance,data.decay);break;case'RectAreaLight':object=new RectAreaLight(data.color,data.intensity,data.width,data.height);break;case'SpotLight':object=new SpotLight(data.color,data.intensity,data.distance,data.angle,data.penumbra,data.decay);break;case'HemisphereLight':object=new HemisphereLight(data.color,data.groundColor,data.intensity);break;case'LightProbe':object=new LightProbe().fromJSON(data);break;case'SkinnedMesh':geometry=getGeometry(data.geometry);material=getMaterial(data.material);object=new SkinnedMesh(geometry,material);if(data.bindMode!==undefined)object.bindMode=data.bindMode;if(data.bindMatrix!==undefined)object.bindMatrix.fromArray(data.bindMatrix);if(data.skeleton!==undefined)object.skeleton=data.skeleton;break;case'Mesh':geometry=getGeometry(data.geometry);material=getMaterial(data.material);object=new Mesh(geometry,material);break;case'InstancedMesh':geometry=getGeometry(data.geometry);material=getMaterial(data.material);var count=data.count;var instanceMatrix=data.instanceMatrix;object=new InstancedMesh(geometry,material,count);object.instanceMatrix=new BufferAttribute(new Float32Array(instanceMatrix.array),16);break;case'LOD':object=new LOD();break;case'Line':object=new Line(getGeometry(data.geometry),getMaterial(data.material));break;case'LineLoop':object=new LineLoop(getGeometry(data.geometry),getMaterial(data.material));break;case'LineSegments':object=new LineSegments(getGeometry(data.geometry),getMaterial(data.material));break;case'PointCloud':case'Points':object=new Points(getGeometry(data.geometry),getMaterial(data.material));break;case'Sprite':object=new Sprite$1(getMaterial(data.material));break;case'Group':object=new Group();break;case'Bone':object=new Bone();break;default:object=new Object3D();}object.uuid=data.uuid;if(data.name!==undefined)object.name=data.name;if(data.matrix!==undefined){object.matrix.fromArray(data.matrix);if(data.matrixAutoUpdate!==undefined)object.matrixAutoUpdate=data.matrixAutoUpdate;if(object.matrixAutoUpdate)object.matrix.decompose(object.position,object.quaternion,object.scale);}else {if(data.position!==undefined)object.position.fromArray(data.position);if(data.rotation!==undefined)object.rotation.fromArray(data.rotation);if(data.quaternion!==undefined)object.quaternion.fromArray(data.quaternion);if(data.scale!==undefined)object.scale.fromArray(data.scale);}if(data.castShadow!==undefined)object.castShadow=data.castShadow;if(data.receiveShadow!==undefined)object.receiveShadow=data.receiveShadow;if(data.shadow){if(data.shadow.bias!==undefined)object.shadow.bias=data.shadow.bias;if(data.shadow.normalBias!==undefined)object.shadow.normalBias=data.shadow.normalBias;if(data.shadow.radius!==undefined)object.shadow.radius=data.shadow.radius;if(data.shadow.mapSize!==undefined)object.shadow.mapSize.fromArray(data.shadow.mapSize);if(data.shadow.camera!==undefined)object.shadow.camera=this.parseObject(data.shadow.camera);}if(data.visible!==undefined)object.visible=data.visible;if(data.frustumCulled!==undefined)object.frustumCulled=data.frustumCulled;if(data.renderOrder!==undefined)object.renderOrder=data.renderOrder;if(data.userData!==undefined)object.userData=data.userData;if(data.layers!==undefined)object.layers.mask=data.layers;if(data.children!==undefined){var children=data.children;for(var _i319=0;_i319<children.length;_i319++){object.add(this.parseObject(children[_i319],geometries,materials,animations));}}if(data.animations!==undefined){var objectAnimations=data.animations;for(var _i320=0;_i320<objectAnimations.length;_i320++){var uuid=objectAnimations[_i320];object.animations.push(animations[uuid]);}}if(data.type==='LOD'){if(data.autoUpdate!==undefined)object.autoUpdate=data.autoUpdate;var levels=data.levels;for(var l=0;l<levels.length;l++){var level=levels[l];var child=object.getObjectByProperty('uuid',level.object);if(child!==undefined){object.addLevel(child,level.distance);}}}return object;}bindSkeletons(object,skeletons){if(Object.keys(skeletons).length===0)return;object.traverse(function(child){if(child.isSkinnedMesh===true&&child.skeleton!==undefined){var skeleton=skeletons[child.skeleton];if(skeleton===undefined){console.warn('THREE.ObjectLoader: No skeleton found with UUID:',child.skeleton);}else {child.bind(skeleton,child.bindMatrix);}}});}/* DEPRECATED */setTexturePath(value){console.warn('THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().');return this.setResourcePath(value);}}var TEXTURE_MAPPING={UVMapping:UVMapping,CubeReflectionMapping:CubeReflectionMapping,CubeRefractionMapping:CubeRefractionMapping,EquirectangularReflectionMapping:EquirectangularReflectionMapping,EquirectangularRefractionMapping:EquirectangularRefractionMapping,CubeUVReflectionMapping:CubeUVReflectionMapping,CubeUVRefractionMapping:CubeUVRefractionMapping};var TEXTURE_WRAPPING={RepeatWrapping:RepeatWrapping,ClampToEdgeWrapping:ClampToEdgeWrapping,MirroredRepeatWrapping:MirroredRepeatWrapping};var TEXTURE_FILTER={NearestFilter:NearestFilter,NearestMipmapNearestFilter:NearestMipmapNearestFilter,NearestMipmapLinearFilter:NearestMipmapLinearFilter,LinearFilter:LinearFilter,LinearMipmapNearestFilter:LinearMipmapNearestFilter,LinearMipmapLinearFilter:LinearMipmapLinearFilter};function ImageBitmapLoader(manager){if(typeof createImageBitmap==='undefined'){console.warn('THREE.ImageBitmapLoader: createImageBitmap() not supported.');}if(typeof fetch==='undefined'){console.warn('THREE.ImageBitmapLoader: fetch() not supported.');}Loader.call(this,manager);this.options={premultiplyAlpha:'none'};}ImageBitmapLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:ImageBitmapLoader,isImageBitmapLoader:true,setOptions:function setOptions(options){this.options=options;return this;},load:function load(url,onLoad,onProgress,onError){if(url===undefined)url='';if(this.path!==undefined)url=this.path+url;url=this.manager.resolveURL(url);var scope=this;var cached=Cache.get(url);if(cached!==undefined){scope.manager.itemStart(url);setTimeout(function(){if(onLoad)onLoad(cached);scope.manager.itemEnd(url);},0);return cached;}var fetchOptions={};fetchOptions.credentials=this.crossOrigin==='anonymous'?'same-origin':'include';fetch(url,fetchOptions).then(function(res){return res.blob();}).then(function(blob){//console.log('getBlob', url )
  2216. return createImageBitmap(blob,scope.options);}).then(function(imageBitmap){Cache.add(url,imageBitmap);if(onLoad)onLoad(imageBitmap);scope.manager.itemEnd(url);}).catch(function(e){//console.log('error', url, e)
  2217. if(onError)onError(e,url);scope.manager.itemError(url);scope.manager.itemEnd(url);});scope.manager.itemStart(url);}});function ShapePath(){this.type='ShapePath';this.color=new Color();this.subPaths=[];this.currentPath=null;}Object.assign(ShapePath.prototype,{moveTo:function moveTo(x,y){this.currentPath=new Path();this.subPaths.push(this.currentPath);this.currentPath.moveTo(x,y);return this;},lineTo:function lineTo(x,y){this.currentPath.lineTo(x,y);return this;},quadraticCurveTo:function quadraticCurveTo(aCPx,aCPy,aX,aY){this.currentPath.quadraticCurveTo(aCPx,aCPy,aX,aY);return this;},bezierCurveTo:function bezierCurveTo(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY){this.currentPath.bezierCurveTo(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY);return this;},splineThru:function splineThru(pts){this.currentPath.splineThru(pts);return this;},toShapes:function toShapes(isCCW,noHoles){function toShapesNoHoles(inSubpaths){var shapes=[];for(var _i321=0,l=inSubpaths.length;_i321<l;_i321++){var _tmpPath=inSubpaths[_i321];var _tmpShape=new Shape();_tmpShape.curves=_tmpPath.curves;shapes.push(_tmpShape);}return shapes;}function isPointInsidePolygon(inPt,inPolygon){var polyLen=inPolygon.length;// inPt on polygon contour => immediate success or
  2218. // toggling of inside/outside at every single! intersection point of an edge
  2219. // with the horizontal line through inPt, left of inPt
  2220. // not counting lowerY endpoints of edges and whole edges on that line
  2221. var inside=false;for(var p=polyLen-1,q=0;q<polyLen;p=q++){var edgeLowPt=inPolygon[p];var edgeHighPt=inPolygon[q];var edgeDx=edgeHighPt.x-edgeLowPt.x;var edgeDy=edgeHighPt.y-edgeLowPt.y;if(Math.abs(edgeDy)>Number.EPSILON){// not parallel
  2222. if(edgeDy<0){edgeLowPt=inPolygon[q];edgeDx=-edgeDx;edgeHighPt=inPolygon[p];edgeDy=-edgeDy;}if(inPt.y<edgeLowPt.y||inPt.y>edgeHighPt.y)continue;if(inPt.y===edgeLowPt.y){if(inPt.x===edgeLowPt.x)return true;// inPt is on contour ?
  2223. // continue; // no intersection or edgeLowPt => doesn't count !!!
  2224. }else {var perpEdge=edgeDy*(inPt.x-edgeLowPt.x)-edgeDx*(inPt.y-edgeLowPt.y);if(perpEdge===0)return true;// inPt is on contour ?
  2225. if(perpEdge<0)continue;inside=!inside;// true intersection left of inPt
  2226. }}else {// parallel or collinear
  2227. if(inPt.y!==edgeLowPt.y)continue;// parallel
  2228. // edge lies on the same horizontal line as inPt
  2229. if(edgeHighPt.x<=inPt.x&&inPt.x<=edgeLowPt.x||edgeLowPt.x<=inPt.x&&inPt.x<=edgeHighPt.x)return true;// inPt: Point on contour !
  2230. // continue;
  2231. }}return inside;}var isClockWise=ShapeUtils.isClockWise;var subPaths=this.subPaths;if(subPaths.length===0)return [];if(noHoles===true)return toShapesNoHoles(subPaths);var solid,tmpPath,tmpShape;var shapes=[];if(subPaths.length===1){tmpPath=subPaths[0];tmpShape=new Shape();tmpShape.curves=tmpPath.curves;shapes.push(tmpShape);return shapes;}var holesFirst=!isClockWise(subPaths[0].getPoints());holesFirst=isCCW?!holesFirst:holesFirst;// console.log("Holes first", holesFirst);
  2232. var betterShapeHoles=[];var newShapes=[];var newShapeHoles=[];var mainIdx=0;var tmpPoints;newShapes[mainIdx]=undefined;newShapeHoles[mainIdx]=[];for(var _i322=0,l=subPaths.length;_i322<l;_i322++){tmpPath=subPaths[_i322];tmpPoints=tmpPath.getPoints();solid=isClockWise(tmpPoints);solid=isCCW?!solid:solid;if(solid){if(!holesFirst&&newShapes[mainIdx])mainIdx++;newShapes[mainIdx]={s:new Shape(),p:tmpPoints};newShapes[mainIdx].s.curves=tmpPath.curves;if(holesFirst)mainIdx++;newShapeHoles[mainIdx]=[];//console.log('cw', i);
  2233. }else {newShapeHoles[mainIdx].push({h:tmpPath,p:tmpPoints[0]});//console.log('ccw', i);
  2234. }}// only Holes? -> probably all Shapes with wrong orientation
  2235. if(!newShapes[0])return toShapesNoHoles(subPaths);if(newShapes.length>1){var ambiguous=false;var toChange=[];for(var sIdx=0,sLen=newShapes.length;sIdx<sLen;sIdx++){betterShapeHoles[sIdx]=[];}for(var _sIdx=0,_sLen=newShapes.length;_sIdx<_sLen;_sIdx++){var sho=newShapeHoles[_sIdx];for(var hIdx=0;hIdx<sho.length;hIdx++){var ho=sho[hIdx];var hole_unassigned=true;for(var s2Idx=0;s2Idx<newShapes.length;s2Idx++){if(isPointInsidePolygon(ho.p,newShapes[s2Idx].p)){if(_sIdx!==s2Idx)toChange.push({froms:_sIdx,tos:s2Idx,hole:hIdx});if(hole_unassigned){hole_unassigned=false;betterShapeHoles[s2Idx].push(ho);}else {ambiguous=true;}}}if(hole_unassigned){betterShapeHoles[_sIdx].push(ho);}}}// console.log("ambiguous: ", ambiguous);
  2236. if(toChange.length>0){// console.log("to change: ", toChange);
  2237. if(!ambiguous)newShapeHoles=betterShapeHoles;}}var tmpHoles;for(var _i323=0,il=newShapes.length;_i323<il;_i323++){tmpShape=newShapes[_i323].s;shapes.push(tmpShape);tmpHoles=newShapeHoles[_i323];for(var j=0,jl=tmpHoles.length;j<jl;j++){tmpShape.holes.push(tmpHoles[j].h);}}//console.log("shape", shapes);
  2238. return shapes;}});function Font(data){this.type='Font';this.data=data;}Object.assign(Font.prototype,{isFont:true,generateShapes:function generateShapes(text){var size=arguments.length>1&&arguments[1]!==undefined?arguments[1]:100;var shapes=[];var paths=createPaths(text,size,this.data);for(var p=0,pl=paths.length;p<pl;p++){Array.prototype.push.apply(shapes,paths[p].toShapes());}return shapes;}});function createPaths(text,size,data){var chars=Array.from?Array.from(text):String(text).split('');// workaround for IE11, see #13988
  2239. var scale=size/data.resolution;var line_height=(data.boundingBox.yMax-data.boundingBox.yMin+data.underlineThickness)*scale;var paths=[];var offsetX=0,offsetY=0;for(var _i324=0;_i324<chars.length;_i324++){var char=chars[_i324];if(char==='\n'){offsetX=0;offsetY-=line_height;}else {var ret=createPath(char,scale,offsetX,offsetY,data);offsetX+=ret.offsetX;paths.push(ret.path);}}return paths;}function createPath(char,scale,offsetX,offsetY,data){var glyph=data.glyphs[char]||data.glyphs['?'];if(!glyph){console.error('THREE.Font: character "'+char+'" does not exists in font family '+data.familyName+'.');return;}var path=new ShapePath();var x,y,cpx,cpy,cpx1,cpy1,cpx2,cpy2;if(glyph.o){var outline=glyph._cachedOutline||(glyph._cachedOutline=glyph.o.split(' '));for(var _i325=0,l=outline.length;_i325<l;){var action=outline[_i325++];switch(action){case'm':// moveTo
  2240. x=outline[_i325++]*scale+offsetX;y=outline[_i325++]*scale+offsetY;path.moveTo(x,y);break;case'l':// lineTo
  2241. x=outline[_i325++]*scale+offsetX;y=outline[_i325++]*scale+offsetY;path.lineTo(x,y);break;case'q':// quadraticCurveTo
  2242. cpx=outline[_i325++]*scale+offsetX;cpy=outline[_i325++]*scale+offsetY;cpx1=outline[_i325++]*scale+offsetX;cpy1=outline[_i325++]*scale+offsetY;path.quadraticCurveTo(cpx1,cpy1,cpx,cpy);break;case'b':// bezierCurveTo
  2243. cpx=outline[_i325++]*scale+offsetX;cpy=outline[_i325++]*scale+offsetY;cpx1=outline[_i325++]*scale+offsetX;cpy1=outline[_i325++]*scale+offsetY;cpx2=outline[_i325++]*scale+offsetX;cpy2=outline[_i325++]*scale+offsetY;path.bezierCurveTo(cpx1,cpy1,cpx2,cpy2,cpx,cpy);break;}}}return {offsetX:glyph.ha*scale,path:path};}function FontLoader(manager){Loader.call(this,manager);}FontLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:FontLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var loader=new FileLoader(this.manager);loader.setPath(this.path);loader.setRequestHeader(this.requestHeader);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(text){var json;try{json=JSON.parse(text);}catch(e){console.warn('THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.');json=JSON.parse(text.substring(65,text.length-2));}var font=scope.parse(json);if(onLoad)onLoad(font);},onProgress,onError);},parse:function parse(json){return new Font(json);}});var _context;var AudioContext={getContext:function getContext(){if(_context===undefined){_context=new(window.AudioContext||window.webkitAudioContext)();}return _context;},setContext:function setContext(value){_context=value;}};function AudioLoader(manager){Loader.call(this,manager);}AudioLoader.prototype=Object.assign(Object.create(Loader.prototype),{constructor:AudioLoader,load:function load(url,onLoad,onProgress,onError){var scope=this;var loader=new FileLoader(scope.manager);loader.setResponseType('arraybuffer');loader.setPath(scope.path);loader.setRequestHeader(scope.requestHeader);loader.setWithCredentials(scope.withCredentials);loader.load(url,function(buffer){try{// Create a copy of the buffer. The `decodeAudioData` method
  2244. // detaches the buffer when complete, preventing reuse.
  2245. var bufferCopy=buffer.slice(0);var context=AudioContext.getContext();context.decodeAudioData(bufferCopy,function(audioBuffer){onLoad(audioBuffer);});}catch(e){if(onError){onError(e);}else {console.error(e);}scope.manager.itemError(url);}},onProgress,onError);}});function HemisphereLightProbe(skyColor,groundColor,intensity){LightProbe.call(this,undefined,intensity);var color1=new Color().set(skyColor);var color2=new Color().set(groundColor);var sky=new Vector3(color1.r,color1.g,color1.b);var ground=new Vector3(color2.r,color2.g,color2.b);// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
  2246. var c0=Math.sqrt(Math.PI);var c1=c0*Math.sqrt(0.75);this.sh.coefficients[0].copy(sky).add(ground).multiplyScalar(c0);this.sh.coefficients[1].copy(sky).sub(ground).multiplyScalar(c1);}HemisphereLightProbe.prototype=Object.assign(Object.create(LightProbe.prototype),{constructor:HemisphereLightProbe,isHemisphereLightProbe:true,copy:function copy(source){// modifying colors not currently supported
  2247. LightProbe.prototype.copy.call(this,source);return this;},toJSON:function toJSON(meta){var data=LightProbe.prototype.toJSON.call(this,meta);// data.sh = this.sh.toArray(); // todo
  2248. return data;}});function AmbientLightProbe(color,intensity){LightProbe.call(this,undefined,intensity);var color1=new Color().set(color);// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
  2249. this.sh.coefficients[0].set(color1.r,color1.g,color1.b).multiplyScalar(2*Math.sqrt(Math.PI));}AmbientLightProbe.prototype=Object.assign(Object.create(LightProbe.prototype),{constructor:AmbientLightProbe,isAmbientLightProbe:true,copy:function copy(source){// modifying color not currently supported
  2250. LightProbe.prototype.copy.call(this,source);return this;},toJSON:function toJSON(meta){var data=LightProbe.prototype.toJSON.call(this,meta);// data.sh = this.sh.toArray(); // todo
  2251. return data;}});var _eyeRight=new Matrix4();var _eyeLeft=new Matrix4();function StereoCamera(){this.type='StereoCamera';this.aspect=1;this.eyeSep=0.064;this.cameraL=new PerspectiveCamera();this.cameraL.layers.enable(1);this.cameraL.matrixAutoUpdate=false;this.cameraR=new PerspectiveCamera();this.cameraR.layers.enable(2);this.cameraR.matrixAutoUpdate=false;this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null};}Object.assign(StereoCamera.prototype,{update:function update(camera){var cache=this._cache;var needsUpdate=cache.focus!==camera.focus||cache.fov!==camera.fov||cache.aspect!==camera.aspect*this.aspect||cache.near!==camera.near||cache.far!==camera.far||cache.zoom!==camera.zoom||cache.eyeSep!==this.eyeSep;if(needsUpdate){cache.focus=camera.focus;cache.fov=camera.fov;cache.aspect=camera.aspect*this.aspect;cache.near=camera.near;cache.far=camera.far;cache.zoom=camera.zoom;cache.eyeSep=this.eyeSep;// Off-axis stereoscopic effect based on
  2252. // http://paulbourke.net/stereographics/stereorender/
  2253. var projectionMatrix=camera.projectionMatrix.clone();var eyeSepHalf=cache.eyeSep/2;var eyeSepOnProjection=eyeSepHalf*cache.near/cache.focus;var ymax=cache.near*Math.tan(MathUtils.DEG2RAD*cache.fov*0.5)/cache.zoom;var xmin,xmax;// translate xOffset
  2254. _eyeLeft.elements[12]=-eyeSepHalf;_eyeRight.elements[12]=eyeSepHalf;// for left eye
  2255. xmin=-ymax*cache.aspect+eyeSepOnProjection;xmax=ymax*cache.aspect+eyeSepOnProjection;projectionMatrix.elements[0]=2*cache.near/(xmax-xmin);projectionMatrix.elements[8]=(xmax+xmin)/(xmax-xmin);this.cameraL.projectionMatrix.copy(projectionMatrix);// for right eye
  2256. xmin=-ymax*cache.aspect-eyeSepOnProjection;xmax=ymax*cache.aspect-eyeSepOnProjection;projectionMatrix.elements[0]=2*cache.near/(xmax-xmin);projectionMatrix.elements[8]=(xmax+xmin)/(xmax-xmin);this.cameraR.projectionMatrix.copy(projectionMatrix);}this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(_eyeLeft);this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(_eyeRight);}});class Clock{constructor(autoStart){this.autoStart=autoStart!==undefined?autoStart:true;this.startTime=0;this.oldTime=0;this.elapsedTime=0;this.running=false;}start(){this.startTime=now();this.oldTime=this.startTime;this.elapsedTime=0;this.running=true;}stop(){this.getElapsedTime();this.running=false;this.autoStart=false;}getElapsedTime(){this.getDelta();return this.elapsedTime;}getDelta(){var diff=0;if(this.autoStart&&!this.running){this.start();return 0;}if(this.running){var newTime=now();diff=(newTime-this.oldTime)/1000;this.oldTime=newTime;this.elapsedTime+=diff;}return diff;}}function now(){return (typeof performance==='undefined'?Date:performance).now();// see #10732
  2257. }var _position$2=/*@__PURE__*/new Vector3();var _quaternion$3=/*@__PURE__*/new Quaternion();var _scale$1=/*@__PURE__*/new Vector3();var _orientation=/*@__PURE__*/new Vector3();class AudioListener extends Object3D{constructor(){super();this.type='AudioListener';this.context=AudioContext.getContext();this.gain=this.context.createGain();this.gain.connect(this.context.destination);this.filter=null;this.timeDelta=0;// private
  2258. this._clock=new Clock();}getInput(){return this.gain;}removeFilter(){if(this.filter!==null){this.gain.disconnect(this.filter);this.filter.disconnect(this.context.destination);this.gain.connect(this.context.destination);this.filter=null;}return this;}getFilter(){return this.filter;}setFilter(value){if(this.filter!==null){this.gain.disconnect(this.filter);this.filter.disconnect(this.context.destination);}else {this.gain.disconnect(this.context.destination);}this.filter=value;this.gain.connect(this.filter);this.filter.connect(this.context.destination);return this;}getMasterVolume(){return this.gain.gain.value;}setMasterVolume(value){this.gain.gain.setTargetAtTime(value,this.context.currentTime,0.01);return this;}updateMatrixWorld(force){super.updateMatrixWorld(force);var listener=this.context.listener;var up=this.up;this.timeDelta=this._clock.getDelta();this.matrixWorld.decompose(_position$2,_quaternion$3,_scale$1);_orientation.set(0,0,-1).applyQuaternion(_quaternion$3);if(listener.positionX){// code path for Chrome (see #14393)
  2259. var endTime=this.context.currentTime+this.timeDelta;listener.positionX.linearRampToValueAtTime(_position$2.x,endTime);listener.positionY.linearRampToValueAtTime(_position$2.y,endTime);listener.positionZ.linearRampToValueAtTime(_position$2.z,endTime);listener.forwardX.linearRampToValueAtTime(_orientation.x,endTime);listener.forwardY.linearRampToValueAtTime(_orientation.y,endTime);listener.forwardZ.linearRampToValueAtTime(_orientation.z,endTime);listener.upX.linearRampToValueAtTime(up.x,endTime);listener.upY.linearRampToValueAtTime(up.y,endTime);listener.upZ.linearRampToValueAtTime(up.z,endTime);}else {listener.setPosition(_position$2.x,_position$2.y,_position$2.z);listener.setOrientation(_orientation.x,_orientation.y,_orientation.z,up.x,up.y,up.z);}}}class Audio extends Object3D{constructor(listener){super();this.type='Audio';this.listener=listener;this.context=listener.context;this.gain=this.context.createGain();this.gain.connect(listener.getInput());this.autoplay=false;this.buffer=null;this.detune=0;this.loop=false;this.loopStart=0;this.loopEnd=0;this.offset=0;this.duration=undefined;this.playbackRate=1;this.isPlaying=false;this.hasPlaybackControl=true;this.source=null;this.sourceType='empty';this._startedAt=0;this._progress=0;this._connected=false;this.filters=[];}getOutput(){return this.gain;}setNodeSource(audioNode){this.hasPlaybackControl=false;this.sourceType='audioNode';this.source=audioNode;this.connect();return this;}setMediaElementSource(mediaElement){this.hasPlaybackControl=false;this.sourceType='mediaNode';this.source=this.context.createMediaElementSource(mediaElement);this.connect();return this;}setMediaStreamSource(mediaStream){this.hasPlaybackControl=false;this.sourceType='mediaStreamNode';this.source=this.context.createMediaStreamSource(mediaStream);this.connect();return this;}setBuffer(audioBuffer){this.buffer=audioBuffer;this.sourceType='buffer';if(this.autoplay)this.play();return this;}play(){var delay=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;if(this.isPlaying===true){console.warn('THREE.Audio: Audio is already playing.');return;}if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return;}this._startedAt=this.context.currentTime+delay;var source=this.context.createBufferSource();source.buffer=this.buffer;source.loop=this.loop;source.loopStart=this.loopStart;source.loopEnd=this.loopEnd;source.onended=this.onEnded.bind(this);source.start(this._startedAt,this._progress+this.offset,this.duration);this.isPlaying=true;this.source=source;this.setDetune(this.detune);this.setPlaybackRate(this.playbackRate);return this.connect();}pause(){if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return;}if(this.isPlaying===true){// update current progress
  2260. this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate;if(this.loop===true){// ensure _progress does not exceed duration with looped audios
  2261. this._progress=this._progress%(this.duration||this.buffer.duration);}this.source.stop();this.source.onended=null;this.isPlaying=false;}return this;}stop(){if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return;}this._progress=0;this.source.stop();this.source.onended=null;this.isPlaying=false;return this;}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(var _i326=1,l=this.filters.length;_i326<l;_i326++){this.filters[_i326-1].connect(this.filters[_i326]);}this.filters[this.filters.length-1].connect(this.getOutput());}else {this.source.connect(this.getOutput());}this._connected=true;return this;}disconnect(){if(this.filters.length>0){this.source.disconnect(this.filters[0]);for(var _i327=1,l=this.filters.length;_i327<l;_i327++){this.filters[_i327-1].disconnect(this.filters[_i327]);}this.filters[this.filters.length-1].disconnect(this.getOutput());}else {this.source.disconnect(this.getOutput());}this._connected=false;return this;}getFilters(){return this.filters;}setFilters(value){if(!value)value=[];if(this._connected===true){this.disconnect();this.filters=value.slice();this.connect();}else {this.filters=value.slice();}return this;}setDetune(value){this.detune=value;if(this.source.detune===undefined)return;// only set detune when available
  2262. if(this.isPlaying===true){this.source.detune.setTargetAtTime(this.detune,this.context.currentTime,0.01);}return this;}getDetune(){return this.detune;}getFilter(){return this.getFilters()[0];}setFilter(filter){return this.setFilters(filter?[filter]:[]);}setPlaybackRate(value){if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return;}this.playbackRate=value;if(this.isPlaying===true){this.source.playbackRate.setTargetAtTime(this.playbackRate,this.context.currentTime,0.01);}return this;}getPlaybackRate(){return this.playbackRate;}onEnded(){this.isPlaying=false;}getLoop(){if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return false;}return this.loop;}setLoop(value){if(this.hasPlaybackControl===false){console.warn('THREE.Audio: this Audio has no playback control.');return;}this.loop=value;if(this.isPlaying===true){this.source.loop=this.loop;}return this;}setLoopStart(value){this.loopStart=value;return this;}setLoopEnd(value){this.loopEnd=value;return this;}getVolume(){return this.gain.gain.value;}setVolume(value){this.gain.gain.setTargetAtTime(value,this.context.currentTime,0.01);return this;}}var _position$3=/*@__PURE__*/new Vector3();var _quaternion$4=/*@__PURE__*/new Quaternion();var _scale$2=/*@__PURE__*/new Vector3();var _orientation$1=/*@__PURE__*/new Vector3();class PositionalAudio extends Audio{constructor(listener){super(listener);this.panner=this.context.createPanner();this.panner.panningModel='HRTF';this.panner.connect(this.gain);}getOutput(){return this.panner;}getRefDistance(){return this.panner.refDistance;}setRefDistance(value){this.panner.refDistance=value;return this;}getRolloffFactor(){return this.panner.rolloffFactor;}setRolloffFactor(value){this.panner.rolloffFactor=value;return this;}getDistanceModel(){return this.panner.distanceModel;}setDistanceModel(value){this.panner.distanceModel=value;return this;}getMaxDistance(){return this.panner.maxDistance;}setMaxDistance(value){this.panner.maxDistance=value;return this;}setDirectionalCone(coneInnerAngle,coneOuterAngle,coneOuterGain){this.panner.coneInnerAngle=coneInnerAngle;this.panner.coneOuterAngle=coneOuterAngle;this.panner.coneOuterGain=coneOuterGain;return this;}updateMatrixWorld(force){super.updateMatrixWorld(force);if(this.hasPlaybackControl===true&&this.isPlaying===false)return;this.matrixWorld.decompose(_position$3,_quaternion$4,_scale$2);_orientation$1.set(0,0,1).applyQuaternion(_quaternion$4);var panner=this.panner;if(panner.positionX){// code path for Chrome and Firefox (see #14393)
  2263. var endTime=this.context.currentTime+this.listener.timeDelta;panner.positionX.linearRampToValueAtTime(_position$3.x,endTime);panner.positionY.linearRampToValueAtTime(_position$3.y,endTime);panner.positionZ.linearRampToValueAtTime(_position$3.z,endTime);panner.orientationX.linearRampToValueAtTime(_orientation$1.x,endTime);panner.orientationY.linearRampToValueAtTime(_orientation$1.y,endTime);panner.orientationZ.linearRampToValueAtTime(_orientation$1.z,endTime);}else {panner.setPosition(_position$3.x,_position$3.y,_position$3.z);panner.setOrientation(_orientation$1.x,_orientation$1.y,_orientation$1.z);}}}class AudioAnalyser{constructor(audio){var fftSize=arguments.length>1&&arguments[1]!==undefined?arguments[1]:2048;this.analyser=audio.context.createAnalyser();this.analyser.fftSize=fftSize;this.data=new Uint8Array(this.analyser.frequencyBinCount);audio.getOutput().connect(this.analyser);}getFrequencyData(){this.analyser.getByteFrequencyData(this.data);return this.data;}getAverageFrequency(){var value=0;var data=this.getFrequencyData();for(var _i328=0;_i328<data.length;_i328++){value+=data[_i328];}return value/data.length;}}function PropertyMixer(binding,typeName,valueSize){this.binding=binding;this.valueSize=valueSize;var mixFunction,mixFunctionAdditive,setIdentity;// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
  2264. //
  2265. // interpolators can use .buffer as their .result
  2266. // the data then goes to 'incoming'
  2267. //
  2268. // 'accu0' and 'accu1' are used frame-interleaved for
  2269. // the cumulative result and are compared to detect
  2270. // changes
  2271. //
  2272. // 'orig' stores the original state of the property
  2273. //
  2274. // 'add' is used for additive cumulative results
  2275. //
  2276. // 'work' is optional and is only present for quaternion types. It is used
  2277. // to store intermediate quaternion multiplication results
  2278. switch(typeName){case'quaternion':mixFunction=this._slerp;mixFunctionAdditive=this._slerpAdditive;setIdentity=this._setAdditiveIdentityQuaternion;this.buffer=new Float64Array(valueSize*6);this._workIndex=5;break;case'string':case'bool':mixFunction=this._select;// Use the regular mix function and for additive on these types,
  2279. // additive is not relevant for non-numeric types
  2280. mixFunctionAdditive=this._select;setIdentity=this._setAdditiveIdentityOther;this.buffer=new Array(valueSize*5);break;default:mixFunction=this._lerp;mixFunctionAdditive=this._lerpAdditive;setIdentity=this._setAdditiveIdentityNumeric;this.buffer=new Float64Array(valueSize*5);}this._mixBufferRegion=mixFunction;this._mixBufferRegionAdditive=mixFunctionAdditive;this._setIdentity=setIdentity;this._origIndex=3;this._addIndex=4;this.cumulativeWeight=0;this.cumulativeWeightAdditive=0;this.useCount=0;this.referenceCount=0;}Object.assign(PropertyMixer.prototype,{// accumulate data in the 'incoming' region into 'accu<i>'
  2281. accumulate:function accumulate(accuIndex,weight){// note: happily accumulating nothing when weight = 0, the caller knows
  2282. // the weight and shouldn't have made the call in the first place
  2283. var buffer=this.buffer,stride=this.valueSize,offset=accuIndex*stride+stride;var currentWeight=this.cumulativeWeight;if(currentWeight===0){// accuN := incoming * weight
  2284. for(var _i329=0;_i329!==stride;++_i329){buffer[offset+_i329]=buffer[_i329];}currentWeight=weight;}else {// accuN := accuN + incoming * weight
  2285. currentWeight+=weight;var mix=weight/currentWeight;this._mixBufferRegion(buffer,offset,0,mix,stride);}this.cumulativeWeight=currentWeight;},// accumulate data in the 'incoming' region into 'add'
  2286. accumulateAdditive:function accumulateAdditive(weight){var buffer=this.buffer,stride=this.valueSize,offset=stride*this._addIndex;if(this.cumulativeWeightAdditive===0){// add = identity
  2287. this._setIdentity();}// add := add + incoming * weight
  2288. this._mixBufferRegionAdditive(buffer,offset,0,weight,stride);this.cumulativeWeightAdditive+=weight;},// apply the state of 'accu<i>' to the binding when accus differ
  2289. apply:function apply(accuIndex){var stride=this.valueSize,buffer=this.buffer,offset=accuIndex*stride+stride,weight=this.cumulativeWeight,weightAdditive=this.cumulativeWeightAdditive,binding=this.binding;this.cumulativeWeight=0;this.cumulativeWeightAdditive=0;if(weight<1){// accuN := accuN + original * ( 1 - cumulativeWeight )
  2290. var originalValueOffset=stride*this._origIndex;this._mixBufferRegion(buffer,offset,originalValueOffset,1-weight,stride);}if(weightAdditive>0){// accuN := accuN + additive accuN
  2291. this._mixBufferRegionAdditive(buffer,offset,this._addIndex*stride,1,stride);}for(var _i330=stride,e=stride+stride;_i330!==e;++_i330){if(buffer[_i330]!==buffer[_i330+stride]){// value has changed -> update scene graph
  2292. binding.setValue(buffer,offset);break;}}},// remember the state of the bound property and copy it to both accus
  2293. saveOriginalState:function saveOriginalState(){var binding=this.binding;var buffer=this.buffer,stride=this.valueSize,originalValueOffset=stride*this._origIndex;binding.getValue(buffer,originalValueOffset);// accu[0..1] := orig -- initially detect changes against the original
  2294. for(var _i331=stride,e=originalValueOffset;_i331!==e;++_i331){buffer[_i331]=buffer[originalValueOffset+_i331%stride];}// Add to identity for additive
  2295. this._setIdentity();this.cumulativeWeight=0;this.cumulativeWeightAdditive=0;},// apply the state previously taken via 'saveOriginalState' to the binding
  2296. restoreOriginalState:function restoreOriginalState(){var originalValueOffset=this.valueSize*3;this.binding.setValue(this.buffer,originalValueOffset);},_setAdditiveIdentityNumeric:function _setAdditiveIdentityNumeric(){var startIndex=this._addIndex*this.valueSize;var endIndex=startIndex+this.valueSize;for(var _i332=startIndex;_i332<endIndex;_i332++){this.buffer[_i332]=0;}},_setAdditiveIdentityQuaternion:function _setAdditiveIdentityQuaternion(){this._setAdditiveIdentityNumeric();this.buffer[this._addIndex*this.valueSize+3]=1;},_setAdditiveIdentityOther:function _setAdditiveIdentityOther(){var startIndex=this._origIndex*this.valueSize;var targetIndex=this._addIndex*this.valueSize;for(var _i333=0;_i333<this.valueSize;_i333++){this.buffer[targetIndex+_i333]=this.buffer[startIndex+_i333];}},// mix functions
  2297. _select:function _select(buffer,dstOffset,srcOffset,t,stride){if(t>=0.5){for(var _i334=0;_i334!==stride;++_i334){buffer[dstOffset+_i334]=buffer[srcOffset+_i334];}}},_slerp:function _slerp(buffer,dstOffset,srcOffset,t){Quaternion.slerpFlat(buffer,dstOffset,buffer,dstOffset,buffer,srcOffset,t);},_slerpAdditive:function _slerpAdditive(buffer,dstOffset,srcOffset,t,stride){var workOffset=this._workIndex*stride;// Store result in intermediate buffer offset
  2298. Quaternion.multiplyQuaternionsFlat(buffer,workOffset,buffer,dstOffset,buffer,srcOffset);// Slerp to the intermediate result
  2299. Quaternion.slerpFlat(buffer,dstOffset,buffer,dstOffset,buffer,workOffset,t);},_lerp:function _lerp(buffer,dstOffset,srcOffset,t,stride){var s=1-t;for(var _i335=0;_i335!==stride;++_i335){var j=dstOffset+_i335;buffer[j]=buffer[j]*s+buffer[srcOffset+_i335]*t;}},_lerpAdditive:function _lerpAdditive(buffer,dstOffset,srcOffset,t,stride){for(var _i336=0;_i336!==stride;++_i336){var j=dstOffset+_i336;buffer[j]=buffer[j]+buffer[srcOffset+_i336]*t;}}});// Characters [].:/ are reserved for track binding syntax.
  2300. var _RESERVED_CHARS_RE='\\[\\]\\.:\\/';var _reservedRe=new RegExp('['+_RESERVED_CHARS_RE+']','g');// Attempts to allow node names from any language. ES5's `\w` regexp matches
  2301. // only latin characters, and the unicode \p{L} is not yet supported. So
  2302. // instead, we exclude reserved characters and match everything else.
  2303. var _wordChar='[^'+_RESERVED_CHARS_RE+']';var _wordCharOrDot='[^'+_RESERVED_CHARS_RE.replace('\\.','')+']';// Parent directories, delimited by '/' or ':'. Currently unused, but must
  2304. // be matched to parse the rest of the track name.
  2305. var _directoryRe=/((?:WC+[\/:])*)/.source.replace('WC',_wordChar);// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
  2306. var _nodeRe=/(WCOD+)?/.source.replace('WCOD',_wordCharOrDot);// Object on target node, and accessor. May not contain reserved
  2307. // characters. Accessor may contain any character except closing bracket.
  2308. var _objectRe=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace('WC',_wordChar);// Property and accessor. May not contain reserved characters. Accessor may
  2309. // contain any non-bracket characters.
  2310. var _propertyRe=/\.(WC+)(?:\[(.+)\])?/.source.replace('WC',_wordChar);var _trackRe=new RegExp(''+'^'+_directoryRe+_nodeRe+_objectRe+_propertyRe+'$');var _supportedObjectNames=['material','materials','bones'];function Composite(targetGroup,path,optionalParsedPath){var parsedPath=optionalParsedPath||PropertyBinding.parseTrackName(path);this._targetGroup=targetGroup;this._bindings=targetGroup.subscribe_(path,parsedPath);}Object.assign(Composite.prototype,{getValue:function getValue(array,offset){this.bind();// bind all binding
  2311. var firstValidIndex=this._targetGroup.nCachedObjects_,binding=this._bindings[firstValidIndex];// and only call .getValue on the first
  2312. if(binding!==undefined)binding.getValue(array,offset);},setValue:function setValue(array,offset){var bindings=this._bindings;for(var _i337=this._targetGroup.nCachedObjects_,n=bindings.length;_i337!==n;++_i337){bindings[_i337].setValue(array,offset);}},bind:function bind(){var bindings=this._bindings;for(var _i338=this._targetGroup.nCachedObjects_,n=bindings.length;_i338!==n;++_i338){bindings[_i338].bind();}},unbind:function unbind(){var bindings=this._bindings;for(var _i339=this._targetGroup.nCachedObjects_,n=bindings.length;_i339!==n;++_i339){bindings[_i339].unbind();}}});function PropertyBinding(rootNode,path,parsedPath){this.path=path;this.parsedPath=parsedPath||PropertyBinding.parseTrackName(path);this.node=PropertyBinding.findNode(rootNode,this.parsedPath.nodeName)||rootNode;this.rootNode=rootNode;}Object.assign(PropertyBinding,{Composite:Composite,create:function create(root,path,parsedPath){if(!(root&&root.isAnimationObjectGroup)){return new PropertyBinding(root,path,parsedPath);}else {return new PropertyBinding.Composite(root,path,parsedPath);}},/**
  2313. * Replaces spaces with underscores and removes unsupported characters from
  2314. * node names, to ensure compatibility with parseTrackName().
  2315. *
  2316. * @param {string} name Node name to be sanitized.
  2317. * @return {string}
  2318. */sanitizeNodeName:function sanitizeNodeName(name){return name.replace(/\s/g,'_').replace(_reservedRe,'');},parseTrackName:function parseTrackName(trackName){var matches=_trackRe.exec(trackName);if(!matches){throw new Error('PropertyBinding: Cannot parse trackName: '+trackName);}var results={// directoryName: matches[ 1 ], // (tschw) currently unused
  2319. nodeName:matches[2],objectName:matches[3],objectIndex:matches[4],propertyName:matches[5],// required
  2320. propertyIndex:matches[6]};var lastDot=results.nodeName&&results.nodeName.lastIndexOf('.');if(lastDot!==undefined&&lastDot!==-1){var objectName=results.nodeName.substring(lastDot+1);// Object names must be checked against an allowlist. Otherwise, there
  2321. // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
  2322. // 'bar' could be the objectName, or part of a nodeName (which can
  2323. // include '.' characters).
  2324. if(_supportedObjectNames.indexOf(objectName)!==-1){results.nodeName=results.nodeName.substring(0,lastDot);results.objectName=objectName;}}if(results.propertyName===null||results.propertyName.length===0){throw new Error('PropertyBinding: can not parse propertyName from trackName: '+trackName);}return results;},findNode:function findNode(root,nodeName){if(!nodeName||nodeName===''||nodeName==='.'||nodeName===-1||nodeName===root.name||nodeName===root.uuid){return root;}// search into skeleton bones.
  2325. if(root.skeleton){var bone=root.skeleton.getBoneByName(nodeName);if(bone!==undefined){return bone;}}// search into node subtree.
  2326. if(root.children){var _searchNodeSubtree=function searchNodeSubtree(children){for(var _i340=0;_i340<children.length;_i340++){var childNode=children[_i340];if(childNode.name===nodeName||childNode.uuid===nodeName){return childNode;}var result=_searchNodeSubtree(childNode.children);if(result)return result;}return null;};var subTreeNode=_searchNodeSubtree(root.children);if(subTreeNode){return subTreeNode;}}return null;}});Object.assign(PropertyBinding.prototype,{// prototype, continued
  2327. // these are used to "bind" a nonexistent property
  2328. _getValue_unavailable:function _getValue_unavailable(){},_setValue_unavailable:function _setValue_unavailable(){},BindingType:{Direct:0,EntireArray:1,ArrayElement:2,HasFromToArray:3},Versioning:{None:0,NeedsUpdate:1,MatrixWorldNeedsUpdate:2},GetterByBindingType:[function getValue_direct(buffer,offset){buffer[offset]=this.node[this.propertyName];},function getValue_array(buffer,offset){var source=this.resolvedProperty;for(var _i341=0,n=source.length;_i341!==n;++_i341){buffer[offset++]=source[_i341];}},function getValue_arrayElement(buffer,offset){buffer[offset]=this.resolvedProperty[this.propertyIndex];},function getValue_toArray(buffer,offset){this.resolvedProperty.toArray(buffer,offset);}],SetterByBindingTypeAndVersioning:[[// Direct
  2329. function setValue_direct(buffer,offset){this.targetObject[this.propertyName]=buffer[offset];},function setValue_direct_setNeedsUpdate(buffer,offset){this.targetObject[this.propertyName]=buffer[offset];this.targetObject.needsUpdate=true;},function setValue_direct_setMatrixWorldNeedsUpdate(buffer,offset){this.targetObject[this.propertyName]=buffer[offset];this.targetObject.matrixWorldNeedsUpdate=true;}],[// EntireArray
  2330. function setValue_array(buffer,offset){var dest=this.resolvedProperty;for(var _i342=0,n=dest.length;_i342!==n;++_i342){dest[_i342]=buffer[offset++];}},function setValue_array_setNeedsUpdate(buffer,offset){var dest=this.resolvedProperty;for(var _i343=0,n=dest.length;_i343!==n;++_i343){dest[_i343]=buffer[offset++];}this.targetObject.needsUpdate=true;},function setValue_array_setMatrixWorldNeedsUpdate(buffer,offset){var dest=this.resolvedProperty;for(var _i344=0,n=dest.length;_i344!==n;++_i344){dest[_i344]=buffer[offset++];}this.targetObject.matrixWorldNeedsUpdate=true;}],[// ArrayElement
  2331. function setValue_arrayElement(buffer,offset){this.resolvedProperty[this.propertyIndex]=buffer[offset];},function setValue_arrayElement_setNeedsUpdate(buffer,offset){this.resolvedProperty[this.propertyIndex]=buffer[offset];this.targetObject.needsUpdate=true;},function setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer,offset){this.resolvedProperty[this.propertyIndex]=buffer[offset];this.targetObject.matrixWorldNeedsUpdate=true;}],[// HasToFromArray
  2332. function setValue_fromArray(buffer,offset){this.resolvedProperty.fromArray(buffer,offset);},function setValue_fromArray_setNeedsUpdate(buffer,offset){this.resolvedProperty.fromArray(buffer,offset);this.targetObject.needsUpdate=true;},function setValue_fromArray_setMatrixWorldNeedsUpdate(buffer,offset){this.resolvedProperty.fromArray(buffer,offset);this.targetObject.matrixWorldNeedsUpdate=true;}]],getValue:function getValue_unbound(targetArray,offset){this.bind();this.getValue(targetArray,offset);// Note: This class uses a State pattern on a per-method basis:
  2333. // 'bind' sets 'this.getValue' / 'setValue' and shadows the
  2334. // prototype version of these methods with one that represents
  2335. // the bound state. When the property is not found, the methods
  2336. // become no-ops.
  2337. },setValue:function getValue_unbound(sourceArray,offset){this.bind();this.setValue(sourceArray,offset);},// create getter / setter pair for a property in the scene graph
  2338. bind:function bind(){var targetObject=this.node;var parsedPath=this.parsedPath;var objectName=parsedPath.objectName;var propertyName=parsedPath.propertyName;var propertyIndex=parsedPath.propertyIndex;if(!targetObject){targetObject=PropertyBinding.findNode(this.rootNode,parsedPath.nodeName)||this.rootNode;this.node=targetObject;}// set fail state so we can just 'return' on error
  2339. this.getValue=this._getValue_unavailable;this.setValue=this._setValue_unavailable;// ensure there is a value node
  2340. if(!targetObject){console.error('THREE.PropertyBinding: Trying to update node for track: '+this.path+' but it wasn\'t found.');return;}if(objectName){var objectIndex=parsedPath.objectIndex;// special cases were we need to reach deeper into the hierarchy to get the face materials....
  2341. switch(objectName){case'materials':if(!targetObject.material){console.error('THREE.PropertyBinding: Can not bind to material as node does not have a material.',this);return;}if(!targetObject.material.materials){console.error('THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.',this);return;}targetObject=targetObject.material.materials;break;case'bones':if(!targetObject.skeleton){console.error('THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.',this);return;}// potential future optimization: skip this if propertyIndex is already an integer
  2342. // and convert the integer string to a true integer.
  2343. targetObject=targetObject.skeleton.bones;// support resolving morphTarget names into indices.
  2344. for(var _i345=0;_i345<targetObject.length;_i345++){if(targetObject[_i345].name===objectIndex){objectIndex=_i345;break;}}break;default:if(targetObject[objectName]===undefined){console.error('THREE.PropertyBinding: Can not bind to objectName of node undefined.',this);return;}targetObject=targetObject[objectName];}if(objectIndex!==undefined){if(targetObject[objectIndex]===undefined){console.error('THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.',this,targetObject);return;}targetObject=targetObject[objectIndex];}}// resolve property
  2345. var nodeProperty=targetObject[propertyName];if(nodeProperty===undefined){var nodeName=parsedPath.nodeName;console.error('THREE.PropertyBinding: Trying to update property for track: '+nodeName+'.'+propertyName+' but it wasn\'t found.',targetObject);return;}// determine versioning scheme
  2346. var versioning=this.Versioning.None;this.targetObject=targetObject;if(targetObject.needsUpdate!==undefined){// material
  2347. versioning=this.Versioning.NeedsUpdate;}else if(targetObject.matrixWorldNeedsUpdate!==undefined){// node transform
  2348. versioning=this.Versioning.MatrixWorldNeedsUpdate;}// determine how the property gets bound
  2349. var bindingType=this.BindingType.Direct;if(propertyIndex!==undefined){// access a sub element of the property array (only primitives are supported right now)
  2350. if(propertyName==='morphTargetInfluences'){// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
  2351. // support resolving morphTarget names into indices.
  2352. if(!targetObject.geometry){console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.',this);return;}if(targetObject.geometry.isBufferGeometry){if(!targetObject.geometry.morphAttributes){console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.',this);return;}if(targetObject.morphTargetDictionary[propertyIndex]!==undefined){propertyIndex=targetObject.morphTargetDictionary[propertyIndex];}}else {console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences on THREE.Geometry. Use THREE.BufferGeometry instead.',this);return;}}bindingType=this.BindingType.ArrayElement;this.resolvedProperty=nodeProperty;this.propertyIndex=propertyIndex;}else if(nodeProperty.fromArray!==undefined&&nodeProperty.toArray!==undefined){// must use copy for Object3D.Euler/Quaternion
  2353. bindingType=this.BindingType.HasFromToArray;this.resolvedProperty=nodeProperty;}else if(Array.isArray(nodeProperty)){bindingType=this.BindingType.EntireArray;this.resolvedProperty=nodeProperty;}else {this.propertyName=propertyName;}// select getter / setter
  2354. this.getValue=this.GetterByBindingType[bindingType];this.setValue=this.SetterByBindingTypeAndVersioning[bindingType][versioning];},unbind:function unbind(){this.node=null;// back to the prototype version of getValue / setValue
  2355. // note: avoiding to mutate the shape of 'this' via 'delete'
  2356. this.getValue=this._getValue_unbound;this.setValue=this._setValue_unbound;}});// DECLARE ALIAS AFTER assign prototype
  2357. Object.assign(PropertyBinding.prototype,{// initial state of these methods that calls 'bind'
  2358. _getValue_unbound:PropertyBinding.prototype.getValue,_setValue_unbound:PropertyBinding.prototype.setValue});/**
  2359. *
  2360. * A group of objects that receives a shared animation state.
  2361. *
  2362. * Usage:
  2363. *
  2364. * - Add objects you would otherwise pass as 'root' to the
  2365. * constructor or the .clipAction method of AnimationMixer.
  2366. *
  2367. * - Instead pass this object as 'root'.
  2368. *
  2369. * - You can also add and remove objects later when the mixer
  2370. * is running.
  2371. *
  2372. * Note:
  2373. *
  2374. * Objects of this class appear as one object to the mixer,
  2375. * so cache control of the individual objects must be done
  2376. * on the group.
  2377. *
  2378. * Limitation:
  2379. *
  2380. * - The animated properties must be compatible among the
  2381. * all objects in the group.
  2382. *
  2383. * - A single property can either be controlled through a
  2384. * target group or directly, but not both.
  2385. */function AnimationObjectGroup(){this.uuid=MathUtils.generateUUID();// cached objects followed by the active ones
  2386. this._objects=Array.prototype.slice.call(arguments);this.nCachedObjects_=0;// threshold
  2387. // note: read by PropertyBinding.Composite
  2388. var indices={};this._indicesByUUID=indices;// for bookkeeping
  2389. for(var _i346=0,n=arguments.length;_i346!==n;++_i346){indices[arguments[_i346].uuid]=_i346;}this._paths=[];// inside: string
  2390. this._parsedPaths=[];// inside: { we don't care, here }
  2391. this._bindings=[];// inside: Array< PropertyBinding >
  2392. this._bindingsIndicesByPath={};// inside: indices in these arrays
  2393. var scope=this;this.stats={objects:{get total(){return scope._objects.length;},get inUse(){return this.total-scope.nCachedObjects_;}},get bindingsPerObject(){return scope._bindings.length;}};}Object.assign(AnimationObjectGroup.prototype,{isAnimationObjectGroup:true,add:function add(){var objects=this._objects,indicesByUUID=this._indicesByUUID,paths=this._paths,parsedPaths=this._parsedPaths,bindings=this._bindings,nBindings=bindings.length;var knownObject=undefined,nObjects=objects.length,nCachedObjects=this.nCachedObjects_;for(var _i347=0,n=arguments.length;_i347!==n;++_i347){var object=arguments[_i347],uuid=object.uuid;var index=indicesByUUID[uuid];if(index===undefined){// unknown object -> add it to the ACTIVE region
  2394. index=nObjects++;indicesByUUID[uuid]=index;objects.push(object);// accounting is done, now do the same for all bindings
  2395. for(var j=0,m=nBindings;j!==m;++j){bindings[j].push(new PropertyBinding(object,paths[j],parsedPaths[j]));}}else if(index<nCachedObjects){knownObject=objects[index];// move existing object to the ACTIVE region
  2396. var firstActiveIndex=--nCachedObjects,lastCachedObject=objects[firstActiveIndex];indicesByUUID[lastCachedObject.uuid]=index;objects[index]=lastCachedObject;indicesByUUID[uuid]=firstActiveIndex;objects[firstActiveIndex]=object;// accounting is done, now do the same for all bindings
  2397. for(var _j25=0,_m2=nBindings;_j25!==_m2;++_j25){var bindingsForPath=bindings[_j25],lastCached=bindingsForPath[firstActiveIndex];var binding=bindingsForPath[index];bindingsForPath[index]=lastCached;if(binding===undefined){// since we do not bother to create new bindings
  2398. // for objects that are cached, the binding may
  2399. // or may not exist
  2400. binding=new PropertyBinding(object,paths[_j25],parsedPaths[_j25]);}bindingsForPath[firstActiveIndex]=binding;}}else if(objects[index]!==knownObject){console.error('THREE.AnimationObjectGroup: Different objects with the same UUID '+'detected. Clean the caches or recreate your infrastructure when reloading scenes.');}// else the object is already where we want it to be
  2401. }// for arguments
  2402. this.nCachedObjects_=nCachedObjects;},remove:function remove(){var objects=this._objects,indicesByUUID=this._indicesByUUID,bindings=this._bindings,nBindings=bindings.length;var nCachedObjects=this.nCachedObjects_;for(var _i348=0,n=arguments.length;_i348!==n;++_i348){var object=arguments[_i348],uuid=object.uuid,index=indicesByUUID[uuid];if(index!==undefined&&index>=nCachedObjects){// move existing object into the CACHED region
  2403. var lastCachedIndex=nCachedObjects++,firstActiveObject=objects[lastCachedIndex];indicesByUUID[firstActiveObject.uuid]=index;objects[index]=firstActiveObject;indicesByUUID[uuid]=lastCachedIndex;objects[lastCachedIndex]=object;// accounting is done, now do the same for all bindings
  2404. for(var j=0,m=nBindings;j!==m;++j){var bindingsForPath=bindings[j],firstActive=bindingsForPath[lastCachedIndex],binding=bindingsForPath[index];bindingsForPath[index]=firstActive;bindingsForPath[lastCachedIndex]=binding;}}}// for arguments
  2405. this.nCachedObjects_=nCachedObjects;},// remove & forget
  2406. uncache:function uncache(){var objects=this._objects,indicesByUUID=this._indicesByUUID,bindings=this._bindings,nBindings=bindings.length;var nCachedObjects=this.nCachedObjects_,nObjects=objects.length;for(var _i349=0,n=arguments.length;_i349!==n;++_i349){var object=arguments[_i349],uuid=object.uuid,index=indicesByUUID[uuid];if(index!==undefined){delete indicesByUUID[uuid];if(index<nCachedObjects){// object is cached, shrink the CACHED region
  2407. var firstActiveIndex=--nCachedObjects,lastCachedObject=objects[firstActiveIndex],lastIndex=--nObjects,lastObject=objects[lastIndex];// last cached object takes this object's place
  2408. indicesByUUID[lastCachedObject.uuid]=index;objects[index]=lastCachedObject;// last object goes to the activated slot and pop
  2409. indicesByUUID[lastObject.uuid]=firstActiveIndex;objects[firstActiveIndex]=lastObject;objects.pop();// accounting is done, now do the same for all bindings
  2410. for(var j=0,m=nBindings;j!==m;++j){var bindingsForPath=bindings[j],lastCached=bindingsForPath[firstActiveIndex],last=bindingsForPath[lastIndex];bindingsForPath[index]=lastCached;bindingsForPath[firstActiveIndex]=last;bindingsForPath.pop();}}else {// object is active, just swap with the last and pop
  2411. var _lastIndex=--nObjects,_lastObject=objects[_lastIndex];if(_lastIndex>0){indicesByUUID[_lastObject.uuid]=index;}objects[index]=_lastObject;objects.pop();// accounting is done, now do the same for all bindings
  2412. for(var _j26=0,_m3=nBindings;_j26!==_m3;++_j26){var _bindingsForPath=bindings[_j26];_bindingsForPath[index]=_bindingsForPath[_lastIndex];_bindingsForPath.pop();}}// cached or active
  2413. }// if object is known
  2414. }// for arguments
  2415. this.nCachedObjects_=nCachedObjects;},// Internal interface used by befriended PropertyBinding.Composite:
  2416. subscribe_:function subscribe_(path,parsedPath){// returns an array of bindings for the given path that is changed
  2417. // according to the contained objects in the group
  2418. var indicesByPath=this._bindingsIndicesByPath;var index=indicesByPath[path];var bindings=this._bindings;if(index!==undefined)return bindings[index];var paths=this._paths,parsedPaths=this._parsedPaths,objects=this._objects,nObjects=objects.length,nCachedObjects=this.nCachedObjects_,bindingsForPath=new Array(nObjects);index=bindings.length;indicesByPath[path]=index;paths.push(path);parsedPaths.push(parsedPath);bindings.push(bindingsForPath);for(var _i350=nCachedObjects,n=objects.length;_i350!==n;++_i350){var object=objects[_i350];bindingsForPath[_i350]=new PropertyBinding(object,path,parsedPath);}return bindingsForPath;},unsubscribe_:function unsubscribe_(path){// tells the group to forget about a property path and no longer
  2419. // update the array previously obtained with 'subscribe_'
  2420. var indicesByPath=this._bindingsIndicesByPath,index=indicesByPath[path];if(index!==undefined){var paths=this._paths,parsedPaths=this._parsedPaths,bindings=this._bindings,lastBindingsIndex=bindings.length-1,lastBindings=bindings[lastBindingsIndex],lastBindingsPath=path[lastBindingsIndex];indicesByPath[lastBindingsPath]=index;bindings[index]=lastBindings;bindings.pop();parsedPaths[index]=parsedPaths[lastBindingsIndex];parsedPaths.pop();paths[index]=paths[lastBindingsIndex];paths.pop();}}});class AnimationAction{constructor(mixer,clip){var localRoot=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var blendMode=arguments.length>3&&arguments[3]!==undefined?arguments[3]:clip.blendMode;this._mixer=mixer;this._clip=clip;this._localRoot=localRoot;this.blendMode=blendMode;var tracks=clip.tracks,nTracks=tracks.length,interpolants=new Array(nTracks);var interpolantSettings={endingStart:ZeroCurvatureEnding,endingEnd:ZeroCurvatureEnding};for(var _i351=0;_i351!==nTracks;++_i351){var interpolant=tracks[_i351].createInterpolant(null);interpolants[_i351]=interpolant;interpolant.settings=interpolantSettings;}this._interpolantSettings=interpolantSettings;this._interpolants=interpolants;// bound by the mixer
  2421. // inside: PropertyMixer (managed by the mixer)
  2422. this._propertyBindings=new Array(nTracks);this._cacheIndex=null;// for the memory manager
  2423. this._byClipCacheIndex=null;// for the memory manager
  2424. this._timeScaleInterpolant=null;this._weightInterpolant=null;this.loop=LoopRepeat;this._loopCount=-1;// global mixer time when the action is to be started
  2425. // it's set back to 'null' upon start of the action
  2426. this._startTime=null;// scaled local time of the action
  2427. // gets clamped or wrapped to 0..clip.duration according to loop
  2428. this.time=0;this.timeScale=1;this._effectiveTimeScale=1;this.weight=1;this._effectiveWeight=1;this.repetitions=Infinity;// no. of repetitions when looping
  2429. this.paused=false;// true -> zero effective time scale
  2430. this.enabled=true;// false -> zero effective weight
  2431. this.clampWhenFinished=false;// keep feeding the last frame?
  2432. this.zeroSlopeAtStart=true;// for smooth interpolation w/o separate
  2433. this.zeroSlopeAtEnd=true;// clips for start, loop and end
  2434. }// State & Scheduling
  2435. play(){this._mixer._activateAction(this);return this;}stop(){this._mixer._deactivateAction(this);return this.reset();}reset(){this.paused=false;this.enabled=true;this.time=0;// restart clip
  2436. this._loopCount=-1;// forget previous loops
  2437. this._startTime=null;// forget scheduling
  2438. return this.stopFading().stopWarping();}isRunning(){return this.enabled&&!this.paused&&this.timeScale!==0&&this._startTime===null&&this._mixer._isActiveAction(this);}// return true when play has been called
  2439. isScheduled(){return this._mixer._isActiveAction(this);}startAt(time){this._startTime=time;return this;}setLoop(mode,repetitions){this.loop=mode;this.repetitions=repetitions;return this;}// Weight
  2440. // set the weight stopping any scheduled fading
  2441. // although .enabled = false yields an effective weight of zero, this
  2442. // method does *not* change .enabled, because it would be confusing
  2443. setEffectiveWeight(weight){this.weight=weight;// note: same logic as when updated at runtime
  2444. this._effectiveWeight=this.enabled?weight:0;return this.stopFading();}// return the weight considering fading and .enabled
  2445. getEffectiveWeight(){return this._effectiveWeight;}fadeIn(duration){return this._scheduleFading(duration,0,1);}fadeOut(duration){return this._scheduleFading(duration,1,0);}crossFadeFrom(fadeOutAction,duration,warp){fadeOutAction.fadeOut(duration);this.fadeIn(duration);if(warp){var fadeInDuration=this._clip.duration,fadeOutDuration=fadeOutAction._clip.duration,startEndRatio=fadeOutDuration/fadeInDuration,endStartRatio=fadeInDuration/fadeOutDuration;fadeOutAction.warp(1.0,startEndRatio,duration);this.warp(endStartRatio,1.0,duration);}return this;}crossFadeTo(fadeInAction,duration,warp){return fadeInAction.crossFadeFrom(this,duration,warp);}stopFading(){var weightInterpolant=this._weightInterpolant;if(weightInterpolant!==null){this._weightInterpolant=null;this._mixer._takeBackControlInterpolant(weightInterpolant);}return this;}// Time Scale Control
  2446. // set the time scale stopping any scheduled warping
  2447. // although .paused = true yields an effective time scale of zero, this
  2448. // method does *not* change .paused, because it would be confusing
  2449. setEffectiveTimeScale(timeScale){this.timeScale=timeScale;this._effectiveTimeScale=this.paused?0:timeScale;return this.stopWarping();}// return the time scale considering warping and .paused
  2450. getEffectiveTimeScale(){return this._effectiveTimeScale;}setDuration(duration){this.timeScale=this._clip.duration/duration;return this.stopWarping();}syncWith(action){this.time=action.time;this.timeScale=action.timeScale;return this.stopWarping();}halt(duration){return this.warp(this._effectiveTimeScale,0,duration);}warp(startTimeScale,endTimeScale,duration){var mixer=this._mixer,now=mixer.time,timeScale=this.timeScale;var interpolant=this._timeScaleInterpolant;if(interpolant===null){interpolant=mixer._lendControlInterpolant();this._timeScaleInterpolant=interpolant;}var times=interpolant.parameterPositions,values=interpolant.sampleValues;times[0]=now;times[1]=now+duration;values[0]=startTimeScale/timeScale;values[1]=endTimeScale/timeScale;return this;}stopWarping(){var timeScaleInterpolant=this._timeScaleInterpolant;if(timeScaleInterpolant!==null){this._timeScaleInterpolant=null;this._mixer._takeBackControlInterpolant(timeScaleInterpolant);}return this;}// Object Accessors
  2451. getMixer(){return this._mixer;}getClip(){return this._clip;}getRoot(){return this._localRoot||this._mixer._root;}// Interna
  2452. _update(time,deltaTime,timeDirection,accuIndex){// called by the mixer
  2453. if(!this.enabled){// call ._updateWeight() to update ._effectiveWeight
  2454. this._updateWeight(time);return;}var startTime=this._startTime;if(startTime!==null){// check for scheduled start of action
  2455. var timeRunning=(time-startTime)*timeDirection;if(timeRunning<0||timeDirection===0){return;// yet to come / don't decide when delta = 0
  2456. }// start
  2457. this._startTime=null;// unschedule
  2458. deltaTime=timeDirection*timeRunning;}// apply time scale and advance time
  2459. deltaTime*=this._updateTimeScale(time);var clipTime=this._updateTime(deltaTime);// note: _updateTime may disable the action resulting in
  2460. // an effective weight of 0
  2461. var weight=this._updateWeight(time);if(weight>0){var interpolants=this._interpolants;var propertyMixers=this._propertyBindings;switch(this.blendMode){case AdditiveAnimationBlendMode:for(var j=0,m=interpolants.length;j!==m;++j){interpolants[j].evaluate(clipTime);propertyMixers[j].accumulateAdditive(weight);}break;case NormalAnimationBlendMode:default:for(var _j27=0,_m4=interpolants.length;_j27!==_m4;++_j27){interpolants[_j27].evaluate(clipTime);propertyMixers[_j27].accumulate(accuIndex,weight);}}}}_updateWeight(time){var weight=0;if(this.enabled){weight=this.weight;var interpolant=this._weightInterpolant;if(interpolant!==null){var interpolantValue=interpolant.evaluate(time)[0];weight*=interpolantValue;if(time>interpolant.parameterPositions[1]){this.stopFading();if(interpolantValue===0){// faded out, disable
  2462. this.enabled=false;}}}}this._effectiveWeight=weight;return weight;}_updateTimeScale(time){var timeScale=0;if(!this.paused){timeScale=this.timeScale;var interpolant=this._timeScaleInterpolant;if(interpolant!==null){var interpolantValue=interpolant.evaluate(time)[0];timeScale*=interpolantValue;if(time>interpolant.parameterPositions[1]){this.stopWarping();if(timeScale===0){// motion has halted, pause
  2463. this.paused=true;}else {// warp done - apply final time scale
  2464. this.timeScale=timeScale;}}}}this._effectiveTimeScale=timeScale;return timeScale;}_updateTime(deltaTime){var duration=this._clip.duration;var loop=this.loop;var time=this.time+deltaTime;var loopCount=this._loopCount;var pingPong=loop===LoopPingPong;if(deltaTime===0){if(loopCount===-1)return time;return pingPong&&(loopCount&1)===1?duration-time:time;}if(loop===LoopOnce){if(loopCount===-1){// just started
  2465. this._loopCount=0;this._setEndings(true,true,false);}handle_stop:{if(time>=duration){time=duration;}else if(time<0){time=0;}else {this.time=time;break handle_stop;}if(this.clampWhenFinished)this.paused=true;else this.enabled=false;this.time=time;this._mixer.dispatchEvent({type:'finished',action:this,direction:deltaTime<0?-1:1});}}else {// repetitive Repeat or PingPong
  2466. if(loopCount===-1){// just started
  2467. if(deltaTime>=0){loopCount=0;this._setEndings(true,this.repetitions===0,pingPong);}else {// when looping in reverse direction, the initial
  2468. // transition through zero counts as a repetition,
  2469. // so leave loopCount at -1
  2470. this._setEndings(this.repetitions===0,true,pingPong);}}if(time>=duration||time<0){// wrap around
  2471. var loopDelta=Math.floor(time/duration);// signed
  2472. time-=duration*loopDelta;loopCount+=Math.abs(loopDelta);var pending=this.repetitions-loopCount;if(pending<=0){// have to stop (switch state, clamp time, fire event)
  2473. if(this.clampWhenFinished)this.paused=true;else this.enabled=false;time=deltaTime>0?duration:0;this.time=time;this._mixer.dispatchEvent({type:'finished',action:this,direction:deltaTime>0?1:-1});}else {// keep running
  2474. if(pending===1){// entering the last round
  2475. var atStart=deltaTime<0;this._setEndings(atStart,!atStart,pingPong);}else {this._setEndings(false,false,pingPong);}this._loopCount=loopCount;this.time=time;this._mixer.dispatchEvent({type:'loop',action:this,loopDelta:loopDelta});}}else {this.time=time;}if(pingPong&&(loopCount&1)===1){// invert time for the "pong round"
  2476. return duration-time;}}return time;}_setEndings(atStart,atEnd,pingPong){var settings=this._interpolantSettings;if(pingPong){settings.endingStart=ZeroSlopeEnding;settings.endingEnd=ZeroSlopeEnding;}else {// assuming for LoopOnce atStart == atEnd == true
  2477. if(atStart){settings.endingStart=this.zeroSlopeAtStart?ZeroSlopeEnding:ZeroCurvatureEnding;}else {settings.endingStart=WrapAroundEnding;}if(atEnd){settings.endingEnd=this.zeroSlopeAtEnd?ZeroSlopeEnding:ZeroCurvatureEnding;}else {settings.endingEnd=WrapAroundEnding;}}}_scheduleFading(duration,weightNow,weightThen){var mixer=this._mixer,now=mixer.time;var interpolant=this._weightInterpolant;if(interpolant===null){interpolant=mixer._lendControlInterpolant();this._weightInterpolant=interpolant;}var times=interpolant.parameterPositions,values=interpolant.sampleValues;times[0]=now;values[0]=weightNow;times[1]=now+duration;values[1]=weightThen;return this;}}function AnimationMixer(root){this._root=root;this._initMemoryManager();this._accuIndex=0;this.time=0;this.timeScale=1.0;}AnimationMixer.prototype=Object.assign(Object.create(EventDispatcher.prototype),{constructor:AnimationMixer,_bindAction:function _bindAction(action,prototypeAction){var root=action._localRoot||this._root,tracks=action._clip.tracks,nTracks=tracks.length,bindings=action._propertyBindings,interpolants=action._interpolants,rootUuid=root.uuid,bindingsByRoot=this._bindingsByRootAndName;var bindingsByName=bindingsByRoot[rootUuid];if(bindingsByName===undefined){bindingsByName={};bindingsByRoot[rootUuid]=bindingsByName;}for(var _i352=0;_i352!==nTracks;++_i352){var track=tracks[_i352],trackName=track.name;var binding=bindingsByName[trackName];if(binding!==undefined){bindings[_i352]=binding;}else {binding=bindings[_i352];if(binding!==undefined){// existing binding, make sure the cache knows
  2478. if(binding._cacheIndex===null){++binding.referenceCount;this._addInactiveBinding(binding,rootUuid,trackName);}continue;}var path=prototypeAction&&prototypeAction._propertyBindings[_i352].binding.parsedPath;binding=new PropertyMixer(PropertyBinding.create(root,trackName,path),track.ValueTypeName,track.getValueSize());++binding.referenceCount;this._addInactiveBinding(binding,rootUuid,trackName);bindings[_i352]=binding;}interpolants[_i352].resultBuffer=binding.buffer;}},_activateAction:function _activateAction(action){if(!this._isActiveAction(action)){if(action._cacheIndex===null){// this action has been forgotten by the cache, but the user
  2479. // appears to be still using it -> rebind
  2480. var rootUuid=(action._localRoot||this._root).uuid,clipUuid=action._clip.uuid,actionsForClip=this._actionsByClip[clipUuid];this._bindAction(action,actionsForClip&&actionsForClip.knownActions[0]);this._addInactiveAction(action,clipUuid,rootUuid);}var bindings=action._propertyBindings;// increment reference counts / sort out state
  2481. for(var _i353=0,n=bindings.length;_i353!==n;++_i353){var binding=bindings[_i353];if(binding.useCount++===0){this._lendBinding(binding);binding.saveOriginalState();}}this._lendAction(action);}},_deactivateAction:function _deactivateAction(action){if(this._isActiveAction(action)){var bindings=action._propertyBindings;// decrement reference counts / sort out state
  2482. for(var _i354=0,n=bindings.length;_i354!==n;++_i354){var binding=bindings[_i354];if(--binding.useCount===0){binding.restoreOriginalState();this._takeBackBinding(binding);}}this._takeBackAction(action);}},// Memory manager
  2483. _initMemoryManager:function _initMemoryManager(){this._actions=[];// 'nActiveActions' followed by inactive ones
  2484. this._nActiveActions=0;this._actionsByClip={};// inside:
  2485. // {
  2486. // knownActions: Array< AnimationAction > - used as prototypes
  2487. // actionByRoot: AnimationAction - lookup
  2488. // }
  2489. this._bindings=[];// 'nActiveBindings' followed by inactive ones
  2490. this._nActiveBindings=0;this._bindingsByRootAndName={};// inside: Map< name, PropertyMixer >
  2491. this._controlInterpolants=[];// same game as above
  2492. this._nActiveControlInterpolants=0;var scope=this;this.stats={actions:{get total(){return scope._actions.length;},get inUse(){return scope._nActiveActions;}},bindings:{get total(){return scope._bindings.length;},get inUse(){return scope._nActiveBindings;}},controlInterpolants:{get total(){return scope._controlInterpolants.length;},get inUse(){return scope._nActiveControlInterpolants;}}};},// Memory management for AnimationAction objects
  2493. _isActiveAction:function _isActiveAction(action){var index=action._cacheIndex;return index!==null&&index<this._nActiveActions;},_addInactiveAction:function _addInactiveAction(action,clipUuid,rootUuid){var actions=this._actions,actionsByClip=this._actionsByClip;var actionsForClip=actionsByClip[clipUuid];if(actionsForClip===undefined){actionsForClip={knownActions:[action],actionByRoot:{}};action._byClipCacheIndex=0;actionsByClip[clipUuid]=actionsForClip;}else {var knownActions=actionsForClip.knownActions;action._byClipCacheIndex=knownActions.length;knownActions.push(action);}action._cacheIndex=actions.length;actions.push(action);actionsForClip.actionByRoot[rootUuid]=action;},_removeInactiveAction:function _removeInactiveAction(action){var actions=this._actions,lastInactiveAction=actions[actions.length-1],cacheIndex=action._cacheIndex;lastInactiveAction._cacheIndex=cacheIndex;actions[cacheIndex]=lastInactiveAction;actions.pop();action._cacheIndex=null;var clipUuid=action._clip.uuid,actionsByClip=this._actionsByClip,actionsForClip=actionsByClip[clipUuid],knownActionsForClip=actionsForClip.knownActions,lastKnownAction=knownActionsForClip[knownActionsForClip.length-1],byClipCacheIndex=action._byClipCacheIndex;lastKnownAction._byClipCacheIndex=byClipCacheIndex;knownActionsForClip[byClipCacheIndex]=lastKnownAction;knownActionsForClip.pop();action._byClipCacheIndex=null;var actionByRoot=actionsForClip.actionByRoot,rootUuid=(action._localRoot||this._root).uuid;delete actionByRoot[rootUuid];if(knownActionsForClip.length===0){delete actionsByClip[clipUuid];}this._removeInactiveBindingsForAction(action);},_removeInactiveBindingsForAction:function _removeInactiveBindingsForAction(action){var bindings=action._propertyBindings;for(var _i355=0,n=bindings.length;_i355!==n;++_i355){var binding=bindings[_i355];if(--binding.referenceCount===0){this._removeInactiveBinding(binding);}}},_lendAction:function _lendAction(action){// [ active actions | inactive actions ]
  2494. // [ active actions >| inactive actions ]
  2495. // s a
  2496. // <-swap->
  2497. // a s
  2498. var actions=this._actions,prevIndex=action._cacheIndex,lastActiveIndex=this._nActiveActions++,firstInactiveAction=actions[lastActiveIndex];action._cacheIndex=lastActiveIndex;actions[lastActiveIndex]=action;firstInactiveAction._cacheIndex=prevIndex;actions[prevIndex]=firstInactiveAction;},_takeBackAction:function _takeBackAction(action){// [ active actions | inactive actions ]
  2499. // [ active actions |< inactive actions ]
  2500. // a s
  2501. // <-swap->
  2502. // s a
  2503. var actions=this._actions,prevIndex=action._cacheIndex,firstInactiveIndex=--this._nActiveActions,lastActiveAction=actions[firstInactiveIndex];action._cacheIndex=firstInactiveIndex;actions[firstInactiveIndex]=action;lastActiveAction._cacheIndex=prevIndex;actions[prevIndex]=lastActiveAction;},// Memory management for PropertyMixer objects
  2504. _addInactiveBinding:function _addInactiveBinding(binding,rootUuid,trackName){var bindingsByRoot=this._bindingsByRootAndName,bindings=this._bindings;var bindingByName=bindingsByRoot[rootUuid];if(bindingByName===undefined){bindingByName={};bindingsByRoot[rootUuid]=bindingByName;}bindingByName[trackName]=binding;binding._cacheIndex=bindings.length;bindings.push(binding);},_removeInactiveBinding:function _removeInactiveBinding(binding){var bindings=this._bindings,propBinding=binding.binding,rootUuid=propBinding.rootNode.uuid,trackName=propBinding.path,bindingsByRoot=this._bindingsByRootAndName,bindingByName=bindingsByRoot[rootUuid],lastInactiveBinding=bindings[bindings.length-1],cacheIndex=binding._cacheIndex;lastInactiveBinding._cacheIndex=cacheIndex;bindings[cacheIndex]=lastInactiveBinding;bindings.pop();delete bindingByName[trackName];if(Object.keys(bindingByName).length===0){delete bindingsByRoot[rootUuid];}},_lendBinding:function _lendBinding(binding){var bindings=this._bindings,prevIndex=binding._cacheIndex,lastActiveIndex=this._nActiveBindings++,firstInactiveBinding=bindings[lastActiveIndex];binding._cacheIndex=lastActiveIndex;bindings[lastActiveIndex]=binding;firstInactiveBinding._cacheIndex=prevIndex;bindings[prevIndex]=firstInactiveBinding;},_takeBackBinding:function _takeBackBinding(binding){var bindings=this._bindings,prevIndex=binding._cacheIndex,firstInactiveIndex=--this._nActiveBindings,lastActiveBinding=bindings[firstInactiveIndex];binding._cacheIndex=firstInactiveIndex;bindings[firstInactiveIndex]=binding;lastActiveBinding._cacheIndex=prevIndex;bindings[prevIndex]=lastActiveBinding;},// Memory management of Interpolants for weight and time scale
  2505. _lendControlInterpolant:function _lendControlInterpolant(){var interpolants=this._controlInterpolants,lastActiveIndex=this._nActiveControlInterpolants++;var interpolant=interpolants[lastActiveIndex];if(interpolant===undefined){interpolant=new LinearInterpolant(new Float32Array(2),new Float32Array(2),1,this._controlInterpolantsResultBuffer);interpolant.__cacheIndex=lastActiveIndex;interpolants[lastActiveIndex]=interpolant;}return interpolant;},_takeBackControlInterpolant:function _takeBackControlInterpolant(interpolant){var interpolants=this._controlInterpolants,prevIndex=interpolant.__cacheIndex,firstInactiveIndex=--this._nActiveControlInterpolants,lastActiveInterpolant=interpolants[firstInactiveIndex];interpolant.__cacheIndex=firstInactiveIndex;interpolants[firstInactiveIndex]=interpolant;lastActiveInterpolant.__cacheIndex=prevIndex;interpolants[prevIndex]=lastActiveInterpolant;},_controlInterpolantsResultBuffer:new Float32Array(1),// return an action for a clip optionally using a custom root target
  2506. // object (this method allocates a lot of dynamic memory in case a
  2507. // previously unknown clip/root combination is specified)
  2508. clipAction:function clipAction(clip,optionalRoot,blendMode){var root=optionalRoot||this._root,rootUuid=root.uuid;var clipObject=typeof clip==='string'?AnimationClip.findByName(root,clip):clip;var clipUuid=clipObject!==null?clipObject.uuid:clip;var actionsForClip=this._actionsByClip[clipUuid];var prototypeAction=null;if(blendMode===undefined){if(clipObject!==null){blendMode=clipObject.blendMode;}else {blendMode=NormalAnimationBlendMode;}}if(actionsForClip!==undefined){var existingAction=actionsForClip.actionByRoot[rootUuid];if(existingAction!==undefined&&existingAction.blendMode===blendMode){return existingAction;}// we know the clip, so we don't have to parse all
  2509. // the bindings again but can just copy
  2510. prototypeAction=actionsForClip.knownActions[0];// also, take the clip from the prototype action
  2511. if(clipObject===null)clipObject=prototypeAction._clip;}// clip must be known when specified via string
  2512. if(clipObject===null)return null;// allocate all resources required to run it
  2513. var newAction=new AnimationAction(this,clipObject,optionalRoot,blendMode);this._bindAction(newAction,prototypeAction);// and make the action known to the memory manager
  2514. this._addInactiveAction(newAction,clipUuid,rootUuid);return newAction;},// get an existing action
  2515. existingAction:function existingAction(clip,optionalRoot){var root=optionalRoot||this._root,rootUuid=root.uuid,clipObject=typeof clip==='string'?AnimationClip.findByName(root,clip):clip,clipUuid=clipObject?clipObject.uuid:clip,actionsForClip=this._actionsByClip[clipUuid];if(actionsForClip!==undefined){return actionsForClip.actionByRoot[rootUuid]||null;}return null;},// deactivates all previously scheduled actions
  2516. stopAllAction:function stopAllAction(){var actions=this._actions,nActions=this._nActiveActions;for(var _i356=nActions-1;_i356>=0;--_i356){actions[_i356].stop();}return this;},// advance the time and update apply the animation
  2517. update:function update(deltaTime){deltaTime*=this.timeScale;var actions=this._actions,nActions=this._nActiveActions,time=this.time+=deltaTime,timeDirection=Math.sign(deltaTime),accuIndex=this._accuIndex^=1;// run active actions
  2518. for(var _i357=0;_i357!==nActions;++_i357){var action=actions[_i357];action._update(time,deltaTime,timeDirection,accuIndex);}// update scene graph
  2519. var bindings=this._bindings,nBindings=this._nActiveBindings;for(var _i358=0;_i358!==nBindings;++_i358){bindings[_i358].apply(accuIndex);}return this;},// Allows you to seek to a specific time in an animation.
  2520. setTime:function setTime(timeInSeconds){this.time=0;// Zero out time attribute for AnimationMixer object;
  2521. for(var _i359=0;_i359<this._actions.length;_i359++){this._actions[_i359].time=0;// Zero out time attribute for all associated AnimationAction objects.
  2522. }return this.update(timeInSeconds);// Update used to set exact time. Returns "this" AnimationMixer object.
  2523. },// return this mixer's root target object
  2524. getRoot:function getRoot(){return this._root;},// free all resources specific to a particular clip
  2525. uncacheClip:function uncacheClip(clip){var actions=this._actions,clipUuid=clip.uuid,actionsByClip=this._actionsByClip,actionsForClip=actionsByClip[clipUuid];if(actionsForClip!==undefined){// note: just calling _removeInactiveAction would mess up the
  2526. // iteration state and also require updating the state we can
  2527. // just throw away
  2528. var actionsToRemove=actionsForClip.knownActions;for(var _i360=0,n=actionsToRemove.length;_i360!==n;++_i360){var action=actionsToRemove[_i360];this._deactivateAction(action);var cacheIndex=action._cacheIndex,lastInactiveAction=actions[actions.length-1];action._cacheIndex=null;action._byClipCacheIndex=null;lastInactiveAction._cacheIndex=cacheIndex;actions[cacheIndex]=lastInactiveAction;actions.pop();this._removeInactiveBindingsForAction(action);}delete actionsByClip[clipUuid];}},// free all resources specific to a particular root target object
  2529. uncacheRoot:function uncacheRoot(root){var rootUuid=root.uuid,actionsByClip=this._actionsByClip;for(var clipUuid in actionsByClip){var actionByRoot=actionsByClip[clipUuid].actionByRoot,action=actionByRoot[rootUuid];if(action!==undefined){this._deactivateAction(action);this._removeInactiveAction(action);}}var bindingsByRoot=this._bindingsByRootAndName,bindingByName=bindingsByRoot[rootUuid];if(bindingByName!==undefined){for(var trackName in bindingByName){var binding=bindingByName[trackName];binding.restoreOriginalState();this._removeInactiveBinding(binding);}}},// remove a targeted clip from the cache
  2530. uncacheAction:function uncacheAction(clip,optionalRoot){var action=this.existingAction(clip,optionalRoot);if(action!==null){this._deactivateAction(action);this._removeInactiveAction(action);}}});class Uniform{constructor(value){if(typeof value==='string'){console.warn('THREE.Uniform: Type parameter is no longer needed.');value=arguments[1];}this.value=value;}clone(){return new Uniform(this.value.clone===undefined?this.value:this.value.clone());}}function InstancedInterleavedBuffer(array,stride,meshPerAttribute){InterleavedBuffer.call(this,array,stride);this.meshPerAttribute=meshPerAttribute||1;}InstancedInterleavedBuffer.prototype=Object.assign(Object.create(InterleavedBuffer.prototype),{constructor:InstancedInterleavedBuffer,isInstancedInterleavedBuffer:true,copy:function copy(source){InterleavedBuffer.prototype.copy.call(this,source);this.meshPerAttribute=source.meshPerAttribute;return this;},clone:function clone(data){var ib=InterleavedBuffer.prototype.clone.call(this,data);ib.meshPerAttribute=this.meshPerAttribute;return ib;},toJSON:function toJSON(data){var json=InterleavedBuffer.prototype.toJSON.call(this,data);json.isInstancedInterleavedBuffer=true;json.meshPerAttribute=this.meshPerAttribute;return json;}});function GLBufferAttribute(buffer,type,itemSize,elementSize,count){this.buffer=buffer;this.type=type;this.itemSize=itemSize;this.elementSize=elementSize;this.count=count;this.version=0;}Object.defineProperty(GLBufferAttribute.prototype,'needsUpdate',{set:function set(value){if(value===true)this.version++;}});Object.assign(GLBufferAttribute.prototype,{isGLBufferAttribute:true,setBuffer:function setBuffer(buffer){this.buffer=buffer;return this;},setType:function setType(type,elementSize){this.type=type;this.elementSize=elementSize;return this;},setItemSize:function setItemSize(itemSize){this.itemSize=itemSize;return this;},setCount:function setCount(count){this.count=count;return this;}});function Raycaster(origin,direction,near,far){this.ray=new Ray(origin,direction);// direction is assumed to be normalized (for accurate distance calculations)
  2531. this.near=near||0;this.far=far||Infinity;this.camera=null;this.layers=new Layers();this.params={Mesh:{},Line:{threshold:1},LOD:{},Points:{threshold:1},Sprite:{}};Object.defineProperties(this.params,{PointCloud:{get:function get(){console.warn('THREE.Raycaster: params.PointCloud has been renamed to params.Points.');return this.Points;}}});}function ascSort(a,b){return a.distance-b.distance;}function _intersectObject(object,raycaster,intersects,recursive){if(object.layers.test(raycaster.layers)){object.raycast(raycaster,intersects);}if(recursive===true){var children=object.children;for(var _i361=0,l=children.length;_i361<l;_i361++){_intersectObject(children[_i361],raycaster,intersects,true);}}}Object.assign(Raycaster.prototype,{set:function set(origin,direction){// direction is assumed to be normalized (for accurate distance calculations)
  2532. this.ray.set(origin,direction);},setFromCamera:function setFromCamera(coords,camera){if(camera&&camera.isPerspectiveCamera){this.ray.origin.setFromMatrixPosition(camera.matrixWorld);this.ray.direction.set(coords.x,coords.y,0.5).unproject(camera).sub(this.ray.origin).normalize();this.camera=camera;}else if(camera&&camera.isOrthographicCamera){this.ray.origin.set(coords.x,coords.y,(camera.near+camera.far)/(camera.near-camera.far)).unproject(camera);// set origin in plane of camera
  2533. this.ray.direction.set(0,0,-1).transformDirection(camera.matrixWorld);this.camera=camera;}else {console.error('THREE.Raycaster: Unsupported camera type: '+camera.type);}},intersectObject:function intersectObject(object,recursive,optionalTarget){var intersects=optionalTarget||[];_intersectObject(object,this,intersects,recursive);intersects.sort(ascSort);return intersects;},intersectObjects:function intersectObjects(objects,recursive,optionalTarget){var intersects=optionalTarget||[];if(Array.isArray(objects)===false){console.warn('THREE.Raycaster.intersectObjects: objects is not an Array.');return intersects;}for(var _i362=0,l=objects.length;_i362<l;_i362++){_intersectObject(objects[_i362],this,intersects,recursive);}intersects.sort(ascSort);return intersects;}});/**
  2534. * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
  2535. *
  2536. * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
  2537. * The azimuthal angle (theta) is measured from the positive z-axis.
  2538. */class Spherical{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var phi=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var theta=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;this.radius=radius;this.phi=phi;// polar angle
  2539. this.theta=theta;// azimuthal angle
  2540. return this;}set(radius,phi,theta){this.radius=radius;this.phi=phi;this.theta=theta;return this;}clone(){return new this.constructor().copy(this);}copy(other){this.radius=other.radius;this.phi=other.phi;this.theta=other.theta;return this;}// restrict phi to be betwee EPS and PI-EPS
  2541. makeSafe(){var EPS=0.000001;this.phi=Math.max(EPS,Math.min(Math.PI-EPS,this.phi));return this;}setFromVector3(v){return this.setFromCartesianCoords(v.x,v.y,v.z);}setFromCartesianCoords(x,y,z){this.radius=Math.sqrt(x*x+y*y+z*z);if(this.radius===0){this.theta=0;this.phi=0;}else {this.theta=Math.atan2(x,z);this.phi=Math.acos(MathUtils.clamp(y/this.radius,-1,1));}return this;}}/**
  2542. * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
  2543. */class Cylindrical{constructor(radius,theta,y){this.radius=radius!==undefined?radius:1.0;// distance from the origin to a point in the x-z plane
  2544. this.theta=theta!==undefined?theta:0;// counterclockwise angle in the x-z plane measured in radians from the positive z-axis
  2545. this.y=y!==undefined?y:0;// height above the x-z plane
  2546. return this;}set(radius,theta,y){this.radius=radius;this.theta=theta;this.y=y;return this;}clone(){return new this.constructor().copy(this);}copy(other){this.radius=other.radius;this.theta=other.theta;this.y=other.y;return this;}setFromVector3(v){return this.setFromCartesianCoords(v.x,v.y,v.z);}setFromCartesianCoords(x,y,z){this.radius=Math.sqrt(x*x+z*z);this.theta=Math.atan2(x,z);this.y=y;return this;}}var _vector$8=/*@__PURE__*/new Vector2();class Box2{constructor(min,max){Object.defineProperty(this,'isBox2',{value:true});this.min=min!==undefined?min:new Vector2(+Infinity,+Infinity);this.max=max!==undefined?max:new Vector2(-Infinity,-Infinity);}set(min,max){this.min.copy(min);this.max.copy(max);return this;}setFromPoints(points){this.makeEmpty();for(var _i363=0,il=points.length;_i363<il;_i363++){this.expandByPoint(points[_i363]);}return this;}setFromCenterAndSize(center,size){var halfSize=_vector$8.copy(size).multiplyScalar(0.5);this.min.copy(center).sub(halfSize);this.max.copy(center).add(halfSize);return this;}clone(){return new this.constructor().copy(this);}copy(box){this.min.copy(box.min);this.max.copy(box.max);return this;}makeEmpty(){this.min.x=this.min.y=+Infinity;this.max.x=this.max.y=-Infinity;return this;}isEmpty(){// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  2547. return this.max.x<this.min.x||this.max.y<this.min.y;}getCenter(target){if(target===undefined){console.warn('THREE.Box2: .getCenter() target is now required');target=new Vector2();}return this.isEmpty()?target.set(0,0):target.addVectors(this.min,this.max).multiplyScalar(0.5);}getSize(target){if(target===undefined){console.warn('THREE.Box2: .getSize() target is now required');target=new Vector2();}return this.isEmpty()?target.set(0,0):target.subVectors(this.max,this.min);}expandByPoint(point){this.min.min(point);this.max.max(point);return this;}expandByVector(vector){this.min.sub(vector);this.max.add(vector);return this;}expandByScalar(scalar){this.min.addScalar(-scalar);this.max.addScalar(scalar);return this;}containsPoint(point){return point.x<this.min.x||point.x>this.max.x||point.y<this.min.y||point.y>this.max.y?false:true;}containsBox(box){return this.min.x<=box.min.x&&box.max.x<=this.max.x&&this.min.y<=box.min.y&&box.max.y<=this.max.y;}getParameter(point,target){// This can potentially have a divide by zero if the box
  2548. // has a size dimension of 0.
  2549. if(target===undefined){console.warn('THREE.Box2: .getParameter() target is now required');target=new Vector2();}return target.set((point.x-this.min.x)/(this.max.x-this.min.x),(point.y-this.min.y)/(this.max.y-this.min.y));}intersectsBox(box){// using 4 splitting planes to rule out intersections
  2550. return box.max.x<this.min.x||box.min.x>this.max.x||box.max.y<this.min.y||box.min.y>this.max.y?false:true;}clampPoint(point,target){if(target===undefined){console.warn('THREE.Box2: .clampPoint() target is now required');target=new Vector2();}return target.copy(point).clamp(this.min,this.max);}distanceToPoint(point){var clampedPoint=_vector$8.copy(point).clamp(this.min,this.max);return clampedPoint.sub(point).length();}intersect(box){this.min.max(box.min);this.max.min(box.max);return this;}union(box){this.min.min(box.min);this.max.max(box.max);return this;}translate(offset){this.min.add(offset);this.max.add(offset);return this;}equals(box){return box.min.equals(this.min)&&box.max.equals(this.max);}}var _startP=/*@__PURE__*/new Vector3();var _startEnd=/*@__PURE__*/new Vector3();class Line3{constructor(start,end){this.start=start!==undefined?start:new Vector3();this.end=end!==undefined?end:new Vector3();}set(start,end){this.start.copy(start);this.end.copy(end);return this;}clone(){return new this.constructor().copy(this);}copy(line){this.start.copy(line.start);this.end.copy(line.end);return this;}getCenter(target){if(target===undefined){console.warn('THREE.Line3: .getCenter() target is now required');target=new Vector3();}return target.addVectors(this.start,this.end).multiplyScalar(0.5);}delta(target){if(target===undefined){console.warn('THREE.Line3: .delta() target is now required');target=new Vector3();}return target.subVectors(this.end,this.start);}distanceSq(){return this.start.distanceToSquared(this.end);}distance(){return this.start.distanceTo(this.end);}at(t,target){if(target===undefined){console.warn('THREE.Line3: .at() target is now required');target=new Vector3();}return this.delta(target).multiplyScalar(t).add(this.start);}closestPointToPointParameter(point,clampToLine){_startP.subVectors(point,this.start);_startEnd.subVectors(this.end,this.start);var startEnd2=_startEnd.dot(_startEnd);var startEnd_startP=_startEnd.dot(_startP);var t=startEnd_startP/startEnd2;if(clampToLine){t=MathUtils.clamp(t,0,1);}return t;}closestPointToPoint(point,clampToLine,target){var t=this.closestPointToPointParameter(point,clampToLine);if(target===undefined){console.warn('THREE.Line3: .closestPointToPoint() target is now required');target=new Vector3();}return this.delta(target).multiplyScalar(t).add(this.start);}applyMatrix4(matrix){this.start.applyMatrix4(matrix);this.end.applyMatrix4(matrix);return this;}equals(line){return line.start.equals(this.start)&&line.end.equals(this.end);}}function ImmediateRenderObject(material){Object3D.call(this);this.material=material;this.render=function/* renderCallback */(){};this.hasPositions=false;this.hasNormals=false;this.hasColors=false;this.hasUvs=false;this.positionArray=null;this.normalArray=null;this.colorArray=null;this.uvArray=null;this.count=0;}ImmediateRenderObject.prototype=Object.create(Object3D.prototype);ImmediateRenderObject.prototype.constructor=ImmediateRenderObject;ImmediateRenderObject.prototype.isImmediateRenderObject=true;var _vector$9=/*@__PURE__*/new Vector3();class SpotLightHelper extends Object3D{constructor(light,color){super();this.light=light;this.light.updateMatrixWorld();this.matrix=light.matrixWorld;this.matrixAutoUpdate=false;this.color=color;var geometry=new BufferGeometry();var positions=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(var _i364=0,j=1,l=32;_i364<l;_i364++,j++){var p1=_i364/l*Math.PI*2;var p2=j/l*Math.PI*2;positions.push(Math.cos(p1),Math.sin(p1),1,Math.cos(p2),Math.sin(p2),1);}geometry.setAttribute('position',new Float32BufferAttribute(positions,3));var material=new LineBasicMaterial({fog:false,toneMapped:false});this.cone=new LineSegments(geometry,material);this.add(this.cone);this.update();}dispose(){this.cone.geometry.dispose();this.cone.material.dispose();}update(){this.light.updateMatrixWorld();var coneLength=this.light.distance?this.light.distance:1000;var coneWidth=coneLength*Math.tan(this.light.angle);this.cone.scale.set(coneWidth,coneWidth,coneLength);_vector$9.setFromMatrixPosition(this.light.target.matrixWorld);this.cone.lookAt(_vector$9);if(this.color!==undefined){this.cone.material.color.set(this.color);}else {this.cone.material.color.copy(this.light.color);}}}var _vector$a=/*@__PURE__*/new Vector3();var _boneMatrix=/*@__PURE__*/new Matrix4();var _matrixWorldInv=/*@__PURE__*/new Matrix4();class SkeletonHelper extends LineSegments{constructor(object){var bones=getBoneList(object);var geometry=new BufferGeometry();var vertices=[];var colors=[];var color1=new Color(0,0,1);var color2=new Color(0,1,0);for(var _i365=0;_i365<bones.length;_i365++){var bone=bones[_i365];if(bone.parent&&bone.parent.isBone){vertices.push(0,0,0);vertices.push(0,0,0);colors.push(color1.r,color1.g,color1.b);colors.push(color2.r,color2.g,color2.b);}}geometry.setAttribute('position',new Float32BufferAttribute(vertices,3));geometry.setAttribute('color',new Float32BufferAttribute(colors,3));var material=new LineBasicMaterial({vertexColors:true,depthTest:false,depthWrite:false,toneMapped:false,transparent:true});super(geometry,material);this.type='SkeletonHelper';this.isSkeletonHelper=true;this.root=object;this.bones=bones;this.matrix=object.matrixWorld;this.matrixAutoUpdate=false;}updateMatrixWorld(force){var bones=this.bones;var geometry=this.geometry;var position=geometry.getAttribute('position');_matrixWorldInv.copy(this.root.matrixWorld).invert();for(var _i366=0,j=0;_i366<bones.length;_i366++){var bone=bones[_i366];if(bone.parent&&bone.parent.isBone){_boneMatrix.multiplyMatrices(_matrixWorldInv,bone.matrixWorld);_vector$a.setFromMatrixPosition(_boneMatrix);position.setXYZ(j,_vector$a.x,_vector$a.y,_vector$a.z);_boneMatrix.multiplyMatrices(_matrixWorldInv,bone.parent.matrixWorld);_vector$a.setFromMatrixPosition(_boneMatrix);position.setXYZ(j+1,_vector$a.x,_vector$a.y,_vector$a.z);j+=2;}}geometry.getAttribute('position').needsUpdate=true;super.updateMatrixWorld(force);}}function getBoneList(object){var boneList=[];if(object&&object.isBone){boneList.push(object);}for(var _i367=0;_i367<object.children.length;_i367++){boneList.push.apply(boneList,getBoneList(object.children[_i367]));}return boneList;}class PointLightHelper extends Mesh{constructor(light,sphereSize,color){var geometry=new SphereBufferGeometry(sphereSize,4,2);var material=new MeshBasicMaterial({wireframe:true,fog:false,toneMapped:false});super(geometry,material);this.light=light;this.light.updateMatrixWorld();this.color=color;this.type='PointLightHelper';this.matrix=this.light.matrixWorld;this.matrixAutoUpdate=false;this.update();/*
  2551. // TODO: delete this comment?
  2552. const distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
  2553. const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
  2554. this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
  2555. this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
  2556. const d = light.distance;
  2557. if ( d === 0.0 ) {
  2558. this.lightDistance.visible = false;
  2559. } else {
  2560. this.lightDistance.scale.set( d, d, d );
  2561. }
  2562. this.add( this.lightDistance );
  2563. */}dispose(){this.geometry.dispose();this.material.dispose();}update(){if(this.color!==undefined){this.material.color.set(this.color);}else {this.material.color.copy(this.light.color);}/*
  2564. const d = this.light.distance;
  2565. if ( d === 0.0 ) {
  2566. this.lightDistance.visible = false;
  2567. } else {
  2568. this.lightDistance.visible = true;
  2569. this.lightDistance.scale.set( d, d, d );
  2570. }
  2571. */}}var _vector$b=/*@__PURE__*/new Vector3();var _color1=/*@__PURE__*/new Color();var _color2=/*@__PURE__*/new Color();class HemisphereLightHelper extends Object3D{constructor(light,size,color){super();this.light=light;this.light.updateMatrixWorld();this.matrix=light.matrixWorld;this.matrixAutoUpdate=false;this.color=color;var geometry=new OctahedronBufferGeometry(size);geometry.rotateY(Math.PI*0.5);this.material=new MeshBasicMaterial({wireframe:true,fog:false,toneMapped:false});if(this.color===undefined)this.material.vertexColors=true;var position=geometry.getAttribute('position');var colors=new Float32Array(position.count*3);geometry.setAttribute('color',new BufferAttribute(colors,3));this.add(new Mesh(geometry,this.material));this.update();}dispose(){this.children[0].geometry.dispose();this.children[0].material.dispose();}update(){var mesh=this.children[0];if(this.color!==undefined){this.material.color.set(this.color);}else {var colors=mesh.geometry.getAttribute('color');_color1.copy(this.light.color);_color2.copy(this.light.groundColor);for(var _i368=0,l=colors.count;_i368<l;_i368++){var color=_i368<l/2?_color1:_color2;colors.setXYZ(_i368,color.r,color.g,color.b);}colors.needsUpdate=true;}mesh.lookAt(_vector$b.setFromMatrixPosition(this.light.matrixWorld).negate());}}class GridHelper extends LineSegments{constructor(){var size=arguments.length>0&&arguments[0]!==undefined?arguments[0]:10;var divisions=arguments.length>1&&arguments[1]!==undefined?arguments[1]:10;var color1=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0x444444;var color2=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0x888888;color1=new Color(color1);color2=new Color(color2);var center=divisions/2;var step=size/divisions;var halfSize=size/2;var vertices=[],colors=[];for(var _i369=0,j=0,k=-halfSize;_i369<=divisions;_i369++,k+=step){vertices.push(-halfSize,0,k,halfSize,0,k);vertices.push(k,0,-halfSize,k,0,halfSize);var color=_i369===center?color1:color2;color.toArray(colors,j);j+=3;color.toArray(colors,j);j+=3;color.toArray(colors,j);j+=3;color.toArray(colors,j);j+=3;}var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute(vertices,3));geometry.setAttribute('color',new Float32BufferAttribute(colors,3));var material=new LineBasicMaterial({vertexColors:true,toneMapped:false});super(geometry,material);this.type='GridHelper';}}class PolarGridHelper extends LineSegments{constructor(){var radius=arguments.length>0&&arguments[0]!==undefined?arguments[0]:10;var radials=arguments.length>1&&arguments[1]!==undefined?arguments[1]:16;var circles=arguments.length>2&&arguments[2]!==undefined?arguments[2]:8;var divisions=arguments.length>3&&arguments[3]!==undefined?arguments[3]:64;var color1=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0x444444;var color2=arguments.length>5&&arguments[5]!==undefined?arguments[5]:0x888888;color1=new Color(color1);color2=new Color(color2);var vertices=[];var colors=[];// create the radials
  2572. for(var _i370=0;_i370<=radials;_i370++){var v=_i370/radials*(Math.PI*2);var x=Math.sin(v)*radius;var z=Math.cos(v)*radius;vertices.push(0,0,0);vertices.push(x,0,z);var color=_i370&1?color1:color2;colors.push(color.r,color.g,color.b);colors.push(color.r,color.g,color.b);}// create the circles
  2573. for(var _i371=0;_i371<=circles;_i371++){var _color=_i371&1?color1:color2;var r=radius-radius/circles*_i371;for(var j=0;j<divisions;j++){// first vertex
  2574. var _v4=j/divisions*(Math.PI*2);var _x5=Math.sin(_v4)*r;var _z3=Math.cos(_v4)*r;vertices.push(_x5,0,_z3);colors.push(_color.r,_color.g,_color.b);// second vertex
  2575. _v4=(j+1)/divisions*(Math.PI*2);_x5=Math.sin(_v4)*r;_z3=Math.cos(_v4)*r;vertices.push(_x5,0,_z3);colors.push(_color.r,_color.g,_color.b);}}var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute(vertices,3));geometry.setAttribute('color',new Float32BufferAttribute(colors,3));var material=new LineBasicMaterial({vertexColors:true,toneMapped:false});super(geometry,material);this.type='PolarGridHelper';}}var _v1$6=/*@__PURE__*/new Vector3();var _v2$3=/*@__PURE__*/new Vector3();var _v3$1=/*@__PURE__*/new Vector3();class DirectionalLightHelper extends Object3D{constructor(light,size,color){super();this.light=light;this.light.updateMatrixWorld();this.matrix=light.matrixWorld;this.matrixAutoUpdate=false;this.color=color;if(size===undefined)size=1;var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute([-size,size,0,size,size,0,size,-size,0,-size,-size,0,-size,size,0],3));var material=new LineBasicMaterial({fog:false,toneMapped:false});this.lightPlane=new Line(geometry,material);this.add(this.lightPlane);geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute([0,0,0,0,0,1],3));this.targetLine=new Line(geometry,material);this.add(this.targetLine);this.update();}dispose(){this.lightPlane.geometry.dispose();this.lightPlane.material.dispose();this.targetLine.geometry.dispose();this.targetLine.material.dispose();}update(){_v1$6.setFromMatrixPosition(this.light.matrixWorld);_v2$3.setFromMatrixPosition(this.light.target.matrixWorld);_v3$1.subVectors(_v2$3,_v1$6);this.lightPlane.lookAt(_v2$3);if(this.color!==undefined){this.lightPlane.material.color.set(this.color);this.targetLine.material.color.set(this.color);}else {this.lightPlane.material.color.copy(this.light.color);this.targetLine.material.color.copy(this.light.color);}this.targetLine.lookAt(_v2$3);this.targetLine.scale.z=_v3$1.length();}}var _vector$c=/*@__PURE__*/new Vector3();var _camera=/*@__PURE__*/new Camera();/**
  2576. * - shows frustum, line of sight and up of the camera
  2577. * - suitable for fast updates
  2578. * - based on frustum visualization in lightgl.js shadowmap example
  2579. * http://evanw.github.com/lightgl.js/tests/shadowmap.html
  2580. */class CameraHelper extends LineSegments{constructor(camera){var geometry=new BufferGeometry();var material=new LineBasicMaterial({color:0xffffff,vertexColors:true,toneMapped:false});var vertices=[];var colors=[];var pointMap={};// colors
  2581. var colorFrustum=new Color(0xffaa00);var colorCone=new Color(0xff0000);var colorUp=new Color(0x00aaff);var colorTarget=new Color(0xffffff);var colorCross=new Color(0x333333);// near
  2582. addLine('n1','n2',colorFrustum);addLine('n2','n4',colorFrustum);addLine('n4','n3',colorFrustum);addLine('n3','n1',colorFrustum);// far
  2583. addLine('f1','f2',colorFrustum);addLine('f2','f4',colorFrustum);addLine('f4','f3',colorFrustum);addLine('f3','f1',colorFrustum);// sides
  2584. addLine('n1','f1',colorFrustum);addLine('n2','f2',colorFrustum);addLine('n3','f3',colorFrustum);addLine('n4','f4',colorFrustum);// cone
  2585. addLine('p','n1',colorCone);addLine('p','n2',colorCone);addLine('p','n3',colorCone);addLine('p','n4',colorCone);// up
  2586. addLine('u1','u2',colorUp);addLine('u2','u3',colorUp);addLine('u3','u1',colorUp);// target
  2587. addLine('c','t',colorTarget);addLine('p','c',colorCross);// cross
  2588. addLine('cn1','cn2',colorCross);addLine('cn3','cn4',colorCross);addLine('cf1','cf2',colorCross);addLine('cf3','cf4',colorCross);function addLine(a,b,color){addPoint(a,color);addPoint(b,color);}function addPoint(id,color){vertices.push(0,0,0);colors.push(color.r,color.g,color.b);if(pointMap[id]===undefined){pointMap[id]=[];}pointMap[id].push(vertices.length/3-1);}geometry.setAttribute('position',new Float32BufferAttribute(vertices,3));geometry.setAttribute('color',new Float32BufferAttribute(colors,3));super(geometry,material);this.type='CameraHelper';this.camera=camera;if(this.camera.updateProjectionMatrix)this.camera.updateProjectionMatrix();this.matrix=camera.matrixWorld;this.matrixAutoUpdate=false;this.pointMap=pointMap;this.update();}update(){var geometry=this.geometry;var pointMap=this.pointMap;var w=1,h=1;// we need just camera projection matrix inverse
  2589. // world matrix must be identity
  2590. _camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse);// center / target
  2591. setPoint('c',pointMap,geometry,_camera,0,0,-1);setPoint('t',pointMap,geometry,_camera,0,0,1);// near
  2592. setPoint('n1',pointMap,geometry,_camera,-w,-h,-1);setPoint('n2',pointMap,geometry,_camera,w,-h,-1);setPoint('n3',pointMap,geometry,_camera,-w,h,-1);setPoint('n4',pointMap,geometry,_camera,w,h,-1);// far
  2593. setPoint('f1',pointMap,geometry,_camera,-w,-h,1);setPoint('f2',pointMap,geometry,_camera,w,-h,1);setPoint('f3',pointMap,geometry,_camera,-w,h,1);setPoint('f4',pointMap,geometry,_camera,w,h,1);// up
  2594. setPoint('u1',pointMap,geometry,_camera,w*0.7,h*1.1,-1);setPoint('u2',pointMap,geometry,_camera,-w*0.7,h*1.1,-1);setPoint('u3',pointMap,geometry,_camera,0,h*2,-1);// cross
  2595. setPoint('cf1',pointMap,geometry,_camera,-w,0,1);setPoint('cf2',pointMap,geometry,_camera,w,0,1);setPoint('cf3',pointMap,geometry,_camera,0,-h,1);setPoint('cf4',pointMap,geometry,_camera,0,h,1);setPoint('cn1',pointMap,geometry,_camera,-w,0,-1);setPoint('cn2',pointMap,geometry,_camera,w,0,-1);setPoint('cn3',pointMap,geometry,_camera,0,-h,-1);setPoint('cn4',pointMap,geometry,_camera,0,h,-1);geometry.getAttribute('position').needsUpdate=true;}}function setPoint(point,pointMap,geometry,camera,x,y,z){_vector$c.set(x,y,z).unproject(camera);var points=pointMap[point];if(points!==undefined){var position=geometry.getAttribute('position');for(var _i372=0,l=points.length;_i372<l;_i372++){position.setXYZ(points[_i372],_vector$c.x,_vector$c.y,_vector$c.z);}}}var _box$3=/*@__PURE__*/new Box3();class BoxHelper extends LineSegments{constructor(object){var color=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0xffff00;var 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]);var positions=new Float32Array(8*3);var geometry=new BufferGeometry();geometry.setIndex(new BufferAttribute(indices,1));geometry.setAttribute('position',new BufferAttribute(positions,3));super(geometry,new LineBasicMaterial({color:color,toneMapped:false}));this.object=object;this.type='BoxHelper';this.matrixAutoUpdate=false;this.update();}update(object){if(object!==undefined){console.warn('THREE.BoxHelper: .update() has no longer arguments.');}if(this.object!==undefined){_box$3.setFromObject(this.object);}if(_box$3.isEmpty())return;var min=_box$3.min;var max=_box$3.max;/*
  2596. 5____4
  2597. 1/___0/|
  2598. | 6__|_7
  2599. 2/___3/
  2600. 0: max.x, max.y, max.z
  2601. 1: min.x, max.y, max.z
  2602. 2: min.x, min.y, max.z
  2603. 3: max.x, min.y, max.z
  2604. 4: max.x, max.y, min.z
  2605. 5: min.x, max.y, min.z
  2606. 6: min.x, min.y, min.z
  2607. 7: max.x, min.y, min.z
  2608. */var position=this.geometry.attributes.position;var array=position.array;array[0]=max.x;array[1]=max.y;array[2]=max.z;array[3]=min.x;array[4]=max.y;array[5]=max.z;array[6]=min.x;array[7]=min.y;array[8]=max.z;array[9]=max.x;array[10]=min.y;array[11]=max.z;array[12]=max.x;array[13]=max.y;array[14]=min.z;array[15]=min.x;array[16]=max.y;array[17]=min.z;array[18]=min.x;array[19]=min.y;array[20]=min.z;array[21]=max.x;array[22]=min.y;array[23]=min.z;position.needsUpdate=true;this.geometry.computeBoundingSphere();}setFromObject(object){this.object=object;this.update();return this;}copy(source){LineSegments.prototype.copy.call(this,source);this.object=source.object;return this;}}class Box3Helper extends LineSegments{constructor(box){var color=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0xffff00;var 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]);var 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];var geometry=new BufferGeometry();geometry.setIndex(new BufferAttribute(indices,1));geometry.setAttribute('position',new Float32BufferAttribute(positions,3));super(geometry,new LineBasicMaterial({color:color,toneMapped:false}));this.box=box;this.type='Box3Helper';this.geometry.computeBoundingSphere();}updateMatrixWorld(force){var box=this.box;if(box.isEmpty())return;box.getCenter(this.position);box.getSize(this.scale);this.scale.multiplyScalar(0.5);super.updateMatrixWorld(force);}}class PlaneHelper extends Line{constructor(plane){var size=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var hex=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0xffff00;var color=hex;var 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];var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute(positions,3));geometry.computeBoundingSphere();super(geometry,new LineBasicMaterial({color:color,toneMapped:false}));this.type='PlaneHelper';this.plane=plane;this.size=size;var positions2=[1,1,1,-1,1,1,-1,-1,1,1,1,1,-1,-1,1,1,-1,1];var geometry2=new BufferGeometry();geometry2.setAttribute('position',new Float32BufferAttribute(positions2,3));geometry2.computeBoundingSphere();this.add(new Mesh(geometry2,new MeshBasicMaterial({color:color,opacity:0.2,transparent:true,depthWrite:false,toneMapped:false})));}updateMatrixWorld(force){var scale=-this.plane.constant;if(Math.abs(scale)<1e-8)scale=1e-8;// sign does not matter
  2609. this.scale.set(0.5*this.size,0.5*this.size,scale);this.children[0].material.side=scale<0?BackSide:FrontSide;// renderer flips side when determinant < 0; flipping not wanted here
  2610. this.lookAt(this.plane.normal);super.updateMatrixWorld(force);}}var _axis=/*@__PURE__*/new Vector3();var _lineGeometry,_coneGeometry;class ArrowHelper extends Object3D{constructor(dir,origin,length,color,headLength,headWidth){super();// dir is assumed to be normalized
  2611. this.type='ArrowHelper';if(dir===undefined)dir=new Vector3(0,0,1);if(origin===undefined)origin=new Vector3(0,0,0);if(length===undefined)length=1;if(color===undefined)color=0xffff00;if(headLength===undefined)headLength=0.2*length;if(headWidth===undefined)headWidth=0.2*headLength;if(_lineGeometry===undefined){_lineGeometry=new BufferGeometry();_lineGeometry.setAttribute('position',new Float32BufferAttribute([0,0,0,0,1,0],3));_coneGeometry=new CylinderBufferGeometry(0,0.5,1,5,1);_coneGeometry.translate(0,-0.5,0);}this.position.copy(origin);this.line=new Line(_lineGeometry,new LineBasicMaterial({color:color,toneMapped:false}));this.line.matrixAutoUpdate=false;this.add(this.line);this.cone=new Mesh(_coneGeometry,new MeshBasicMaterial({color:color,toneMapped:false}));this.cone.matrixAutoUpdate=false;this.add(this.cone);this.setDirection(dir);this.setLength(length,headLength,headWidth);}setDirection(dir){// dir is assumed to be normalized
  2612. if(dir.y>0.99999){this.quaternion.set(0,0,0,1);}else if(dir.y<-0.99999){this.quaternion.set(1,0,0,0);}else {_axis.set(dir.z,0,-dir.x).normalize();var radians=Math.acos(dir.y);this.quaternion.setFromAxisAngle(_axis,radians);}}setLength(length,headLength,headWidth){if(headLength===undefined)headLength=0.2*length;if(headWidth===undefined)headWidth=0.2*headLength;this.line.scale.set(1,Math.max(0.0001,length-headLength),1);// see #17458
  2613. this.line.updateMatrix();this.cone.scale.set(headWidth,headLength,headWidth);this.cone.position.y=length;this.cone.updateMatrix();}setColor(color){this.line.material.color.set(color);this.cone.material.color.set(color);}copy(source){super.copy(source,false);this.line.copy(source.line);this.cone.copy(source.cone);return this;}}class AxesHelper extends LineSegments{constructor(){var size=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1;var vertices=[0,0,0,size,0,0,0,0,0,0,size,0,0,0,0,0,0,size];var colors=[1,0,0,1,0.6,0,0,1,0,0.6,1,0,0,0,1,0,0.6,1];var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute(vertices,3));geometry.setAttribute('color',new Float32BufferAttribute(colors,3));var material=new LineBasicMaterial({vertexColors:true,toneMapped:false});super(geometry,material);this.type='AxesHelper';}}var _floatView=new Float32Array(1);var _int32View=new Int32Array(_floatView.buffer);var DataUtils={// Converts float32 to float16 (stored as uint16 value).
  2614. toHalfFloat:function toHalfFloat(val){// Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
  2615. /* This method is faster than the OpenEXR implementation (very often
  2616. * used, eg. in Ogre), with the additional benefit of rounding, inspired
  2617. * by James Tursa?s half-precision code. */_floatView[0]=val;var x=_int32View[0];var bits=x>>16&0x8000;/* Get the sign */var m=x>>12&0x07ff;/* Keep one extra bit for rounding */var e=x>>23&0xff;/* Using int is faster here */ /* If zero, or denormal, or exponent underflows too much for a denormal
  2618. * half, return signed zero. */if(e<103)return bits;/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */if(e>142){bits|=0x7c00;/* If exponent was 0xff and one mantissa bit was set, it means NaN,
  2619. * not Inf, so make sure we set one mantissa bit too. */bits|=(e==255?0:1)&&x&0x007fffff;return bits;}/* If exponent underflows but not too much, return a denormal */if(e<113){m|=0x0800;/* Extra rounding may overflow and set mantissa to 0 and exponent
  2620. * to 1, which is OK. */bits|=(m>>114-e)+(m>>113-e&1);return bits;}bits|=e-112<<10|m>>1;/* Extra rounding. An overflow will set mantissa to 0 and increment
  2621. * the exponent, which is OK. */bits+=m&1;return bits;}};var LOD_MIN=4;var LOD_MAX=8;var SIZE_MAX=Math.pow(2,LOD_MAX);// The standard deviations (radians) associated with the extra mips. These are
  2622. // chosen to approximate a Trowbridge-Reitz distribution function times the
  2623. // geometric shadowing function. These sigma values squared must match the
  2624. // variance #defines in cube_uv_reflection_fragment.glsl.js.
  2625. var EXTRA_LOD_SIGMA=[0.125,0.215,0.35,0.446,0.526,0.582];var TOTAL_LODS=LOD_MAX-LOD_MIN+1+EXTRA_LOD_SIGMA.length;// The maximum length of the blur for loop. Smaller sigmas will use fewer
  2626. // samples and exit early, but not recompile the shader.
  2627. var MAX_SAMPLES=20;var ENCODINGS={[LinearEncoding]:0,[sRGBEncoding]:1,[RGBEEncoding]:2,[RGBM7Encoding]:3,[RGBM16Encoding]:4,[RGBDEncoding]:5,[GammaEncoding]:6};var _flatCamera=/*@__PURE__*/new OrthographicCamera();var{_lodPlanes,_sizeLods,_sigmas}=/*@__PURE__*/_createPlanes();var _clearColor=/*@__PURE__*/new Color();var _oldTarget=null;// Golden Ratio
  2628. var PHI=(1+Math.sqrt(5))/2;var INV_PHI=1/PHI;// Vertices of a dodecahedron (except the opposites, which represent the
  2629. // same axis), used as axis directions evenly spread on a sphere.
  2630. var _axisDirections=[/*@__PURE__*/new Vector3(1,1,1),/*@__PURE__*/new Vector3(-1,1,1),/*@__PURE__*/new Vector3(1,1,-1),/*@__PURE__*/new Vector3(-1,1,-1),/*@__PURE__*/new Vector3(0,PHI,INV_PHI),/*@__PURE__*/new Vector3(0,PHI,-INV_PHI),/*@__PURE__*/new Vector3(INV_PHI,0,PHI),/*@__PURE__*/new Vector3(-INV_PHI,0,PHI),/*@__PURE__*/new Vector3(PHI,INV_PHI,0),/*@__PURE__*/new Vector3(-PHI,INV_PHI,0)];/**
  2631. * This class generates a Prefiltered, Mipmapped Radiance Environment Map
  2632. * (PMREM) from a cubeMap environment texture. This allows different levels of
  2633. * blur to be quickly accessed based on material roughness. It is packed into a
  2634. * special CubeUV format that allows us to perform custom interpolation so that
  2635. * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
  2636. * chain, it only goes down to the LOD_MIN level (above), and then creates extra
  2637. * even more filtered 'mips' at the same LOD_MIN resolution, associated with
  2638. * higher roughness levels. In this way we maintain resolution to smoothly
  2639. * interpolate diffuse lighting while limiting sampling computation.
  2640. */class PMREMGenerator{constructor(renderer){this._renderer=renderer;this._pingPongRenderTarget=null;this._blurMaterial=_getBlurShader(MAX_SAMPLES);this._equirectShader=null;this._cubemapShader=null;this._compileMaterial(this._blurMaterial);}/**
  2641. * Generates a PMREM from a supplied Scene, which can be faster than using an
  2642. * image if networking bandwidth is low. Optional sigma specifies a blur radius
  2643. * in radians to be applied to the scene before PMREM generation. Optional near
  2644. * and far planes ensure the scene is rendered in its entirety (the cubeCamera
  2645. * is placed at the origin).
  2646. */fromScene(scene){var sigma=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var near=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0.1;var far=arguments.length>3&&arguments[3]!==undefined?arguments[3]:100;_oldTarget=this._renderer.getRenderTarget();var cubeUVRenderTarget=this._allocateTargets();this._sceneToCubeUV(scene,near,far,cubeUVRenderTarget);if(sigma>0){this._blur(cubeUVRenderTarget,0,0,sigma);}this._applyPMREM(cubeUVRenderTarget);this._cleanup(cubeUVRenderTarget);return cubeUVRenderTarget;}/**
  2647. * Generates a PMREM from an equirectangular texture, which can be either LDR
  2648. * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
  2649. * as this matches best with the 256 x 256 cubemap output.
  2650. */fromEquirectangular(equirectangular){return this._fromTexture(equirectangular);}/**
  2651. * Generates a PMREM from an cubemap texture, which can be either LDR
  2652. * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
  2653. * as this matches best with the 256 x 256 cubemap output.
  2654. */fromCubemap(cubemap){return this._fromTexture(cubemap);}/**
  2655. * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
  2656. * your texture's network fetch for increased concurrency.
  2657. */compileCubemapShader(){if(this._cubemapShader===null){this._cubemapShader=_getCubemapShader();this._compileMaterial(this._cubemapShader);}}/**
  2658. * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
  2659. * your texture's network fetch for increased concurrency.
  2660. */compileEquirectangularShader(){if(this._equirectShader===null){this._equirectShader=_getEquirectShader();this._compileMaterial(this._equirectShader);}}/**
  2661. * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
  2662. * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
  2663. * one of them will cause any others to also become unusable.
  2664. */dispose(){this._blurMaterial.dispose();if(this._cubemapShader!==null)this._cubemapShader.dispose();if(this._equirectShader!==null)this._equirectShader.dispose();for(var _i373=0;_i373<_lodPlanes.length;_i373++){_lodPlanes[_i373].dispose();}}// private interface
  2665. _cleanup(outputTarget){this._pingPongRenderTarget.dispose();this._renderer.setRenderTarget(_oldTarget);outputTarget.scissorTest=false;_setViewport(outputTarget,0,0,outputTarget.width,outputTarget.height);}_fromTexture(texture){_oldTarget=this._renderer.getRenderTarget();var cubeUVRenderTarget=this._allocateTargets(texture);this._textureToCubeUV(texture,cubeUVRenderTarget);this._applyPMREM(cubeUVRenderTarget);this._cleanup(cubeUVRenderTarget);return cubeUVRenderTarget;}_allocateTargets(texture){// warning: null texture is valid
  2666. var params={magFilter:NearestFilter,minFilter:NearestFilter,generateMipmaps:false,type:UnsignedByteType,format:RGBEFormat,encoding:_isLDR(texture)?texture.encoding:RGBEEncoding,depthBuffer:false};var cubeUVRenderTarget=_createRenderTarget(params);cubeUVRenderTarget.depthBuffer=texture?false:true;this._pingPongRenderTarget=_createRenderTarget(params);return cubeUVRenderTarget;}_compileMaterial(material){var tmpMesh=new Mesh(_lodPlanes[0],material);this._renderer.compile(tmpMesh,_flatCamera);}_sceneToCubeUV(scene,near,far,cubeUVRenderTarget){var fov=90;var aspect=1;var cubeCamera=new PerspectiveCamera(fov,aspect,near,far);var upSign=[1,-1,1,1,1,1];var forwardSign=[1,1,1,-1,-1,-1];var renderer=this._renderer;var outputEncoding=renderer.outputEncoding;var toneMapping=renderer.toneMapping;renderer.getClearColor(_clearColor);var clearAlpha=renderer.getClearAlpha();renderer.toneMapping=NoToneMapping;renderer.outputEncoding=LinearEncoding;var background=scene.background;if(background&&background.isColor){background.convertSRGBToLinear();// Convert linear to RGBE
  2667. var maxComponent=Math.max(background.r,background.g,background.b);var fExp=Math.min(Math.max(Math.ceil(Math.log2(maxComponent)),-128.0),127.0);background=background.multiplyScalar(Math.pow(2.0,-fExp));var alpha=(fExp+128.0)/255.0;renderer.setClearColor(background,alpha);scene.background=null;}for(var _i374=0;_i374<6;_i374++){var col=_i374%3;if(col==0){cubeCamera.up.set(0,upSign[_i374],0);cubeCamera.lookAt(forwardSign[_i374],0,0);}else if(col==1){cubeCamera.up.set(0,0,upSign[_i374]);cubeCamera.lookAt(0,forwardSign[_i374],0);}else {cubeCamera.up.set(0,upSign[_i374],0);cubeCamera.lookAt(0,0,forwardSign[_i374]);}_setViewport(cubeUVRenderTarget,col*SIZE_MAX,_i374>2?SIZE_MAX:0,SIZE_MAX,SIZE_MAX);renderer.setRenderTarget(cubeUVRenderTarget);renderer.render(scene,cubeCamera);}renderer.toneMapping=toneMapping;renderer.outputEncoding=outputEncoding;renderer.setClearColor(_clearColor,clearAlpha);}_textureToCubeUV(texture,cubeUVRenderTarget){var renderer=this._renderer;if(texture.isCubeTexture){if(this._cubemapShader==null){this._cubemapShader=_getCubemapShader();}}else {if(this._equirectShader==null){this._equirectShader=_getEquirectShader();}}var material=texture.isCubeTexture?this._cubemapShader:this._equirectShader;var mesh=new Mesh(_lodPlanes[0],material);var uniforms=material.uniforms;uniforms['envMap'].value=texture;if(!texture.isCubeTexture){uniforms['texelSize'].value.set(1.0/texture.image.width,1.0/texture.image.height);}uniforms['inputEncoding'].value=ENCODINGS[texture.encoding];uniforms['outputEncoding'].value=ENCODINGS[cubeUVRenderTarget.texture.encoding];_setViewport(cubeUVRenderTarget,0,0,3*SIZE_MAX,2*SIZE_MAX);renderer.setRenderTarget(cubeUVRenderTarget);renderer.render(mesh,_flatCamera);}_applyPMREM(cubeUVRenderTarget){var renderer=this._renderer;var autoClear=renderer.autoClear;renderer.autoClear=false;for(var _i375=1;_i375<TOTAL_LODS;_i375++){var sigma=Math.sqrt(_sigmas[_i375]*_sigmas[_i375]-_sigmas[_i375-1]*_sigmas[_i375-1]);var poleAxis=_axisDirections[(_i375-1)%_axisDirections.length];this._blur(cubeUVRenderTarget,_i375-1,_i375,sigma,poleAxis);}renderer.autoClear=autoClear;}/**
  2668. * This is a two-pass Gaussian blur for a cubemap. Normally this is done
  2669. * vertically and horizontally, but this breaks down on a cube. Here we apply
  2670. * the blur latitudinally (around the poles), and then longitudinally (towards
  2671. * the poles) to approximate the orthogonally-separable blur. It is least
  2672. * accurate at the poles, but still does a decent job.
  2673. */_blur(cubeUVRenderTarget,lodIn,lodOut,sigma,poleAxis){var pingPongRenderTarget=this._pingPongRenderTarget;this._halfBlur(cubeUVRenderTarget,pingPongRenderTarget,lodIn,lodOut,sigma,'latitudinal',poleAxis);this._halfBlur(pingPongRenderTarget,cubeUVRenderTarget,lodOut,lodOut,sigma,'longitudinal',poleAxis);}_halfBlur(targetIn,targetOut,lodIn,lodOut,sigmaRadians,direction,poleAxis){var renderer=this._renderer;var blurMaterial=this._blurMaterial;if(direction!=='latitudinal'&&direction!=='longitudinal'){console.error('blur direction must be either latitudinal or longitudinal!');}// Number of standard deviations at which to cut off the discrete approximation.
  2674. var STANDARD_DEVIATIONS=3;var blurMesh=new Mesh(_lodPlanes[lodOut],blurMaterial);var blurUniforms=blurMaterial.uniforms;var pixels=_sizeLods[lodIn]-1;var radiansPerPixel=isFinite(sigmaRadians)?Math.PI/(2*pixels):2*Math.PI/(2*MAX_SAMPLES-1);var sigmaPixels=sigmaRadians/radiansPerPixel;var samples=isFinite(sigmaRadians)?1+Math.floor(STANDARD_DEVIATIONS*sigmaPixels):MAX_SAMPLES;if(samples>MAX_SAMPLES){console.warn("sigmaRadians, ".concat(sigmaRadians,", is too large and will clip, as it requested ").concat(samples," samples when the maximum is set to ").concat(MAX_SAMPLES));}var weights=[];var sum=0;for(var _i376=0;_i376<MAX_SAMPLES;++_i376){var _x6=_i376/sigmaPixels;var weight=Math.exp(-_x6*_x6/2);weights.push(weight);if(_i376==0){sum+=weight;}else if(_i376<samples){sum+=2*weight;}}for(var _i377=0;_i377<weights.length;_i377++){weights[_i377]=weights[_i377]/sum;}blurUniforms['envMap'].value=targetIn.texture;blurUniforms['samples'].value=samples;blurUniforms['weights'].value=weights;blurUniforms['latitudinal'].value=direction==='latitudinal';if(poleAxis){blurUniforms['poleAxis'].value=poleAxis;}blurUniforms['dTheta'].value=radiansPerPixel;blurUniforms['mipInt'].value=LOD_MAX-lodIn;blurUniforms['inputEncoding'].value=ENCODINGS[targetIn.texture.encoding];blurUniforms['outputEncoding'].value=ENCODINGS[targetIn.texture.encoding];var outputSize=_sizeLods[lodOut];var x=3*Math.max(0,SIZE_MAX-2*outputSize);var y=(lodOut===0?0:2*SIZE_MAX)+2*outputSize*(lodOut>LOD_MAX-LOD_MIN?lodOut-LOD_MAX+LOD_MIN:0);_setViewport(targetOut,x,y,3*outputSize,2*outputSize);renderer.setRenderTarget(targetOut);renderer.render(blurMesh,_flatCamera);}}function _isLDR(texture){if(texture===undefined||texture.type!==UnsignedByteType)return false;return texture.encoding===LinearEncoding||texture.encoding===sRGBEncoding||texture.encoding===GammaEncoding;}function _createPlanes(){var _lodPlanes=[];var _sizeLods=[];var _sigmas=[];var lod=LOD_MAX;for(var _i378=0;_i378<TOTAL_LODS;_i378++){var sizeLod=Math.pow(2,lod);_sizeLods.push(sizeLod);var sigma=1.0/sizeLod;if(_i378>LOD_MAX-LOD_MIN){sigma=EXTRA_LOD_SIGMA[_i378-LOD_MAX+LOD_MIN-1];}else if(_i378==0){sigma=0;}_sigmas.push(sigma);var texelSize=1.0/(sizeLod-1);var min=-texelSize/2;var max=1+texelSize/2;var uv1=[min,min,max,min,max,max,min,min,max,max,min,max];var cubeFaces=6;var vertices=6;var positionSize=3;var uvSize=2;var faceIndexSize=1;var position=new Float32Array(positionSize*vertices*cubeFaces);var uv=new Float32Array(uvSize*vertices*cubeFaces);var faceIndex=new Float32Array(faceIndexSize*vertices*cubeFaces);for(var face=0;face<cubeFaces;face++){var x=face%3*2/3-1;var y=face>2?0:-1;var coordinates=[x,y,0,x+2/3,y,0,x+2/3,y+1,0,x,y,0,x+2/3,y+1,0,x,y+1,0];position.set(coordinates,positionSize*vertices*face);uv.set(uv1,uvSize*vertices*face);var fill=[face,face,face,face,face,face];faceIndex.set(fill,faceIndexSize*vertices*face);}var planes=new BufferGeometry();planes.setAttribute('position',new BufferAttribute(position,positionSize));planes.setAttribute('uv',new BufferAttribute(uv,uvSize));planes.setAttribute('faceIndex',new BufferAttribute(faceIndex,faceIndexSize));_lodPlanes.push(planes);if(lod>LOD_MIN){lod--;}}return {_lodPlanes,_sizeLods,_sigmas};}function _createRenderTarget(params){var cubeUVRenderTarget=new WebGLRenderTarget(3*SIZE_MAX,3*SIZE_MAX,params);cubeUVRenderTarget.texture.mapping=CubeUVReflectionMapping;cubeUVRenderTarget.texture.name='PMREM.cubeUv';cubeUVRenderTarget.scissorTest=true;return cubeUVRenderTarget;}function _setViewport(target,x,y,width,height){target.viewport.set(x,y,width,height);target.scissor.set(x,y,width,height);}function _getBlurShader(maxSamples){var weights=new Float32Array(maxSamples);var poleAxis=new Vector3(0,1,0);var shaderMaterial=new RawShaderMaterial({name:'SphericalGaussianBlur',defines:{'n':maxSamples},uniforms:{'envMap':{value:null},'samples':{value:1},'weights':{value:weights},'latitudinal':{value:false},'dTheta':{value:0},'mipInt':{value:0},'poleAxis':{value:poleAxis},'inputEncoding':{value:ENCODINGS[LinearEncoding]},'outputEncoding':{value:ENCODINGS[LinearEncoding]}},vertexShader:_getCommonVertexShader(),fragmentShader:/* glsl */"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t".concat(_getEncodings(),"\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include <cube_uv_reflection_fragment>\n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t"),blending:NoBlending,depthTest:false,depthWrite:false});return shaderMaterial;}function _getEquirectShader(){var texelSize=new Vector2(1,1);var shaderMaterial=new RawShaderMaterial({name:'EquirectangularToCubeUV',uniforms:{'envMap':{value:null},'texelSize':{value:texelSize},'inputEncoding':{value:ENCODINGS[LinearEncoding]},'outputEncoding':{value:ENCODINGS[LinearEncoding]}},vertexShader:_getCommonVertexShader(),fragmentShader:/* glsl */"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform vec2 texelSize;\n\n\t\t\t".concat(_getEncodings(),"\n\n\t\t\t#include <common>\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tvec2 f = fract( uv / texelSize - 0.5 );\n\t\t\t\tuv -= f * texelSize;\n\t\t\t\tvec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.x += texelSize.x;\n\t\t\t\tvec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.y += texelSize.y;\n\t\t\t\tvec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\t\t\t\tuv.x -= texelSize.x;\n\t\t\t\tvec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;\n\n\t\t\t\tvec3 tm = mix( tl, tr, f.x );\n\t\t\t\tvec3 bm = mix( bl, br, f.x );\n\t\t\t\tgl_FragColor.rgb = mix( tm, bm, f.y );\n\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t"),blending:NoBlending,depthTest:false,depthWrite:false});return shaderMaterial;}function _getCubemapShader(){var shaderMaterial=new RawShaderMaterial({name:'CubemapToCubeUV',uniforms:{'envMap':{value:null},'inputEncoding':{value:ENCODINGS[LinearEncoding]},'outputEncoding':{value:ENCODINGS[LinearEncoding]}},vertexShader:_getCommonVertexShader(),fragmentShader:/* glsl */"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\t".concat(_getEncodings(),"\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;\n\t\t\t\tgl_FragColor = linearToOutputTexel( gl_FragColor );\n\n\t\t\t}\n\t\t"),blending:NoBlending,depthTest:false,depthWrite:false});return shaderMaterial;}function _getCommonVertexShader(){return/* glsl */"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute vec3 position;\n\t\tattribute vec2 uv;\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t";}function _getEncodings(){return/* glsl */"\n\n\t\tuniform int inputEncoding;\n\t\tuniform int outputEncoding;\n\n\t\t#include <encodings_pars_fragment>\n\n\t\tvec4 inputTexelToLinear( vec4 value ) {\n\n\t\t\tif ( inputEncoding == 0 ) {\n\n\t\t\t\treturn value;\n\n\t\t\t} else if ( inputEncoding == 1 ) {\n\n\t\t\t\treturn sRGBToLinear( value );\n\n\t\t\t} else if ( inputEncoding == 2 ) {\n\n\t\t\t\treturn RGBEToLinear( value );\n\n\t\t\t} else if ( inputEncoding == 3 ) {\n\n\t\t\t\treturn RGBMToLinear( value, 7.0 );\n\n\t\t\t} else if ( inputEncoding == 4 ) {\n\n\t\t\t\treturn RGBMToLinear( value, 16.0 );\n\n\t\t\t} else if ( inputEncoding == 5 ) {\n\n\t\t\t\treturn RGBDToLinear( value, 256.0 );\n\n\t\t\t} else {\n\n\t\t\t\treturn GammaToLinear( value, 2.2 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvec4 linearToOutputTexel( vec4 value ) {\n\n\t\t\tif ( outputEncoding == 0 ) {\n\n\t\t\t\treturn value;\n\n\t\t\t} else if ( outputEncoding == 1 ) {\n\n\t\t\t\treturn LinearTosRGB( value );\n\n\t\t\t} else if ( outputEncoding == 2 ) {\n\n\t\t\t\treturn LinearToRGBE( value );\n\n\t\t\t} else if ( outputEncoding == 3 ) {\n\n\t\t\t\treturn LinearToRGBM( value, 7.0 );\n\n\t\t\t} else if ( outputEncoding == 4 ) {\n\n\t\t\t\treturn LinearToRGBM( value, 16.0 );\n\n\t\t\t} else if ( outputEncoding == 5 ) {\n\n\t\t\t\treturn LinearToRGBD( value, 256.0 );\n\n\t\t\t} else {\n\n\t\t\t\treturn LinearToGamma( value, 2.2 );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvec4 envMapTexelToLinear( vec4 color ) {\n\n\t\t\treturn inputTexelToLinear( color );\n\n\t\t}\n\t";}function Face4(a,b,c,d,normal,color,materialIndex){console.warn('THREE.Face4 has been removed. A THREE.Face3 will be created instead.');return new Face3(a,b,c,normal,color,materialIndex);}var LineStrip=0;var LinePieces=1;var NoColors=0;var FaceColors=1;var VertexColors=2;function MeshFaceMaterial(materials){console.warn('THREE.MeshFaceMaterial has been removed. Use an Array instead.');return materials;}function MultiMaterial(){var materials=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];console.warn('THREE.MultiMaterial has been removed. Use an Array instead.');materials.isMultiMaterial=true;materials.materials=materials;materials.clone=function(){return materials.slice();};return materials;}function PointCloud(geometry,material){console.warn('THREE.PointCloud has been renamed to THREE.Points.');return new Points(geometry,material);}function Particle(material){console.warn('THREE.Particle has been renamed to THREE.Sprite.');return new Sprite$1(material);}function ParticleSystem(geometry,material){console.warn('THREE.ParticleSystem has been renamed to THREE.Points.');return new Points(geometry,material);}function PointCloudMaterial(parameters){console.warn('THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.');return new PointsMaterial(parameters);}function ParticleBasicMaterial(parameters){console.warn('THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.');return new PointsMaterial(parameters);}function ParticleSystemMaterial(parameters){console.warn('THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.');return new PointsMaterial(parameters);}function Vertex(x,y,z){console.warn('THREE.Vertex has been removed. Use THREE.Vector3 instead.');return new Vector3(x,y,z);}//
  2675. function DynamicBufferAttribute(array,itemSize){console.warn('THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead.');return new BufferAttribute(array,itemSize).setUsage(DynamicDrawUsage);}function Int8Attribute(array,itemSize){console.warn('THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.');return new Int8BufferAttribute(array,itemSize);}function Uint8Attribute(array,itemSize){console.warn('THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.');return new Uint8BufferAttribute(array,itemSize);}function Uint8ClampedAttribute(array,itemSize){console.warn('THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.');return new Uint8ClampedBufferAttribute(array,itemSize);}function Int16Attribute(array,itemSize){console.warn('THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.');return new Int16BufferAttribute(array,itemSize);}function Uint16Attribute(array,itemSize){console.warn('THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.');return new Uint16BufferAttribute(array,itemSize);}function Int32Attribute(array,itemSize){console.warn('THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.');return new Int32BufferAttribute(array,itemSize);}function Uint32Attribute(array,itemSize){console.warn('THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.');return new Uint32BufferAttribute(array,itemSize);}function Float32Attribute(array,itemSize){console.warn('THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.');return new Float32BufferAttribute(array,itemSize);}function Float64Attribute(array,itemSize){console.warn('THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.');return new Float64BufferAttribute(array,itemSize);}//
  2676. Curve.create=function(construct,getPoint){console.log('THREE.Curve.create() has been deprecated');construct.prototype=Object.create(Curve.prototype);construct.prototype.constructor=construct;construct.prototype.getPoint=getPoint;return construct;};//
  2677. Object.assign(CurvePath.prototype,{createPointsGeometry:function createPointsGeometry(divisions){console.warn('THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');// generate geometry from path points (for Line or Points objects)
  2678. var pts=this.getPoints(divisions);return this.createGeometry(pts);},createSpacedPointsGeometry:function createSpacedPointsGeometry(divisions){console.warn('THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');// generate geometry from equidistant sampling along the path
  2679. var pts=this.getSpacedPoints(divisions);return this.createGeometry(pts);},createGeometry:function createGeometry(points){console.warn('THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.');var geometry=new Geometry();for(var _i379=0,l=points.length;_i379<l;_i379++){var point=points[_i379];geometry.vertices.push(new Vector3(point.x,point.y,point.z||0));}return geometry;}});//
  2680. Object.assign(Path.prototype,{fromPoints:function fromPoints(points){console.warn('THREE.Path: .fromPoints() has been renamed to .setFromPoints().');return this.setFromPoints(points);}});//
  2681. function ClosedSplineCurve3(points){console.warn('THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.');CatmullRomCurve3.call(this,points);this.type='catmullrom';this.closed=true;}ClosedSplineCurve3.prototype=Object.create(CatmullRomCurve3.prototype);//
  2682. function SplineCurve3(points){console.warn('THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.');CatmullRomCurve3.call(this,points);this.type='catmullrom';}SplineCurve3.prototype=Object.create(CatmullRomCurve3.prototype);//
  2683. function Spline(points){console.warn('THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.');CatmullRomCurve3.call(this,points);this.type='catmullrom';}Spline.prototype=Object.create(CatmullRomCurve3.prototype);Object.assign(Spline.prototype,{initFromArray:function initFromArray(/* a */){console.error('THREE.Spline: .initFromArray() has been removed.');},getControlPointsArray:function getControlPointsArray(/* optionalTarget */){console.error('THREE.Spline: .getControlPointsArray() has been removed.');},reparametrizeByArcLength:function reparametrizeByArcLength(/* samplingCoef */){console.error('THREE.Spline: .reparametrizeByArcLength() has been removed.');}});//
  2684. function AxisHelper(size){console.warn('THREE.AxisHelper has been renamed to THREE.AxesHelper.');return new AxesHelper(size);}function BoundingBoxHelper(object,color){console.warn('THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.');return new BoxHelper(object,color);}function EdgesHelper(object,hex){console.warn('THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.');return new LineSegments(new EdgesGeometry(object.geometry),new LineBasicMaterial({color:hex!==undefined?hex:0xffffff}));}GridHelper.prototype.setColors=function(){console.error('THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.');};SkeletonHelper.prototype.update=function(){console.error('THREE.SkeletonHelper: update() no longer needs to be called.');};function WireframeHelper(object,hex){console.warn('THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.');return new LineSegments(new WireframeGeometry(object.geometry),new LineBasicMaterial({color:hex!==undefined?hex:0xffffff}));}//
  2685. Object.assign(Loader.prototype,{extractUrlBase:function extractUrlBase(url){console.warn('THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.');return LoaderUtils.extractUrlBase(url);}});Loader.Handlers={add:function add(/* regex, loader */){console.error('THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.');},get:function get(/* file */){console.error('THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.');}};function XHRLoader(manager){console.warn('THREE.XHRLoader has been renamed to THREE.FileLoader.');return new FileLoader(manager);}function BinaryTextureLoader(manager){console.warn('THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.');return new DataTextureLoader(manager);}//
  2686. Object.assign(Box2.prototype,{center:function center(optionalTarget){console.warn('THREE.Box2: .center() has been renamed to .getCenter().');return this.getCenter(optionalTarget);},empty:function empty(){console.warn('THREE.Box2: .empty() has been renamed to .isEmpty().');return this.isEmpty();},isIntersectionBox:function isIntersectionBox(box){console.warn('THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().');return this.intersectsBox(box);},size:function size(optionalTarget){console.warn('THREE.Box2: .size() has been renamed to .getSize().');return this.getSize(optionalTarget);}});Object.assign(Box3.prototype,{center:function center(optionalTarget){console.warn('THREE.Box3: .center() has been renamed to .getCenter().');return this.getCenter(optionalTarget);},empty:function empty(){console.warn('THREE.Box3: .empty() has been renamed to .isEmpty().');return this.isEmpty();},isIntersectionBox:function isIntersectionBox(box){console.warn('THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().');return this.intersectsBox(box);},isIntersectionSphere:function isIntersectionSphere(sphere){console.warn('THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().');return this.intersectsSphere(sphere);},size:function size(optionalTarget){console.warn('THREE.Box3: .size() has been renamed to .getSize().');return this.getSize(optionalTarget);}});Object.assign(Sphere.prototype,{empty:function empty(){console.warn('THREE.Sphere: .empty() has been renamed to .isEmpty().');return this.isEmpty();}});Frustum.prototype.setFromMatrix=function(m){console.warn('THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().');return this.setFromProjectionMatrix(m);};Line3.prototype.center=function(optionalTarget){console.warn('THREE.Line3: .center() has been renamed to .getCenter().');return this.getCenter(optionalTarget);};Object.assign(MathUtils,{random16:function random16(){console.warn('THREE.Math: .random16() has been deprecated. Use Math.random() instead.');return Math.random();},nearestPowerOfTwo:function nearestPowerOfTwo(value){console.warn('THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().');return MathUtils.floorPowerOfTwo(value);},nextPowerOfTwo:function nextPowerOfTwo(value){console.warn('THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().');return MathUtils.ceilPowerOfTwo(value);}});Object.assign(Matrix3.prototype,{flattenToArrayOffset:function flattenToArrayOffset(array,offset){console.warn('THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.');return this.toArray(array,offset);},multiplyVector3:function multiplyVector3(vector){console.warn('THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.');return vector.applyMatrix3(this);},multiplyVector3Array:function multiplyVector3Array(/* a */){console.error('THREE.Matrix3: .multiplyVector3Array() has been removed.');},applyToBufferAttribute:function applyToBufferAttribute(attribute){console.warn('THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.');return attribute.applyMatrix3(this);},applyToVector3Array:function applyToVector3Array(/* array, offset, length */){console.error('THREE.Matrix3: .applyToVector3Array() has been removed.');},getInverse:function getInverse(matrix){console.warn('THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.');return this.copy(matrix).invert();}});Object.assign(Matrix4.prototype,{extractPosition:function extractPosition(m){console.warn('THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().');return this.copyPosition(m);},flattenToArrayOffset:function flattenToArrayOffset(array,offset){console.warn('THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.');return this.toArray(array,offset);},getPosition:function getPosition(){console.warn('THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.');return new Vector3().setFromMatrixColumn(this,3);},setRotationFromQuaternion:function setRotationFromQuaternion(q){console.warn('THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().');return this.makeRotationFromQuaternion(q);},multiplyToArray:function multiplyToArray(){console.warn('THREE.Matrix4: .multiplyToArray() has been removed.');},multiplyVector3:function multiplyVector3(vector){console.warn('THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.');return vector.applyMatrix4(this);},multiplyVector4:function multiplyVector4(vector){console.warn('THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.');return vector.applyMatrix4(this);},multiplyVector3Array:function multiplyVector3Array(/* a */){console.error('THREE.Matrix4: .multiplyVector3Array() has been removed.');},rotateAxis:function rotateAxis(v){console.warn('THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.');v.transformDirection(this);},crossVector:function crossVector(vector){console.warn('THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.');return vector.applyMatrix4(this);},translate:function translate(){console.error('THREE.Matrix4: .translate() has been removed.');},rotateX:function rotateX(){console.error('THREE.Matrix4: .rotateX() has been removed.');},rotateY:function rotateY(){console.error('THREE.Matrix4: .rotateY() has been removed.');},rotateZ:function rotateZ(){console.error('THREE.Matrix4: .rotateZ() has been removed.');},rotateByAxis:function rotateByAxis(){console.error('THREE.Matrix4: .rotateByAxis() has been removed.');},applyToBufferAttribute:function applyToBufferAttribute(attribute){console.warn('THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.');return attribute.applyMatrix4(this);},applyToVector3Array:function applyToVector3Array(/* array, offset, length */){console.error('THREE.Matrix4: .applyToVector3Array() has been removed.');},makeFrustum:function makeFrustum(left,right,bottom,top,near,far){console.warn('THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.');return this.makePerspective(left,right,top,bottom,near,far);},getInverse:function getInverse(matrix){console.warn('THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead.');return this.copy(matrix).invert();}});Plane.prototype.isIntersectionLine=function(line){console.warn('THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().');return this.intersectsLine(line);};Object.assign(Quaternion.prototype,{multiplyVector3:function multiplyVector3(vector){console.warn('THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.');return vector.applyQuaternion(this);},inverse:function inverse(){console.warn('THREE.Quaternion: .inverse() has been renamed to invert().');return this.invert();}});Object.assign(Ray.prototype,{isIntersectionBox:function isIntersectionBox(box){console.warn('THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().');return this.intersectsBox(box);},isIntersectionPlane:function isIntersectionPlane(plane){console.warn('THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().');return this.intersectsPlane(plane);},isIntersectionSphere:function isIntersectionSphere(sphere){console.warn('THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().');return this.intersectsSphere(sphere);}});Object.assign(Triangle.prototype,{area:function area(){console.warn('THREE.Triangle: .area() has been renamed to .getArea().');return this.getArea();},barycoordFromPoint:function barycoordFromPoint(point,target){console.warn('THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().');return this.getBarycoord(point,target);},midpoint:function midpoint(target){console.warn('THREE.Triangle: .midpoint() has been renamed to .getMidpoint().');return this.getMidpoint(target);},normal:function normal(target){console.warn('THREE.Triangle: .normal() has been renamed to .getNormal().');return this.getNormal(target);},plane:function plane(target){console.warn('THREE.Triangle: .plane() has been renamed to .getPlane().');return this.getPlane(target);}});Object.assign(Triangle,{barycoordFromPoint:function barycoordFromPoint(point,a,b,c,target){console.warn('THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().');return Triangle.getBarycoord(point,a,b,c,target);},normal:function normal(a,b,c,target){console.warn('THREE.Triangle: .normal() has been renamed to .getNormal().');return Triangle.getNormal(a,b,c,target);}});Object.assign(Shape.prototype,{extractAllPoints:function extractAllPoints(divisions){console.warn('THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.');return this.extractPoints(divisions);},extrude:function extrude(options){console.warn('THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.');return new ExtrudeGeometry(this,options);},makeGeometry:function makeGeometry(options){console.warn('THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.');return new ShapeGeometry(this,options);}});Object.assign(Vector2.prototype,{fromAttribute:function fromAttribute(attribute,index,offset){console.warn('THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().');return this.fromBufferAttribute(attribute,index,offset);},distanceToManhattan:function distanceToManhattan(v){console.warn('THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().');return this.manhattanDistanceTo(v);},lengthManhattan:function lengthManhattan(){console.warn('THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().');return this.manhattanLength();}});Object.assign(Vector3.prototype,{setEulerFromRotationMatrix:function setEulerFromRotationMatrix(){console.error('THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.');},setEulerFromQuaternion:function setEulerFromQuaternion(){console.error('THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.');},getPositionFromMatrix:function getPositionFromMatrix(m){console.warn('THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().');return this.setFromMatrixPosition(m);},getScaleFromMatrix:function getScaleFromMatrix(m){console.warn('THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().');return this.setFromMatrixScale(m);},getColumnFromMatrix:function getColumnFromMatrix(index,matrix){console.warn('THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().');return this.setFromMatrixColumn(matrix,index);},applyProjection:function applyProjection(m){console.warn('THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.');return this.applyMatrix4(m);},fromAttribute:function fromAttribute(attribute,index,offset){console.warn('THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().');return this.fromBufferAttribute(attribute,index,offset);},distanceToManhattan:function distanceToManhattan(v){console.warn('THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().');return this.manhattanDistanceTo(v);},lengthManhattan:function lengthManhattan(){console.warn('THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().');return this.manhattanLength();}});Object.assign(Vector4.prototype,{fromAttribute:function fromAttribute(attribute,index,offset){console.warn('THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().');return this.fromBufferAttribute(attribute,index,offset);},lengthManhattan:function lengthManhattan(){console.warn('THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().');return this.manhattanLength();}});//
  2687. Object.assign(Geometry.prototype,{computeTangents:function computeTangents(){console.error('THREE.Geometry: .computeTangents() has been removed.');},computeLineDistances:function computeLineDistances(){console.error('THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.');},applyMatrix:function applyMatrix(matrix){console.warn('THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().');return this.applyMatrix4(matrix);}});Object.assign(Object3D.prototype,{getChildByName:function getChildByName(name){console.warn('THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().');return this.getObjectByName(name);},renderDepth:function renderDepth(){console.warn('THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.');},translate:function translate(distance,axis){console.warn('THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.');return this.translateOnAxis(axis,distance);},getWorldRotation:function getWorldRotation(){console.error('THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.');},applyMatrix:function applyMatrix(matrix){console.warn('THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().');return this.applyMatrix4(matrix);}});Object.defineProperties(Object3D.prototype,{eulerOrder:{get:function get(){console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');return this.rotation.order;},set:function set(value){console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');this.rotation.order=value;}},useQuaternion:{get:function get(){console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');},set:function set(){console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');}}});Object.assign(Mesh.prototype,{setDrawMode:function setDrawMode(){console.error('THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.');}});Object.defineProperties(Mesh.prototype,{drawMode:{get:function get(){console.error('THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.');return TrianglesDrawMode;},set:function set(){console.error('THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.');}}});Object.defineProperties(LOD.prototype,{objects:{get:function get(){console.warn('THREE.LOD: .objects has been renamed to .levels.');return this.levels;}}});Object.defineProperty(Skeleton.prototype,'useVertexTexture',{get:function get(){console.warn('THREE.Skeleton: useVertexTexture has been removed.');},set:function set(){console.warn('THREE.Skeleton: useVertexTexture has been removed.');}});SkinnedMesh.prototype.initBones=function(){console.error('THREE.SkinnedMesh: initBones() has been removed.');};Object.defineProperty(Curve.prototype,'__arcLengthDivisions',{get:function get(){console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.');return this.arcLengthDivisions;},set:function set(value){console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.');this.arcLengthDivisions=value;}});//
  2688. PerspectiveCamera.prototype.setLens=function(focalLength,filmGauge){console.warn('THREE.PerspectiveCamera.setLens is deprecated. '+'Use .setFocalLength and .filmGauge for a photographic setup.');if(filmGauge!==undefined)this.filmGauge=filmGauge;this.setFocalLength(focalLength);};//
  2689. Object.defineProperties(Light.prototype,{onlyShadow:{set:function set(){console.warn('THREE.Light: .onlyShadow has been removed.');}},shadowCameraFov:{set:function set(value){console.warn('THREE.Light: .shadowCameraFov is now .shadow.camera.fov.');this.shadow.camera.fov=value;}},shadowCameraLeft:{set:function set(value){console.warn('THREE.Light: .shadowCameraLeft is now .shadow.camera.left.');this.shadow.camera.left=value;}},shadowCameraRight:{set:function set(value){console.warn('THREE.Light: .shadowCameraRight is now .shadow.camera.right.');this.shadow.camera.right=value;}},shadowCameraTop:{set:function set(value){console.warn('THREE.Light: .shadowCameraTop is now .shadow.camera.top.');this.shadow.camera.top=value;}},shadowCameraBottom:{set:function set(value){console.warn('THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.');this.shadow.camera.bottom=value;}},shadowCameraNear:{set:function set(value){console.warn('THREE.Light: .shadowCameraNear is now .shadow.camera.near.');this.shadow.camera.near=value;}},shadowCameraFar:{set:function set(value){console.warn('THREE.Light: .shadowCameraFar is now .shadow.camera.far.');this.shadow.camera.far=value;}},shadowCameraVisible:{set:function set(){console.warn('THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.');}},shadowBias:{set:function set(value){console.warn('THREE.Light: .shadowBias is now .shadow.bias.');this.shadow.bias=value;}},shadowDarkness:{set:function set(){console.warn('THREE.Light: .shadowDarkness has been removed.');}},shadowMapWidth:{set:function set(value){console.warn('THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.');this.shadow.mapSize.width=value;}},shadowMapHeight:{set:function set(value){console.warn('THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.');this.shadow.mapSize.height=value;}}});//
  2690. Object.defineProperties(BufferAttribute.prototype,{length:{get:function get(){console.warn('THREE.BufferAttribute: .length has been deprecated. Use .count instead.');return this.array.length;}},dynamic:{get:function get(){console.warn('THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.');return this.usage===DynamicDrawUsage;},set:function set(/* value */){console.warn('THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.');this.setUsage(DynamicDrawUsage);}}});Object.assign(BufferAttribute.prototype,{setDynamic:function setDynamic(value){//console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
  2691. this.setUsage(value===true?DynamicDrawUsage:StaticDrawUsage);return this;},copyIndicesArray:function copyIndicesArray(/* indices */){console.error('THREE.BufferAttribute: .copyIndicesArray() has been removed.');},setArray:function setArray(/* array */){console.error('THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers');}});Object.assign(BufferGeometry.prototype,{addIndex:function addIndex(index){console.warn('THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().');this.setIndex(index);},addAttribute:function addAttribute(name,attribute){console.warn('THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().');if(!(attribute&&attribute.isBufferAttribute)&&!(attribute&&attribute.isInterleavedBufferAttribute)){console.warn('THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).');return this.setAttribute(name,new BufferAttribute(arguments[1],arguments[2]));}if(name==='index'){console.warn('THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.');this.setIndex(attribute);return this;}return this.setAttribute(name,attribute);},addDrawCall:function addDrawCall(start,count,indexOffset){if(indexOffset!==undefined){console.warn('THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.');}console.warn('THREE.BufferGeometry: .addDrawCall() is now .addGroup().');this.addGroup(start,count);},clearDrawCalls:function clearDrawCalls(){console.warn('THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().');this.clearGroups();},computeTangents:function computeTangents(){console.warn('THREE.BufferGeometry: .computeTangents() has been removed.');},computeOffsets:function computeOffsets(){console.warn('THREE.BufferGeometry: .computeOffsets() has been removed.');},removeAttribute:function removeAttribute(name){console.warn('THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().');return this.deleteAttribute(name);},applyMatrix:function applyMatrix(matrix){console.warn('THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().');return this.applyMatrix4(matrix);}});Object.defineProperties(BufferGeometry.prototype,{drawcalls:{get:function get(){console.error('THREE.BufferGeometry: .drawcalls has been renamed to .groups.');return this.groups;}},offsets:{get:function get(){console.warn('THREE.BufferGeometry: .offsets has been renamed to .groups.');return this.groups;}}});Object.defineProperties(InstancedBufferGeometry.prototype,{maxInstancedCount:{get:function get(){console.warn('THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.');return this.instanceCount;},set:function set(value){console.warn('THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.');this.instanceCount=value;}}});Object.defineProperties(Raycaster.prototype,{linePrecision:{get:function get(){console.warn('THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.');return this.params.Line.threshold;},set:function set(value){console.warn('THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.');this.params.Line.threshold=value;}}});Object.defineProperties(InterleavedBuffer.prototype,{dynamic:{get:function get(){console.warn('THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.');return this.usage===DynamicDrawUsage;},set:function set(value){console.warn('THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.');this.setUsage(value);}}});Object.assign(InterleavedBuffer.prototype,{setDynamic:function setDynamic(value){console.warn('THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.');this.setUsage(value===true?DynamicDrawUsage:StaticDrawUsage);return this;},setArray:function setArray(/* array */){console.error('THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers');}});//
  2692. Object.assign(ExtrudeBufferGeometry.prototype,{getArrays:function getArrays(){console.error('THREE.ExtrudeBufferGeometry: .getArrays() has been removed.');},addShapeList:function addShapeList(){console.error('THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.');},addShape:function addShape(){console.error('THREE.ExtrudeBufferGeometry: .addShape() has been removed.');}});//
  2693. Object.assign(Scene.prototype,{dispose:function dispose(){console.error('THREE.Scene: .dispose() has been removed.');}});//
  2694. Object.defineProperties(Uniform.prototype,{dynamic:{set:function set(){console.warn('THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.');}},onUpdate:{value:function value(){console.warn('THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.');return this;}}});//
  2695. Object.defineProperties(Material.prototype,{wrapAround:{get:function get(){console.warn('THREE.Material: .wrapAround has been removed.');},set:function set(){console.warn('THREE.Material: .wrapAround has been removed.');}},overdraw:{get:function get(){console.warn('THREE.Material: .overdraw has been removed.');},set:function set(){console.warn('THREE.Material: .overdraw has been removed.');}},wrapRGB:{get:function get(){console.warn('THREE.Material: .wrapRGB has been removed.');return new Color();}},shading:{get:function get(){console.error('THREE.'+this.type+': .shading has been removed. Use the boolean .flatShading instead.');},set:function set(value){console.warn('THREE.'+this.type+': .shading has been removed. Use the boolean .flatShading instead.');this.flatShading=value===FlatShading$1;}},stencilMask:{get:function get(){console.warn('THREE.'+this.type+': .stencilMask has been removed. Use .stencilFuncMask instead.');return this.stencilFuncMask;},set:function set(value){console.warn('THREE.'+this.type+': .stencilMask has been removed. Use .stencilFuncMask instead.');this.stencilFuncMask=value;}}});Object.defineProperties(MeshPhongMaterial.prototype,{metal:{get:function get(){console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.');return false;},set:function set(){console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead');}}});Object.defineProperties(MeshPhysicalMaterial.prototype,{transparency:{get:function get(){console.warn('THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.');return this.transmission;},set:function set(value){console.warn('THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.');this.transmission=value;}}});Object.defineProperties(ShaderMaterial.prototype,{derivatives:{get:function get(){console.warn('THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');return this.extensions.derivatives;},set:function set(value){console.warn('THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');this.extensions.derivatives=value;}}});//
  2696. Object.assign(WebGLRenderer.prototype,{clearTarget:function clearTarget(renderTarget,color,depth,stencil){console.warn('THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.');this.setRenderTarget(renderTarget);this.clear(color,depth,stencil);},animate:function animate(callback){console.warn('THREE.WebGLRenderer: .animate() is now .setAnimationLoop().');this.setAnimationLoop(callback);},getCurrentRenderTarget:function getCurrentRenderTarget(){console.warn('THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().');return this.getRenderTarget();},getMaxAnisotropy:function getMaxAnisotropy(){console.warn('THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().');return this.capabilities.getMaxAnisotropy();},getPrecision:function getPrecision(){console.warn('THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.');return this.capabilities.precision;},resetGLState:function resetGLState(){console.warn('THREE.WebGLRenderer: .resetGLState() is now .state.reset().');return this.state.reset();},supportsFloatTextures:function supportsFloatTextures(){console.warn('THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).');return this.extensions.get('OES_texture_float');},supportsHalfFloatTextures:function supportsHalfFloatTextures(){console.warn('THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).');return this.extensions.get('OES_texture_half_float');},supportsStandardDerivatives:function supportsStandardDerivatives(){console.warn('THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).');return this.extensions.get('OES_standard_derivatives');},supportsCompressedTextureS3TC:function supportsCompressedTextureS3TC(){console.warn('THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).');return this.extensions.get('WEBGL_compressed_texture_s3tc');},supportsCompressedTexturePVRTC:function supportsCompressedTexturePVRTC(){console.warn('THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).');return this.extensions.get('WEBGL_compressed_texture_pvrtc');},supportsBlendMinMax:function supportsBlendMinMax(){console.warn('THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).');return this.extensions.get('EXT_blend_minmax');},supportsVertexTextures:function supportsVertexTextures(){console.warn('THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.');return this.capabilities.vertexTextures;},supportsInstancedArrays:function supportsInstancedArrays(){console.warn('THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).');return this.extensions.get('ANGLE_instanced_arrays');},enableScissorTest:function enableScissorTest(boolean){console.warn('THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().');this.setScissorTest(boolean);},initMaterial:function initMaterial(){console.warn('THREE.WebGLRenderer: .initMaterial() has been removed.');},addPrePlugin:function addPrePlugin(){console.warn('THREE.WebGLRenderer: .addPrePlugin() has been removed.');},addPostPlugin:function addPostPlugin(){console.warn('THREE.WebGLRenderer: .addPostPlugin() has been removed.');},updateShadowMap:function updateShadowMap(){console.warn('THREE.WebGLRenderer: .updateShadowMap() has been removed.');},setFaceCulling:function setFaceCulling(){console.warn('THREE.WebGLRenderer: .setFaceCulling() has been removed.');},allocTextureUnit:function allocTextureUnit(){console.warn('THREE.WebGLRenderer: .allocTextureUnit() has been removed.');},setTexture:function setTexture(){console.warn('THREE.WebGLRenderer: .setTexture() has been removed.');},setTexture2D:function setTexture2D(){console.warn('THREE.WebGLRenderer: .setTexture2D() has been removed.');},setTextureCube:function setTextureCube(){console.warn('THREE.WebGLRenderer: .setTextureCube() has been removed.');},getActiveMipMapLevel:function getActiveMipMapLevel(){console.warn('THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().');return this.getActiveMipmapLevel();}});Object.defineProperties(WebGLRenderer.prototype,{shadowMapEnabled:{get:function get(){return this.shadowMap.enabled;},set:function set(value){console.warn('THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.');this.shadowMap.enabled=value;}},shadowMapType:{get:function get(){return this.shadowMap.type;},set:function set(value){console.warn('THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.');this.shadowMap.type=value;}},shadowMapCullFace:{get:function get(){console.warn('THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.');return undefined;},set:function set(/* value */){console.warn('THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.');}},context:{get:function get(){console.warn('THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.');return this.getContext();}},vr:{get:function get(){console.warn('THREE.WebGLRenderer: .vr has been renamed to .xr');return this.xr;}},gammaInput:{get:function get(){console.warn('THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.');return false;},set:function set(){console.warn('THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.');}},gammaOutput:{get:function get(){console.warn('THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.');return false;},set:function set(value){console.warn('THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.');this.outputEncoding=value===true?sRGBEncoding:LinearEncoding;}},toneMappingWhitePoint:{get:function get(){console.warn('THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.');return 1.0;},set:function set(){console.warn('THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.');}}});Object.defineProperties(WebGLShadowMap.prototype,{cullFace:{get:function get(){console.warn('THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.');return undefined;},set:function set(/* cullFace */){console.warn('THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.');}},renderReverseSided:{get:function get(){console.warn('THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.');return undefined;},set:function set(){console.warn('THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.');}},renderSingleSided:{get:function get(){console.warn('THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.');return undefined;},set:function set(){console.warn('THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.');}}});function WebGLRenderTargetCube(width,height,options){console.warn('THREE.WebGLRenderTargetCube( width, height, options ) is now WebGLCubeRenderTarget( size, options ).');return new WebGLCubeRenderTarget(width,options);}//
  2697. Object.defineProperties(WebGLRenderTarget.prototype,{wrapS:{get:function get(){console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');return this.texture.wrapS;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');this.texture.wrapS=value;}},wrapT:{get:function get(){console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');return this.texture.wrapT;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');this.texture.wrapT=value;}},magFilter:{get:function get(){console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');return this.texture.magFilter;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');this.texture.magFilter=value;}},minFilter:{get:function get(){console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');return this.texture.minFilter;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');this.texture.minFilter=value;}},anisotropy:{get:function get(){console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');return this.texture.anisotropy;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');this.texture.anisotropy=value;}},offset:{get:function get(){console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');return this.texture.offset;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');this.texture.offset=value;}},repeat:{get:function get(){console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');return this.texture.repeat;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');this.texture.repeat=value;}},format:{get:function get(){console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');return this.texture.format;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');this.texture.format=value;}},type:{get:function get(){console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');return this.texture.type;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');this.texture.type=value;}},generateMipmaps:{get:function get(){console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');return this.texture.generateMipmaps;},set:function set(value){console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');this.texture.generateMipmaps=value;}}});//
  2698. Object.defineProperties(Audio.prototype,{load:{value:function value(file){console.warn('THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.');var scope=this;var audioLoader=new AudioLoader();audioLoader.load(file,function(buffer){scope.setBuffer(buffer);});return this;}},startTime:{set:function set(){console.warn('THREE.Audio: .startTime is now .play( delay ).');}}});AudioAnalyser.prototype.getData=function(){console.warn('THREE.AudioAnalyser: .getData() is now .getFrequencyData().');return this.getFrequencyData();};//
  2699. CubeCamera.prototype.updateCubeMap=function(renderer,scene){console.warn('THREE.CubeCamera: .updateCubeMap() is now .update().');return this.update(renderer,scene);};CubeCamera.prototype.clear=function(renderer,color,depth,stencil){console.warn('THREE.CubeCamera: .clear() is now .renderTarget.clear().');return this.renderTarget.clear(renderer,color,depth,stencil);};//
  2700. var GeometryUtils={merge:function merge(geometry1,geometry2,materialIndexOffset){console.warn('THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.');var matrix;if(geometry2.isMesh){geometry2.matrixAutoUpdate&&geometry2.updateMatrix();matrix=geometry2.matrix;geometry2=geometry2.geometry;}geometry1.merge(geometry2,matrix,materialIndexOffset);},center:function center(geometry){console.warn('THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.');return geometry.center();}};ImageUtils.crossOrigin=undefined;ImageUtils.loadTexture=function(url,mapping,onLoad,onError){console.warn('THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.');var loader=new TextureLoader();loader.setCrossOrigin(this.crossOrigin);var texture=loader.load(url,onLoad,undefined,onError);if(mapping)texture.mapping=mapping;return texture;};ImageUtils.loadTextureCube=function(urls,mapping,onLoad,onError){console.warn('THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.');var loader=new CubeTextureLoader();loader.setCrossOrigin(this.crossOrigin);var texture=loader.load(urls,onLoad,undefined,onError);if(mapping)texture.mapping=mapping;return texture;};ImageUtils.loadCompressedTexture=function(){console.error('THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.');};ImageUtils.loadCompressedTextureCube=function(){console.error('THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.');};//
  2701. function CanvasRenderer(){console.error('THREE.CanvasRenderer has been removed');}//
  2702. function JSONLoader(){console.error('THREE.JSONLoader has been removed.');}//
  2703. var SceneUtils={createMultiMaterialObject:function createMultiMaterialObject(/* geometry, materials */){console.error('THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js');},detach:function detach(/* child, parent, scene */){console.error('THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js');},attach:function attach(/* child, scene, parent */){console.error('THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js');}};//
  2704. function LensFlare(){console.error('THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js');}if(typeof __THREE_DEVTOOLS__!=='undefined'){/* eslint-disable no-undef */__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('register',{detail:{revision:REVISION}}));/* eslint-enable no-undef */}//xzw add: 用于添加扩展
  2705. var Shim={};
  2706. var THREE$1 = /*#__PURE__*/Object.freeze({
  2707. __proto__: null,
  2708. Shim: Shim,
  2709. AnimationAction: AnimationAction,
  2710. ACESFilmicToneMapping: ACESFilmicToneMapping,
  2711. AddEquation: AddEquation,
  2712. AddOperation: AddOperation,
  2713. AdditiveAnimationBlendMode: AdditiveAnimationBlendMode,
  2714. AdditiveBlending: AdditiveBlending,
  2715. AlphaFormat: AlphaFormat,
  2716. AlwaysDepth: AlwaysDepth,
  2717. AlwaysStencilFunc: AlwaysStencilFunc,
  2718. AmbientLight: AmbientLight,
  2719. AmbientLightProbe: AmbientLightProbe,
  2720. AnimationClip: AnimationClip,
  2721. AnimationLoader: AnimationLoader,
  2722. AnimationMixer: AnimationMixer,
  2723. AnimationObjectGroup: AnimationObjectGroup,
  2724. AnimationUtils: AnimationUtils,
  2725. ArcCurve: ArcCurve,
  2726. ArrayCamera: ArrayCamera,
  2727. ArrowHelper: ArrowHelper,
  2728. Audio: Audio,
  2729. AudioAnalyser: AudioAnalyser,
  2730. AudioContext: AudioContext,
  2731. AudioListener: AudioListener,
  2732. AudioLoader: AudioLoader,
  2733. AxesHelper: AxesHelper,
  2734. AxisHelper: AxisHelper,
  2735. BackSide: BackSide,
  2736. BasicDepthPacking: BasicDepthPacking,
  2737. BasicShadowMap: BasicShadowMap,
  2738. BinaryTextureLoader: BinaryTextureLoader,
  2739. Bone: Bone,
  2740. BooleanKeyframeTrack: BooleanKeyframeTrack,
  2741. BoundingBoxHelper: BoundingBoxHelper,
  2742. Box2: Box2,
  2743. Box3: Box3,
  2744. Box3Helper: Box3Helper,
  2745. BoxBufferGeometry: BoxBufferGeometry,
  2746. BoxGeometry: BoxGeometry,
  2747. BoxHelper: BoxHelper,
  2748. BufferAttribute: BufferAttribute,
  2749. BufferGeometry: BufferGeometry,
  2750. BufferGeometryLoader: BufferGeometryLoader,
  2751. ByteType: ByteType,
  2752. Cache: Cache,
  2753. Camera: Camera,
  2754. CameraHelper: CameraHelper,
  2755. CanvasRenderer: CanvasRenderer,
  2756. CanvasTexture: CanvasTexture,
  2757. CatmullRomCurve3: CatmullRomCurve3,
  2758. CineonToneMapping: CineonToneMapping,
  2759. CircleBufferGeometry: CircleBufferGeometry,
  2760. CircleGeometry: CircleGeometry,
  2761. ClampToEdgeWrapping: ClampToEdgeWrapping,
  2762. Clock: Clock,
  2763. ClosedSplineCurve3: ClosedSplineCurve3,
  2764. Color: Color,
  2765. ColorKeyframeTrack: ColorKeyframeTrack,
  2766. CompressedTexture: CompressedTexture,
  2767. CompressedTextureLoader: CompressedTextureLoader,
  2768. ConeBufferGeometry: ConeBufferGeometry,
  2769. ConeGeometry: ConeGeometry,
  2770. CubeCamera: CubeCamera,
  2771. CubeGeometry: BoxGeometry,
  2772. CubeReflectionMapping: CubeReflectionMapping,
  2773. CubeRefractionMapping: CubeRefractionMapping,
  2774. CubeTexture: CubeTexture,
  2775. CubeTextureLoader: CubeTextureLoader,
  2776. CubeUVReflectionMapping: CubeUVReflectionMapping,
  2777. CubeUVRefractionMapping: CubeUVRefractionMapping,
  2778. CubicBezierCurve: CubicBezierCurve,
  2779. CubicBezierCurve3: CubicBezierCurve3,
  2780. CubicInterpolant: CubicInterpolant,
  2781. CullFaceBack: CullFaceBack,
  2782. CullFaceFront: CullFaceFront,
  2783. CullFaceFrontBack: CullFaceFrontBack,
  2784. CullFaceNone: CullFaceNone,
  2785. Curve: Curve,
  2786. CurvePath: CurvePath,
  2787. CustomBlending: CustomBlending,
  2788. CustomToneMapping: CustomToneMapping,
  2789. CylinderBufferGeometry: CylinderBufferGeometry,
  2790. CylinderGeometry: CylinderGeometry,
  2791. Cylindrical: Cylindrical,
  2792. DataTexture: DataTexture,
  2793. DataTexture2DArray: DataTexture2DArray,
  2794. DataTexture3D: DataTexture3D,
  2795. DataTextureLoader: DataTextureLoader,
  2796. DataUtils: DataUtils,
  2797. DecrementStencilOp: DecrementStencilOp,
  2798. DecrementWrapStencilOp: DecrementWrapStencilOp,
  2799. DefaultLoadingManager: DefaultLoadingManager,
  2800. DepthFormat: DepthFormat,
  2801. DepthStencilFormat: DepthStencilFormat,
  2802. DepthTexture: DepthTexture,
  2803. DirectionalLight: DirectionalLight,
  2804. DirectionalLightHelper: DirectionalLightHelper,
  2805. DiscreteInterpolant: DiscreteInterpolant,
  2806. DodecahedronBufferGeometry: DodecahedronBufferGeometry,
  2807. DodecahedronGeometry: DodecahedronGeometry,
  2808. DoubleSide: DoubleSide,
  2809. DstAlphaFactor: DstAlphaFactor,
  2810. DstColorFactor: DstColorFactor,
  2811. DynamicBufferAttribute: DynamicBufferAttribute,
  2812. DynamicCopyUsage: DynamicCopyUsage,
  2813. DynamicDrawUsage: DynamicDrawUsage,
  2814. DynamicReadUsage: DynamicReadUsage,
  2815. EdgesGeometry: EdgesGeometry,
  2816. EdgesHelper: EdgesHelper,
  2817. EllipseCurve: EllipseCurve,
  2818. EqualDepth: EqualDepth,
  2819. EqualStencilFunc: EqualStencilFunc,
  2820. EquirectangularReflectionMapping: EquirectangularReflectionMapping,
  2821. EquirectangularRefractionMapping: EquirectangularRefractionMapping,
  2822. Euler: Euler,
  2823. EventDispatcher: EventDispatcher,
  2824. ExtrudeBufferGeometry: ExtrudeBufferGeometry,
  2825. ExtrudeGeometry: ExtrudeGeometry,
  2826. Face3: Face3,
  2827. Face4: Face4,
  2828. FaceColors: FaceColors,
  2829. FileLoader: FileLoader,
  2830. FlatShading: FlatShading$1,
  2831. Float16BufferAttribute: Float16BufferAttribute,
  2832. Float32Attribute: Float32Attribute,
  2833. Float32BufferAttribute: Float32BufferAttribute,
  2834. Float64Attribute: Float64Attribute,
  2835. Float64BufferAttribute: Float64BufferAttribute,
  2836. FloatType: FloatType,
  2837. Fog: Fog,
  2838. FogExp2: FogExp2,
  2839. Font: Font,
  2840. FontLoader: FontLoader,
  2841. FrontSide: FrontSide,
  2842. Frustum: Frustum,
  2843. GLBufferAttribute: GLBufferAttribute,
  2844. GLSL1: GLSL1,
  2845. GLSL3: GLSL3,
  2846. GammaEncoding: GammaEncoding,
  2847. Geometry: Geometry,
  2848. GeometryUtils: GeometryUtils,
  2849. GreaterDepth: GreaterDepth,
  2850. GreaterEqualDepth: GreaterEqualDepth,
  2851. GreaterEqualStencilFunc: GreaterEqualStencilFunc,
  2852. GreaterStencilFunc: GreaterStencilFunc,
  2853. GridHelper: GridHelper,
  2854. Group: Group,
  2855. HalfFloatType: HalfFloatType,
  2856. HemisphereLight: HemisphereLight,
  2857. HemisphereLightHelper: HemisphereLightHelper,
  2858. HemisphereLightProbe: HemisphereLightProbe,
  2859. IcosahedronBufferGeometry: IcosahedronBufferGeometry,
  2860. IcosahedronGeometry: IcosahedronGeometry,
  2861. ImageBitmapLoader: ImageBitmapLoader,
  2862. ImageLoader: ImageLoader,
  2863. ImageUtils: ImageUtils,
  2864. ImmediateRenderObject: ImmediateRenderObject,
  2865. IncrementStencilOp: IncrementStencilOp,
  2866. IncrementWrapStencilOp: IncrementWrapStencilOp,
  2867. InstancedBufferAttribute: InstancedBufferAttribute,
  2868. InstancedBufferGeometry: InstancedBufferGeometry,
  2869. InstancedInterleavedBuffer: InstancedInterleavedBuffer,
  2870. InstancedMesh: InstancedMesh,
  2871. Int16Attribute: Int16Attribute,
  2872. Int16BufferAttribute: Int16BufferAttribute,
  2873. Int32Attribute: Int32Attribute,
  2874. Int32BufferAttribute: Int32BufferAttribute,
  2875. Int8Attribute: Int8Attribute,
  2876. Int8BufferAttribute: Int8BufferAttribute,
  2877. IntType: IntType,
  2878. InterleavedBuffer: InterleavedBuffer,
  2879. InterleavedBufferAttribute: InterleavedBufferAttribute,
  2880. Interpolant: Interpolant,
  2881. InterpolateDiscrete: InterpolateDiscrete,
  2882. InterpolateLinear: InterpolateLinear,
  2883. InterpolateSmooth: InterpolateSmooth,
  2884. InvertStencilOp: InvertStencilOp,
  2885. JSONLoader: JSONLoader,
  2886. KeepStencilOp: KeepStencilOp,
  2887. KeyframeTrack: KeyframeTrack,
  2888. LOD: LOD,
  2889. LatheBufferGeometry: LatheBufferGeometry,
  2890. LatheGeometry: LatheGeometry,
  2891. Layers: Layers,
  2892. LensFlare: LensFlare,
  2893. LessDepth: LessDepth,
  2894. LessEqualDepth: LessEqualDepth,
  2895. LessEqualStencilFunc: LessEqualStencilFunc,
  2896. LessStencilFunc: LessStencilFunc,
  2897. Light: Light,
  2898. LightProbe: LightProbe,
  2899. Line: Line,
  2900. Line3: Line3,
  2901. LineBasicMaterial: LineBasicMaterial,
  2902. LineCurve: LineCurve,
  2903. LineCurve3: LineCurve3,
  2904. LineDashedMaterial: LineDashedMaterial,
  2905. LineLoop: LineLoop,
  2906. LinePieces: LinePieces,
  2907. LineSegments: LineSegments,
  2908. LineStrip: LineStrip,
  2909. LinearEncoding: LinearEncoding,
  2910. LinearFilter: LinearFilter,
  2911. LinearInterpolant: LinearInterpolant,
  2912. LinearMipMapLinearFilter: LinearMipMapLinearFilter,
  2913. LinearMipMapNearestFilter: LinearMipMapNearestFilter,
  2914. LinearMipmapLinearFilter: LinearMipmapLinearFilter,
  2915. LinearMipmapNearestFilter: LinearMipmapNearestFilter,
  2916. LinearToneMapping: LinearToneMapping,
  2917. Loader: Loader,
  2918. LoaderUtils: LoaderUtils,
  2919. LoadingManager: LoadingManager,
  2920. LogLuvEncoding: LogLuvEncoding,
  2921. LoopOnce: LoopOnce,
  2922. LoopPingPong: LoopPingPong,
  2923. LoopRepeat: LoopRepeat,
  2924. LuminanceAlphaFormat: LuminanceAlphaFormat,
  2925. LuminanceFormat: LuminanceFormat,
  2926. MOUSE: MOUSE,
  2927. Material: Material,
  2928. MaterialLoader: MaterialLoader,
  2929. Math: MathUtils,
  2930. MathUtils: MathUtils,
  2931. Matrix3: Matrix3,
  2932. Matrix4: Matrix4,
  2933. MaxEquation: MaxEquation,
  2934. Mesh: Mesh,
  2935. MeshBasicMaterial: MeshBasicMaterial,
  2936. MeshDepthMaterial: MeshDepthMaterial,
  2937. MeshDistanceMaterial: MeshDistanceMaterial,
  2938. MeshFaceMaterial: MeshFaceMaterial,
  2939. MeshLambertMaterial: MeshLambertMaterial,
  2940. MeshMatcapMaterial: MeshMatcapMaterial,
  2941. MeshNormalMaterial: MeshNormalMaterial,
  2942. MeshPhongMaterial: MeshPhongMaterial,
  2943. MeshPhysicalMaterial: MeshPhysicalMaterial,
  2944. MeshStandardMaterial: MeshStandardMaterial,
  2945. MeshToonMaterial: MeshToonMaterial,
  2946. MinEquation: MinEquation,
  2947. MirroredRepeatWrapping: MirroredRepeatWrapping,
  2948. MixOperation: MixOperation,
  2949. MultiMaterial: MultiMaterial,
  2950. MultiplyBlending: MultiplyBlending,
  2951. MultiplyOperation: MultiplyOperation,
  2952. NearestFilter: NearestFilter,
  2953. NearestMipMapLinearFilter: NearestMipMapLinearFilter,
  2954. NearestMipMapNearestFilter: NearestMipMapNearestFilter,
  2955. NearestMipmapLinearFilter: NearestMipmapLinearFilter,
  2956. NearestMipmapNearestFilter: NearestMipmapNearestFilter,
  2957. NeverDepth: NeverDepth,
  2958. NeverStencilFunc: NeverStencilFunc,
  2959. NoBlending: NoBlending,
  2960. NoColors: NoColors,
  2961. NoToneMapping: NoToneMapping,
  2962. NormalAnimationBlendMode: NormalAnimationBlendMode,
  2963. NormalBlending: NormalBlending,
  2964. NotEqualDepth: NotEqualDepth,
  2965. NotEqualStencilFunc: NotEqualStencilFunc,
  2966. NumberKeyframeTrack: NumberKeyframeTrack,
  2967. Object3D: Object3D,
  2968. ObjectLoader: ObjectLoader,
  2969. ObjectSpaceNormalMap: ObjectSpaceNormalMap,
  2970. OctahedronBufferGeometry: OctahedronBufferGeometry,
  2971. OctahedronGeometry: OctahedronGeometry,
  2972. OneFactor: OneFactor,
  2973. OneMinusDstAlphaFactor: OneMinusDstAlphaFactor,
  2974. OneMinusDstColorFactor: OneMinusDstColorFactor,
  2975. OneMinusSrcAlphaFactor: OneMinusSrcAlphaFactor,
  2976. OneMinusSrcColorFactor: OneMinusSrcColorFactor,
  2977. OrthographicCamera: OrthographicCamera,
  2978. PCFShadowMap: PCFShadowMap,
  2979. PCFSoftShadowMap: PCFSoftShadowMap,
  2980. PMREMGenerator: PMREMGenerator,
  2981. ParametricBufferGeometry: ParametricBufferGeometry,
  2982. ParametricGeometry: ParametricGeometry,
  2983. Particle: Particle,
  2984. ParticleBasicMaterial: ParticleBasicMaterial,
  2985. ParticleSystem: ParticleSystem,
  2986. ParticleSystemMaterial: ParticleSystemMaterial,
  2987. Path: Path,
  2988. PerspectiveCamera: PerspectiveCamera,
  2989. Plane: Plane,
  2990. PlaneBufferGeometry: PlaneBufferGeometry,
  2991. PlaneGeometry: PlaneGeometry,
  2992. PlaneHelper: PlaneHelper,
  2993. PointCloud: PointCloud,
  2994. PointCloudMaterial: PointCloudMaterial,
  2995. PointLight: PointLight,
  2996. PointLightHelper: PointLightHelper,
  2997. Points: Points,
  2998. PointsMaterial: PointsMaterial,
  2999. PolarGridHelper: PolarGridHelper,
  3000. PolyhedronBufferGeometry: PolyhedronBufferGeometry,
  3001. PolyhedronGeometry: PolyhedronGeometry,
  3002. PositionalAudio: PositionalAudio,
  3003. PropertyBinding: PropertyBinding,
  3004. PropertyMixer: PropertyMixer,
  3005. QuadraticBezierCurve: QuadraticBezierCurve,
  3006. QuadraticBezierCurve3: QuadraticBezierCurve3,
  3007. Quaternion: Quaternion,
  3008. QuaternionKeyframeTrack: QuaternionKeyframeTrack,
  3009. QuaternionLinearInterpolant: QuaternionLinearInterpolant,
  3010. REVISION: REVISION,
  3011. RGBADepthPacking: RGBADepthPacking,
  3012. RGBAFormat: RGBAFormat,
  3013. RGBAIntegerFormat: RGBAIntegerFormat,
  3014. RGBA_ASTC_10x10_Format: RGBA_ASTC_10x10_Format,
  3015. RGBA_ASTC_10x5_Format: RGBA_ASTC_10x5_Format,
  3016. RGBA_ASTC_10x6_Format: RGBA_ASTC_10x6_Format,
  3017. RGBA_ASTC_10x8_Format: RGBA_ASTC_10x8_Format,
  3018. RGBA_ASTC_12x10_Format: RGBA_ASTC_12x10_Format,
  3019. RGBA_ASTC_12x12_Format: RGBA_ASTC_12x12_Format,
  3020. RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
  3021. RGBA_ASTC_5x4_Format: RGBA_ASTC_5x4_Format,
  3022. RGBA_ASTC_5x5_Format: RGBA_ASTC_5x5_Format,
  3023. RGBA_ASTC_6x5_Format: RGBA_ASTC_6x5_Format,
  3024. RGBA_ASTC_6x6_Format: RGBA_ASTC_6x6_Format,
  3025. RGBA_ASTC_8x5_Format: RGBA_ASTC_8x5_Format,
  3026. RGBA_ASTC_8x6_Format: RGBA_ASTC_8x6_Format,
  3027. RGBA_ASTC_8x8_Format: RGBA_ASTC_8x8_Format,
  3028. RGBA_BPTC_Format: RGBA_BPTC_Format,
  3029. RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
  3030. RGBA_PVRTC_2BPPV1_Format: RGBA_PVRTC_2BPPV1_Format,
  3031. RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
  3032. RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format$1,
  3033. RGBA_S3TC_DXT3_Format: RGBA_S3TC_DXT3_Format,
  3034. RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format$1,
  3035. RGBDEncoding: RGBDEncoding,
  3036. RGBEEncoding: RGBEEncoding,
  3037. RGBEFormat: RGBEFormat,
  3038. RGBFormat: RGBFormat,
  3039. RGBIntegerFormat: RGBIntegerFormat,
  3040. RGBM16Encoding: RGBM16Encoding,
  3041. RGBM7Encoding: RGBM7Encoding,
  3042. RGB_ETC1_Format: RGB_ETC1_Format,
  3043. RGB_ETC2_Format: RGB_ETC2_Format,
  3044. RGB_PVRTC_2BPPV1_Format: RGB_PVRTC_2BPPV1_Format,
  3045. RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
  3046. RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format,
  3047. RGFormat: RGFormat,
  3048. RGIntegerFormat: RGIntegerFormat,
  3049. RawShaderMaterial: RawShaderMaterial,
  3050. Ray: Ray,
  3051. Raycaster: Raycaster,
  3052. RectAreaLight: RectAreaLight,
  3053. RedFormat: RedFormat,
  3054. RedIntegerFormat: RedIntegerFormat,
  3055. ReinhardToneMapping: ReinhardToneMapping,
  3056. RepeatWrapping: RepeatWrapping,
  3057. ReplaceStencilOp: ReplaceStencilOp,
  3058. ReverseSubtractEquation: ReverseSubtractEquation,
  3059. RingBufferGeometry: RingBufferGeometry,
  3060. RingGeometry: RingGeometry,
  3061. SRGB8_ALPHA8_ASTC_10x10_Format: SRGB8_ALPHA8_ASTC_10x10_Format,
  3062. SRGB8_ALPHA8_ASTC_10x5_Format: SRGB8_ALPHA8_ASTC_10x5_Format,
  3063. SRGB8_ALPHA8_ASTC_10x6_Format: SRGB8_ALPHA8_ASTC_10x6_Format,
  3064. SRGB8_ALPHA8_ASTC_10x8_Format: SRGB8_ALPHA8_ASTC_10x8_Format,
  3065. SRGB8_ALPHA8_ASTC_12x10_Format: SRGB8_ALPHA8_ASTC_12x10_Format,
  3066. SRGB8_ALPHA8_ASTC_12x12_Format: SRGB8_ALPHA8_ASTC_12x12_Format,
  3067. SRGB8_ALPHA8_ASTC_4x4_Format: SRGB8_ALPHA8_ASTC_4x4_Format,
  3068. SRGB8_ALPHA8_ASTC_5x4_Format: SRGB8_ALPHA8_ASTC_5x4_Format,
  3069. SRGB8_ALPHA8_ASTC_5x5_Format: SRGB8_ALPHA8_ASTC_5x5_Format,
  3070. SRGB8_ALPHA8_ASTC_6x5_Format: SRGB8_ALPHA8_ASTC_6x5_Format,
  3071. SRGB8_ALPHA8_ASTC_6x6_Format: SRGB8_ALPHA8_ASTC_6x6_Format,
  3072. SRGB8_ALPHA8_ASTC_8x5_Format: SRGB8_ALPHA8_ASTC_8x5_Format,
  3073. SRGB8_ALPHA8_ASTC_8x6_Format: SRGB8_ALPHA8_ASTC_8x6_Format,
  3074. SRGB8_ALPHA8_ASTC_8x8_Format: SRGB8_ALPHA8_ASTC_8x8_Format,
  3075. Scene: Scene,
  3076. SceneUtils: SceneUtils,
  3077. ShaderChunk: ShaderChunk,
  3078. ShaderLib: ShaderLib,
  3079. ShaderMaterial: ShaderMaterial,
  3080. ShadowMaterial: ShadowMaterial,
  3081. Shape: Shape,
  3082. ShapeBufferGeometry: ShapeBufferGeometry,
  3083. ShapeGeometry: ShapeGeometry,
  3084. ShapePath: ShapePath,
  3085. ShapeUtils: ShapeUtils,
  3086. ShortType: ShortType,
  3087. Skeleton: Skeleton,
  3088. SkeletonHelper: SkeletonHelper,
  3089. SkinnedMesh: SkinnedMesh,
  3090. SmoothShading: SmoothShading,
  3091. Sphere: Sphere,
  3092. SphereBufferGeometry: SphereBufferGeometry,
  3093. SphereGeometry: SphereGeometry,
  3094. Spherical: Spherical,
  3095. SphericalHarmonics3: SphericalHarmonics3,
  3096. Spline: Spline,
  3097. SplineCurve: SplineCurve,
  3098. SplineCurve3: SplineCurve3,
  3099. SpotLight: SpotLight,
  3100. SpotLightHelper: SpotLightHelper,
  3101. Sprite: Sprite$1,
  3102. SpriteMaterial: SpriteMaterial,
  3103. SrcAlphaFactor: SrcAlphaFactor,
  3104. SrcAlphaSaturateFactor: SrcAlphaSaturateFactor,
  3105. SrcColorFactor: SrcColorFactor,
  3106. StaticCopyUsage: StaticCopyUsage,
  3107. StaticDrawUsage: StaticDrawUsage,
  3108. StaticReadUsage: StaticReadUsage,
  3109. StereoCamera: StereoCamera,
  3110. StreamCopyUsage: StreamCopyUsage,
  3111. StreamDrawUsage: StreamDrawUsage,
  3112. StreamReadUsage: StreamReadUsage,
  3113. StringKeyframeTrack: StringKeyframeTrack,
  3114. SubtractEquation: SubtractEquation,
  3115. SubtractiveBlending: SubtractiveBlending,
  3116. TOUCH: TOUCH,
  3117. TangentSpaceNormalMap: TangentSpaceNormalMap,
  3118. TetrahedronBufferGeometry: TetrahedronBufferGeometry,
  3119. TetrahedronGeometry: TetrahedronGeometry,
  3120. TextBufferGeometry: TextBufferGeometry,
  3121. TextGeometry: TextGeometry,
  3122. Texture: Texture,
  3123. TextureLoader: TextureLoader,
  3124. TorusBufferGeometry: TorusBufferGeometry,
  3125. TorusGeometry: TorusGeometry,
  3126. TorusKnotBufferGeometry: TorusKnotBufferGeometry,
  3127. TorusKnotGeometry: TorusKnotGeometry,
  3128. Triangle: Triangle,
  3129. TriangleFanDrawMode: TriangleFanDrawMode,
  3130. TriangleStripDrawMode: TriangleStripDrawMode,
  3131. TrianglesDrawMode: TrianglesDrawMode,
  3132. TubeBufferGeometry: TubeBufferGeometry,
  3133. TubeGeometry: TubeGeometry,
  3134. UVMapping: UVMapping,
  3135. Uint16Attribute: Uint16Attribute,
  3136. Uint16BufferAttribute: Uint16BufferAttribute,
  3137. Uint32Attribute: Uint32Attribute,
  3138. Uint32BufferAttribute: Uint32BufferAttribute,
  3139. Uint8Attribute: Uint8Attribute,
  3140. Uint8BufferAttribute: Uint8BufferAttribute,
  3141. Uint8ClampedAttribute: Uint8ClampedAttribute,
  3142. Uint8ClampedBufferAttribute: Uint8ClampedBufferAttribute,
  3143. Uniform: Uniform,
  3144. UniformsLib: UniformsLib,
  3145. UniformsUtils: UniformsUtils,
  3146. UnsignedByteType: UnsignedByteType,
  3147. UnsignedInt248Type: UnsignedInt248Type$1,
  3148. UnsignedIntType: UnsignedIntType,
  3149. UnsignedShort4444Type: UnsignedShort4444Type,
  3150. UnsignedShort5551Type: UnsignedShort5551Type,
  3151. UnsignedShort565Type: UnsignedShort565Type,
  3152. UnsignedShortType: UnsignedShortType,
  3153. VSMShadowMap: VSMShadowMap,
  3154. Vector2: Vector2,
  3155. Vector3: Vector3,
  3156. Vector4: Vector4,
  3157. VectorKeyframeTrack: VectorKeyframeTrack,
  3158. Vertex: Vertex,
  3159. VertexColors: VertexColors,
  3160. VideoTexture: VideoTexture,
  3161. WebGL1Renderer: WebGL1Renderer,
  3162. WebGLCubeRenderTarget: WebGLCubeRenderTarget,
  3163. WebGLMultisampleRenderTarget: WebGLMultisampleRenderTarget,
  3164. WebGLRenderTarget: WebGLRenderTarget,
  3165. WebGLRenderTargetCube: WebGLRenderTargetCube,
  3166. WebGLRenderer: WebGLRenderer,
  3167. WebGLUtils: WebGLUtils,
  3168. WireframeGeometry: WireframeGeometry,
  3169. WireframeHelper: WireframeHelper,
  3170. WrapAroundEnding: WrapAroundEnding,
  3171. XHRLoader: XHRLoader,
  3172. ZeroCurvatureEnding: ZeroCurvatureEnding,
  3173. ZeroFactor: ZeroFactor,
  3174. ZeroSlopeEnding: ZeroSlopeEnding,
  3175. ZeroStencilOp: ZeroStencilOp,
  3176. sRGBEncoding: sRGBEncoding
  3177. });
  3178. var points = [];
  3179. var lines = [];
  3180. var rings = [];
  3181. var precision = 0.1; //容错精度 //正常是0.01 但是在编辑时容易出现交错的线看不出来,导致需要getSliceLines 然后多出新增点
  3182. var getPoint = function getPoint(o, type) {
  3183. var point;
  3184. if (typeof o == "string" || typeof o == "number") point = points.find(p => p.ids.includes(o));else {
  3185. point = points.find(p => math.closeTo(p.x, o.x, precision) && math.closeTo(p.y, o.y, precision));
  3186. if (!point) point = new Point(o.x, o.y, {
  3187. record: true,
  3188. id: o.id
  3189. }, type);else {
  3190. //console.log('addPoint', point, o)
  3191. point.addPoint(o.id);
  3192. }
  3193. }
  3194. if (!point) {
  3195. console.log("no point!");
  3196. }
  3197. return point;
  3198. };
  3199. var getLine = function getLine(id) {
  3200. return lines.find(line => line.ids.includes(id));
  3201. };
  3202. var getAngleInfo = function getAngleInfo(points) {
  3203. var info = {};
  3204. info.angle = points[1].clone().sub(points[0]).angle();
  3205. if (math.closeTo(info.angle, Math.PI * 2)) {
  3206. //如360-0.01
  3207. info.angle -= Math.PI * 2; //有可能得到负数-0.001
  3208. } else if (info.angle > Math.PI || math.closeTo(info.angle, Math.PI)) {
  3209. //如180+-0.01
  3210. info.angle -= Math.PI;
  3211. info.reverse = true;
  3212. }
  3213. return info; //结果大约是 0 - 3.14
  3214. };
  3215. class Point extends Vector2 {
  3216. constructor(x, y) {
  3217. var o = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  3218. super(x, y);
  3219. if (o.record) {
  3220. this.id = o.id;
  3221. if (this.id == void 0) this.id = "add_" + points.length;
  3222. this.ids = [this.id]; //存储拥有该坐标的点原始数据的id
  3223. points.push(this);
  3224. }
  3225. this.type = o.type || "";
  3226. this.lines = [];
  3227. }
  3228. addPoint(id) {
  3229. this.ids.push(id);
  3230. }
  3231. searchLineByFactor(dir, type, comeLine) {
  3232. var lines = this.lines.filter(line => line.searchTime < 2);
  3233. if (lines.length == 0) return;else if (lines.length == 1) return lines[0];else lines = lines.filter(line => line != comeLine);
  3234. if (lines.length == 1) return lines[0];
  3235. var result;
  3236. lines.forEach(line => {
  3237. var vec = line.getVector();
  3238. if (line.points[1] == this) vec.negate();
  3239. var factor = math.getVec2Angle(dir, vec);
  3240. if (new Vector3(dir.x, dir.y, 0).cross(new Vector3(vec.x, vec.y, 0)).z < 0) factor *= -1; /////
  3241. if (!result) {
  3242. result = {
  3243. line,
  3244. factor
  3245. };
  3246. } else {
  3247. if (type == "min" && factor < result.factor || type == "max" && factor > result.factor) result = {
  3248. line,
  3249. factor
  3250. };
  3251. }
  3252. });
  3253. return result.line;
  3254. }
  3255. }
  3256. var lineLen = 0;
  3257. class Line$1 {
  3258. constructor(o) {
  3259. if (o.points[0] == o.points[1]) return;
  3260. this.points = o.points;
  3261. this.type = o.type || 'line';
  3262. if (this.type == 'line') {
  3263. var oldLine = lines.find(line => line.points.includes(o.points[0]) && line.points.includes(o.points[1]));
  3264. if (oldLine) {
  3265. o.id != void 0 && oldLine.ids.push(o.id);
  3266. return oldLine;
  3267. }
  3268. this.id = o.id == void 0 ? "line" + lineLen++ : o.id;
  3269. this.ids = [this.id];
  3270. o.dontWriteToPoint || this.points.forEach(point => {
  3271. point.lines.push(this);
  3272. });
  3273. o.isChild || lines.push(this);
  3274. this.searchTime = 0; // 最多两次
  3275. }
  3276. this.children = []; //分割
  3277. this.parents = []; //分割
  3278. this.match = [];
  3279. }
  3280. getAngleInfo() {
  3281. var angleInfo = getAngleInfo(this.points);
  3282. this.angle = angleInfo.angle;
  3283. this.reverse = angleInfo.reverse;
  3284. }
  3285. getIntersectWithLine(line, precision) {
  3286. var joint = line.points.find(point => this.points.includes(point));
  3287. if (joint) return {
  3288. point: joint,
  3289. type: "joint"
  3290. };
  3291. var intersect = math.isLineIntersect(line.points, this.points, false, precision);
  3292. if (intersect) return {
  3293. point: intersect,
  3294. type: "intersect"
  3295. };
  3296. }
  3297. writeToPoint() {
  3298. this.points.forEach(point => {
  3299. point.lines.includes(this) || point.lines.push(this);
  3300. });
  3301. }
  3302. checkIfParent(line) {
  3303. if (this == line) {
  3304. return true; //原因就是slice的点和端点很近 误差导致
  3305. } else return this.parents.find(e => e.checkIfParent(line));
  3306. }
  3307. splitByPoint(point) {
  3308. var line1 = new Line$1({
  3309. points: [point, this.points[0]],
  3310. dontWriteToPoint: true,
  3311. hasntsure: true
  3312. });
  3313. var line2 = new Line$1({
  3314. points: [point, this.points[1]],
  3315. dontWriteToPoint: true,
  3316. hasntsure: true
  3317. });
  3318. if (!line1.points || !line2.points) {
  3319. //有至少一个是点相同的,没写到group.lines里
  3320. console.warn('splitByPoint 线有点相同');
  3321. return;
  3322. }
  3323. if (this.checkIfParent(line1) || this.checkIfParent(line2) || line1.checkIfParent(this) || line2.checkIfParent(this)) {
  3324. console.warn("splitByPoint 发现parent和children一样"); //,请检查getSliceWalls,尤其 if(math.closeTo(line1.angle,line2.angle)){ 处
  3325. return;
  3326. }
  3327. var deal = line => {
  3328. this.children.push(line);
  3329. line.parents.push(this);
  3330. if (!lines.includes(line)) lines.push(line);
  3331. line.writeToPoint();
  3332. };
  3333. deal(line1);
  3334. deal(line2);
  3335. var index = this.points[0].lines.indexOf(this);
  3336. index > -1 && this.points[0].lines.splice(index, 1);
  3337. var index = this.points[1].lines.indexOf(this);
  3338. index > -1 && this.points[1].lines.splice(index, 1);
  3339. return [line1, line2];
  3340. }
  3341. splitByPoints(points) {
  3342. points = points.map(point => {
  3343. return {
  3344. dis: point.distanceTo(this.points[0]),
  3345. point: point
  3346. };
  3347. });
  3348. points.sort((point1, point2) => {
  3349. return point1.dis - point2.dis;
  3350. });
  3351. var children = [];
  3352. points.forEach((point, index) => {
  3353. var line1 = new Line$1({
  3354. points: [point.point, index == 0 ? this.points[0] : points[index - 1].point],
  3355. group: this.group,
  3356. dontWriteToPoint: true,
  3357. hasntsure: true
  3358. });
  3359. children.push(line1);
  3360. });
  3361. var line2 = new Line$1({
  3362. points: [points[points.length - 1].point, this.points[1]],
  3363. group: this.group,
  3364. dontWriteToPoint: true,
  3365. hasntsure: true
  3366. });
  3367. children.push(line2);
  3368. var a = children.find(line => !line.points || this.checkIfParent(line) || line.checkIfParent(this));
  3369. if (a) {
  3370. console.error("splitByPoints return");
  3371. return;
  3372. }
  3373. children.forEach(line => {
  3374. this.children.push(line);
  3375. line.parents.push(this);
  3376. if (!lines.includes(line)) lines.push(line);
  3377. line.writeToPoint();
  3378. line.writeToPoint();
  3379. });
  3380. var index = this.points[0].lines.indexOf(this);
  3381. index > -1 && this.points[0].lines.splice(index, 1);
  3382. var index = this.points[1].lines.indexOf(this);
  3383. index > -1 && this.points[1].lines.splice(index, 1);
  3384. }
  3385. getAllSlices() {
  3386. //如果有被分割的片段 就返回片段,否则返回自身
  3387. var children = [];
  3388. var _traverse = function traverse(elem) {
  3389. if (elem.children.length == 0) children.push(elem);else elem.children.forEach(_traverse);
  3390. };
  3391. _traverse(this);
  3392. return children;
  3393. }
  3394. getVector() {
  3395. return this.points[1].clone().sub(this.points[0]);
  3396. }
  3397. getLength() {
  3398. return this.points[0].distanceTo(this.points[1]);
  3399. }
  3400. getCenter() {
  3401. return this.points[1].clone().add(this.points[0]).multiplyScalar(.5);
  3402. }
  3403. }
  3404. var getMixedSet = function getMixedSet(arr1, arr2) {
  3405. //交集
  3406. return arr1.filter(item => arr2.includes(item));
  3407. };
  3408. var getUnionSet = function getUnionSet(arr1, arr2) {
  3409. //并集
  3410. return arr1.concat(arr2.filter(item => !arr1.includes(item)));
  3411. };
  3412. var getDifferenceSet = function getDifferenceSet(arr1, arr2) {
  3413. //差集
  3414. var arr11 = arr1.filter(item => !arr2.includes(item));
  3415. var arr22 = arr2.filter(item => !arr1.includes(item));
  3416. return arr11.concat(arr22);
  3417. };
  3418. var getDifferenceSetMuti = function getDifferenceSetMuti(arr) {
  3419. //收集绝对没有重复的元素,也就是判断出现次数=1的
  3420. var set = [];
  3421. arr.forEach(arr1 => {
  3422. arr1.forEach(item => {
  3423. var index = set.indexOf(item);
  3424. if (index > -1) {
  3425. set.splice(index, 1);
  3426. } else {
  3427. set.push(item);
  3428. }
  3429. });
  3430. });
  3431. return set;
  3432. };
  3433. function DoorAtWhichLine(points, lines) {
  3434. var mid = points[0].clone().add(points[1]).multiplyScalar(0.5);
  3435. lines = lines.filter(line => math.ifPointAtLineBound(mid, line.points, precision));
  3436. if (lines.length == 0) return;
  3437. var result = {
  3438. line: null,
  3439. dis: Infinity
  3440. };
  3441. lines.forEach(line => {
  3442. var foot = math.getFootPoint(mid, line.points[0], line.points[1]);
  3443. var dis = foot.distanceTo(mid);
  3444. if (dis < result.dis) {
  3445. result.line = line;
  3446. result.dis = dis;
  3447. }
  3448. });
  3449. return result;
  3450. }
  3451. var ringLen = 0;
  3452. class Ring {
  3453. constructor(o) {
  3454. this.id = ringLen++;
  3455. this.type = o.type || 'normal';
  3456. this.points = o.points;
  3457. this.lines = o.lines;
  3458. rings.push(this);
  3459. this.child = []; //包含的环
  3460. this.parent = []; //被包含的环
  3461. this.smallNeibours = []; //相邻最小环(存在和它有一个以上的相同边的最小环)
  3462. var area = math.getArea(this.points);
  3463. this.area = Math.abs(area);
  3464. this.isClockwise = area < 0; //是否逆时针。一般都是逆时针得到的,如果是顺时针,可能是贪吃蛇的情况,可能不是最小环,需要去掉。
  3465. }
  3466. }
  3467. var findLine = function findLine(p1, p2) {
  3468. return lines.find(line => line.points.includes(p1) && line.points.includes(p2));
  3469. };
  3470. var ifSamePart = function ifSamePart(checkPart, part) {
  3471. //checkPart中所包含的part片段是否和基准part的顺序一样(逆序也可以, 中间有其他数也可以,起始不同也行。比如 01234和204一样的)
  3472. var axis,
  3473. startIndex,
  3474. newCheckPart = [];
  3475. for (var j = 0, len1 = checkPart.length; j < len1; j++) {
  3476. //将checkPart中比part多的数除去,使两个数组中包含的数完全相同。
  3477. if (part.indexOf(checkPart[j]) > -1) newCheckPart.push(checkPart[j]);
  3478. }
  3479. for (var i = 0, len = part.length; i < len; i++) {
  3480. var index = newCheckPart.indexOf(part[i]);
  3481. if (index == -1) return false;
  3482. if (i == 0) startIndex = index; //标记第一个查找点对应的index
  3483. else if (i == 1) {
  3484. //标记查找顺序是正还是逆
  3485. axis = index - startIndex;
  3486. if (axis == len - 1) axis = -1; //刚好是首和尾
  3487. else if (axis == 1 - len) axis = 1;
  3488. if (axis != -1 && axis != 1) {
  3489. return false;
  3490. }
  3491. } else {
  3492. //判断是否是按顺序的
  3493. if (index != (startIndex + axis * i + len) % len) return false;
  3494. }
  3495. }
  3496. return {
  3497. sameAxis: axis > 0
  3498. }; //如果一样的话返回正逆是否相同
  3499. };
  3500. //或者判断是否有相同边(但是相同点是可以组成不同环)
  3501. var ifSameRing = function ifSameRing(ring1, ring2) {
  3502. //判断两个环是否相等。 除了可以逆向外顺序要对
  3503. if (ring1 instanceof Ring) ring1 = ring1.points;
  3504. if (ring2 instanceof Ring) ring2 = ring2.points;
  3505. if (ring1.length != ring2.length) return false;
  3506. if (ring1.lines && ring2.lines) {
  3507. if (getDifferenceSet(ring1.lines, ring2.lines).length == 0) return true; //差集个数为0
  3508. } else {
  3509. if (ifSamePart(ring1, ring2)) return true;
  3510. }
  3511. };
  3512. var _atWhichChildLine = function atWhichChildLine(point, line, precision) {
  3513. if (line.children.length == 0) {
  3514. //这里可能要放低精度 保证能找到
  3515. if (math.ifPointAtLineBound(point, line.points, precision)) return line;
  3516. } else {
  3517. for (var i = 0; i < line.children.length; i++) {
  3518. var at = _atWhichChildLine(point, line.children[i], precision);
  3519. if (at) return at;
  3520. }
  3521. }
  3522. };
  3523. function getSliceLines() {
  3524. var len = lines.length;
  3525. var _deal = function deal(line1, line2) {
  3526. if (line1 == line2) return;
  3527. if (line1.angle == void 0) line1.getAngleInfo();
  3528. if (line2.angle == void 0) line2.getAngleInfo();
  3529. var intersect = line1.getIntersectWithLine(line2, precision);
  3530. if (intersect) {
  3531. var point; //得到交点
  3532. if (intersect.type == "intersect") {
  3533. point = getPoint(intersect.point, "whenGetSliceLines");
  3534. var line1_ = _atWhichChildLine(point, line1);
  3535. var line2_ = _atWhichChildLine(point, line2);
  3536. //重合的情况还没考虑(平行)
  3537. if (!line1_) line1_ = _atWhichChildLine(point, line1, precision); //降低精度
  3538. if (!line1_) line1_ = _atWhichChildLine(point, line1, precision * 2); //降低精度
  3539. if (!line2_) line2_ = _atWhichChildLine(point, line2, precision);
  3540. if (!line2_) line2_ = _atWhichChildLine(point, line2, precision * 2); //降低精度
  3541. //拆分线条:
  3542. //如果还报错,找不到ChildLine,就直接返回吧 或者搞个循环 逐渐降低精度
  3543. if (!line1_ || !line2_) {
  3544. console.warn("atWhichChildLine仍旧找不到 :" + line1.id + ',' + line2.id + ", pointId: " + point.id);
  3545. line1_ || console.warn("找不到line1");
  3546. line2_ || console.warn("找不到line2");
  3547. return;
  3548. }
  3549. if (line1_.points.find(p => p == point) && line2_.points.find(p => p == point)) {//这个点是line1_、 line2_端点,不做处理
  3550. //console.log("joint型 "+point.id)
  3551. } else if (line1_.points.find(p => p == point)) {
  3552. //T型交叉
  3553. line2_.splitByPoint(point); //加入到母线中,之后还先用母线判断交点
  3554. //console.log("T型交叉1 "+point.id)
  3555. } else if (line2_.points.find(p => p == point)) {
  3556. //T型交叉
  3557. line1_.splitByPoint(point);
  3558. //console.log("T型交叉2 "+point.id)
  3559. } else {
  3560. //十字交叉
  3561. line1_.splitByPoint(point);
  3562. line2_.splitByPoint(point);
  3563. }
  3564. } else {
  3565. point = intersect.point; //交点是端点
  3566. if (math.closeTo(line1.angle, line2.angle)) {
  3567. //重合一部分
  3568. var children1 = line1.getAllSlices();
  3569. var children2 = line2.getAllSlices();
  3570. if (children1.length > 1 || children2.length > 1) {
  3571. //使用最小分割片段来比较
  3572. children1.forEach(child1 => {
  3573. children2.forEach(child2 => {
  3574. _deal(child1, child2);
  3575. });
  3576. });
  3577. return;
  3578. }
  3579. var anotherPoint1 = line1.points.find(point_ => point_ != point);
  3580. var anotherPoint2 = line2.points.find(point_ => point_ != point);
  3581. if (math.ifPointAtLineBound(anotherPoint1, line2.points)) {
  3582. line2.splitByPoint(anotherPoint1);
  3583. } else if (math.ifPointAtLineBound(anotherPoint2, line1.points)) {
  3584. line1.splitByPoint(anotherPoint2);
  3585. }
  3586. }
  3587. }
  3588. } else if (math.closeTo(line1.angle, line2.angle)) {
  3589. var vec1 = line1.getVector();
  3590. var vec = line1.points[0].clone().sub(line2.points[0]);
  3591. var cos = math.getVec2Cos(vec1, vec);
  3592. if (math.closeTo(cos, -1, 1e-4) || math.closeTo(cos, 1, 1e-4)) {
  3593. //共线
  3594. var children1 = line1.getAllSlices();
  3595. var children2 = line2.getAllSlices();
  3596. if (children1.length > 1 || children2.length > 1) {
  3597. //使用最小分割片段来比较
  3598. children1.forEach(child1 => {
  3599. children2.forEach(child2 => {
  3600. _deal(child1, child2);
  3601. });
  3602. });
  3603. return;
  3604. }
  3605. //判断是否重叠
  3606. var A = line1.points[0];
  3607. var C = line1.reverse == line2.reverse ? line2.points[0] : line2.points[1];
  3608. var B = line1.points[1];
  3609. var D = line1.reverse == line2.reverse ? line2.points[1] : line2.points[0];
  3610. var BC = C.clone().sub(B);
  3611. var AD = D.clone().sub(A);
  3612. if (BC.length() < AD.length()) {
  3613. var BA = A.clone().sub(B);
  3614. if (math.getVec2Angle(BC, BA) >= 1.57) return; //没有重叠部分
  3615. } else {
  3616. var AB = B.clone().sub(A);
  3617. if (math.getVec2Angle(AD, AB) >= 1.57) return;
  3618. }
  3619. var f = function f(line1, line2) {
  3620. var one = math.ifPointAtLineBound(line1.points[0], line2.points);
  3621. var two = math.ifPointAtLineBound(line1.points[1], line2.points);
  3622. if (one && two) {
  3623. //line1在line2上
  3624. line2.splitByPoints(line1.points);
  3625. return true;
  3626. } else if (one || two) {
  3627. //错开
  3628. var point1 = one ? line1.points[0] : line1.points[1];
  3629. var anotherPoint1 = one ? line1.points[1] : line1.points[0];
  3630. var dis1 = line2.points[0].distanceTo(anotherPoint1);
  3631. var dis2 = line2.points[1].distanceTo(anotherPoint1);
  3632. var point2 = dis1 < dis2 ? line2.points[0] : line2.points[1];
  3633. line1.splitByPoint(point2);
  3634. line2.splitByPoint(point1);
  3635. return true;
  3636. }
  3637. };
  3638. f(line1, line2) || f(line2, line1);
  3639. }
  3640. }
  3641. };
  3642. for (var i = 0; i < len; i++) {
  3643. var line1 = lines[i];
  3644. for (var j = i + 1; j < len; j++) {
  3645. var line2 = lines[j];
  3646. _deal(line1, line2);
  3647. }
  3648. }
  3649. //console.log("原有线条个数:"+len)
  3650. //lines = lines.filter((line)=>{return line.children.length == 0})
  3651. //console.log("现有线条个数:"+lines.length)
  3652. }
  3653. var bound = new Box2();
  3654. var build = function build(o) {
  3655. //融合了相近点
  3656. //根据bound 处理precision
  3657. o.points.forEach(p => {
  3658. bound.expandByPoint(new Vector2(p.x, p.y));
  3659. });
  3660. if (o.precision != void 0) {
  3661. precision = o.precision;
  3662. } else {
  3663. var boundSize = bound.getSize(new Vector2());
  3664. precision = MathUtils.clamp(Math.max(boundSize.x, boundSize.y) / 70, 0.2, 2);
  3665. }
  3666. o.points.forEach(point => getPoint(point)); //{x:..,y:..}
  3667. o.lines.forEach(line => {
  3668. //{p1:id1. p2:id2}
  3669. new Line$1({
  3670. points: [getPoint(line.p1), getPoint(line.p2)],
  3671. id: line.id
  3672. });
  3673. });
  3674. //注意:不能出现一条线的两个点坐标一致,否则寻路时方向出错。 所以手动融合下相近点。
  3675. };
  3676. var searchRings = function searchRings() {
  3677. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  3678. points = [];
  3679. lines = [];
  3680. rings = [];
  3681. lineLen = ringLen = 0;
  3682. o.points = o.points || [];
  3683. o.lines = o.lines || [];
  3684. build(o);
  3685. if (!o.dontSliceLines) {
  3686. getSliceLines();
  3687. }
  3688. //查找最小回路:
  3689. //参考: 引入方向因子的最小回路、最大回路搜索算法.pdf
  3690. //方法: 逆时针寻找(标记)最外层大环 -->从走过的点开始逆时针寻找最小环(直到所有可走的路被走过两次)-->逆时针寻找最外层大环(直到所有可走的路被走过两次)-->..
  3691. //其中找大环时选择方向因子最小的路, 而小环则相反(但只有开始第一条路是一样的, 都是选择最左边的点的因子最小的路)。
  3692. //标记方法: 每条线需要被搜索两次才算完毕。搜索完毕的线退出搜索。(依据:搜索完全部最小回路后 , 在无向图中删除搜索过 2 次的边及孤立节点得到退化图 , 恰好构成最大回路。)
  3693. var searchTime = 0;
  3694. var addRingJudgeCount = 0;
  3695. var addRingJudge = function addRingJudge(ring, lines, connectedLines, type) {
  3696. // 处理拣出的片段
  3697. addRingJudgeCount++;
  3698. //console.log("addRingJudge points("+ type+"):"+ ring.map(point=>point.id) )
  3699. if (o.onlyGetOutRing && type == "small") return;
  3700. if (type == "small" || o.onlyGetOutRing) {
  3701. //挑出回路:
  3702. var newRings = [];
  3703. while (ring.length) {
  3704. var road = [];
  3705. var turnBack = false;
  3706. for (var i = 0; i < ring.length; i++) {
  3707. if (road.includes(ring[i])) {
  3708. //如果走到方才的点,可能形成回路。 无论是不是回路都要摘去这段。
  3709. var index = road.indexOf(ring[i]);
  3710. var pointArr = ring.slice(index, i);
  3711. var linesArr = lines.slice(index, i);
  3712. ring.splice(index, i - index);
  3713. lines.splice(index, i - index);
  3714. if (pointArr.length > 2) {
  3715. // 如果只有两个数,代表原路返回, 如 1->2(->1)
  3716. if (!rings.find(ring_ => ifSameRing(pointArr, ring_))) newRings.push(new Ring({
  3717. points: pointArr,
  3718. lines: linesArr
  3719. }));
  3720. }
  3721. turnBack = true;
  3722. break;
  3723. } else {
  3724. road.push(ring[i]);
  3725. turnBack = false;
  3726. }
  3727. }
  3728. if (!turnBack) {
  3729. //没有重复的点,那么就直接处理整条。
  3730. if (ring.length > 2) {
  3731. // 如果只有两个数,代表原路返回, 如 1->2(->1)
  3732. if (!rings.find(ring_ => ifSameRing(ring, ring_))) newRings.push(new Ring({
  3733. points: ring,
  3734. lines
  3735. }));
  3736. }
  3737. break;
  3738. }
  3739. }
  3740. if (type != 'small') {
  3741. newRings.forEach(e => e.isOutRing = true);
  3742. }
  3743. //console.log(newRings)
  3744. } else {
  3745. return ring;
  3746. }
  3747. };
  3748. var _search = function search(point2d, comeRoad, type, connectedLines) {
  3749. searchTime++;
  3750. var goLine;
  3751. var direction;
  3752. if (type.includes("big")) {
  3753. if (!comeRoad) {
  3754. if (type.includes("Left")) {
  3755. //逆时针
  3756. direction = new Vector2(1, 0);
  3757. } else {
  3758. direction = new Vector2(-1, 0);
  3759. }
  3760. goLine = point2d.searchLineByFactor(direction, "min");
  3761. } else {
  3762. var lastPoint = comeRoad.points[comeRoad.points.length - 1];
  3763. direction = point2d.clone().sub(lastPoint);
  3764. goLine = point2d.searchLineByFactor(direction, "min", findLine(point2d, lastPoint));
  3765. }
  3766. } else {
  3767. if (!comeRoad) {
  3768. //似乎找最小环时,第一条线也是找最小的因子,这样才能保证逆时针(除非只有顺时针一条路)
  3769. direction = new Vector2(1, 0);
  3770. goLine = point2d.searchLineByFactor(direction, "min");
  3771. } else {
  3772. var lastPoint = comeRoad.points[comeRoad.points.length - 1];
  3773. direction = point2d.clone().sub(lastPoint);
  3774. goLine = point2d.searchLineByFactor(direction, "max", findLine(point2d, lastPoint));
  3775. }
  3776. }
  3777. if (!goLine) return;
  3778. goLine.searchTime++;
  3779. connectedLines.includes(goLine) || connectedLines.push(goLine);
  3780. var nextPoint = goLine.points.find(point => point2d != point);
  3781. //if( comeRoad && comeRoad.points[comeRoad.points.length - 1] == nextPoint ) return;//不能查找来时的方向(反方向)
  3782. //走不通就原路返回
  3783. var roadPoints = comeRoad ? comeRoad.points.concat([point2d]) : [point2d]; //每个分叉都能构成一条新的road
  3784. var roadLines = comeRoad ? comeRoad.lines.concat([goLine]) : [goLine];
  3785. //走到第一个点就算停止,这时候可能得到一个环、或者一段走了两遍的线、或者一条线上带了些环。
  3786. if (nextPoint == roadPoints[0]) return addRingJudge(roadPoints, roadLines, connectedLines, type); //形成环
  3787. else {
  3788. /* var len = roadPoints.indexOf(nextPoint);
  3789. if( len > -1){ //走到走过的路的某一点 构成这段路的回路
  3790. var points = roadPoints.slice(len, roadPoints.length);
  3791. var lines = roadLines.slice(len, roadPoints.length);
  3792. addRingJudge(points, lines)
  3793. }else{ */
  3794. return _search(nextPoint, {
  3795. lines: roadLines,
  3796. points: roadPoints
  3797. }, type, connectedLines); //继续寻路
  3798. //}
  3799. }
  3800. };
  3801. while (1) {
  3802. //搜寻一次大环
  3803. var connectedLines = []; //被搜寻过的且searchTime<2的线。一旦全部搜完就说明该连通区域搜寻完毕,继续查下一个连通区域。
  3804. var startPoint = null;
  3805. points.forEach(point => {
  3806. //找出x最小的点
  3807. if (!point.lines.find(line => line.searchTime < 2)) return;
  3808. if (!startPoint) startPoint = point;else if (point.x < startPoint.x) startPoint = point;
  3809. });
  3810. if (!startPoint) break; //说明全部找完
  3811. var ring = _search(startPoint, null, "bigLeft", connectedLines); //逆时针
  3812. //search(startPoint, null, "bigRight", connectedLines);//顺时针(为了防止最外层不是回路之前写了顺时针,但如果是回路就会走重复。后来发现只要逆时针即可,因为走完后剩下的可以再次找大环)
  3813. connectedLines = connectedLines.filter(line => line.searchTime < 2);
  3814. var _loop = function _loop() {
  3815. //目标是顺着connectedLines把所有连通的小环都找到
  3816. var points_ = []; //connectedLines中所有的点
  3817. connectedLines.forEach(line => line.points.forEach(point => {
  3818. if (!points_.includes(point)) points_.push(point);
  3819. }));
  3820. startPoint = null;
  3821. points_.forEach(point => {
  3822. //找出x最小的点
  3823. if (!point.lines.find(line => line.searchTime < 2)) return;
  3824. if (!startPoint) startPoint = point;else if (point.x < startPoint.x) startPoint = point;
  3825. });
  3826. if (!startPoint) return 1; // break
  3827. _search(startPoint, null, "small", connectedLines);
  3828. connectedLines = connectedLines.filter(line => line.searchTime < 2);
  3829. },
  3830. startPoint;
  3831. while (connectedLines.length > 0) {
  3832. if (_loop()) break;
  3833. }
  3834. }
  3835. /* if(o.onlyGetOutRing){
  3836. rings = rings.filter(e=>e.isOutRing)
  3837. } */
  3838. //console.log("searchTime "+searchTime + ", addRingJudgeCount " +addRingJudgeCount)
  3839. //找出所有的相邻关系,包括公共边
  3840. var len = rings.length;
  3841. for (var i = 0; i < len; i++) {
  3842. var ring1 = rings[i];
  3843. for (var j = i + 1; j < len; j++) {
  3844. var ring2 = rings[j];
  3845. var bothHasLines = getMixedSet(ring1.lines, ring2.lines);
  3846. if (bothHasLines.length) {
  3847. //ring1oíring2?àáú
  3848. ring1.smallNeibours.push(ring2);
  3849. ring2.smallNeibours.push(ring1);
  3850. } else {}
  3851. }
  3852. }
  3853. rings.forEach(ring1 => {
  3854. for (var _i = 0; _i < len; _i++) {
  3855. var ring2 = rings[_i];
  3856. if (ring1 == ring2 || ring1.smallNeibours.includes(ring2)) continue;
  3857. var inside = void 0;
  3858. for (var u = 0; u < ring1.points.length; u++) {
  3859. inside = math.isPointInArea(ring2.points, null, ring1.points[u]);
  3860. if (!inside) break;else if (inside && !inside.atLine) {
  3861. break;
  3862. }
  3863. }
  3864. if (inside) {
  3865. //只要其中一个点在ring2内,就说明ring1是内环
  3866. if (inside.atLine) {
  3867. //(还是会存在点全在线上的情况,这时候判断中心点)
  3868. var center = math.getCenterOfGravityPoint(ring1.points);
  3869. var inside1 = math.isPointInArea(ring2.points, null, center);
  3870. if (!inside1) {
  3871. continue;
  3872. }
  3873. }
  3874. ring2.child.push(ring1);
  3875. ring1.parent.push(ring2);
  3876. }
  3877. }
  3878. });
  3879. //去除非最小的ring 是否应该检测parent child?
  3880. /*
  3881. like this:
  3882. |———————————————————————|
  3883. |———|———————|———————| |
  3884. | | | | |
  3885. | |———————|———————| |
  3886. |———————————————————————|
  3887. */
  3888. var wiseRings = rings.filter(r => !r.isClockwise); //一般都是逆时针得到的,如果是顺时针,可能是贪吃蛇的情况,可能不是最小环,需要去掉。
  3889. if (wiseRings.length > 0) {
  3890. //console.log('%c存在非最小的ring! 进行处理:',"color:#00f");
  3891. wiseRings.forEach(ring => {
  3892. //(此案例验证出smallNeibours就是它的最小构成,可以再看看别的案例)
  3893. if (ring.smallNeibours.length > 0) {
  3894. //另:如果内部只有一个,说明它是最小环,不需要处理
  3895. var is = false;
  3896. var difference = getDifferenceSet(ring.lines, getDifferenceSetMuti(ring.smallNeibours.concat(ring.child).map(ring => ring.lines))); //获取所有smallNeibours和child的边中没有重复过的边(就是outline) 和该ring的线比较
  3897. is = difference.every(line => ring.child.find(r => r.lines.includes(line))); //多出的线只能是child中的线
  3898. if (is) {
  3899. console.log('%c删除非最小环 ring' + ring.id, "color:#00f");
  3900. console.log(ring);
  3901. rings.splice(rings.indexOf(ring), 1);
  3902. ring.child.forEach(c => {
  3903. var index = c.parent.indexOf(ring);
  3904. index > -1 && c.parent.splice(index, 1);
  3905. });
  3906. ring.parent.forEach(c => {
  3907. var index = c.child.indexOf(ring);
  3908. index > -1 && c.child.splice(index, 1);
  3909. });
  3910. ring.smallNeibours.forEach(c => {
  3911. var index = c.smallNeibours.indexOf(ring);
  3912. index > -1 && c.smallNeibours.splice(index, 1);
  3913. });
  3914. }
  3915. }
  3916. });
  3917. }
  3918. /* rings = rings.filter(ring=>{
  3919. rings = rings.filter(ring=>{
  3920. var enoughSize = ring.area > 0.5
  3921. if(!enoughSize){console.log('因面积过小去除ring '+ring.id + " , area: "+ring.area)}
  3922. return enoughSize
  3923. })
  3924. rings.forEach(ring=>{
  3925. if(ring.closetChilds){
  3926. ring.closetChilds = ring.closetChilds.filter(e=>rings.includes(e))
  3927. }
  3928. })
  3929. return rings
  3930. }) */ //在dealRings前不能随意删除rings,因为判断是否是最小环时需要全部的环
  3931. rings.forEach(ring => {
  3932. //这里和cad中的不太一样, cad中双数个parent算外环,单数内环; 这里不分内外, 只看有无parent child
  3933. if (ring.parent.length) {
  3934. ring.closetParent = ring.parent.find(ring_ => ring_.parent.length == ring.parent.length - 1); //最近一层的大环就是比它的parent个数少一的
  3935. ring.closetParent.closetChilds || (ring.closetParent.closetChilds = []); //内环可能多个
  3936. ring.closetParent.closetChilds.push(ring);
  3937. }
  3938. });
  3939. //console.log(rings)
  3940. var _ring = rings.map(ring => {
  3941. var data = {
  3942. id: ring.id,
  3943. points: ring.points.map(point => {
  3944. return {
  3945. id: point.ids[0],
  3946. x: point.x,
  3947. y: point.y
  3948. };
  3949. }),
  3950. /* doors : o.doors.filter(door=>{
  3951. if(ring.closetChilds){
  3952. var childOutLines = getDifferenceSetMuti(ring.closetChilds.map(ring=>ring.lines)) //最近子环的外边
  3953. return ring.lines.concat(childOutLines).includes(door.atLine)
  3954. }else{
  3955. return ring.lines.includes(door.atLine)
  3956. }
  3957. }), */
  3958. area: ring.area,
  3959. closetParent: ring.closetParent && ring.closetParent.id,
  3960. closetChilds: ring.closetChilds && ring.closetChilds.map(e => e.id)
  3961. };
  3962. return data;
  3963. });
  3964. //console.log(JSON.stringify(_ring))
  3965. return _ring;
  3966. };
  3967. var easing = {};
  3968. //渐变曲线函数,反应加速度的变化
  3969. //currentTime:x轴当前时间(从0-到duration), startY:起始点, duration:总时长, wholeY:路程 (即endY-startY)
  3970. //参数基本是 x, 0, 1, 1
  3971. /*
  3972. easeOut 基本是y= m * (x-dur)^k + n, 若k为偶数,m<0, 若k为奇数,m>0; (因为偶数的话必须开口向下才能获得斜率递减的递增的那段,而奇数是对称的,单调递增. )
  3973. 根据x=0时y=0, x=dur时y=S , 得 n = S,m = -S/(-dur)^k
  3974. */
  3975. easing.getEaseOut = function (k) {
  3976. // k 是>=2的整数. 越大变化率越大, 相同初始速度所需要时间越久
  3977. var easeFun;
  3978. k = Math.round(k);
  3979. if (k < 2) {
  3980. k = Math.PI / 2;
  3981. easeFun = easing.easeOutSine;
  3982. } else {
  3983. easeFun = function easeFun(currentTime, startY, wholeY, duration) {
  3984. if (k > 2) {
  3985. console.log(k);
  3986. }
  3987. return -wholeY / Math.pow(-duration, k) * Math.pow(currentTime - duration, k) + wholeY;
  3988. };
  3989. }
  3990. return {
  3991. k,
  3992. easeFun
  3993. };
  3994. };
  3995. easing.linearTween = function (currentTime, startY, wholeY, duration) {
  3996. return wholeY * currentTime / duration + startY;
  3997. }, easing.easeInQuad = function (currentTime, startY, wholeY, duration) {
  3998. return currentTime /= duration, wholeY * currentTime * currentTime + startY;
  3999. }, easing.easeOutQuad = function (currentTime, startY, wholeY, duration) {
  4000. // 如套上实际的距离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
  4001. return currentTime /= duration, -wholeY * currentTime * (currentTime - 2) + startY;
  4002. }, easing.easeInOutQuad = function (currentTime, startY, wholeY, duration) {
  4003. return currentTime /= duration / 2, currentTime < 1 ? wholeY / 2 * currentTime * currentTime + startY : (currentTime--, -wholeY / 2 * (currentTime * (currentTime - 2) - 1) + startY);
  4004. }, easing.easeInCubic = function (currentTime, startY, wholeY, duration) {
  4005. return currentTime /= duration, wholeY * currentTime * currentTime * currentTime + startY;
  4006. }, easing.easeOutCubic = function (currentTime, startY, wholeY, duration) {
  4007. // y = S / dur^3 *(x-dur)^3 + S,对称中心是(dur,S),从0-dur是 斜率递减的递增函数,导数为3S/dur^3 * (x-dur)^2, 0时速度为3S/dur
  4008. return currentTime /= duration, currentTime--, wholeY * (currentTime * currentTime * currentTime + 1) + startY;
  4009. }, easing.easeInOutCubic = function (currentTime, startY, wholeY, duration) {
  4010. return currentTime /= duration / 2, currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime + startY : (currentTime -= 2, wholeY / 2 * (currentTime * currentTime * currentTime + 2) + startY);
  4011. }, easing.easeInQuart = function (currentTime, startY, wholeY, duration) {
  4012. return currentTime /= duration, wholeY * currentTime * currentTime * currentTime * currentTime + startY;
  4013. }, easing.easeOutQuart = function (currentTime, startY, wholeY, duration) {
  4014. //根据上面的计算,估计0时速度应该是4S/dur吧……
  4015. return currentTime /= duration, currentTime--, -wholeY * (currentTime * currentTime * currentTime * currentTime - 1) + startY;
  4016. }, easing.easeInOutQuart = function (currentTime, startY, wholeY, duration) {
  4017. return currentTime /= duration / 2, currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime * currentTime + startY : (currentTime -= 2, -wholeY / 2 * (currentTime * currentTime * currentTime * currentTime - 2) + startY);
  4018. }, easing.easeInQuint = function (currentTime, startY, wholeY, duration) {
  4019. return currentTime /= duration, wholeY * currentTime * currentTime * currentTime * currentTime * currentTime + startY;
  4020. }, easing.easeOutQuint = function (currentTime, startY, wholeY, duration) {
  4021. return currentTime /= duration, currentTime--, wholeY * (currentTime * currentTime * currentTime * currentTime * currentTime + 1) + startY;
  4022. }, easing.easeInOutQuint = function (currentTime, startY, wholeY, duration) {
  4023. return currentTime /= duration / 2, currentTime < 1 ? wholeY / 2 * currentTime * currentTime * currentTime * currentTime * currentTime + startY : (currentTime -= 2, wholeY / 2 * (currentTime * currentTime * currentTime * currentTime * currentTime + 2) + startY);
  4024. }, easing.easeInSine = function (currentTime, startY, wholeY, duration) {
  4025. return -wholeY * Math.cos(currentTime / duration * (Math.PI / 2)) + wholeY + startY;
  4026. }, easing.easeOutSine = function (currentTime, startY, wholeY, duration) {
  4027. // y' = S * PI / 2 / dur * cos(PI/2/dur * x)
  4028. return wholeY * Math.sin(currentTime / duration * (Math.PI / 2)) + startY;
  4029. }, easing.easeInOutSine = function (currentTime, startY, wholeY, duration) {
  4030. return -wholeY / 2 * (Math.cos(Math.PI * currentTime / duration) - 1) + startY;
  4031. }, easing.easeInExpo = function (currentTime, startY, wholeY, duration) {
  4032. return wholeY * Math.pow(2, 10 * (currentTime / duration - 1)) + startY;
  4033. }, easing.easeOutExpo = function (currentTime, startY, wholeY, duration) {
  4034. return wholeY * (-Math.pow(2, -10 * currentTime / duration) + 1) + startY;
  4035. }, easing.easeInOutExpo = function (currentTime, startY, wholeY, duration) {
  4036. return currentTime /= duration / 2, currentTime < 1 ? wholeY / 2 * Math.pow(2, 10 * (currentTime - 1)) + startY : (currentTime--, wholeY / 2 * (-Math.pow(2, -10 * currentTime) + 2) + startY);
  4037. }, easing.easeInCirc = function (currentTime, startY, wholeY, duration) {
  4038. return currentTime /= duration, -wholeY * (Math.sqrt(1 - currentTime * currentTime) - 1) + startY;
  4039. }, easing.easeOutCirc = function (currentTime, startY, wholeY, duration) {
  4040. return currentTime /= duration, currentTime--, wholeY * Math.sqrt(1 - currentTime * currentTime) + startY;
  4041. }, easing.easeInOutCirc = function (currentTime, startY, wholeY, duration) {
  4042. return currentTime /= duration / 2, currentTime < 1 ? -wholeY / 2 * (Math.sqrt(1 - currentTime * currentTime) - 1) + startY : (currentTime -= 2, wholeY / 2 * (Math.sqrt(1 - currentTime * currentTime) + 1) + startY);
  4043. }, easing.easeInElastic = function (currentTime, startY, wholeY, duration) {
  4044. var r = 1.70158,
  4045. o = 0,
  4046. a = wholeY;
  4047. return 0 === currentTime ? startY : 1 === (currentTime /= duration) ? startY + wholeY : (o || (o = .3 * duration), a < Math.abs(wholeY) ? (a = wholeY, r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a), -(a * Math.pow(2, 10 * (currentTime -= 1)) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o)) + startY);
  4048. }, easing.easeOutElastic = function (currentTime, startY, wholeY, duration) {
  4049. var r = 1.70158,
  4050. o = 0,
  4051. a = wholeY;
  4052. return 0 === currentTime ? startY : 1 === (currentTime /= duration) ? startY + wholeY : (o || (o = .3 * duration), a < Math.abs(wholeY) ? (a = wholeY, r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a), a * Math.pow(2, -10 * currentTime) * Math.sin((currentTime * duration - r) * (2 * Math.PI) / o) + wholeY + startY);
  4053. }, easing.easeInOutElastic = function (currentTime, startY, wholeY, duration) {
  4054. var r = 1.70158,
  4055. o = 0,
  4056. a = wholeY;
  4057. return 0 === currentTime ? startY : 2 === (currentTime /= duration / 2) ? startY + wholeY : (o || (o = duration * (.3 * 1.5)), a < Math.abs(wholeY) ? (a = wholeY, r = o / 4) : r = o / (2 * Math.PI) * Math.asin(wholeY / a), 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);
  4058. }, easing.easeInBack = function (currentTime, startY, wholeY, duration, r) {
  4059. return void 0 === r && (r = 1.70158), wholeY * (currentTime /= duration) * currentTime * ((r + 1) * currentTime - r) + startY;
  4060. }, easing.easeOutBack = function (currentTime, startY, wholeY, duration, r) {
  4061. return void 0 === r && (r = 1.70158), wholeY * ((currentTime = currentTime / duration - 1) * currentTime * ((r + 1) * currentTime + r) + 1) + startY;
  4062. }, easing.easeInOutBack = function (currentTime, startY, wholeY, duration, r) {
  4063. return void 0 === r && (r = 1.70158), (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;
  4064. }, easing.easeOutBounce = function (currentTime, startY, wholeY, duration) {
  4065. 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;
  4066. }, easing.easeInBounce = function (currentTime, startY, wholeY, r) {
  4067. return wholeY - easing.easeOutBounce(r - currentTime, 0, wholeY, r) + startY;
  4068. }, easing.easeInOutBounce = function (currentTime, startY, wholeY, r) {
  4069. 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;
  4070. };
  4071. var lerp = {
  4072. /* vector: function(currentTime, startY, f) {//xzw change, add f
  4073. var wholeY = currentTime.clone();
  4074. return startY = startY.clone(),
  4075. function(duration) {
  4076. currentTime.set(wholeY.x * (1 - duration) + startY.x * duration, wholeY.y * (1 - duration) + startY.y * duration, wholeY.z * (1 - duration) + startY.z * duration)
  4077. f && f(currentTime,duration);
  4078. }
  4079. },
  4080. quaternion: function(currentTime, startY, f) {//xzw change, add f
  4081. var wholeY = currentTime.clone();
  4082. return function(duration) {
  4083. currentTime.copy(wholeY).slerp(startY, duration);
  4084. f && f(currentTime,duration);
  4085. }
  4086. },
  4087. property: function(currentTime, startY, wholeY, duration) {
  4088. var r = currentTime[startY];
  4089. return function(o) {
  4090. currentTime[startY] = r * (1 - o) + wholeY * o,
  4091. duration && duration(currentTime[startY])
  4092. }
  4093. },
  4094. uniform: function(currentTime, startY, wholeY) {
  4095. var duration = currentTime.material.uniforms[startY].value;
  4096. return function(r) {
  4097. try{
  4098. currentTime.material.uniforms[startY] && (currentTime.material.uniforms[startY].value = duration * (1 - r) + wholeY * r)
  4099. }catch(currentTime){
  4100. console.log(1)
  4101. }
  4102. }
  4103. },
  4104. matrix4: function(currentTime, startY) {
  4105. var wholeY = currentTime.clone();
  4106. return function(duration) {
  4107. for (var r = currentTime.elements, o = wholeY.elements, a = startY.elements, s = 0; s < 16; s++)
  4108. r[s] = o[s] * (1 - duration) + a[s] * duration
  4109. }
  4110. },
  4111. allUniforms: function(currentTime, startY, wholeY) {
  4112. var duration = currentTime.map(function(currentTime) {
  4113. return this.uniform(currentTime, startY, wholeY)
  4114. }
  4115. .bind(this));
  4116. return function(currentTime) {
  4117. duration.forEach(function(startY) {
  4118. startY(currentTime)
  4119. })
  4120. }
  4121. } */
  4122. vector: function vector(t, i, f) {
  4123. //xzw change, add f
  4124. var n = t.clone();
  4125. return i = i.clone(), function (e, delta) {
  4126. t.set(n.x * (1 - e) + i.x * e, n.y * (1 - e) + i.y * e, n.z * (1 - e) + i.z * e);
  4127. f && f(t, e, delta);
  4128. };
  4129. },
  4130. quaternion: function quaternion(t, i, f) {
  4131. //xzw change, add f
  4132. var n = t.clone();
  4133. return function (e) {
  4134. t.copy(n).slerp(i, e);
  4135. f && f(t, e);
  4136. };
  4137. },
  4138. property: function property(t, i, n, r) {
  4139. var o = t[i];
  4140. return function (e) {
  4141. t[i] = o * (1 - e) + n * e, r && r(t[i]);
  4142. };
  4143. },
  4144. uniform: function uniform(t, i, n) {
  4145. var r = t.material.uniforms[i].value;
  4146. return function (e) {
  4147. t.material.uniforms[i] && (t.material.uniforms[i].value = r * (1 - e) + n * e);
  4148. };
  4149. },
  4150. matrix4: function matrix4(o, a) {
  4151. var s = o.clone();
  4152. return function (e) {
  4153. for (var t = o.elements, i = s.elements, n = a.elements, r = 0; r < 16; r++) t[r] = i[r] * (1 - e) + n[r] * e;
  4154. };
  4155. },
  4156. allUniforms: function allUniforms(e, t, i) {
  4157. var n = e.map(function (e) {
  4158. return this.uniform(e, t, i);
  4159. }.bind(this));
  4160. return function (t) {
  4161. n.forEach(function (e) {
  4162. e(t);
  4163. });
  4164. };
  4165. },
  4166. color: function color(e, t, f) {
  4167. var i = e.clone();
  4168. return function (n) {
  4169. e.copy(i).lerp(t, n);
  4170. f && f(e, n);
  4171. };
  4172. }
  4173. };
  4174. /*
  4175. 渐变
  4176. */
  4177. var transitions = {
  4178. globalDone: null,
  4179. funcs: [],
  4180. counter: 0,
  4181. uniqueID: 0,
  4182. start: function start(func, duration, done, delay, ease, name, id, cancelFun) {
  4183. var ignoreFirstFrame = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true;
  4184. return delay = delay || 0, this.funcs.push({
  4185. func: func,
  4186. current: -delay * Math.abs(duration),
  4187. //当前时间
  4188. duration: (1 - Math.max(delay, 0)) * Math.abs(duration),
  4189. //总时长
  4190. done: done,
  4191. easing: ease || easing.linearTween,
  4192. //渐变曲线
  4193. cycling: duration < 0,
  4194. running: !0,
  4195. debug: delay < 0,
  4196. name: name || "T" + this.counter,
  4197. id: void 0 === id ? this.counter : id,
  4198. paused: !1,
  4199. cancelFun: cancelFun,
  4200. //取消时执行的函数
  4201. updateCount: 0,
  4202. ignoreFirstFrame
  4203. }), func(0, 16), this.counter += 1, func;
  4204. },
  4205. trigger: function trigger(e) {
  4206. var t = void 0 === e.delayRatio ? 0 : e.delayRatio,
  4207. u = e.func || function () {},
  4208. r = void 0 === e.duration ? 0 : e.duration;
  4209. void 0 !== e.cycling && e.cycling && (r = -Math.abs(r));
  4210. var o = e.done || null,
  4211. a = e.easing || easing.linearTween,
  4212. s = e.name || "R" + this.counter,
  4213. l = void 0 === e.id ? this.counter : e.id;
  4214. return this.start(u, r, o, t, a, s, l);
  4215. },
  4216. setTimeout: function setTimeout(e, t, u) {
  4217. var duration = void 0 === u ? this.counter : u;
  4218. return this.trigger({
  4219. done: e,
  4220. duration: void 0 === t ? 0 : t,
  4221. name: "O" + this.counter,
  4222. id: duration
  4223. });
  4224. },
  4225. pause: function pause() {
  4226. this.paused = !0;
  4227. },
  4228. resume: function resume() {
  4229. this.paused = !1;
  4230. },
  4231. update: function update(e) {
  4232. this.funcs.forEach(function (t) {
  4233. if (t.updateCount++ == 0 && t.ignoreFirstFrame) return; //add start可能发生在一帧中任意时刻,而每次update的是在一帧中的固定时刻,所以从start到第一次update的时间并不是所传入的delta,该delta 是上一帧的update到这一帧的update的耗时。 故去掉了第一次的update,相当于延迟一帧再update.
  4234. if (!(t.paused || (t.current += 1e3 * e, t.current < 0))) {
  4235. if (t.current >= t.duration && !t.cycling) {
  4236. var u = t.easing(1, 0, 1, 1);
  4237. t.func(u, 1e3 * e), t.done && t.done(), t.running = !1;
  4238. } else {
  4239. var duration = t.easing(t.current % t.duration / t.duration, 0, 1, 1),
  4240. r = t.func(duration, 1e3 * e) || !1;
  4241. r && (t.done && t.done(), t.running = !1);
  4242. }
  4243. }
  4244. });
  4245. var t = this.funcs.length;
  4246. this.funcs = this.funcs.filter(function (e) {
  4247. return e.running;
  4248. });
  4249. var u = this.funcs.length;
  4250. if (t > 0 && 0 === u && this.globalDone) {
  4251. var duration = this.globalDone;
  4252. this.globalDone = null, duration();
  4253. }
  4254. },
  4255. adjustSpeed: function adjustSpeed(e, t) {
  4256. for (var u = this.getById(e), n = 0; n < u.length; n++) {
  4257. var r = u[n];
  4258. r.duration /= t, r.current /= t;
  4259. }
  4260. },
  4261. getById: function getById(e) {
  4262. return this.funcs.filter(function (t) {
  4263. return e === t.id;
  4264. });
  4265. },
  4266. get: function get(e) {
  4267. for (var t = 0; t < this.funcs.length; t += 1) if (this.funcs[t].func === e) return this.funcs[t];
  4268. return null;
  4269. },
  4270. isRunning: function isRunning(e) {
  4271. var t = this.get(e);
  4272. return null !== t && t.running;
  4273. },
  4274. countActive: function countActive() {
  4275. for (var e = 0, t = 0; t < this.funcs.length; t += 1) e += this.funcs[t].running;
  4276. return e;
  4277. },
  4278. listActive: function listActive() {
  4279. for (var e = [], t = 0; t < this.funcs.length; t += 1) this.funcs[t].running && e.push(this.funcs[t].name);
  4280. return e;
  4281. },
  4282. done: function done(e) {
  4283. this.globalDone = e;
  4284. },
  4285. cancelById: function cancelById(e, dealCancelFun) {
  4286. //xzw add dealDone
  4287. var t = void 0 === e ? 0 : e;
  4288. var cancels = [];
  4289. this.funcs = this.funcs.filter(function (e) {
  4290. var is = e.id == t;
  4291. if (is && dealCancelFun) {
  4292. e.cancelFun && cancels.push(e.cancelFun);
  4293. } /* else if(is && e.cancelFun){
  4294. console.warn('cancelById', e.id,e.name)
  4295. } */
  4296. return !is;
  4297. });
  4298. cancels.forEach(e => {
  4299. e();
  4300. }); //先从funcs中去除后再执行
  4301. },
  4302. cancel: function cancel(e) {
  4303. //console.warn('cancel', e )
  4304. this.funcs = this.funcs.filter(function (t) {
  4305. return t.func !== e;
  4306. });
  4307. },
  4308. getUniqueId: function getUniqueId() {
  4309. return this.uniqueID -= 1, this.uniqueID;
  4310. }
  4311. };
  4312. var UPNG$1 = function () {
  4313. var _bin = {
  4314. nextZero: function nextZero(data, p) {
  4315. while (data[p] != 0) p++;
  4316. return p;
  4317. },
  4318. readUshort: function readUshort(buff, p) {
  4319. return buff[p] << 8 | buff[p + 1];
  4320. },
  4321. writeUshort: function writeUshort(buff, p, n) {
  4322. buff[p] = n >> 8 & 255;
  4323. buff[p + 1] = n & 255;
  4324. },
  4325. readUint: function readUint(buff, p) {
  4326. return buff[p] * (256 * 256 * 256) + (buff[p + 1] << 16 | buff[p + 2] << 8 | buff[p + 3]);
  4327. },
  4328. writeUint: function writeUint(buff, p, n) {
  4329. buff[p] = n >> 24 & 255;
  4330. buff[p + 1] = n >> 16 & 255;
  4331. buff[p + 2] = n >> 8 & 255;
  4332. buff[p + 3] = n & 255;
  4333. },
  4334. readASCII: function readASCII(buff, p, l) {
  4335. var s = "";
  4336. for (var i = 0; i < l; i++) s += String.fromCharCode(buff[p + i]);
  4337. return s;
  4338. },
  4339. writeASCII: function writeASCII(data, p, s) {
  4340. for (var i = 0; i < s.length; i++) data[p + i] = s.charCodeAt(i);
  4341. },
  4342. readBytes: function readBytes(buff, p, l) {
  4343. var arr = [];
  4344. for (var i = 0; i < l; i++) arr.push(buff[p + i]);
  4345. return arr;
  4346. },
  4347. pad: function pad(n) {
  4348. return n.length < 2 ? "0" + n : n;
  4349. },
  4350. readUTF8: function readUTF8(buff, p, l) {
  4351. var s = "",
  4352. ns;
  4353. for (var i = 0; i < l; i++) s += "%" + _bin.pad(buff[p + i].toString(16));
  4354. try {
  4355. ns = decodeURIComponent(s);
  4356. } catch (e) {
  4357. return _bin.readASCII(buff, p, l);
  4358. }
  4359. return ns;
  4360. }
  4361. };
  4362. function toRGBA8(out) {
  4363. var w = out.width,
  4364. h = out.height;
  4365. if (out.tabs.acTL == null) return [decodeImage(out.data, w, h, out).buffer];
  4366. var frms = [];
  4367. if (out.frames[0].data == null) out.frames[0].data = out.data;
  4368. var len = w * h * 4,
  4369. img = new Uint8Array(len),
  4370. empty = new Uint8Array(len),
  4371. prev = new Uint8Array(len);
  4372. for (var i = 0; i < out.frames.length; i++) {
  4373. var frm = out.frames[i];
  4374. var fx = frm.rect.x,
  4375. fy = frm.rect.y,
  4376. fw = frm.rect.width,
  4377. fh = frm.rect.height;
  4378. var fdata = decodeImage(frm.data, fw, fh, out);
  4379. if (i != 0) for (var j = 0; j < len; j++) prev[j] = img[j];
  4380. if (frm.blend == 0) _copyTile(fdata, fw, fh, img, w, h, fx, fy, 0);else if (frm.blend == 1) _copyTile(fdata, fw, fh, img, w, h, fx, fy, 1);
  4381. frms.push(img.buffer.slice(0));
  4382. if (frm.dispose == 0) {} else if (frm.dispose == 1) _copyTile(empty, fw, fh, img, w, h, fx, fy, 0);else if (frm.dispose == 2) for (var j = 0; j < len; j++) img[j] = prev[j];
  4383. }
  4384. return frms;
  4385. }
  4386. function decodeImage(data, w, h, out) {
  4387. var area = w * h,
  4388. bpp = _getBPP(out);
  4389. var bpl = Math.ceil(w * bpp / 8); // bytes per line
  4390. var bf = new Uint8Array(area * 4),
  4391. bf32 = new Uint32Array(bf.buffer);
  4392. var ctype = out.ctype,
  4393. depth = out.depth;
  4394. var rs = _bin.readUshort;
  4395. //console.log(ctype, depth);
  4396. var time = Date.now();
  4397. if (ctype == 6) {
  4398. // RGB + alpha
  4399. var qarea = area << 2;
  4400. if (depth == 8) for (var i = 0; i < qarea; i += 4) {
  4401. bf[i] = data[i];
  4402. bf[i + 1] = data[i + 1];
  4403. bf[i + 2] = data[i + 2];
  4404. bf[i + 3] = data[i + 3];
  4405. }
  4406. if (depth == 16) for (var i = 0; i < qarea; i++) {
  4407. bf[i] = data[i << 1];
  4408. }
  4409. } else if (ctype == 2) {
  4410. // RGB
  4411. var ts = out.tabs["tRNS"];
  4412. if (ts == null) {
  4413. if (depth == 8) for (var i = 0; i < area; i++) {
  4414. var ti = i * 3;
  4415. bf32[i] = 255 << 24 | data[ti + 2] << 16 | data[ti + 1] << 8 | data[ti];
  4416. }
  4417. if (depth == 16) for (var i = 0; i < area; i++) {
  4418. var ti = i * 6;
  4419. bf32[i] = 255 << 24 | data[ti + 4] << 16 | data[ti + 2] << 8 | data[ti];
  4420. }
  4421. } else {
  4422. var tr = ts[0],
  4423. tg = ts[1],
  4424. tb = ts[2];
  4425. if (depth == 8) for (var i = 0; i < area; i++) {
  4426. var qi = i << 2,
  4427. ti = i * 3;
  4428. bf32[i] = 255 << 24 | data[ti + 2] << 16 | data[ti + 1] << 8 | data[ti];
  4429. if (data[ti] == tr && data[ti + 1] == tg && data[ti + 2] == tb) bf[qi + 3] = 0;
  4430. }
  4431. if (depth == 16) for (var i = 0; i < area; i++) {
  4432. var qi = i << 2,
  4433. ti = i * 6;
  4434. bf32[i] = 255 << 24 | data[ti + 4] << 16 | data[ti + 2] << 8 | data[ti];
  4435. if (rs(data, ti) == tr && rs(data, ti + 2) == tg && rs(data, ti + 4) == tb) bf[qi + 3] = 0;
  4436. }
  4437. }
  4438. } else if (ctype == 3) {
  4439. // palette
  4440. var p = out.tabs["PLTE"],
  4441. ap = out.tabs["tRNS"],
  4442. tl = ap ? ap.length : 0;
  4443. //console.log(p, ap);
  4444. if (depth == 1) for (var y = 0; y < h; y++) {
  4445. var s0 = y * bpl,
  4446. t0 = y * w;
  4447. for (var i = 0; i < w; i++) {
  4448. var qi = t0 + i << 2,
  4449. j = data[s0 + (i >> 3)] >> 7 - ((i & 7) << 0) & 1,
  4450. cj = 3 * j;
  4451. bf[qi] = p[cj];
  4452. bf[qi + 1] = p[cj + 1];
  4453. bf[qi + 2] = p[cj + 2];
  4454. bf[qi + 3] = j < tl ? ap[j] : 255;
  4455. }
  4456. }
  4457. if (depth == 2) for (var y = 0; y < h; y++) {
  4458. var s0 = y * bpl,
  4459. t0 = y * w;
  4460. for (var i = 0; i < w; i++) {
  4461. var qi = t0 + i << 2,
  4462. j = data[s0 + (i >> 2)] >> 6 - ((i & 3) << 1) & 3,
  4463. cj = 3 * j;
  4464. bf[qi] = p[cj];
  4465. bf[qi + 1] = p[cj + 1];
  4466. bf[qi + 2] = p[cj + 2];
  4467. bf[qi + 3] = j < tl ? ap[j] : 255;
  4468. }
  4469. }
  4470. if (depth == 4) for (var y = 0; y < h; y++) {
  4471. var s0 = y * bpl,
  4472. t0 = y * w;
  4473. for (var i = 0; i < w; i++) {
  4474. var qi = t0 + i << 2,
  4475. j = data[s0 + (i >> 1)] >> 4 - ((i & 1) << 2) & 15,
  4476. cj = 3 * j;
  4477. bf[qi] = p[cj];
  4478. bf[qi + 1] = p[cj + 1];
  4479. bf[qi + 2] = p[cj + 2];
  4480. bf[qi + 3] = j < tl ? ap[j] : 255;
  4481. }
  4482. }
  4483. if (depth == 8) for (var i = 0; i < area; i++) {
  4484. var qi = i << 2,
  4485. j = data[i],
  4486. cj = 3 * j;
  4487. bf[qi] = p[cj];
  4488. bf[qi + 1] = p[cj + 1];
  4489. bf[qi + 2] = p[cj + 2];
  4490. bf[qi + 3] = j < tl ? ap[j] : 255;
  4491. }
  4492. } else if (ctype == 4) {
  4493. // gray + alpha
  4494. if (depth == 8) for (var i = 0; i < area; i++) {
  4495. var qi = i << 2,
  4496. di = i << 1,
  4497. gr = data[di];
  4498. bf[qi] = gr;
  4499. bf[qi + 1] = gr;
  4500. bf[qi + 2] = gr;
  4501. bf[qi + 3] = data[di + 1];
  4502. }
  4503. if (depth == 16) for (var i = 0; i < area; i++) {
  4504. var qi = i << 2,
  4505. di = i << 2,
  4506. gr = data[di];
  4507. bf[qi] = gr;
  4508. bf[qi + 1] = gr;
  4509. bf[qi + 2] = gr;
  4510. bf[qi + 3] = data[di + 2];
  4511. }
  4512. } else if (ctype == 0) {
  4513. // gray
  4514. var tr = out.tabs["tRNS"] ? out.tabs["tRNS"] : -1;
  4515. for (var y = 0; y < h; y++) {
  4516. var off = y * bpl,
  4517. to = y * w;
  4518. if (depth == 1) for (var x = 0; x < w; x++) {
  4519. var gr = 255 * (data[off + (x >>> 3)] >>> 7 - (x & 7) & 1),
  4520. al = gr == tr * 255 ? 0 : 255;
  4521. bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr;
  4522. } else if (depth == 2) for (var x = 0; x < w; x++) {
  4523. var gr = 85 * (data[off + (x >>> 2)] >>> 6 - ((x & 3) << 1) & 3),
  4524. al = gr == tr * 85 ? 0 : 255;
  4525. bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr;
  4526. } else if (depth == 4) for (var x = 0; x < w; x++) {
  4527. var gr = 17 * (data[off + (x >>> 1)] >>> 4 - ((x & 1) << 2) & 15),
  4528. al = gr == tr * 17 ? 0 : 255;
  4529. bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr;
  4530. } else if (depth == 8) for (var x = 0; x < w; x++) {
  4531. var gr = data[off + x],
  4532. al = gr == tr ? 0 : 255;
  4533. bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr;
  4534. } else if (depth == 16) for (var x = 0; x < w; x++) {
  4535. var gr = data[off + (x << 1)],
  4536. al = rs(data, off + (x << 1)) == tr ? 0 : 255;
  4537. bf32[to + x] = al << 24 | gr << 16 | gr << 8 | gr;
  4538. }
  4539. }
  4540. }
  4541. //console.log(Date.now()-time);
  4542. return bf;
  4543. }
  4544. function decode(buff) {
  4545. var data = new Uint8Array(buff),
  4546. offset = 8,
  4547. bin = _bin,
  4548. rUs = bin.readUshort,
  4549. rUi = bin.readUint;
  4550. var out = {
  4551. tabs: {},
  4552. frames: []
  4553. };
  4554. var dd = new Uint8Array(data.length),
  4555. doff = 0; // put all IDAT data into it
  4556. var fd,
  4557. foff = 0; // frames
  4558. var mgck = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
  4559. for (var i = 0; i < 8; i++) if (data[i] != mgck[i]) throw "The input is not a PNG file!";
  4560. while (offset < data.length) {
  4561. var len = bin.readUint(data, offset);
  4562. offset += 4;
  4563. var type = bin.readASCII(data, offset, 4);
  4564. offset += 4;
  4565. //console.log(type,len);
  4566. if (type == "IHDR") {
  4567. _IHDR(data, offset, out);
  4568. } else if (type == "iCCP") {
  4569. var off = offset;
  4570. while (data[off] != 0) off++;
  4571. var nam = bin.readASCII(data, offset, off - offset);
  4572. var cpr = data[off + 1];
  4573. var fil = data.slice(off + 2, offset + len);
  4574. var res = null;
  4575. try {
  4576. res = _inflate(fil);
  4577. } catch (e) {
  4578. res = inflateRaw(fil);
  4579. }
  4580. out.tabs[type] = res;
  4581. } else if (type == "CgBI") {
  4582. out.tabs[type] = data.slice(offset, offset + 4);
  4583. } else if (type == "IDAT") {
  4584. for (var i = 0; i < len; i++) dd[doff + i] = data[offset + i];
  4585. doff += len;
  4586. } else if (type == "acTL") {
  4587. out.tabs[type] = {
  4588. num_frames: rUi(data, offset),
  4589. num_plays: rUi(data, offset + 4)
  4590. };
  4591. fd = new Uint8Array(data.length);
  4592. } else if (type == "fcTL") {
  4593. if (foff != 0) {
  4594. var fr = out.frames[out.frames.length - 1];
  4595. fr.data = _decompress(out, fd.slice(0, foff), fr.rect.width, fr.rect.height);
  4596. foff = 0;
  4597. }
  4598. var rct = {
  4599. x: rUi(data, offset + 12),
  4600. y: rUi(data, offset + 16),
  4601. width: rUi(data, offset + 4),
  4602. height: rUi(data, offset + 8)
  4603. };
  4604. var del = rUs(data, offset + 22);
  4605. del = rUs(data, offset + 20) / (del == 0 ? 100 : del);
  4606. var frm = {
  4607. rect: rct,
  4608. delay: Math.round(del * 1000),
  4609. dispose: data[offset + 24],
  4610. blend: data[offset + 25]
  4611. };
  4612. //console.log(frm);
  4613. out.frames.push(frm);
  4614. } else if (type == "fdAT") {
  4615. for (var i = 0; i < len - 4; i++) fd[foff + i] = data[offset + i + 4];
  4616. foff += len - 4;
  4617. } else if (type == "pHYs") {
  4618. out.tabs[type] = [bin.readUint(data, offset), bin.readUint(data, offset + 4), data[offset + 8]];
  4619. } else if (type == "cHRM") {
  4620. out.tabs[type] = [];
  4621. for (var i = 0; i < 8; i++) out.tabs[type].push(bin.readUint(data, offset + i * 4));
  4622. } else if (type == "tEXt" || type == "zTXt") {
  4623. if (out.tabs[type] == null) out.tabs[type] = {};
  4624. var nz = bin.nextZero(data, offset);
  4625. var keyw = bin.readASCII(data, offset, nz - offset);
  4626. var text,
  4627. tl = offset + len - nz - 1;
  4628. if (type == "tEXt") text = bin.readASCII(data, nz + 1, tl);else {
  4629. var bfr = _inflate(data.slice(nz + 2, nz + 2 + tl));
  4630. text = bin.readUTF8(bfr, 0, bfr.length);
  4631. }
  4632. out.tabs[type][keyw] = text;
  4633. } else if (type == "iTXt") {
  4634. if (out.tabs[type] == null) out.tabs[type] = {};
  4635. var nz = 0,
  4636. off = offset;
  4637. nz = bin.nextZero(data, off);
  4638. var keyw = bin.readASCII(data, off, nz - off);
  4639. off = nz + 1;
  4640. var cflag = data[off],
  4641. cmeth = data[off + 1];
  4642. off += 2;
  4643. nz = bin.nextZero(data, off);
  4644. var ltag = bin.readASCII(data, off, nz - off);
  4645. off = nz + 1;
  4646. nz = bin.nextZero(data, off);
  4647. var tkeyw = bin.readUTF8(data, off, nz - off);
  4648. off = nz + 1;
  4649. var text,
  4650. tl = len - (off - offset);
  4651. if (cflag == 0) text = bin.readUTF8(data, off, tl);else {
  4652. var bfr = _inflate(data.slice(off, off + tl));
  4653. text = bin.readUTF8(bfr, 0, bfr.length);
  4654. }
  4655. out.tabs[type][keyw] = text;
  4656. } else if (type == "PLTE") {
  4657. out.tabs[type] = bin.readBytes(data, offset, len);
  4658. } else if (type == "hIST") {
  4659. var pl = out.tabs["PLTE"].length / 3;
  4660. out.tabs[type] = [];
  4661. for (var i = 0; i < pl; i++) out.tabs[type].push(rUs(data, offset + i * 2));
  4662. } else if (type == "tRNS") {
  4663. if (out.ctype == 3) out.tabs[type] = bin.readBytes(data, offset, len);else if (out.ctype == 0) out.tabs[type] = rUs(data, offset);else if (out.ctype == 2) out.tabs[type] = [rUs(data, offset), rUs(data, offset + 2), rUs(data, offset + 4)];
  4664. //else console.log("tRNS for unsupported color type",out.ctype, len);
  4665. } else if (type == "gAMA") out.tabs[type] = bin.readUint(data, offset) / 100000;else if (type == "sRGB") out.tabs[type] = data[offset];else if (type == "bKGD") {
  4666. if (out.ctype == 0 || out.ctype == 4) out.tabs[type] = [rUs(data, offset)];else if (out.ctype == 2 || out.ctype == 6) out.tabs[type] = [rUs(data, offset), rUs(data, offset + 2), rUs(data, offset + 4)];else if (out.ctype == 3) out.tabs[type] = data[offset];
  4667. } else if (type == "IEND") {
  4668. break;
  4669. }
  4670. //else { console.log("unknown chunk type", type, len); out.tabs[type]=data.slice(offset,offset+len); }
  4671. offset += len;
  4672. var crc = bin.readUint(data, offset);
  4673. offset += 4;
  4674. }
  4675. if (foff != 0) {
  4676. var fr = out.frames[out.frames.length - 1];
  4677. fr.data = _decompress(out, fd.slice(0, foff), fr.rect.width, fr.rect.height);
  4678. }
  4679. out.data = _decompress(out, dd, out.width, out.height);
  4680. delete out.compress;
  4681. delete out.interlace;
  4682. delete out.filter;
  4683. return out;
  4684. }
  4685. function _decompress(out, dd, w, h) {
  4686. var time = Date.now();
  4687. var bpp = _getBPP(out),
  4688. bpl = Math.ceil(w * bpp / 8),
  4689. buff = new Uint8Array((bpl + 1 + out.interlace) * h);
  4690. if (out.tabs["CgBI"]) dd = inflateRaw(dd, buff);else dd = _inflate(dd, buff);
  4691. //console.log(dd.length, buff.length);
  4692. //console.log(Date.now()-time);
  4693. var time = Date.now();
  4694. if (out.interlace == 0) dd = _filterZero(dd, out, 0, w, h);else if (out.interlace == 1) dd = _readInterlace(dd, out);
  4695. //console.log(Date.now()-time);
  4696. return dd;
  4697. }
  4698. function _inflate(data, buff) {
  4699. var out = inflateRaw(new Uint8Array(data.buffer, 2, data.length - 6), buff);
  4700. return out;
  4701. }
  4702. var inflateRaw = function () {
  4703. var D = function () {
  4704. var o = Uint16Array,
  4705. j = Uint32Array;
  4706. return {
  4707. m: new o(16),
  4708. v: new o(16),
  4709. d: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
  4710. o: [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 999, 999, 999],
  4711. z: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
  4712. B: new o(32),
  4713. p: [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535],
  4714. w: [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0],
  4715. h: new j(32),
  4716. g: new o(512),
  4717. s: [],
  4718. A: new o(32),
  4719. t: [],
  4720. k: new o(32768),
  4721. c: [],
  4722. a: [],
  4723. n: new o(32768),
  4724. e: [],
  4725. C: new o(512),
  4726. b: [],
  4727. i: new o(1 << 15),
  4728. r: new j(286),
  4729. f: new j(30),
  4730. l: new j(19),
  4731. u: new j(15e3),
  4732. q: new o(1 << 16),
  4733. j: new o(1 << 15)
  4734. };
  4735. }();
  4736. function C(o, j) {
  4737. var I = o.length,
  4738. A,
  4739. r,
  4740. i,
  4741. y,
  4742. G,
  4743. f = D.v;
  4744. for (var y = 0; y <= j; y++) f[y] = 0;
  4745. for (y = 1; y < I; y += 2) f[o[y]]++;
  4746. var a = D.m;
  4747. A = 0;
  4748. f[0] = 0;
  4749. for (r = 1; r <= j; r++) {
  4750. A = A + f[r - 1] << 1;
  4751. a[r] = A;
  4752. }
  4753. for (i = 0; i < I; i += 2) {
  4754. G = o[i + 1];
  4755. if (G != 0) {
  4756. o[i] = a[G];
  4757. a[G]++;
  4758. }
  4759. }
  4760. }
  4761. function t(o, j, I) {
  4762. var A = o.length,
  4763. r = D.i;
  4764. for (var i = 0; i < A; i += 2) if (o[i + 1] != 0) {
  4765. var y = i >> 1,
  4766. G = o[i + 1],
  4767. f = y << 4 | G,
  4768. a = j - G,
  4769. k = o[i] << a,
  4770. N = k + (1 << a);
  4771. while (k != N) {
  4772. var x = r[k] >>> 15 - j;
  4773. I[x] = f;
  4774. k++;
  4775. }
  4776. }
  4777. }
  4778. function g(o, j) {
  4779. var I = D.i,
  4780. A = 15 - j;
  4781. for (var r = 0; r < o.length; r += 2) {
  4782. var i = o[r] << j - o[r + 1];
  4783. o[r] = I[i] >>> A;
  4784. }
  4785. }
  4786. (function () {
  4787. var o = 1 << 15;
  4788. for (var j = 0; j < o; j++) {
  4789. var I = j;
  4790. I = (I & 2863311530) >>> 1 | (I & 1431655765) << 1;
  4791. I = (I & 3435973836) >>> 2 | (I & 858993459) << 2;
  4792. I = (I & 4042322160) >>> 4 | (I & 252645135) << 4;
  4793. I = (I & 4278255360) >>> 8 | (I & 16711935) << 8;
  4794. D.i[j] = (I >>> 16 | I << 16) >>> 17;
  4795. }
  4796. function A(r, i, y) {
  4797. while (i-- != 0) r.push(0, y);
  4798. }
  4799. for (var j = 0; j < 32; j++) {
  4800. D.B[j] = D.o[j] << 3 | D.z[j];
  4801. D.h[j] = D.p[j] << 4 | D.w[j];
  4802. }
  4803. A(D.s, 144, 8);
  4804. A(D.s, 255 - 143, 9);
  4805. A(D.s, 279 - 255, 7);
  4806. A(D.s, 287 - 279, 8);
  4807. C(D.s, 9);
  4808. t(D.s, 9, D.g);
  4809. g(D.s, 9);
  4810. A(D.t, 32, 5);
  4811. C(D.t, 5);
  4812. t(D.t, 5, D.A);
  4813. g(D.t, 5);
  4814. A(D.b, 19, 0);
  4815. A(D.c, 286, 0);
  4816. A(D.e, 30, 0);
  4817. A(D.a, 320, 0);
  4818. })();
  4819. function F(o, j, I) {
  4820. return (o[j >>> 3] | o[(j >>> 3) + 1] << 8) >>> (j & 7) & (1 << I) - 1;
  4821. }
  4822. function s(o, j, I) {
  4823. return (o[j >>> 3] | o[(j >>> 3) + 1] << 8 | o[(j >>> 3) + 2] << 16) >>> (j & 7) & (1 << I) - 1;
  4824. }
  4825. function w(o, j) {
  4826. return (o[j >>> 3] | o[(j >>> 3) + 1] << 8 | o[(j >>> 3) + 2] << 16) >>> (j & 7);
  4827. }
  4828. function b(o, j) {
  4829. return (o[j >>> 3] | o[(j >>> 3) + 1] << 8 | o[(j >>> 3) + 2] << 16 | o[(j >>> 3) + 3] << 24) >>> (j & 7);
  4830. }
  4831. function v(o, j) {
  4832. var I = Uint8Array,
  4833. r = 0,
  4834. i = 0,
  4835. y = 0,
  4836. G = 0,
  4837. f = 0,
  4838. a = 0,
  4839. k = 0,
  4840. N = 0,
  4841. x = 0,
  4842. P,
  4843. J;
  4844. if (o[0] == 3 && o[1] == 0) return j ? j : new I(0);
  4845. var A = j == null;
  4846. if (A) j = new I(o.length >>> 2 << 3);
  4847. while (r == 0) {
  4848. r = s(o, x, 1);
  4849. i = s(o, x + 1, 2);
  4850. x += 3;
  4851. if (i == 0) {
  4852. if ((x & 7) != 0) x += 8 - (x & 7);
  4853. var K = (x >>> 3) + 4,
  4854. m = o[K - 4] | o[K - 3] << 8;
  4855. if (A) j = H(j, N + m);
  4856. j.set(new I(o.buffer, o.byteOffset + K, m), N);
  4857. x = K + m << 3;
  4858. N += m;
  4859. continue;
  4860. }
  4861. if (A) j = H(j, N + (1 << 17));
  4862. if (i == 1) {
  4863. P = D.g;
  4864. J = D.A;
  4865. a = (1 << 9) - 1;
  4866. k = (1 << 5) - 1;
  4867. }
  4868. if (i == 2) {
  4869. y = F(o, x, 5) + 257;
  4870. G = F(o, x + 5, 5) + 1;
  4871. f = F(o, x + 10, 4) + 4;
  4872. x += 14;
  4873. var O = x,
  4874. Q = 1;
  4875. for (var p = 0; p < 38; p += 2) {
  4876. D.b[p] = 0;
  4877. D.b[p + 1] = 0;
  4878. }
  4879. for (var p = 0; p < f; p++) {
  4880. var l = F(o, x + p * 3, 3);
  4881. D.b[(D.d[p] << 1) + 1] = l;
  4882. if (l > Q) Q = l;
  4883. }
  4884. x += 3 * f;
  4885. C(D.b, Q);
  4886. t(D.b, Q, D.C);
  4887. P = D.k;
  4888. J = D.n;
  4889. x = B(D.C, (1 << Q) - 1, y + G, o, x, D.a);
  4890. var u = d(D.a, 0, y, D.c);
  4891. a = (1 << u) - 1;
  4892. var n = d(D.a, y, G, D.e);
  4893. k = (1 << n) - 1;
  4894. C(D.c, u);
  4895. t(D.c, u, P);
  4896. C(D.e, n);
  4897. t(D.e, n, J);
  4898. }
  4899. while (!0) {
  4900. var h = P[w(o, x) & a];
  4901. x += h & 15;
  4902. var L = h >>> 4;
  4903. if (L >>> 8 == 0) {
  4904. j[N++] = L;
  4905. } else if (L == 256) {
  4906. break;
  4907. } else {
  4908. var M = N + L - 254;
  4909. if (L > 264) {
  4910. var z = D.B[L - 257];
  4911. M = N + (z >>> 3) + F(o, x, z & 7);
  4912. x += z & 7;
  4913. }
  4914. var e = J[w(o, x) & k];
  4915. x += e & 15;
  4916. var E = e >>> 4,
  4917. c = D.h[E],
  4918. q = (c >>> 4) + s(o, x, c & 15);
  4919. x += c & 15;
  4920. if (A) j = H(j, N + (1 << 17));
  4921. while (N < M) {
  4922. j[N] = j[N++ - q];
  4923. j[N] = j[N++ - q];
  4924. j[N] = j[N++ - q];
  4925. j[N] = j[N++ - q];
  4926. }
  4927. N = M;
  4928. }
  4929. }
  4930. }
  4931. return j.length == N ? j : j.slice(0, N);
  4932. }
  4933. function H(o, j) {
  4934. var I = o.length;
  4935. if (j <= I) return o;
  4936. var A = new Uint8Array(Math.max(I << 1, j));
  4937. A.set(o, 0);
  4938. return A;
  4939. }
  4940. function B(o, j, I, A, r, i) {
  4941. var y = 0;
  4942. while (y < I) {
  4943. var G = o[w(A, r) & j];
  4944. r += G & 15;
  4945. var f = G >>> 4;
  4946. if (f <= 15) {
  4947. i[y] = f;
  4948. y++;
  4949. } else {
  4950. var a = 0,
  4951. k = 0;
  4952. if (f == 16) {
  4953. k = 3 + F(A, r, 2);
  4954. r += 2;
  4955. a = i[y - 1];
  4956. } else if (f == 17) {
  4957. k = 3 + F(A, r, 3);
  4958. r += 3;
  4959. } else if (f == 18) {
  4960. k = 11 + F(A, r, 7);
  4961. r += 7;
  4962. }
  4963. var N = y + k;
  4964. while (y < N) {
  4965. i[y] = a;
  4966. y++;
  4967. }
  4968. }
  4969. }
  4970. return r;
  4971. }
  4972. function d(o, j, I, A) {
  4973. var r = 0,
  4974. i = 0,
  4975. y = A.length >>> 1;
  4976. while (i < I) {
  4977. var G = o[i + j];
  4978. A[i << 1] = 0;
  4979. A[(i << 1) + 1] = G;
  4980. if (G > r) r = G;
  4981. i++;
  4982. }
  4983. while (i < y) {
  4984. A[i << 1] = 0;
  4985. A[(i << 1) + 1] = 0;
  4986. i++;
  4987. }
  4988. return r;
  4989. }
  4990. return v;
  4991. }();
  4992. function _readInterlace(data, out) {
  4993. var w = out.width,
  4994. h = out.height;
  4995. var bpp = _getBPP(out),
  4996. cbpp = bpp >> 3,
  4997. bpl = Math.ceil(w * bpp / 8);
  4998. var img = new Uint8Array(h * bpl);
  4999. var di = 0;
  5000. var starting_row = [0, 0, 4, 0, 2, 0, 1];
  5001. var starting_col = [0, 4, 0, 2, 0, 1, 0];
  5002. var row_increment = [8, 8, 8, 4, 4, 2, 2];
  5003. var col_increment = [8, 8, 4, 4, 2, 2, 1];
  5004. var pass = 0;
  5005. while (pass < 7) {
  5006. var ri = row_increment[pass],
  5007. ci = col_increment[pass];
  5008. var sw = 0,
  5009. sh = 0;
  5010. var cr = starting_row[pass];
  5011. while (cr < h) {
  5012. cr += ri;
  5013. sh++;
  5014. }
  5015. var cc = starting_col[pass];
  5016. while (cc < w) {
  5017. cc += ci;
  5018. sw++;
  5019. }
  5020. var bpll = Math.ceil(sw * bpp / 8);
  5021. _filterZero(data, out, di, sw, sh);
  5022. var y = 0,
  5023. row = starting_row[pass];
  5024. while (row < h) {
  5025. var col = starting_col[pass];
  5026. var cdi = di + y * bpll << 3;
  5027. while (col < w) {
  5028. if (bpp == 1) {
  5029. var val = data[cdi >> 3];
  5030. val = val >> 7 - (cdi & 7) & 1;
  5031. img[row * bpl + (col >> 3)] |= val << 7 - ((col & 7) << 0);
  5032. }
  5033. if (bpp == 2) {
  5034. var val = data[cdi >> 3];
  5035. val = val >> 6 - (cdi & 7) & 3;
  5036. img[row * bpl + (col >> 2)] |= val << 6 - ((col & 3) << 1);
  5037. }
  5038. if (bpp == 4) {
  5039. var val = data[cdi >> 3];
  5040. val = val >> 4 - (cdi & 7) & 15;
  5041. img[row * bpl + (col >> 1)] |= val << 4 - ((col & 1) << 2);
  5042. }
  5043. if (bpp >= 8) {
  5044. var ii = row * bpl + col * cbpp;
  5045. for (var j = 0; j < cbpp; j++) img[ii + j] = data[(cdi >> 3) + j];
  5046. }
  5047. cdi += bpp;
  5048. col += ci;
  5049. }
  5050. y++;
  5051. row += ri;
  5052. }
  5053. if (sw * sh != 0) di += sh * (1 + bpll);
  5054. pass = pass + 1;
  5055. }
  5056. return img;
  5057. }
  5058. function _getBPP(out) {
  5059. var noc = [1, null, 3, 1, 2, null, 4][out.ctype];
  5060. return noc * out.depth;
  5061. }
  5062. function _filterZero(data, out, off, w, h) {
  5063. var bpp = _getBPP(out),
  5064. bpl = Math.ceil(w * bpp / 8);
  5065. bpp = Math.ceil(bpp / 8);
  5066. var i,
  5067. di,
  5068. type = data[off],
  5069. x = 0;
  5070. if (type > 1) data[off] = [0, 0, 1][type - 2];
  5071. if (type == 3) for (x = bpp; x < bpl; x++) data[x + 1] = data[x + 1] + (data[x + 1 - bpp] >>> 1) & 255;
  5072. for (var y = 0; y < h; y++) {
  5073. i = off + y * bpl;
  5074. di = i + y + 1;
  5075. type = data[di - 1];
  5076. x = 0;
  5077. if (type == 0) for (; x < bpl; x++) data[i + x] = data[di + x];else if (type == 1) {
  5078. for (; x < bpp; x++) data[i + x] = data[di + x];
  5079. for (; x < bpl; x++) data[i + x] = data[di + x] + data[i + x - bpp];
  5080. } else if (type == 2) {
  5081. for (; x < bpl; x++) data[i + x] = data[di + x] + data[i + x - bpl];
  5082. } else if (type == 3) {
  5083. for (; x < bpp; x++) data[i + x] = data[di + x] + (data[i + x - bpl] >>> 1);
  5084. for (; x < bpl; x++) data[i + x] = data[di + x] + (data[i + x - bpl] + data[i + x - bpp] >>> 1);
  5085. } else {
  5086. for (; x < bpp; x++) data[i + x] = data[di + x] + _paeth(0, data[i + x - bpl], 0);
  5087. for (; x < bpl; x++) data[i + x] = data[di + x] + _paeth(data[i + x - bpp], data[i + x - bpl], data[i + x - bpp - bpl]);
  5088. }
  5089. }
  5090. return data;
  5091. }
  5092. function _paeth(a, b, c) {
  5093. var p = a + b - c,
  5094. pa = p - a,
  5095. pb = p - b,
  5096. pc = p - c;
  5097. if (pa * pa <= pb * pb && pa * pa <= pc * pc) return a;else if (pb * pb <= pc * pc) return b;
  5098. return c;
  5099. }
  5100. function _IHDR(data, offset, out) {
  5101. out.width = _bin.readUint(data, offset);
  5102. offset += 4;
  5103. out.height = _bin.readUint(data, offset);
  5104. offset += 4;
  5105. out.depth = data[offset];
  5106. offset++;
  5107. out.ctype = data[offset];
  5108. offset++;
  5109. out.compress = data[offset];
  5110. offset++;
  5111. out.filter = data[offset];
  5112. offset++;
  5113. out.interlace = data[offset];
  5114. offset++;
  5115. }
  5116. function _copyTile(sb, sw, sh, tb, tw, th, xoff, yoff, mode) {
  5117. var w = Math.min(sw, tw),
  5118. h = Math.min(sh, th);
  5119. var si = 0,
  5120. ti = 0;
  5121. for (var y = 0; y < h; y++) for (var x = 0; x < w; x++) {
  5122. if (xoff >= 0 && yoff >= 0) {
  5123. si = y * sw + x << 2;
  5124. ti = (yoff + y) * tw + xoff + x << 2;
  5125. } else {
  5126. si = (-yoff + y) * sw - xoff + x << 2;
  5127. ti = y * tw + x << 2;
  5128. }
  5129. if (mode == 0) {
  5130. tb[ti] = sb[si];
  5131. tb[ti + 1] = sb[si + 1];
  5132. tb[ti + 2] = sb[si + 2];
  5133. tb[ti + 3] = sb[si + 3];
  5134. } else if (mode == 1) {
  5135. var fa = sb[si + 3] * (1 / 255),
  5136. fr = sb[si] * fa,
  5137. fg = sb[si + 1] * fa,
  5138. fb = sb[si + 2] * fa;
  5139. var ba = tb[ti + 3] * (1 / 255),
  5140. br = tb[ti] * ba,
  5141. bg = tb[ti + 1] * ba,
  5142. bb = tb[ti + 2] * ba;
  5143. var ifa = 1 - fa,
  5144. oa = fa + ba * ifa,
  5145. ioa = oa == 0 ? 0 : 1 / oa;
  5146. tb[ti + 3] = 255 * oa;
  5147. tb[ti + 0] = (fr + br * ifa) * ioa;
  5148. tb[ti + 1] = (fg + bg * ifa) * ioa;
  5149. tb[ti + 2] = (fb + bb * ifa) * ioa;
  5150. } else if (mode == 2) {
  5151. // copy only differences, otherwise zero
  5152. var fa = sb[si + 3],
  5153. fr = sb[si],
  5154. fg = sb[si + 1],
  5155. fb = sb[si + 2];
  5156. var ba = tb[ti + 3],
  5157. br = tb[ti],
  5158. bg = tb[ti + 1],
  5159. bb = tb[ti + 2];
  5160. if (fa == ba && fr == br && fg == bg && fb == bb) {
  5161. tb[ti] = 0;
  5162. tb[ti + 1] = 0;
  5163. tb[ti + 2] = 0;
  5164. tb[ti + 3] = 0;
  5165. } else {
  5166. tb[ti] = fr;
  5167. tb[ti + 1] = fg;
  5168. tb[ti + 2] = fb;
  5169. tb[ti + 3] = fa;
  5170. }
  5171. } else if (mode == 3) {
  5172. // check if can be blended
  5173. var fa = sb[si + 3],
  5174. fr = sb[si],
  5175. fg = sb[si + 1],
  5176. fb = sb[si + 2];
  5177. var ba = tb[ti + 3],
  5178. br = tb[ti],
  5179. bg = tb[ti + 1],
  5180. bb = tb[ti + 2];
  5181. if (fa == ba && fr == br && fg == bg && fb == bb) continue;
  5182. //if(fa!=255 && ba!=0) return false;
  5183. if (fa < 220 && ba > 20) return false;
  5184. }
  5185. }
  5186. return true;
  5187. }
  5188. return {
  5189. decode: decode,
  5190. toRGBA8: toRGBA8,
  5191. _paeth: _paeth,
  5192. _copyTile: _copyTile,
  5193. _bin: _bin
  5194. };
  5195. }();
  5196. (function () {
  5197. var _copyTile = UPNG$1._copyTile,
  5198. _bin = UPNG$1._bin,
  5199. paeth = UPNG$1._paeth;
  5200. var crcLib = {
  5201. table: function () {
  5202. var tab = new Uint32Array(256);
  5203. for (var n = 0; n < 256; n++) {
  5204. var c = n;
  5205. for (var k = 0; k < 8; k++) {
  5206. if (c & 1) c = 0xedb88320 ^ c >>> 1;else c = c >>> 1;
  5207. }
  5208. tab[n] = c;
  5209. }
  5210. return tab;
  5211. }(),
  5212. update: function update(c, buf, off, len) {
  5213. for (var i = 0; i < len; i++) c = crcLib.table[(c ^ buf[off + i]) & 0xff] ^ c >>> 8;
  5214. return c;
  5215. },
  5216. crc: function crc(b, o, l) {
  5217. return crcLib.update(0xffffffff, b, o, l) ^ 0xffffffff;
  5218. }
  5219. };
  5220. function addErr(er, tg, ti, f) {
  5221. tg[ti] += er[0] * f >> 4;
  5222. tg[ti + 1] += er[1] * f >> 4;
  5223. tg[ti + 2] += er[2] * f >> 4;
  5224. tg[ti + 3] += er[3] * f >> 4;
  5225. }
  5226. function N(x) {
  5227. return Math.max(0, Math.min(255, x));
  5228. }
  5229. function D(a, b) {
  5230. var dr = a[0] - b[0],
  5231. dg = a[1] - b[1],
  5232. db = a[2] - b[2],
  5233. da = a[3] - b[3];
  5234. return dr * dr + dg * dg + db * db + da * da;
  5235. }
  5236. // MTD: 0: None, 1: floyd-steinberg, 2: Bayer
  5237. function dither(sb, w, h, plte, tb, oind, MTD) {
  5238. if (MTD == null) MTD = 1;
  5239. var pc = plte.length,
  5240. nplt = [],
  5241. rads = [];
  5242. for (var i = 0; i < pc; i++) {
  5243. var c = plte[i];
  5244. nplt.push([c >>> 0 & 255, c >>> 8 & 255, c >>> 16 & 255, c >>> 24 & 255]);
  5245. }
  5246. for (var i = 0; i < pc; i++) {
  5247. var ne = 0xffffffff,
  5248. ni = 0;
  5249. for (var j = 0; j < pc; j++) {
  5250. var ce = D(nplt[i], nplt[j]);
  5251. if (j != i && ce < ne) {
  5252. ne = ce;
  5253. ni = j;
  5254. }
  5255. }
  5256. var hd = Math.sqrt(ne) / 2;
  5257. rads[i] = ~~(hd * hd);
  5258. }
  5259. var tb32 = new Uint32Array(tb.buffer);
  5260. var err = new Int16Array(w * h * 4);
  5261. /*
  5262. var S=2, M = [
  5263. 0,2,
  5264. 3,1]; //*/
  5265. //*
  5266. var S = 4,
  5267. M = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5]; //*/
  5268. for (var i = 0; i < M.length; i++) M[i] = 255 * (-0.5 + (M[i] + 0.5) / (S * S));
  5269. for (var y = 0; y < h; y++) {
  5270. for (var x = 0; x < w; x++) {
  5271. var i = (y * w + x) * 4;
  5272. var cc;
  5273. if (MTD != 2) cc = [N(sb[i] + err[i]), N(sb[i + 1] + err[i + 1]), N(sb[i + 2] + err[i + 2]), N(sb[i + 3] + err[i + 3])];else {
  5274. var ce = M[(y & S - 1) * S + (x & S - 1)];
  5275. cc = [N(sb[i] + ce), N(sb[i + 1] + ce), N(sb[i + 2] + ce), N(sb[i + 3] + ce)];
  5276. }
  5277. var ni = 0,
  5278. nd = 0xffffff;
  5279. for (var j = 0; j < pc; j++) {
  5280. var cd = D(cc, nplt[j]);
  5281. if (cd < nd) {
  5282. nd = cd;
  5283. ni = j;
  5284. }
  5285. }
  5286. var nc = nplt[ni];
  5287. var er = [cc[0] - nc[0], cc[1] - nc[1], cc[2] - nc[2], cc[3] - nc[3]];
  5288. if (MTD == 1) {
  5289. //addErr(er, err, i+4, 16);
  5290. if (x != w - 1) addErr(er, err, i + 4, 7);
  5291. if (y != h - 1) {
  5292. if (x != 0) addErr(er, err, i + 4 * w - 4, 3);
  5293. addErr(er, err, i + 4 * w, 5);
  5294. if (x != w - 1) addErr(er, err, i + 4 * w + 4, 1);
  5295. } //*/
  5296. }
  5297. oind[i >> 2] = ni;
  5298. tb32[i >> 2] = plte[ni];
  5299. }
  5300. }
  5301. }
  5302. function encode(bufs, w, h, ps, dels, tabs, forbidPlte) {
  5303. if (ps == null) ps = 0;
  5304. if (forbidPlte == null) forbidPlte = false;
  5305. var nimg = compress(bufs, w, h, ps, [false, false, false, 0, forbidPlte, false]);
  5306. compressPNG(nimg, -1);
  5307. return _main(nimg, w, h, dels, tabs);
  5308. }
  5309. function encodeLL(bufs, w, h, cc, ac, depth, dels, tabs) {
  5310. var nimg = {
  5311. ctype: 0 + (cc == 1 ? 0 : 2) + (ac == 0 ? 0 : 4),
  5312. depth: depth,
  5313. frames: []
  5314. };
  5315. var time = Date.now();
  5316. var bipp = (cc + ac) * depth,
  5317. bipl = bipp * w;
  5318. for (var i = 0; i < bufs.length; i++) nimg.frames.push({
  5319. rect: {
  5320. x: 0,
  5321. y: 0,
  5322. width: w,
  5323. height: h
  5324. },
  5325. img: new Uint8Array(bufs[i]),
  5326. blend: 0,
  5327. dispose: 1,
  5328. bpp: Math.ceil(bipp / 8),
  5329. bpl: Math.ceil(bipl / 8)
  5330. });
  5331. compressPNG(nimg, 0, true);
  5332. var out = _main(nimg, w, h, dels, tabs);
  5333. return out;
  5334. }
  5335. function _main(nimg, w, h, dels, tabs) {
  5336. if (tabs == null) tabs = {};
  5337. var crc = crcLib.crc,
  5338. wUi = _bin.writeUint,
  5339. wUs = _bin.writeUshort,
  5340. wAs = _bin.writeASCII;
  5341. var offset = 8,
  5342. anim = nimg.frames.length > 1,
  5343. pltAlpha = false;
  5344. var cicc;
  5345. var leng = 8 + (16 + 5 + 4) /*+ (9+4)*/ + (anim ? 20 : 0);
  5346. if (tabs["sRGB"] != null) leng += 8 + 1 + 4;
  5347. if (tabs["pHYs"] != null) leng += 8 + 9 + 4;
  5348. if (tabs["iCCP"] != null) {
  5349. cicc = pako.deflate(tabs["iCCP"]);
  5350. leng += 8 + 11 + 2 + cicc.length + 4;
  5351. }
  5352. if (nimg.ctype == 3) {
  5353. var dl = nimg.plte.length;
  5354. for (var i = 0; i < dl; i++) if (nimg.plte[i] >>> 24 != 255) pltAlpha = true;
  5355. leng += 8 + dl * 3 + 4 + (pltAlpha ? 8 + dl * 1 + 4 : 0);
  5356. }
  5357. for (var j = 0; j < nimg.frames.length; j++) {
  5358. var fr = nimg.frames[j];
  5359. if (anim) leng += 38;
  5360. leng += fr.cimg.length + 12;
  5361. if (j != 0) leng += 4;
  5362. }
  5363. leng += 12;
  5364. var data = new Uint8Array(leng);
  5365. var wr = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
  5366. for (var i = 0; i < 8; i++) data[i] = wr[i];
  5367. wUi(data, offset, 13);
  5368. offset += 4;
  5369. wAs(data, offset, "IHDR");
  5370. offset += 4;
  5371. wUi(data, offset, w);
  5372. offset += 4;
  5373. wUi(data, offset, h);
  5374. offset += 4;
  5375. data[offset] = nimg.depth;
  5376. offset++; // depth
  5377. data[offset] = nimg.ctype;
  5378. offset++; // ctype
  5379. data[offset] = 0;
  5380. offset++; // compress
  5381. data[offset] = 0;
  5382. offset++; // filter
  5383. data[offset] = 0;
  5384. offset++; // interlace
  5385. wUi(data, offset, crc(data, offset - 17, 17));
  5386. offset += 4; // crc
  5387. // 13 bytes to say, that it is sRGB
  5388. if (tabs["sRGB"] != null) {
  5389. wUi(data, offset, 1);
  5390. offset += 4;
  5391. wAs(data, offset, "sRGB");
  5392. offset += 4;
  5393. data[offset] = tabs["sRGB"];
  5394. offset++;
  5395. wUi(data, offset, crc(data, offset - 5, 5));
  5396. offset += 4; // crc
  5397. }
  5398. if (tabs["iCCP"] != null) {
  5399. var sl = 11 + 2 + cicc.length;
  5400. wUi(data, offset, sl);
  5401. offset += 4;
  5402. wAs(data, offset, "iCCP");
  5403. offset += 4;
  5404. wAs(data, offset, "ICC profile");
  5405. offset += 11;
  5406. offset += 2;
  5407. data.set(cicc, offset);
  5408. offset += cicc.length;
  5409. wUi(data, offset, crc(data, offset - (sl + 4), sl + 4));
  5410. offset += 4; // crc
  5411. }
  5412. if (tabs["pHYs"] != null) {
  5413. wUi(data, offset, 9);
  5414. offset += 4;
  5415. wAs(data, offset, "pHYs");
  5416. offset += 4;
  5417. wUi(data, offset, tabs["pHYs"][0]);
  5418. offset += 4;
  5419. wUi(data, offset, tabs["pHYs"][1]);
  5420. offset += 4;
  5421. data[offset] = tabs["pHYs"][2];
  5422. offset++;
  5423. wUi(data, offset, crc(data, offset - 13, 13));
  5424. offset += 4; // crc
  5425. }
  5426. if (anim) {
  5427. wUi(data, offset, 8);
  5428. offset += 4;
  5429. wAs(data, offset, "acTL");
  5430. offset += 4;
  5431. wUi(data, offset, nimg.frames.length);
  5432. offset += 4;
  5433. wUi(data, offset, tabs["loop"] != null ? tabs["loop"] : 0);
  5434. offset += 4;
  5435. wUi(data, offset, crc(data, offset - 12, 12));
  5436. offset += 4; // crc
  5437. }
  5438. if (nimg.ctype == 3) {
  5439. var dl = nimg.plte.length;
  5440. wUi(data, offset, dl * 3);
  5441. offset += 4;
  5442. wAs(data, offset, "PLTE");
  5443. offset += 4;
  5444. for (var i = 0; i < dl; i++) {
  5445. var ti = i * 3,
  5446. c = nimg.plte[i],
  5447. r = c & 255,
  5448. g = c >>> 8 & 255,
  5449. b = c >>> 16 & 255;
  5450. data[offset + ti + 0] = r;
  5451. data[offset + ti + 1] = g;
  5452. data[offset + ti + 2] = b;
  5453. }
  5454. offset += dl * 3;
  5455. wUi(data, offset, crc(data, offset - dl * 3 - 4, dl * 3 + 4));
  5456. offset += 4; // crc
  5457. if (pltAlpha) {
  5458. wUi(data, offset, dl);
  5459. offset += 4;
  5460. wAs(data, offset, "tRNS");
  5461. offset += 4;
  5462. for (var i = 0; i < dl; i++) data[offset + i] = nimg.plte[i] >>> 24 & 255;
  5463. offset += dl;
  5464. wUi(data, offset, crc(data, offset - dl - 4, dl + 4));
  5465. offset += 4; // crc
  5466. }
  5467. }
  5468. var fi = 0;
  5469. for (var j = 0; j < nimg.frames.length; j++) {
  5470. var fr = nimg.frames[j];
  5471. if (anim) {
  5472. wUi(data, offset, 26);
  5473. offset += 4;
  5474. wAs(data, offset, "fcTL");
  5475. offset += 4;
  5476. wUi(data, offset, fi++);
  5477. offset += 4;
  5478. wUi(data, offset, fr.rect.width);
  5479. offset += 4;
  5480. wUi(data, offset, fr.rect.height);
  5481. offset += 4;
  5482. wUi(data, offset, fr.rect.x);
  5483. offset += 4;
  5484. wUi(data, offset, fr.rect.y);
  5485. offset += 4;
  5486. wUs(data, offset, dels[j]);
  5487. offset += 2;
  5488. wUs(data, offset, 1000);
  5489. offset += 2;
  5490. data[offset] = fr.dispose;
  5491. offset++; // dispose
  5492. data[offset] = fr.blend;
  5493. offset++; // blend
  5494. wUi(data, offset, crc(data, offset - 30, 30));
  5495. offset += 4; // crc
  5496. }
  5497. var imgd = fr.cimg,
  5498. dl = imgd.length;
  5499. wUi(data, offset, dl + (j == 0 ? 0 : 4));
  5500. offset += 4;
  5501. var ioff = offset;
  5502. wAs(data, offset, j == 0 ? "IDAT" : "fdAT");
  5503. offset += 4;
  5504. if (j != 0) {
  5505. wUi(data, offset, fi++);
  5506. offset += 4;
  5507. }
  5508. data.set(imgd, offset);
  5509. offset += dl;
  5510. wUi(data, offset, crc(data, ioff, offset - ioff));
  5511. offset += 4; // crc
  5512. }
  5513. wUi(data, offset, 0);
  5514. offset += 4;
  5515. wAs(data, offset, "IEND");
  5516. offset += 4;
  5517. wUi(data, offset, crc(data, offset - 4, 4));
  5518. offset += 4; // crc
  5519. return data.buffer;
  5520. }
  5521. function compressPNG(out, filter, levelZero) {
  5522. for (var i = 0; i < out.frames.length; i++) {
  5523. var frm = out.frames[i],
  5524. nw = frm.rect.width,
  5525. nh = frm.rect.height;
  5526. var fdata = new Uint8Array(nh * frm.bpl + nh);
  5527. frm.cimg = _filterZero(frm.img, nh, frm.bpp, frm.bpl, fdata, filter, levelZero);
  5528. }
  5529. }
  5530. function compress(bufs, w, h, ps, prms)
  5531. // prms: onlyBlend, minBits, forbidPlte
  5532. {
  5533. //var time = Date.now();
  5534. var onlyBlend = prms[0],
  5535. evenCrd = prms[1],
  5536. forbidPrev = prms[2],
  5537. minBits = prms[3],
  5538. forbidPlte = prms[4],
  5539. dith = prms[5];
  5540. var ctype = 6,
  5541. depth = 8,
  5542. alphaAnd = 255;
  5543. for (var j = 0; j < bufs.length; j++) {
  5544. // when not quantized, other frames can contain colors, that are not in an initial frame
  5545. var img = new Uint8Array(bufs[j]),
  5546. ilen = img.length;
  5547. for (var i = 0; i < ilen; i += 4) alphaAnd &= img[i + 3];
  5548. }
  5549. var gotAlpha = alphaAnd != 255;
  5550. //console.log("alpha check", Date.now()-time); time = Date.now();
  5551. //var brute = gotAlpha && forGIF; // brute : frames can only be copied, not "blended"
  5552. var frms = framize(bufs, w, h, onlyBlend, evenCrd, forbidPrev);
  5553. //console.log("framize", Date.now()-time); time = Date.now();
  5554. var cmap = {},
  5555. plte = [],
  5556. inds = [];
  5557. if (ps != 0) {
  5558. var nbufs = [];
  5559. for (var i = 0; i < frms.length; i++) nbufs.push(frms[i].img.buffer);
  5560. var abuf = concatRGBA(nbufs),
  5561. qres = quantize(abuf, ps);
  5562. for (var i = 0; i < qres.plte.length; i++) plte.push(qres.plte[i].est.rgba);
  5563. var cof = 0;
  5564. for (var i = 0; i < frms.length; i++) {
  5565. var frm = frms[i],
  5566. bln = frm.img.length,
  5567. ind = new Uint8Array(qres.inds.buffer, cof >> 2, bln >> 2);
  5568. inds.push(ind);
  5569. var bb = new Uint8Array(qres.abuf, cof, bln);
  5570. //console.log(frm.img, frm.width, frm.height);
  5571. //var time = Date.now();
  5572. if (dith) dither(frm.img, frm.rect.width, frm.rect.height, plte, bb, ind);
  5573. //console.log(Date.now()-time);
  5574. frm.img.set(bb);
  5575. cof += bln;
  5576. }
  5577. //console.log("quantize", Date.now()-time); time = Date.now();
  5578. } else {
  5579. // what if ps==0, but there are <=256 colors? we still need to detect, if the palette could be used
  5580. for (var j = 0; j < frms.length; j++) {
  5581. // when not quantized, other frames can contain colors, that are not in an initial frame
  5582. var frm = frms[j],
  5583. img32 = new Uint32Array(frm.img.buffer),
  5584. nw = frm.rect.width,
  5585. ilen = img32.length;
  5586. var ind = new Uint8Array(ilen);
  5587. inds.push(ind);
  5588. for (var i = 0; i < ilen; i++) {
  5589. var c = img32[i];
  5590. if (i != 0 && c == img32[i - 1]) ind[i] = ind[i - 1];else if (i > nw && c == img32[i - nw]) ind[i] = ind[i - nw];else {
  5591. var cmc = cmap[c];
  5592. if (cmc == null) {
  5593. cmap[c] = cmc = plte.length;
  5594. plte.push(c);
  5595. if (plte.length >= 300) break;
  5596. }
  5597. ind[i] = cmc;
  5598. }
  5599. }
  5600. }
  5601. //console.log("make palette", Date.now()-time); time = Date.now();
  5602. }
  5603. var cc = plte.length; //console.log("colors:",cc);
  5604. if (cc <= 256 && forbidPlte == false) {
  5605. if (cc <= 2) depth = 1;else if (cc <= 4) depth = 2;else if (cc <= 16) depth = 4;else depth = 8;
  5606. depth = Math.max(depth, minBits);
  5607. }
  5608. for (var j = 0; j < frms.length; j++) {
  5609. var frm = frms[j],
  5610. nx = frm.rect.x,
  5611. ny = frm.rect.y,
  5612. nw = frm.rect.width,
  5613. nh = frm.rect.height;
  5614. var cimg = frm.img,
  5615. cimg32 = new Uint32Array(cimg.buffer);
  5616. var bpl = 4 * nw,
  5617. bpp = 4;
  5618. if (cc <= 256 && forbidPlte == false) {
  5619. bpl = Math.ceil(depth * nw / 8);
  5620. var nimg = new Uint8Array(bpl * nh);
  5621. var inj = inds[j];
  5622. for (var y = 0; y < nh; y++) {
  5623. var i = y * bpl,
  5624. ii = y * nw;
  5625. if (depth == 8) for (var x = 0; x < nw; x++) nimg[i + x] = inj[ii + x];else if (depth == 4) for (var x = 0; x < nw; x++) nimg[i + (x >> 1)] |= inj[ii + x] << 4 - (x & 1) * 4;else if (depth == 2) for (var x = 0; x < nw; x++) nimg[i + (x >> 2)] |= inj[ii + x] << 6 - (x & 3) * 2;else if (depth == 1) for (var x = 0; x < nw; x++) nimg[i + (x >> 3)] |= inj[ii + x] << 7 - (x & 7) * 1;
  5626. }
  5627. cimg = nimg;
  5628. ctype = 3;
  5629. bpp = 1;
  5630. } else if (gotAlpha == false && frms.length == 1) {
  5631. // some next "reduced" frames may contain alpha for blending
  5632. var nimg = new Uint8Array(nw * nh * 3),
  5633. area = nw * nh;
  5634. for (var i = 0; i < area; i++) {
  5635. var ti = i * 3,
  5636. qi = i * 4;
  5637. nimg[ti] = cimg[qi];
  5638. nimg[ti + 1] = cimg[qi + 1];
  5639. nimg[ti + 2] = cimg[qi + 2];
  5640. }
  5641. cimg = nimg;
  5642. ctype = 2;
  5643. bpp = 3;
  5644. bpl = 3 * nw;
  5645. }
  5646. frm.img = cimg;
  5647. frm.bpl = bpl;
  5648. frm.bpp = bpp;
  5649. }
  5650. //console.log("colors => palette indices", Date.now()-time); time = Date.now();
  5651. return {
  5652. ctype: ctype,
  5653. depth: depth,
  5654. plte: plte,
  5655. frames: frms
  5656. };
  5657. }
  5658. function framize(bufs, w, h, alwaysBlend, evenCrd, forbidPrev) {
  5659. /* DISPOSE
  5660. - 0 : no change
  5661. - 1 : clear to transparent
  5662. - 2 : retstore to content before rendering (previous frame disposed)
  5663. BLEND
  5664. - 0 : replace
  5665. - 1 : blend
  5666. */
  5667. var frms = [];
  5668. for (var j = 0; j < bufs.length; j++) {
  5669. var cimg = new Uint8Array(bufs[j]),
  5670. cimg32 = new Uint32Array(cimg.buffer);
  5671. var nimg;
  5672. var nx = 0,
  5673. ny = 0,
  5674. nw = w,
  5675. nh = h,
  5676. blend = alwaysBlend ? 1 : 0;
  5677. if (j != 0) {
  5678. var tlim = forbidPrev || alwaysBlend || j == 1 || frms[j - 2].dispose != 0 ? 1 : 2,
  5679. tstp = 0,
  5680. tarea = 1e9;
  5681. for (var it = 0; it < tlim; it++) {
  5682. var pimg = new Uint8Array(bufs[j - 1 - it]),
  5683. p32 = new Uint32Array(bufs[j - 1 - it]);
  5684. var mix = w,
  5685. miy = h,
  5686. max = -1,
  5687. may = -1;
  5688. for (var y = 0; y < h; y++) for (var x = 0; x < w; x++) {
  5689. var i = y * w + x;
  5690. if (cimg32[i] != p32[i]) {
  5691. if (x < mix) mix = x;
  5692. if (x > max) max = x;
  5693. if (y < miy) miy = y;
  5694. if (y > may) may = y;
  5695. }
  5696. }
  5697. if (max == -1) mix = miy = max = may = 0;
  5698. if (evenCrd) {
  5699. if ((mix & 1) == 1) mix--;
  5700. if ((miy & 1) == 1) miy--;
  5701. }
  5702. var sarea = (max - mix + 1) * (may - miy + 1);
  5703. if (sarea < tarea) {
  5704. tarea = sarea;
  5705. tstp = it;
  5706. nx = mix;
  5707. ny = miy;
  5708. nw = max - mix + 1;
  5709. nh = may - miy + 1;
  5710. }
  5711. }
  5712. // alwaysBlend: pokud zjistím, že blendit nelze, nastavím předchozímu snímku dispose=1. Zajistím, aby obsahoval můj obdélník.
  5713. var pimg = new Uint8Array(bufs[j - 1 - tstp]);
  5714. if (tstp == 1) frms[j - 1].dispose = 2;
  5715. nimg = new Uint8Array(nw * nh * 4);
  5716. _copyTile(pimg, w, h, nimg, nw, nh, -nx, -ny, 0);
  5717. blend = _copyTile(cimg, w, h, nimg, nw, nh, -nx, -ny, 3) ? 1 : 0;
  5718. if (blend == 1) _prepareDiff(cimg, w, h, nimg, {
  5719. x: nx,
  5720. y: ny,
  5721. width: nw,
  5722. height: nh
  5723. });else _copyTile(cimg, w, h, nimg, nw, nh, -nx, -ny, 0);
  5724. } else nimg = cimg.slice(0); // img may be rewritten further ... don't rewrite input
  5725. frms.push({
  5726. rect: {
  5727. x: nx,
  5728. y: ny,
  5729. width: nw,
  5730. height: nh
  5731. },
  5732. img: nimg,
  5733. blend: blend,
  5734. dispose: 0
  5735. });
  5736. }
  5737. if (alwaysBlend) for (var j = 0; j < frms.length; j++) {
  5738. var frm = frms[j];
  5739. if (frm.blend == 1) continue;
  5740. var r0 = frm.rect,
  5741. r1 = frms[j - 1].rect;
  5742. var miX = Math.min(r0.x, r1.x),
  5743. miY = Math.min(r0.y, r1.y);
  5744. var maX = Math.max(r0.x + r0.width, r1.x + r1.width),
  5745. maY = Math.max(r0.y + r0.height, r1.y + r1.height);
  5746. var r = {
  5747. x: miX,
  5748. y: miY,
  5749. width: maX - miX,
  5750. height: maY - miY
  5751. };
  5752. frms[j - 1].dispose = 1;
  5753. if (j - 1 != 0) _updateFrame(bufs, w, h, frms, j - 1, r, evenCrd);
  5754. _updateFrame(bufs, w, h, frms, j, r, evenCrd);
  5755. }
  5756. var area = 0;
  5757. if (bufs.length != 1) for (var i = 0; i < frms.length; i++) {
  5758. var frm = frms[i];
  5759. area += frm.rect.width * frm.rect.height;
  5760. //if(i==0 || frm.blend!=1) continue;
  5761. //var ob = new Uint8Array(
  5762. //console.log(frm.blend, frm.dispose, frm.rect);
  5763. }
  5764. //if(area!=0) console.log(area);
  5765. return frms;
  5766. }
  5767. function _updateFrame(bufs, w, h, frms, i, r, evenCrd) {
  5768. var U8 = Uint8Array,
  5769. U32 = Uint32Array;
  5770. var pimg = new U8(bufs[i - 1]),
  5771. pimg32 = new U32(bufs[i - 1]),
  5772. nimg = i + 1 < bufs.length ? new U8(bufs[i + 1]) : null;
  5773. var cimg = new U8(bufs[i]),
  5774. cimg32 = new U32(cimg.buffer);
  5775. var mix = w,
  5776. miy = h,
  5777. max = -1,
  5778. may = -1;
  5779. for (var y = 0; y < r.height; y++) for (var x = 0; x < r.width; x++) {
  5780. var cx = r.x + x,
  5781. cy = r.y + y;
  5782. var j = cy * w + cx,
  5783. cc = cimg32[j];
  5784. // no need to draw transparency, or to dispose it. Or, if writing the same color and the next one does not need transparency.
  5785. if (cc == 0 || frms[i - 1].dispose == 0 && pimg32[j] == cc && (nimg == null || nimg[j * 4 + 3] != 0) /**/) {} else {
  5786. if (cx < mix) mix = cx;
  5787. if (cx > max) max = cx;
  5788. if (cy < miy) miy = cy;
  5789. if (cy > may) may = cy;
  5790. }
  5791. }
  5792. if (max == -1) mix = miy = max = may = 0;
  5793. if (evenCrd) {
  5794. if ((mix & 1) == 1) mix--;
  5795. if ((miy & 1) == 1) miy--;
  5796. }
  5797. r = {
  5798. x: mix,
  5799. y: miy,
  5800. width: max - mix + 1,
  5801. height: may - miy + 1
  5802. };
  5803. var fr = frms[i];
  5804. fr.rect = r;
  5805. fr.blend = 1;
  5806. fr.img = new Uint8Array(r.width * r.height * 4);
  5807. if (frms[i - 1].dispose == 0) {
  5808. _copyTile(pimg, w, h, fr.img, r.width, r.height, -r.x, -r.y, 0);
  5809. _prepareDiff(cimg, w, h, fr.img, r);
  5810. } else _copyTile(cimg, w, h, fr.img, r.width, r.height, -r.x, -r.y, 0);
  5811. }
  5812. function _prepareDiff(cimg, w, h, nimg, rec) {
  5813. _copyTile(cimg, w, h, nimg, rec.width, rec.height, -rec.x, -rec.y, 2);
  5814. }
  5815. function _filterZero(img, h, bpp, bpl, data, filter, levelZero) {
  5816. var fls = [],
  5817. ftry = [0, 1, 2, 3, 4];
  5818. if (filter != -1) ftry = [filter];else if (h * bpl > 500000 || bpp == 1) ftry = [0];
  5819. var opts;
  5820. if (levelZero) opts = {
  5821. level: 0
  5822. };
  5823. var CMPR = data.length > 10e6 && window.UZIP != null ? window.UZIP : pako;
  5824. var time = Date.now();
  5825. for (var i = 0; i < ftry.length; i++) {
  5826. for (var y = 0; y < h; y++) _filterLine(data, img, y, bpl, bpp, ftry[i]);
  5827. //var nimg = new Uint8Array(data.length);
  5828. //var sz = UZIP.F.deflate(data, nimg); fls.push(nimg.slice(0,sz));
  5829. //var dfl = pako["deflate"](data), dl=dfl.length-4;
  5830. //var crc = (dfl[dl+3]<<24)|(dfl[dl+2]<<16)|(dfl[dl+1]<<8)|(dfl[dl+0]<<0);
  5831. //console.log(crc, UZIP.adler(data,2,data.length-6));
  5832. fls.push(CMPR["deflate"](data, opts));
  5833. }
  5834. var ti,
  5835. tsize = 1e9;
  5836. for (var i = 0; i < fls.length; i++) if (fls[i].length < tsize) {
  5837. ti = i;
  5838. tsize = fls[i].length;
  5839. }
  5840. return fls[ti];
  5841. }
  5842. function _filterLine(data, img, y, bpl, bpp, type) {
  5843. var i = y * bpl,
  5844. di = i + y;
  5845. data[di] = type;
  5846. di++;
  5847. if (type == 0) {
  5848. if (bpl < 500) for (var x = 0; x < bpl; x++) data[di + x] = img[i + x];else data.set(new Uint8Array(img.buffer, i, bpl), di);
  5849. } else if (type == 1) {
  5850. for (var x = 0; x < bpp; x++) data[di + x] = img[i + x];
  5851. for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - img[i + x - bpp] + 256 & 255;
  5852. } else if (y == 0) {
  5853. for (var x = 0; x < bpp; x++) data[di + x] = img[i + x];
  5854. if (type == 2) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x];
  5855. if (type == 3) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - (img[i + x - bpp] >> 1) + 256 & 255;
  5856. if (type == 4) for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] - paeth(img[i + x - bpp], 0, 0) + 256 & 255;
  5857. } else {
  5858. if (type == 2) {
  5859. for (var x = 0; x < bpl; x++) data[di + x] = img[i + x] + 256 - img[i + x - bpl] & 255;
  5860. }
  5861. if (type == 3) {
  5862. for (var x = 0; x < bpp; x++) data[di + x] = img[i + x] + 256 - (img[i + x - bpl] >> 1) & 255;
  5863. for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] + 256 - (img[i + x - bpl] + img[i + x - bpp] >> 1) & 255;
  5864. }
  5865. if (type == 4) {
  5866. for (var x = 0; x < bpp; x++) data[di + x] = img[i + x] + 256 - paeth(0, img[i + x - bpl], 0) & 255;
  5867. for (var x = bpp; x < bpl; x++) data[di + x] = img[i + x] + 256 - paeth(img[i + x - bpp], img[i + x - bpl], img[i + x - bpp - bpl]) & 255;
  5868. }
  5869. }
  5870. }
  5871. function quantize(abuf, ps, doKmeans) {
  5872. var time = Date.now();
  5873. var sb = new Uint8Array(abuf),
  5874. tb = sb.slice(0),
  5875. tb32 = new Uint32Array(tb.buffer);
  5876. var KD = getKDtree(tb, ps);
  5877. var root = KD[0],
  5878. leafs = KD[1],
  5879. K = leafs.length;
  5880. //console.log(Date.now()-time, "tree made"); time = Date.now();
  5881. var cl32 = new Uint32Array(K),
  5882. clr8 = new Uint8Array(cl32.buffer);
  5883. for (var i = 0; i < K; i++) cl32[i] = leafs[i].est.rgba;
  5884. var len = sb.length;
  5885. var inds = new Uint8Array(len >> 2),
  5886. nd;
  5887. if (K <= 60) {
  5888. findNearest(sb, inds, clr8);
  5889. remap(inds, tb32, cl32);
  5890. } else if (sb.length < 32e6)
  5891. // precise, but slow :(
  5892. //for(var j=0; j<4; j++)
  5893. for (var i = 0; i < len; i += 4) {
  5894. var r = sb[i] * (1 / 255),
  5895. g = sb[i + 1] * (1 / 255),
  5896. b = sb[i + 2] * (1 / 255),
  5897. a = sb[i + 3] * (1 / 255);
  5898. nd = getNearest(root, r, g, b, a);
  5899. inds[i >> 2] = nd.ind;
  5900. tb32[i >> 2] = nd.est.rgba;
  5901. } else for (var i = 0; i < len; i += 4) {
  5902. var r = sb[i] * (1 / 255),
  5903. g = sb[i + 1] * (1 / 255),
  5904. b = sb[i + 2] * (1 / 255),
  5905. a = sb[i + 3] * (1 / 255);
  5906. nd = root;
  5907. while (nd.left) nd = planeDst(nd.est, r, g, b, a) <= 0 ? nd.left : nd.right;
  5908. inds[i >> 2] = nd.ind;
  5909. tb32[i >> 2] = nd.est.rgba;
  5910. }
  5911. //console.log(Date.now()-time, "nearest found"); time = Date.now();
  5912. if (doKmeans || sb.length * K < 10 * 4e6) {
  5913. var le = 1e9;
  5914. for (var i = 0; i < 10; i++) {
  5915. var ce = kmeans(sb, inds, clr8); //console.log(i,ce);
  5916. if (ce / le > 0.997) break;
  5917. le = ce;
  5918. }
  5919. for (var i = 0; i < K; i++) leafs[i].est.rgba = cl32[i];
  5920. remap(inds, tb32, cl32);
  5921. //console.log(Date.now()-time, "k-means");
  5922. }
  5923. return {
  5924. abuf: tb.buffer,
  5925. inds: inds,
  5926. plte: leafs
  5927. };
  5928. }
  5929. function remap(inds, tb32, pl32) {
  5930. for (var i = 0; i < inds.length; i++) tb32[i] = pl32[inds[i]];
  5931. }
  5932. function kmeans(sb, inds, plte) {
  5933. updatePalette(sb, inds, plte);
  5934. var err = findNearest(sb, inds, plte);
  5935. return err;
  5936. }
  5937. function updatePalette(sb, inds, plte) {
  5938. var K = plte.length >>> 2;
  5939. var sums = new Uint32Array(K * 4),
  5940. cnts = new Uint32Array(K);
  5941. for (var i = 0; i < sb.length; i += 4) {
  5942. var ind = inds[i >>> 2],
  5943. qi = ind * 4;
  5944. cnts[ind]++;
  5945. sums[qi] += sb[i];
  5946. sums[qi + 1] += sb[i + 1];
  5947. sums[qi + 2] += sb[i + 2];
  5948. sums[qi + 3] += sb[i + 3];
  5949. }
  5950. for (var i = 0; i < plte.length; i++) plte[i] = Math.round(sums[i] / cnts[i >>> 2]);
  5951. }
  5952. function findNearest(sb, inds, plte) {
  5953. var terr = 0,
  5954. K = plte.length >>> 2;
  5955. var nd = []; // squared half-distance to the nearest color
  5956. for (var i = 0; i < K; i++) {
  5957. var qi = i * 4;
  5958. var r = plte[qi],
  5959. g = plte[qi + 1],
  5960. b = plte[qi + 2],
  5961. a = plte[qi + 3],
  5962. ti = 0,
  5963. te = 1e9;
  5964. for (var j = 0; j < K; j++) {
  5965. if (i == j) continue;
  5966. var qj = j * 4,
  5967. dr = r - plte[qj],
  5968. dg = g - plte[qj + 1],
  5969. db = b - plte[qj + 2],
  5970. da = a - plte[qj + 3];
  5971. var err = dr * dr + dg * dg + db * db + da * da;
  5972. if (err < te) {
  5973. te = err;
  5974. ti = j;
  5975. }
  5976. }
  5977. nd[i] = Math.sqrt(te) * 0.5;
  5978. nd[i] = nd[i] * nd[i];
  5979. }
  5980. for (var i = 0; i < sb.length; i += 4) {
  5981. var r = sb[i],
  5982. g = sb[i + 1],
  5983. b = sb[i + 2],
  5984. a = sb[i + 3];
  5985. var ti = inds[i >>> 2],
  5986. qi = ti * 4,
  5987. dr = r - plte[qi],
  5988. dg = g - plte[qi + 1],
  5989. db = b - plte[qi + 2],
  5990. da = a - plte[qi + 3],
  5991. te = dr * dr + dg * dg + db * db + da * da;
  5992. if (te > nd[ti]) for (var j = 0; j < K; j++) {
  5993. qi = j * 4;
  5994. dr = r - plte[qi];
  5995. dg = g - plte[qi + 1];
  5996. db = b - plte[qi + 2];
  5997. da = a - plte[qi + 3];
  5998. var err = dr * dr + dg * dg + db * db + da * da;
  5999. if (err < te) {
  6000. te = err;
  6001. ti = j;
  6002. if (te < nd[j]) break;
  6003. }
  6004. }
  6005. inds[i >>> 2] = ti;
  6006. terr += te;
  6007. }
  6008. return terr / (sb.length >>> 2);
  6009. }
  6010. function getKDtree(nimg, ps, err) {
  6011. if (err == null) err = 0.0001;
  6012. var nimg32 = new Uint32Array(nimg.buffer);
  6013. var root = {
  6014. i0: 0,
  6015. i1: nimg.length,
  6016. bst: null,
  6017. est: null,
  6018. tdst: 0,
  6019. left: null,
  6020. right: null
  6021. }; // basic statistic, extra statistic
  6022. root.bst = stats(nimg, root.i0, root.i1);
  6023. root.est = estats(root.bst);
  6024. var leafs = [root];
  6025. while (leafs.length < ps) {
  6026. var maxL = 0,
  6027. mi = 0;
  6028. for (var i = 0; i < leafs.length; i++) if (leafs[i].est.L > maxL) {
  6029. maxL = leafs[i].est.L;
  6030. mi = i;
  6031. }
  6032. if (maxL < err) break;
  6033. var node = leafs[mi];
  6034. var s0 = splitPixels(nimg, nimg32, node.i0, node.i1, node.est.e, node.est.eMq255);
  6035. var s0wrong = node.i0 >= s0 || node.i1 <= s0;
  6036. //console.log(maxL, leafs.length, mi);
  6037. if (s0wrong) {
  6038. node.est.L = 0;
  6039. continue;
  6040. }
  6041. var ln = {
  6042. i0: node.i0,
  6043. i1: s0,
  6044. bst: null,
  6045. est: null,
  6046. tdst: 0,
  6047. left: null,
  6048. right: null
  6049. };
  6050. ln.bst = stats(nimg, ln.i0, ln.i1);
  6051. ln.est = estats(ln.bst);
  6052. var rn = {
  6053. i0: s0,
  6054. i1: node.i1,
  6055. bst: null,
  6056. est: null,
  6057. tdst: 0,
  6058. left: null,
  6059. right: null
  6060. };
  6061. rn.bst = {
  6062. R: [],
  6063. m: [],
  6064. N: node.bst.N - ln.bst.N
  6065. };
  6066. for (var i = 0; i < 16; i++) rn.bst.R[i] = node.bst.R[i] - ln.bst.R[i];
  6067. for (var i = 0; i < 4; i++) rn.bst.m[i] = node.bst.m[i] - ln.bst.m[i];
  6068. rn.est = estats(rn.bst);
  6069. node.left = ln;
  6070. node.right = rn;
  6071. leafs[mi] = ln;
  6072. leafs.push(rn);
  6073. }
  6074. leafs.sort(function (a, b) {
  6075. return b.bst.N - a.bst.N;
  6076. });
  6077. for (var i = 0; i < leafs.length; i++) leafs[i].ind = i;
  6078. return [root, leafs];
  6079. }
  6080. function getNearest(nd, r, g, b, a) {
  6081. if (nd.left == null) {
  6082. nd.tdst = dist(nd.est.q, r, g, b, a);
  6083. return nd;
  6084. }
  6085. var pd = planeDst(nd.est, r, g, b, a);
  6086. var node0 = nd.left,
  6087. node1 = nd.right;
  6088. if (pd > 0) {
  6089. node0 = nd.right;
  6090. node1 = nd.left;
  6091. }
  6092. var ln = getNearest(node0, r, g, b, a);
  6093. if (ln.tdst <= pd * pd) return ln;
  6094. var rn = getNearest(node1, r, g, b, a);
  6095. return rn.tdst < ln.tdst ? rn : ln;
  6096. }
  6097. function planeDst(est, r, g, b, a) {
  6098. var e = est.e;
  6099. return e[0] * r + e[1] * g + e[2] * b + e[3] * a - est.eMq;
  6100. }
  6101. function dist(q, r, g, b, a) {
  6102. var d0 = r - q[0],
  6103. d1 = g - q[1],
  6104. d2 = b - q[2],
  6105. d3 = a - q[3];
  6106. return d0 * d0 + d1 * d1 + d2 * d2 + d3 * d3;
  6107. }
  6108. function splitPixels(nimg, nimg32, i0, i1, e, eMq) {
  6109. i1 -= 4;
  6110. var shfs = 0;
  6111. while (i0 < i1) {
  6112. while (vecDot(nimg, i0, e) <= eMq) i0 += 4;
  6113. while (vecDot(nimg, i1, e) > eMq) i1 -= 4;
  6114. if (i0 >= i1) break;
  6115. var t = nimg32[i0 >> 2];
  6116. nimg32[i0 >> 2] = nimg32[i1 >> 2];
  6117. nimg32[i1 >> 2] = t;
  6118. i0 += 4;
  6119. i1 -= 4;
  6120. }
  6121. while (vecDot(nimg, i0, e) > eMq) i0 -= 4;
  6122. return i0 + 4;
  6123. }
  6124. function vecDot(nimg, i, e) {
  6125. return nimg[i] * e[0] + nimg[i + 1] * e[1] + nimg[i + 2] * e[2] + nimg[i + 3] * e[3];
  6126. }
  6127. function stats(nimg, i0, i1) {
  6128. var R = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  6129. var m = [0, 0, 0, 0];
  6130. var N = i1 - i0 >> 2;
  6131. for (var i = i0; i < i1; i += 4) {
  6132. var r = nimg[i] * (1 / 255),
  6133. g = nimg[i + 1] * (1 / 255),
  6134. b = nimg[i + 2] * (1 / 255),
  6135. a = nimg[i + 3] * (1 / 255);
  6136. //var r = nimg[i], g = nimg[i+1], b = nimg[i+2], a = nimg[i+3];
  6137. m[0] += r;
  6138. m[1] += g;
  6139. m[2] += b;
  6140. m[3] += a;
  6141. R[0] += r * r;
  6142. R[1] += r * g;
  6143. R[2] += r * b;
  6144. R[3] += r * a;
  6145. R[5] += g * g;
  6146. R[6] += g * b;
  6147. R[7] += g * a;
  6148. R[10] += b * b;
  6149. R[11] += b * a;
  6150. R[15] += a * a;
  6151. }
  6152. R[4] = R[1];
  6153. R[8] = R[2];
  6154. R[9] = R[6];
  6155. R[12] = R[3];
  6156. R[13] = R[7];
  6157. R[14] = R[11];
  6158. return {
  6159. R: R,
  6160. m: m,
  6161. N: N
  6162. };
  6163. }
  6164. function estats(stats) {
  6165. var R = stats.R,
  6166. m = stats.m,
  6167. N = stats.N;
  6168. // when all samples are equal, but N is large (millions), the Rj can be non-zero ( 0.0003.... - precission error)
  6169. var m0 = m[0],
  6170. m1 = m[1],
  6171. m2 = m[2],
  6172. m3 = m[3],
  6173. iN = N == 0 ? 0 : 1 / N;
  6174. var Rj = [R[0] - m0 * m0 * iN, R[1] - m0 * m1 * iN, R[2] - m0 * m2 * iN, R[3] - m0 * m3 * iN, R[4] - m1 * m0 * iN, R[5] - m1 * m1 * iN, R[6] - m1 * m2 * iN, R[7] - m1 * m3 * iN, R[8] - m2 * m0 * iN, R[9] - m2 * m1 * iN, R[10] - m2 * m2 * iN, R[11] - m2 * m3 * iN, R[12] - m3 * m0 * iN, R[13] - m3 * m1 * iN, R[14] - m3 * m2 * iN, R[15] - m3 * m3 * iN];
  6175. var A = Rj,
  6176. M = M4;
  6177. var b = [Math.random(), Math.random(), Math.random(), Math.random()],
  6178. mi = 0,
  6179. tmi = 0;
  6180. if (N != 0) for (var i = 0; i < 16; i++) {
  6181. b = M.multVec(A, b);
  6182. tmi = Math.sqrt(M.dot(b, b));
  6183. b = M.sml(1 / tmi, b);
  6184. if (i != 0 && Math.abs(tmi - mi) < 1e-9) break;
  6185. mi = tmi;
  6186. }
  6187. //b = [0,0,1,0]; mi=N;
  6188. var q = [m0 * iN, m1 * iN, m2 * iN, m3 * iN];
  6189. var eMq255 = M.dot(M.sml(255, q), b);
  6190. return {
  6191. Cov: Rj,
  6192. q: q,
  6193. e: b,
  6194. L: mi,
  6195. eMq255: eMq255,
  6196. eMq: M.dot(b, q),
  6197. rgba: (Math.round(255 * q[3]) << 24 | Math.round(255 * q[2]) << 16 | Math.round(255 * q[1]) << 8 | Math.round(255 * q[0]) << 0) >>> 0
  6198. };
  6199. }
  6200. var M4 = {
  6201. multVec: function multVec(m, v) {
  6202. return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * v[3], m[4] * v[0] + m[5] * v[1] + m[6] * v[2] + m[7] * v[3], m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11] * v[3], m[12] * v[0] + m[13] * v[1] + m[14] * v[2] + m[15] * v[3]];
  6203. },
  6204. dot: function dot(x, y) {
  6205. return x[0] * y[0] + x[1] * y[1] + x[2] * y[2] + x[3] * y[3];
  6206. },
  6207. sml: function sml(a, y) {
  6208. return [a * y[0], a * y[1], a * y[2], a * y[3]];
  6209. }
  6210. };
  6211. function concatRGBA(bufs) {
  6212. var tlen = 0;
  6213. for (var i = 0; i < bufs.length; i++) tlen += bufs[i].byteLength;
  6214. var nimg = new Uint8Array(tlen),
  6215. noff = 0;
  6216. for (var i = 0; i < bufs.length; i++) {
  6217. var img = new Uint8Array(bufs[i]),
  6218. il = img.length;
  6219. for (var j = 0; j < il; j += 4) {
  6220. var r = img[j],
  6221. g = img[j + 1],
  6222. b = img[j + 2],
  6223. a = img[j + 3];
  6224. if (a == 0) r = g = b = 0;
  6225. nimg[noff + j] = r;
  6226. nimg[noff + j + 1] = g;
  6227. nimg[noff + j + 2] = b;
  6228. nimg[noff + j + 3] = a;
  6229. }
  6230. noff += il;
  6231. }
  6232. return nimg.buffer;
  6233. }
  6234. UPNG$1.encode = encode;
  6235. UPNG$1.encodeLL = encodeLL;
  6236. UPNG$1.encode.compress = compress;
  6237. UPNG$1.encode.dither = dither;
  6238. UPNG$1.quantize = quantize;
  6239. UPNG$1.quantize.findNearest = findNearest;
  6240. UPNG$1.quantize.getKDtree = getKDtree;
  6241. UPNG$1.quantize.getNearest = getNearest;
  6242. })();
  6243. window.UPNG = UPNG$1;
  6244. var Common$1 = {
  6245. autoPlayList: [],
  6246. sortByScore: function sortByScore(list, request, rank) {
  6247. var i = request ? Common$1.filterAll(list, request) : list;
  6248. return 0 === i.length ? [] : i = i.map(function (e) {
  6249. var results = rank.map(function (f) {
  6250. return f(e);
  6251. });
  6252. var scores = results.map(e => e.score != void 0 ? e.score : e);
  6253. var logs = results.map(e => e.log);
  6254. return {
  6255. item: e,
  6256. scores,
  6257. logs,
  6258. score: scores.reduce(function (t, i) {
  6259. //总分
  6260. return t + i;
  6261. }, 0)
  6262. };
  6263. }).sort(function (e, t) {
  6264. return t.score - e.score;
  6265. });
  6266. },
  6267. filterAll: function filterAll(e, t) {
  6268. return e.filter(function (e) {
  6269. return t.every(function (t) {
  6270. return t(e);
  6271. });
  6272. });
  6273. },
  6274. //---------------
  6275. find: function find(list, request, rank, sortByScore) {
  6276. if (sortByScore) {
  6277. var r = this.sortByScore(list, request, rank);
  6278. return r[0] && r[0].item;
  6279. } else {
  6280. var i = request ? Common$1.filterAll(list, request) : list;
  6281. return 0 === i.length ? null : (rank && rank.forEach(function (e) {
  6282. i = Common$1.stableSort(i, e);
  6283. }), i[0]);
  6284. }
  6285. },
  6286. stableSort: function stableSort(e, f) {
  6287. //用到排序函数,涉及到两个item相减
  6288. return e.map(function (e, i) {
  6289. return {
  6290. value: e,
  6291. index: i
  6292. };
  6293. }).sort(function (e, u) {
  6294. var n = f(e.value, u.value);
  6295. return 0 !== n ? n : e.index - u.index; //似乎就是加多了这一步:若差距为0,按照原顺序
  6296. }).map(function (e) {
  6297. return e.value;
  6298. });
  6299. },
  6300. average: function average(e, t) {
  6301. if (0 === e.length) return null;
  6302. for (var i = 0, n = 0, r = 0; r < e.length; r++) {
  6303. var o = t ? e[r][t] : e[r];
  6304. i += o, n++;
  6305. }
  6306. return i / n;
  6307. },
  6308. //---------------------------
  6309. getMixedSet: function getMixedSet(arr1, arr2) {
  6310. //交集
  6311. return arr1.filter(item => arr2.includes(item));
  6312. },
  6313. getUnionSet: function getUnionSet(arr1, arr2) {
  6314. //并集
  6315. return arr1.concat(arr2.filter(item => !arr1.includes(item)));
  6316. },
  6317. getDifferenceSet: function getDifferenceSet(arr1, arr2) {
  6318. //差集 不能识别重复的,如getDifferenceSet([1,2,2],[1,1,2]) 为空
  6319. var arr11 = arr1.filter(item => !arr2.includes(item));
  6320. var arr22 = arr2.filter(item => !arr1.includes(item));
  6321. return arr11.concat(arr22);
  6322. },
  6323. getDifferenceSetMuti: function getDifferenceSetMuti(arr) {
  6324. //收集绝对没有重复的元素,也就是判断出现次数=1的
  6325. var set = [];
  6326. arr.forEach(arr1 => {
  6327. arr1.forEach(item => {
  6328. var index = set.indexOf(item);
  6329. if (index > -1) {
  6330. set.splice(index, 1);
  6331. } else {
  6332. set.push(item);
  6333. }
  6334. });
  6335. });
  6336. return set;
  6337. },
  6338. CloneJson: function CloneJson(data) {
  6339. var str = JSON.stringify(data);
  6340. return JSON.parse(str);
  6341. },
  6342. CloneObject: function CloneObject(copyObj, isSimpleCopy) {
  6343. var simpleCopyList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  6344. var judgeSimpleCopyFun = arguments.length > 3 ? arguments[3] : undefined;
  6345. //isSimpleCopy 只复制最外层
  6346. //复制json result的可能:普通数字或字符串、普通数组、复杂对象
  6347. judgeSimpleCopyFun || (judgeSimpleCopyFun = () => {});
  6348. if (!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' || copyObj.isObject3D || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className) || judgeSimpleCopyFun(copyObj)) {
  6349. return copyObj;
  6350. }
  6351. if (copyObj instanceof Array) {
  6352. return copyObj.map(e => {
  6353. return this.CloneObject(e, isSimpleCopy, simpleCopyList, judgeSimpleCopyFun);
  6354. });
  6355. } else {
  6356. if (copyObj.clone instanceof Function) {
  6357. //解决一部分
  6358. return copyObj.clone();
  6359. }
  6360. }
  6361. var result = {};
  6362. for (var key in copyObj) {
  6363. if (copyObj[key] instanceof Object && !isSimpleCopy) result[key] = this.CloneObject(copyObj[key], isSimpleCopy, simpleCopyList, judgeSimpleCopyFun);else result[key] = copyObj[key];
  6364. //如果是函数类同基本数据,即复制引用
  6365. }
  6366. return result;
  6367. },
  6368. CloneClassObject: function CloneClassObject(copyObj) {
  6369. var {
  6370. ignoreList = [],
  6371. simpleCopyList = []
  6372. } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  6373. //复杂类对象
  6374. var newobj = new copyObj.constructor();
  6375. this.CopyClassObject(newobj, copyObj, {
  6376. ignoreList,
  6377. simpleCopyList
  6378. });
  6379. return newobj;
  6380. },
  6381. CopyClassObject: function CopyClassObject(targetObj, copyObj) {
  6382. var {
  6383. ignoreList = [],
  6384. simpleCopyList = []
  6385. } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  6386. //复杂类对象
  6387. for (var i in copyObj) {
  6388. if (i in copyObj.__proto__) break; //到函数了跳出
  6389. if (ignoreList.includes(i)) {
  6390. continue;
  6391. } else if (simpleCopyList.includes(i)) {
  6392. targetObj[i] = copyObj[i];
  6393. } else {
  6394. targetObj[i] = this.CloneObject(copyObj[i], false, simpleCopyList);
  6395. }
  6396. /* else if(copyObj[i].clone instanceof Function ){
  6397. targetObj[i] = copyObj[i].clone()
  6398. }else{
  6399. targetObj[i] = copyObj[i];
  6400. } */
  6401. }
  6402. },
  6403. ifSame: function ifSame(object1, object2) {
  6404. var simpleEqualClass = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  6405. //对于复杂的类对象,若能简单判断就直接写进simpleEqualClass
  6406. if (object1 == object2) return true; // 0 != undefined , 0 == ''
  6407. else if (!object1 || !object2) return false;else if (object1.constructor != object2.constructor) {
  6408. return false;
  6409. } else if (simpleEqualClass.some(className => object1 instanceof className)) {
  6410. return object1 == object2;
  6411. } else if (object1 instanceof Array) {
  6412. if (object1.length != object2.length) return false;
  6413. var _object2 = object2.slice(0);
  6414. var _loop = function _loop(i) {
  6415. u = _object2.find(e => Common$1.ifSame(object1[i], e, simpleEqualClass));
  6416. if (u == void 0 && !_object2.includes(u) && !object1.includes(u)) return {
  6417. v: false
  6418. };else {
  6419. var index = _object2.indexOf(u);
  6420. _object2.splice(index, 1);
  6421. }
  6422. },
  6423. u,
  6424. _ret;
  6425. for (var i = 0; i < object1.length; i++) {
  6426. _ret = _loop(i);
  6427. if (_ret) return _ret.v;
  6428. }
  6429. return true;
  6430. } else if (object1.equals instanceof Function) {
  6431. //复杂数据仅支持这种,其他的可能卡住?
  6432. return object1.equals(object2);
  6433. } else if (typeof object1 == 'number' || typeof object1 == 'string') {
  6434. if (isNaN(object1) && isNaN(object2)) return true;else return object1 == object2;
  6435. } else if (typeof object1 == "object") {
  6436. var keys1 = Object.keys(object1);
  6437. var keys2 = Object.keys(object2);
  6438. if (!Common$1.ifSame(keys1, keys2, simpleEqualClass)) return false;
  6439. for (var _i in object1) {
  6440. var same = Common$1.ifSame(object1[_i], object2[_i], simpleEqualClass);
  6441. if (!same) return false;
  6442. }
  6443. return true;
  6444. } else {
  6445. console.log('isSame出现例外');
  6446. }
  6447. },
  6448. downloadFile: function downloadFile(data, filename, cb) {
  6449. var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  6450. save_link.href = data;
  6451. save_link.download = filename;
  6452. var event = document.createEvent('MouseEvents');
  6453. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  6454. save_link.dispatchEvent(event);
  6455. cb && cb();
  6456. },
  6457. replaceAll: function replaceAll(str, f, e) {
  6458. //f全部替换成e
  6459. if (str.replaceAll) return str.replaceAll(f, e);else {
  6460. var escapeRegExp = string => {
  6461. return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  6462. };
  6463. return str.replace(new RegExp(escapeRegExp(f), 'g'), e);
  6464. /* var reg = new RegExp(f, "g"); //创建正则RegExp对象 这个没法转换'('
  6465. return str.replace(reg, e); //str.split(f).join(e); */
  6466. }
  6467. },
  6468. dealURL() {
  6469. var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  6470. var urlNew = this.replaceAll(url, "+", "%2B"); //this.replaceAll(url, "\\+", "%2B");// 浏览器似乎不支持访问带+的地址
  6471. urlNew = this.replaceAll(urlNew, "/.//", "/"); //去除双斜杠(/.//)
  6472. //urlNew = encodeURIComponent(url)
  6473. return urlNew;
  6474. },
  6475. getNameFromURL(url, removePostfix) {
  6476. if (!url) return '';
  6477. var get = e => {
  6478. var a = e.split('/').pop();
  6479. if (removePostfix) a = a.split('.')[0];
  6480. return a;
  6481. };
  6482. if (url instanceof Array) {
  6483. return url.map(e => get(e));
  6484. }
  6485. return get(url);
  6486. },
  6487. getBoundPoints(bound, matrixWorld) {
  6488. var points = [new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.max.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), new Vector3(bound.min.x, bound.max.y, bound.max.z), new Vector3(bound.max.x, bound.max.y, bound.max.z)];
  6489. matrixWorld && points.forEach(e => e.applyMatrix4(matrixWorld));
  6490. return points;
  6491. },
  6492. //---------------------------
  6493. intervalTool: {
  6494. //延时update,防止卡顿
  6495. list: [],
  6496. /* isWaiting:function(name, func, delayTime){
  6497. if(!this.list.includes(name)){ //如果没有该项, 则开始判断
  6498. var needWait = func(); //触发了改变,则等待一段时间后再自动判断
  6499. if(needWait){
  6500. this.list.push(name);
  6501. setTimeout(()=>{
  6502. var a = this.list.indexOf(name);
  6503. this.list.splice(a,1);
  6504. this.isWaiting(name, func, delayTime) //循环
  6505. },delayTime)
  6506. }
  6507. }
  6508. }, */
  6509. isWaiting: function isWaiting(name, func, delayTime /* , autoCycle */) {
  6510. var item = this.list.find(e => e.name == name);
  6511. if (!item) {
  6512. //如果没有该项, 则加入循环
  6513. var ifContinue = func();
  6514. item = {
  6515. name,
  6516. func,
  6517. delayTime
  6518. };
  6519. /* if(name == 'processPriorityQueue'){
  6520. console.log('isWaiting', delayTime)
  6521. } */
  6522. this.list.push(item);
  6523. setTimeout(() => {
  6524. var a = this.list.indexOf(item);
  6525. this.list.splice(a, 1);
  6526. var {
  6527. func,
  6528. delayTime
  6529. } = item;
  6530. if (item.requestUpdate || ifContinue) this.isWaiting(name, func, delayTime); //循环
  6531. }, delayTime);
  6532. } else {
  6533. //如果有该项,说明现在请求下一次继续更新
  6534. //if(delayTime == 0){//想立刻更新一次
  6535. // func()
  6536. //}else{
  6537. //更新属性
  6538. item.func = func;
  6539. item.delayTime = delayTime;
  6540. item.requestUpdate = true;
  6541. //}
  6542. }
  6543. }
  6544. },
  6545. waitTool: {
  6546. //定时器,在等待的这段时间内如果又触发则重新计时
  6547. list: [],
  6548. wait(name, func, time) {
  6549. var item = this.list.find(e => e.name == name);
  6550. var timer = setTimeout(() => {
  6551. func();
  6552. var index = this.list.indexOf(item);
  6553. this.list.splice(index, 1);
  6554. }, time);
  6555. if (item) {
  6556. clearTimeout(item.timer);
  6557. } else {
  6558. item = {
  6559. name
  6560. };
  6561. this.list.push(item);
  6562. }
  6563. item.timer = timer;
  6564. },
  6565. cancel(name) {
  6566. var index = this.list.findIndex(e => e.name == name);
  6567. index > -1 && this.list.splice(index, 1);
  6568. }
  6569. },
  6570. pushToGroupAuto: function pushToGroupAuto(items, groups, recognizeFunction, recognizeGroup) {
  6571. //自动分组。 items是将分到一起的组合。items.length = 1 or 2.
  6572. recognizeFunction = recognizeFunction || function () {};
  6573. if (recognizeGroup) {
  6574. //有更复杂的识别处理,直接传递整个组
  6575. var atGroups = groups.filter(group => recognizeGroup(group, items));
  6576. } else {
  6577. var atGroups = groups.filter(group => group.find(item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1])));
  6578. }
  6579. if (atGroups.length) {
  6580. //在不同组
  6581. //因为items是一组的,所以先都放入组1
  6582. items.forEach(item => {
  6583. if (!atGroups[0].includes(item)) atGroups[0].push(item);
  6584. });
  6585. if (atGroups.length > 1) {
  6586. //如果在不同组,说明这两个组需要合并
  6587. var combineGroup = [];
  6588. atGroups.forEach(group => {
  6589. combineGroup = Common$1.getUnionSet(combineGroup, group);
  6590. groups.splice(groups.indexOf(group), 1);
  6591. });
  6592. groups.push(combineGroup);
  6593. }
  6594. } else {
  6595. //直接加入为一组
  6596. groups.push(items);
  6597. }
  6598. },
  6599. getBestCount: function () {
  6600. var lastCount = {};
  6601. return function (name) {
  6602. var minCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  6603. var maxCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 6;
  6604. var durBound1 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1.2;
  6605. var durBound2 = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 10;
  6606. var ifLog = arguments.length > 5 ? arguments[5] : undefined;
  6607. var maxHistory = arguments.length > 6 ? arguments[6] : undefined;
  6608. var timeStamp = performance.getEntriesByName("loop-start");
  6609. var count;
  6610. if (timeStamp.length) {
  6611. var dur = performance.now() - timeStamp[timeStamp.length - 1].startTime; //dur在iphoneX中静止有7,pc是2
  6612. count = Math.round(math.linearClamp(dur, [durBound1, durBound2], [maxCount, minCount]));
  6613. if (maxHistory) {
  6614. if (!lastCount[name]) lastCount[name] = [];
  6615. if (count == 0 && lastCount[name].length > maxHistory - 1 && !lastCount[name].some(e => e > 0)) {
  6616. count = 1;
  6617. }
  6618. lastCount[name].push(count);
  6619. if (lastCount[name].length > maxHistory) lastCount[name].splice(0, 1);
  6620. }
  6621. if (ifLog) {
  6622. //注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
  6623. name && count && console.log(name, count, ' ,dur:', dur.toFixed(3));
  6624. }
  6625. } else {
  6626. count = maxCount; // ?
  6627. }
  6628. //主要在手机端有效果。
  6629. return count;
  6630. };
  6631. }(),
  6632. getBestCountFPS(name, ifLog) {
  6633. var minCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  6634. var maxCount = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 6;
  6635. var minFps = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 10;
  6636. var maxFps = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 60;
  6637. var minPanoCount = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 200;
  6638. var maxPanoCount = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1000;
  6639. var fps = Potree.fps;
  6640. var count = math.linearClamp(fps, [minFps, maxFps], [minCount, maxCount]);
  6641. var count2 = math.linearClamp(viewer.images360.panos.length, [minPanoCount, maxPanoCount], [minCount, maxCount]);
  6642. count = (count + count2) / 2;
  6643. count = Math.round(count);
  6644. if (ifLog) {
  6645. name && count && console.log(name, count, ' ,fps:', fps.toFixed(3));
  6646. }
  6647. return count;
  6648. },
  6649. batchHandling: {
  6650. //分批处理
  6651. lists: [],
  6652. getSlice: function getSlice(name, items, _ref) {
  6653. var {
  6654. stopWhenAllUsed,
  6655. min = 5,
  6656. max = 100,
  6657. durBound1,
  6658. durBound2,
  6659. useEquals,
  6660. maxUseCount
  6661. } = _ref;
  6662. if (items.length == 0 || (maxUseCount = maxUseCount == void 0 ? Common$1.getBestCount(name, min, max, durBound1, durBound2 /* , true */) : maxUseCount, !maxUseCount) //本次最多可以使用的个数
  6663. ) {
  6664. return {
  6665. list: []
  6666. };
  6667. }
  6668. if (!this.lists[name]) this.lists[name] = {
  6669. list: []
  6670. };
  6671. //更新列表项目,但不变原来的顺序
  6672. var list = this.lists[name].list.filter(a => items.some(item => useEquals ? a.item.equals(item) : a.item == item)); //去掉已经不在items里的项目
  6673. this.lists[name].list = list;
  6674. items.forEach(item => {
  6675. //增加新的项目。
  6676. if (!list.some(a => useEquals ? a.item.equals(item) : a.item == item)) {
  6677. list.push({
  6678. item,
  6679. count: 0
  6680. });
  6681. }
  6682. });
  6683. //至此,在后排的都是未使用的
  6684. var unUsed = list.filter(e => e.count == 0); //未使用的项目(count为0)优先
  6685. var result = [];
  6686. unUsed.slice(0, maxUseCount).forEach(e => {
  6687. result.push(e.item);
  6688. e.count++;
  6689. });
  6690. if (unUsed.length > maxUseCount) {
  6691. //还是剩有未使用的项目,等待下一次
  6692. } else {
  6693. //所有项目都能使用一次
  6694. if (!stopWhenAllUsed) {
  6695. //若不是全部使用就停止
  6696. var wholeCount = Math.min(items.length, maxUseCount);
  6697. var restCount = wholeCount - result.length; //补齐
  6698. list.slice(0, restCount).forEach(e => {
  6699. result.push(e.item);
  6700. e.count++;
  6701. });
  6702. }
  6703. list.forEach(e => e.count--); //复原,等待新的循环
  6704. }
  6705. /* result.forEach((e,i)=>{//有重复的
  6706. if( result.slice(0,i).some(a=>a.equals(e)) || result.slice(i+1).some(a=>a.equals(e)) ) {
  6707. console.log(e)
  6708. }
  6709. }) */
  6710. return {
  6711. list: result
  6712. };
  6713. }
  6714. },
  6715. getRootWindow() {
  6716. //获取包含Potree的根window
  6717. var win = window;
  6718. try {
  6719. while (win.parent != win && win.parent.Potree) {
  6720. win = win.parent;
  6721. }
  6722. if (window != win) return win;
  6723. } catch (e) {
  6724. //console.log(e) //可能跨域,从而win.parent.Potree报错
  6725. console.log('getRootWindow 跨域');
  6726. return;
  6727. }
  6728. },
  6729. watch: function watch(object, propName, initialValue) {
  6730. //监听某个属性的变化
  6731. var v = initialValue;
  6732. Object.defineProperty(object, propName, {
  6733. get: function get() {
  6734. return v;
  6735. },
  6736. set: function set(e) {
  6737. console.warn('watch:', propName, e);
  6738. v = e;
  6739. }
  6740. });
  6741. },
  6742. imgAddLabel: function imgAddLabel(img, labelImg) {
  6743. var labelInfo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  6744. //图上加另一张小图,用于添加水印
  6745. var canvas;
  6746. if (img instanceof Image) {
  6747. canvas = document.createElement('canvas');
  6748. } else {
  6749. canvas = img;
  6750. }
  6751. var context = canvas.getContext('2d');
  6752. var marginLeft = labelInfo.bgMargin && labelInfo.bgMargin.left || 0;
  6753. var marginRight = labelInfo.bgMargin && labelInfo.bgMargin.right || 0;
  6754. var marginTop = labelInfo.bgMargin && labelInfo.bgMargin.top || 0;
  6755. var marginBottom = labelInfo.bgMargin && labelInfo.bgMargin.bottom || 0;
  6756. if (img instanceof Image) {
  6757. //如果img是canvas,说明已绘制在canvas上了就不用绘制了
  6758. var width = img.width + marginLeft + marginRight;
  6759. var height = img.height + marginTop + marginBottom;
  6760. canvas.width = width;
  6761. canvas.height = height;
  6762. if (labelInfo.bgColor) {
  6763. context.fillStyle = 'rgba(' + labelInfo.bgColor.r + ',' + labelInfo.bgColor.g + ',' + labelInfo.bgColor.b + ',' + labelInfo.bgColor.a + ')';
  6764. context.fillRect(0, 0, width, height);
  6765. }
  6766. context.drawImage(img, marginLeft, marginTop, img.width, img.height);
  6767. }
  6768. var labelWidth = labelInfo.widthRatioToImg ? img.width * labelInfo.widthRatioToImg : labelImg.width; //widthRatioToImg:label的width占img的width的比例
  6769. var labelHeight = labelWidth * labelImg.height / labelImg.width;
  6770. if (labelInfo.leftRatioToImg == void 0 && labelInfo.rightRatioToImg != void 0) {
  6771. labelInfo.leftRatioToImg = 1 - labelInfo.rightRatioToImg - (labelInfo.widthRatioToImg || labelImg.width / img.width);
  6772. }
  6773. if (labelInfo.topRatioToImg == void 0 && labelInfo.bottomRatioToImg != void 0) {
  6774. labelInfo.topRatioToImg = 1 - labelInfo.bottomRatioToImg - labelHeight / img.height;
  6775. }
  6776. var labelLeft = img.width * labelInfo.leftRatioToImg + marginLeft; //leftRatioToImg:label的left占img的width的比例
  6777. var labelTop = img.height * labelInfo.topRatioToImg + marginTop; //topRatioToImg:label的top占img的height的比例
  6778. context.globalAlpha = labelInfo.opacity != void 0 ? labelInfo.opacity : 1;
  6779. context.drawImage(labelImg, labelLeft, labelTop, labelWidth, labelHeight);
  6780. if (labelInfo.outputCanvas) {
  6781. return canvas;
  6782. }
  6783. var dataUrl = canvas.toDataURL('image/png', labelInfo.compressRatio);
  6784. //Common.downloadFile(dataUrl, 'screenshot.png')
  6785. context.clearRect(0, 0, canvas.width, canvas.height);
  6786. return dataUrl;
  6787. },
  6788. mobileAutoPlay(media, playFun) {
  6789. //移动端。不这么写video不会播放 . (2022.11.29: 可为何加了Hot.updateHots之后又会自动播了?https有关?
  6790. if (this.autoPlayList.includes(media)) return;
  6791. this.autoPlayList.push(media);
  6792. viewer.addEventListener;
  6793. var events = ['global_touchstart', 'global_mousedown'];
  6794. var fun = () => {
  6795. var index = this.autoPlayList.indexOf(media);
  6796. if (index > -1) {
  6797. console.log('try autoplay ' + media.src);
  6798. playFun();
  6799. this.autoPlayList.splice(index, 1);
  6800. events.forEach(eventName => {
  6801. viewer.removeEventListener(eventName, fun);
  6802. });
  6803. }
  6804. };
  6805. events.forEach(eventName => {
  6806. viewer.addEventListener(eventName, fun);
  6807. });
  6808. },
  6809. /* changeShaderToWebgl2(vs, fs, matType, otherReplaces=[]){//部分shader要根据webgl版本作更改
  6810. if(!Potree.settings.isWebgl2)return {vs, fs}
  6811. let turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT') )
  6812. let addV300 = turnTo300 && matType != 'RawShaderMaterial' // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
  6813. let change = (shader, shaderType)=>{
  6814. let newShader = shader
  6815. if(turnTo300){ //非shaderMaterial需要手动改为300 es的写法
  6816. addV300 && (newShader = '#version 300 es \n' + newShader) //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
  6817. newShader = newShader.replaceAll('varying ', shaderType == 'vs' ? 'out ' : 'in ')
  6818. newShader = newShader.replaceAll('attribute ', 'in ')
  6819. if(shaderType == 'fs'){
  6820. newShader = newShader.replaceAll('gl_FragColor', 'fragColor')
  6821. newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main' )//在void main前加入这个声明
  6822. }
  6823. newShader = newShader.replaceAll('gl_FragDepthEXT','gl_FragDepth')
  6824. newShader = newShader.replaceAll('texture2D','texture')
  6825. newShader = newShader.replaceAll('textureCube','texture')
  6826. }
  6827. newShader = newShader.replace('#extension GL_EXT_frag_depth : enable','')
  6828. newShader = newShader.replaceAll('defined(GL_EXT_frag_depth) &&','')
  6829. otherReplaces.forEach(({oldStr,newStr})=>{
  6830. newShader = newShader.replaceAll(oldStr,newStr)
  6831. })
  6832. return newShader
  6833. }
  6834. vs = change(vs,'vs')
  6835. fs = change(fs,'fs')
  6836. //console.log('成功替换为webgl2' )
  6837. return {vs,fs}
  6838. }//three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
  6839. */
  6840. changeShaderToWebgl2(vs, fs, matType) {
  6841. var otherReplaces = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
  6842. //部分shader要根据webgl版本作更改
  6843. if (!Potree.settings.isWebgl2) return {
  6844. vs,
  6845. fs
  6846. };
  6847. var turnTo300 = matType != 'ShaderMaterial' && (vs.includes('gl_FragDepthEXT') || fs.includes('gl_FragDepthEXT'));
  6848. var addV300 = turnTo300 && matType != 'RawShaderMaterial'; // RawShaderMaterial直接material.glslVersion = '300 es' 以加在define之前
  6849. var change = (shader, shaderType) => {
  6850. var newShader = shader;
  6851. if (turnTo300) {
  6852. //非shaderMaterial需要手动改为300 es的写法
  6853. addV300 && (newShader = '#version 300 es \n' + newShader); //需要加 #version 300 es。 three.js自带的渲染会自动加所以不用
  6854. newShader = this.replaceAll(newShader, 'varying ', shaderType == 'vs' ? 'out ' : 'in ');
  6855. newShader = this.replaceAll(newShader, 'attribute ', 'in ');
  6856. if (shaderType == 'fs') {
  6857. newShader = this.replaceAll(newShader, 'gl_FragColor', 'fragColor');
  6858. newShader = newShader.replace('void main', 'out vec4 fragColor;\n void main'); //在void main前加入这个声明
  6859. }
  6860. newShader = this.replaceAll(newShader, 'gl_FragDepthEXT', 'gl_FragDepth');
  6861. newShader = this.replaceAll(newShader, 'texture2D', 'texture');
  6862. newShader = this.replaceAll(newShader, 'textureCube', 'texture');
  6863. }
  6864. newShader = newShader.replace('#extension GL_EXT_frag_depth : enable', '');
  6865. newShader = this.replaceAll(newShader, 'defined(GL_EXT_frag_depth) &&', '');
  6866. otherReplaces.forEach(_ref2 => {
  6867. var {
  6868. oldStr,
  6869. newStr
  6870. } = _ref2;
  6871. newShader = this.replaceAll(newShader, oldStr, newStr);
  6872. });
  6873. return newShader;
  6874. };
  6875. vs = change(vs, 'vs');
  6876. fs = change(fs, 'fs');
  6877. //console.log('成功替换为webgl2' )
  6878. return {
  6879. vs,
  6880. fs
  6881. };
  6882. },
  6883. //three.js的shaderMaterial也有替换功能,搜 '#define gl_FragDepthEXT gl_FragDepth',
  6884. load16bitPngTex(src, onLoad, onError, pixelFun) {
  6885. //单通道无符号16位的png (正常图片是32位一个像素)
  6886. var texture = new DataTexture();
  6887. fetch(src).then(response => {
  6888. if (!response.ok) {
  6889. console.log('loadFile失败', src);
  6890. return onError && onError();
  6891. }
  6892. return response.arrayBuffer();
  6893. }).then(arrayBuffer => {
  6894. //文件数据
  6895. var png = UPNG.decode(arrayBuffer); //解析出像素数据
  6896. var pixelCount = png.width * png.height;
  6897. var data = new Uint8Array(pixelCount * 4);
  6898. var view = new DataView(data.buffer);
  6899. for (var i = 0; i < pixelCount; i++) {
  6900. //将uint16的只有两个byte的扩充到四个byte,因为贴图只支持4个byte的
  6901. var r = png.data[i * 2];
  6902. var g = png.data[i * 2 + 1];
  6903. data[i * 4 + 0] = g; //反了
  6904. data[i * 4 + 1] = r;
  6905. data[i * 4 + 2] = data[i * 4 + 3] = 255; //无用值填充
  6906. if (pixelFun) {
  6907. pixelFun(view.getUint16(i * 4, true), i, pixelCount); //原值
  6908. }
  6909. }
  6910. texture.image.data = data;
  6911. texture.image.width = png.width;
  6912. texture.image.height = png.height;
  6913. texture.image.src = src;
  6914. texture.needsUpdate = true;
  6915. onLoad && onLoad();
  6916. }).catch(error => {
  6917. onError && onError(error);
  6918. });
  6919. return texture;
  6920. }
  6921. };
  6922. Potree.Common = Common$1;
  6923. class View {
  6924. //base
  6925. constructor() {
  6926. this.position = new Vector3(0, 0, 0);
  6927. this.yaw = Math.PI / 4;
  6928. this._pitch = -Math.PI / 4;
  6929. this.radius = 1;
  6930. this.maxPitch = Math.PI / 2;
  6931. this.minPitch = -Math.PI / 2;
  6932. }
  6933. clone() {
  6934. var c = new View();
  6935. c.yaw = this.yaw;
  6936. c._pitch = this.pitch;
  6937. c.radius = this.radius;
  6938. c.maxPitch = this.maxPitch;
  6939. c.minPitch = this.minPitch;
  6940. return c;
  6941. }
  6942. get pitch() {
  6943. return this._pitch;
  6944. }
  6945. set pitch(angle) {
  6946. this._pitch = Math.max(Math.min(angle, this.maxPitch), this.minPitch);
  6947. }
  6948. get direction() {
  6949. var dir = new Vector3(0, 1, 0);
  6950. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  6951. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  6952. return dir;
  6953. }
  6954. set direction(dir) {
  6955. dir = dir.clone().normalize(); //add
  6956. if (dir.x === 0 && dir.y === 0) {
  6957. this.pitch = Math.PI / 2 * Math.sign(dir.z);
  6958. //this.yaw = 0 //add:还是要指定一下, 否则不统一
  6959. } else {
  6960. var yaw = Math.atan2(dir.y, dir.x) - Math.PI / 2;
  6961. var pitch = Math.atan2(dir.z, Math.sqrt(dir.x * dir.x + dir.y * dir.y));
  6962. this.yaw = yaw;
  6963. this.pitch = pitch;
  6964. }
  6965. }
  6966. lookAt(t) {
  6967. //setPivot
  6968. var V;
  6969. if (arguments.length === 1) {
  6970. V = new Vector3().subVectors(t, this.position);
  6971. } else if (arguments.length === 3) {
  6972. V = new Vector3().subVectors(new Vector3(...arguments), this.position);
  6973. }
  6974. var radius = V.length();
  6975. var dir = V.normalize();
  6976. this.radius = radius;
  6977. this.direction = dir;
  6978. }
  6979. getPivot() {
  6980. return new Vector3().addVectors(this.position, this.direction.multiplyScalar(this.radius));
  6981. }
  6982. getSide() {
  6983. var side = new Vector3(1, 0, 0);
  6984. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  6985. return side;
  6986. }
  6987. pan(x, y) {
  6988. var dir = new Vector3(0, 1, 0);
  6989. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  6990. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  6991. // let side = new THREE.Vector3(1, 0, 0);
  6992. // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  6993. var side = this.getSide();
  6994. var up = side.clone().cross(dir);
  6995. var pan = side.multiplyScalar(x).add(up.multiplyScalar(y));
  6996. this.position = this.position.add(pan);
  6997. // this.target = this.target.add(pan);
  6998. }
  6999. translate(x, y, z) {
  7000. var dir = new Vector3(0, 1, 0);
  7001. dir.applyAxisAngle(new Vector3(1, 0, 0), this.pitch);
  7002. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  7003. var side = new Vector3(1, 0, 0);
  7004. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw);
  7005. var up = side.clone().cross(dir);
  7006. var t = side.multiplyScalar(x).add(dir.multiplyScalar(y)).add(up.multiplyScalar(z));
  7007. this.position = this.position.add(t);
  7008. }
  7009. translateWorld(x, y, z) {
  7010. this.position.x += x;
  7011. this.position.y += y;
  7012. this.position.z += z;
  7013. }
  7014. setView(position, target) {
  7015. var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  7016. var callback = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  7017. var endPosition = null;
  7018. if (position instanceof Array) {
  7019. endPosition = new Vector3(...position);
  7020. } else if (position.x != null) {
  7021. endPosition = position.clone();
  7022. }
  7023. var endTarget = null;
  7024. if (target instanceof Array) {
  7025. endTarget = new Vector3(...target);
  7026. } else if (target.x != null) {
  7027. endTarget = target.clone();
  7028. }
  7029. var startPosition = this.position.clone();
  7030. var startTarget = this.getPivot();
  7031. //const endPosition = position.clone();
  7032. //const endTarget = target.clone();
  7033. var easing = TWEEN.Easing.Quartic.Out;
  7034. if (duration === 0) {
  7035. this.position.copy(endPosition);
  7036. this.lookAt(endTarget);
  7037. } else {
  7038. var value = {
  7039. x: 0
  7040. };
  7041. var tween = new TWEEN.Tween(value).to({
  7042. x: 1
  7043. }, duration);
  7044. tween.easing(easing);
  7045. //this.tweens.push(tween);
  7046. tween.onUpdate(() => {
  7047. var t = value.x;
  7048. //console.log(t);
  7049. var pos = new Vector3((1 - t) * startPosition.x + t * endPosition.x, (1 - t) * startPosition.y + t * endPosition.y, (1 - t) * startPosition.z + t * endPosition.z);
  7050. var target = new Vector3((1 - t) * startTarget.x + t * endTarget.x, (1 - t) * startTarget.y + t * endTarget.y, (1 - t) * startTarget.z + t * endTarget.z);
  7051. this.position.copy(pos);
  7052. this.lookAt(target);
  7053. });
  7054. tween.start();
  7055. tween.onComplete(() => {
  7056. if (callback) {
  7057. callback();
  7058. }
  7059. });
  7060. }
  7061. }
  7062. }
  7063. ;
  7064. var sid = 0;
  7065. class ExtendView extends View {
  7066. constructor() {
  7067. super();
  7068. this.yaw = 0; //Math.PI / 4; // = 4dkk lon + 90
  7069. this._pitch = 0; //-Math.PI / 4; //上下旋转 = 4dkk lat
  7070. this.sid = sid++;
  7071. this.LookTransition = 'LookTransition' + this.sid;
  7072. this.FlyTransition = 'FlyTransition' + this.sid;
  7073. this.freeQuaternion = new Quaternion();
  7074. }
  7075. //add------
  7076. applyToCamera(camera) {
  7077. camera.position.copy(this.position);
  7078. if (this.rotMode == 'free') {
  7079. //不受相机旋转模式限定,可以歪着,任意角度
  7080. camera.quaternion.copy(this.freeQuaternion);
  7081. } else {
  7082. camera.rotation.copy(this.rotation);
  7083. }
  7084. camera.updateMatrix();
  7085. camera.updateMatrixWorld();
  7086. //camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
  7087. }
  7088. get rotation() {
  7089. var rotation = new Euler();
  7090. rotation.order = "ZXY";
  7091. rotation.x = Math.PI / 2 + this.pitch;
  7092. rotation.z = this.yaw;
  7093. return rotation;
  7094. }
  7095. set rotation(rotation) {
  7096. if (rotation.y != 0) {
  7097. //因为 rotation的y不一定是0 , 所以不能直接逆着get rotation写。
  7098. //console.error('set rotation y不为0!!!!?', rotation ) //过渡时因为quaternion lerp所以不为0。没办法了orz
  7099. this.direction = new Vector3(0, 0, -1).applyEuler(rotation); //转回direction有损耗,在俯视时的(dir.x==dir.y==0), 丢失yaw信息从而 yaw无法获取(希望不要遇到这种情况,如果有的话,考虑先计算yaw,似乎好像可以算)
  7100. } else {
  7101. //尽量不用direction
  7102. this.pitch = rotation.x - Math.PI / 2;
  7103. this.yaw = rotation.z;
  7104. }
  7105. }
  7106. setRotMode(mode) {
  7107. if (mode == 'free') {
  7108. this.freeQuaternion.copy(this.quaternion);
  7109. }
  7110. this.rotMode = mode;
  7111. }
  7112. get quaternion() {
  7113. if (this.rotMode == 'free') {
  7114. return this.freeQuaternion;
  7115. } else {
  7116. return new Quaternion().setFromEuler(this.rotation);
  7117. }
  7118. }
  7119. set quaternion(q) {
  7120. if (this.rotMode == 'free') {
  7121. this.freeQuaternion.copy(q);
  7122. } else {
  7123. this.rotation = new Euler().setFromQuaternion(q);
  7124. }
  7125. }
  7126. copy(a) {
  7127. Common$1.CopyClassObject(this, a, {
  7128. ignoreList: ['_listeners']
  7129. });
  7130. }
  7131. clone() {
  7132. return Common$1.CloneClassObject(this, {
  7133. ignoreList: ['_listeners']
  7134. });
  7135. }
  7136. //----------
  7137. setCubeView(dir) {
  7138. switch (dir) {
  7139. case "front":
  7140. this.yaw = 0;
  7141. this.pitch = 0;
  7142. break;
  7143. case "back":
  7144. this.yaw = Math.PI;
  7145. this.pitch = 0;
  7146. break;
  7147. case "left":
  7148. this.yaw = -Math.PI / 2;
  7149. this.pitch = 0;
  7150. break;
  7151. case "right":
  7152. this.yaw = Math.PI / 2;
  7153. this.pitch = 0;
  7154. break;
  7155. case "top":
  7156. this.yaw = 0;
  7157. this.pitch = -Math.PI / 2;
  7158. break;
  7159. case "bottom":
  7160. this.yaw = -Math.PI;
  7161. this.pitch = Math.PI / 2;
  7162. break;
  7163. }
  7164. }
  7165. /* pan (x, y) {
  7166. let dir = new THREE.Vector3(0, 1, 0);
  7167. dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch);
  7168. dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  7169. // let side = new THREE.Vector3(1, 0, 0);
  7170. // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw);
  7171. let side = this.getSide();
  7172. let up = side.clone().cross(dir);
  7173. let pan = side.multiplyScalar(x).add(up.multiplyScalar(y));
  7174. this.position = this.position.add(pan);
  7175. // this.target = this.target.add(pan);
  7176. } */
  7177. pan(x, y) {
  7178. //发现pan其实就是translate
  7179. this.translate(x, 0, y);
  7180. }
  7181. translate(x, y, z, forceHorizon) {
  7182. //相机方向
  7183. var dir = new Vector3(0, 1, 0);
  7184. dir.applyAxisAngle(new Vector3(1, 0, 0), forceHorizon ? 0 : this.pitch); //上下角度
  7185. dir.applyAxisAngle(new Vector3(0, 0, 1), this.yaw); //水平角度
  7186. var side = new Vector3(1, 0, 0);
  7187. side.applyAxisAngle(new Vector3(0, 0, 1), this.yaw); //垂直于相机当前水平朝向的 左右方向
  7188. var up = side.clone().cross(dir); //垂直于相机当前水平朝向的 向上方向
  7189. var t = side.multiplyScalar(x) //x影响 左右分量
  7190. .add(dir.multiplyScalar(y)) //y影响 前后分量
  7191. .add(up.multiplyScalar(z)); //z影响 上下分量
  7192. this.position = this.position.add(t);
  7193. if ((!math.closeTo(x, 0, 1e-2) || !math.closeTo(y, 0, 1e-2) || !math.closeTo(z, 0, 1e-2)) && Potree.settings.displayMode != 'showPanos') {
  7194. this.cancelFlying('pos');
  7195. }
  7196. this.restrictPos();
  7197. }
  7198. translateWorld(x, y, z) {
  7199. super.translateWorld(x, y, z);
  7200. if ((!math.closeTo(x, 0, 1e-2) || !math.closeTo(y, 0, 1e-2) || !math.closeTo(z, 0, 1e-2)) && Potree.settings.displayMode != 'showPanos') {
  7201. this.cancelFlying('pos');
  7202. }
  7203. this.restrictPos();
  7204. }
  7205. restrictPos(position) {
  7206. //add
  7207. if (this.limitBound) {
  7208. (position || this.position).clamp(this.limitBound.min, this.limitBound.max);
  7209. }
  7210. }
  7211. isFlying() {
  7212. var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'all';
  7213. var a = transitions.getById(this.FlyTransition).length > 0;
  7214. var b = transitions.getById(this.LookTransition).length > 0;
  7215. return type == 'pos' ? a : type == 'rotate' ? b : a || b;
  7216. }
  7217. cancelFlying() {
  7218. var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'all';
  7219. var dealCancel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  7220. //外界只能通过这个来cancel
  7221. type == 'pos' ? transitions.cancelById(this.FlyTransition, dealCancel) : type == 'rotate' ? transitions.cancelById(this.LookTransition, dealCancel) : (transitions.cancelById(this.FlyTransition, dealCancel), transitions.cancelById(this.LookTransition, dealCancel));
  7222. //console.log('cancelFlying ' , this.sid, type)
  7223. }
  7224. setView() {
  7225. var info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7226. // position, target, duration = 0, callback = null, onUpdate = null, Easing='', cancelFun
  7227. this.cancelFlying();
  7228. var posWaitDone, rotWaitDone, dir;
  7229. var posDone = () => {
  7230. rotWaitDone || done();
  7231. posWaitDone = false;
  7232. };
  7233. var rotDone = () => {
  7234. if (endTarget) {
  7235. this.lookAt(endTarget); //compute radius for orbitcontrol
  7236. } else if (endQuaternion) {
  7237. this.rotation = new Euler().setFromQuaternion(endQuaternion);
  7238. }
  7239. if (endYaw != void 0) {
  7240. //前面两种在正俯视仰视时不准,故额外加一个这个
  7241. this.yaw = endYaw, this.pitch = endPitch;
  7242. }
  7243. //if(dir.x == 0 && dir.y == 0)this.yaw = 0 //统一一下 朝上的话是正的。朝下的一般不是0,会保留一个接近0的小数所以不用管
  7244. posWaitDone || done();
  7245. rotWaitDone = false;
  7246. };
  7247. var done = () => {
  7248. //一定要旋转和位移都结束了才能执行
  7249. var f = () => {
  7250. this.position.copy(endPosition); //因为延时 后control的update会导致位置改变
  7251. info.callback && info.callback();
  7252. this.dispatchEvent('flyingDone');
  7253. };
  7254. if (info.duration) {
  7255. setTimeout(f, 10); //延迟是为了使isFlying先为false 1有概率不够
  7256. } else {
  7257. f(); //有的需要迅速执行回调
  7258. }
  7259. };
  7260. var endPosition = new Vector3().copy(info.position);
  7261. var startPosition = this.position.clone();
  7262. var startQuaternion,
  7263. endQuaternion,
  7264. endTarget = info.target && new Vector3().copy(info.target),
  7265. endYaw,
  7266. startYaw,
  7267. endPitch,
  7268. startPitch;
  7269. this.restrictPos(endPosition);
  7270. if (info.endYaw == void 0) {
  7271. if (info.target) {
  7272. endQuaternion = math.getQuaFromPosAim(endPosition, endTarget); //若为垂直,会自动偏向x负的方向
  7273. } else if (info.quaternion) {
  7274. endQuaternion = info.quaternion.clone();
  7275. }
  7276. if (this.rotMode != 'free' && endQuaternion && math.closeTo(Math.abs(this.direction.z), 1, 1e-4)) {
  7277. //在垂直的视角下的quaternion刚开始突变的厉害,这时候可能渐变yaw比较好(如俯视时点击测量线)
  7278. var a = this.clone();
  7279. a.quaternion = endQuaternion;
  7280. info.endYaw = a.yaw;
  7281. info.endPitch = a.pitch;
  7282. //console.log('turn to yaw')
  7283. }
  7284. }
  7285. if (info.endYaw != void 0) {
  7286. startPitch = this.pitch;
  7287. endPitch = info.endPitch;
  7288. startYaw = this.yaw;
  7289. endYaw = info.endYaw;
  7290. if (Math.abs(startYaw - endYaw) > Math.PI) {
  7291. //如果差距大于半个圆,就要反个方向转(把大的那个数字减去360度)
  7292. startYaw > endYaw ? startYaw -= Math.PI * 2 : endYaw -= Math.PI * 2;
  7293. }
  7294. //console.log('startYaw', startYaw, 'endYaw', endYaw)
  7295. }
  7296. if (endQuaternion) {
  7297. startQuaternion = this.quaternion;
  7298. }
  7299. if (!info.duration) {
  7300. this.position.copy(endPosition);
  7301. this.restrictPos();
  7302. posWaitDone = true, rotWaitDone = true;
  7303. info.onUpdate && info.onUpdate(1);
  7304. posDone();
  7305. rotDone();
  7306. } else {
  7307. info.onUpdate && info.onUpdate(0); //初始化progress
  7308. var posChange = !this.position.equals(endPosition);
  7309. if (posChange) {
  7310. posWaitDone = true;
  7311. transitions.start(lerp.vector(this.position, endPosition, (pos, progress, delta) => {
  7312. info.onUpdate && info.onUpdate(progress, delta);
  7313. }), info.duration, posDone, 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine, null, this.FlyTransition, () => {
  7314. //中途取消
  7315. if (rotWaitDone) {
  7316. /* endPosition = new THREE.Vector3().copy(this.position)//更改旋转的endQuaternion
  7317. endQuaternion = math.getQuaFromPosAim(endPosition,endTarget) */
  7318. //直接改变endQuaternion会突变,所以还是cancel吧
  7319. this.cancelFlying('rotate');
  7320. } else {
  7321. this.dispatchEvent('flyCancel');
  7322. }
  7323. posWaitDone = false;
  7324. info.cancelFun && info.cancelFun();
  7325. }, info.ignoreFirstFrame);
  7326. }
  7327. if (endQuaternion || endYaw != void 0) {
  7328. rotWaitDone = true;
  7329. transitions.start((progress, delta) => {
  7330. if (endYaw != void 0) {
  7331. this.yaw = startYaw * (1 - progress) + endYaw * progress;
  7332. this.pitch = startPitch * (1 - progress) + endPitch * progress;
  7333. } else {
  7334. var quaternion = new Quaternion().copy(startQuaternion);
  7335. lerp.quaternion(quaternion, endQuaternion)(progress); //在垂直的视角下的角度突变的厉害,这时候可能渐变yaw比较好
  7336. this.quaternion = quaternion;
  7337. //console.log(quaternion,this.yaw)
  7338. }
  7339. posChange || info.onUpdate && info.onUpdate(progress, delta);
  7340. }, info.duration, rotDone, 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine, null, this.LookTransition, () => {
  7341. //中途取消
  7342. rotWaitDone = false;
  7343. info.cancelFun && info.cancelFun();
  7344. this.dispatchEvent('flyCancel');
  7345. }, info.ignoreFirstFrame);
  7346. }
  7347. if (!posWaitDone && !rotWaitDone) {
  7348. //已经到达目标
  7349. info.onUpdate && info.onUpdate(1);
  7350. done();
  7351. }
  7352. /* transitions.start(lerp.vector(this.position, endPosition, (pos, progress)=>{
  7353. let t = progress
  7354. if(endQuaternion){
  7355. let quaternion = (new THREE.Quaternion()).copy(startQuaternion)
  7356. lerp.quaternion(quaternion, endQuaternion)(progress),
  7357. this.rotation = new THREE.Euler().setFromQuaternion(quaternion)
  7358. }
  7359. this.restrictPos()
  7360. //console.log('setView flying')
  7361. info.onUpdate && info.onUpdate(t)//add
  7362. }), info.duration, done, 0, info.Easing ? easing[info.Easing] : easing.easeInOutSine ,null, this.LookTransition, info.cancelFun); //easeInOutQuad
  7363. */
  7364. }
  7365. }
  7366. //平移Ortho相机
  7367. moveOrthoCamera(viewport, info, duration, easeName) {
  7368. //boundSize优先于endZoom。
  7369. var camera = info.camera || viewport.camera;
  7370. var startZoom = camera.zoom;
  7371. var endPosition = info.endPosition;
  7372. var boundSize = info.boundSize;
  7373. var endZoom = info.endZoom;
  7374. var margin = info.margin || {
  7375. x: 0,
  7376. y: 0
  7377. }; /* 200 */ //像素
  7378. var _onUpdate = info.onUpdate;
  7379. if (info.bound) {
  7380. //需要修改boundSize以适应相机的旋转,当相机不在xy水平面上朝向z时
  7381. endPosition = endPosition || info.bound.getCenter(new Vector3());
  7382. var matrixRot = new Matrix4().makeRotationFromEuler(this.rotation).invert();
  7383. var boundingBox = info.bound.clone().applyMatrix4(matrixRot);
  7384. boundSize = boundingBox.getSize(new Vector3());
  7385. }
  7386. if (boundSize && boundSize.x == 0 && boundSize.y == 0) {
  7387. boundSize.set(1, 1); //避免infinity
  7388. }
  7389. this.setView(Object.assign(info, {
  7390. position: endPosition,
  7391. duration,
  7392. onUpdate: (progress, delta) => {
  7393. if (boundSize || endZoom) {
  7394. if (boundSize) {
  7395. var aspect = boundSize.x / boundSize.y;
  7396. var w, h;
  7397. if (camera.aspect > aspect) {
  7398. //视野更宽则用bound的纵向来决定
  7399. h = boundSize.y;
  7400. endZoom = (viewport.resolution.y - margin.y) / h; //注意,要在resolution不为0时执行
  7401. } else {
  7402. w = boundSize.x;
  7403. endZoom = (viewport.resolution.x - margin.x) / w;
  7404. }
  7405. //onUpdate时更新endzoom是因为画布大小可能更改
  7406. }
  7407. this.zoom = camera.zoom = endZoom * progress + startZoom * (1 - progress); //view里也加一下,有些地方需要记录,如截图
  7408. camera.updateProjectionMatrix();
  7409. _onUpdate && _onUpdate(progress, delta);
  7410. }
  7411. },
  7412. Easing: easeName
  7413. }));
  7414. }
  7415. zoomOrthoCamera(camera, endZoom, pointer, duration, onProgress) {
  7416. //定点缩放
  7417. var startZoom = camera.zoom;
  7418. var pointerPos = new Vector3(pointer.x, pointer.y, 0.5);
  7419. transitions.start(progress => {
  7420. var oldPos = pointerPos.clone().unproject(camera);
  7421. this.zoom = camera.zoom = endZoom * progress + startZoom * (1 - progress);
  7422. camera.updateProjectionMatrix();
  7423. var newPos = pointerPos.clone().unproject(camera);
  7424. //定点缩放, 恢复一下鼠标所在位置的位置改变量
  7425. var moveVec = new Vector3().subVectors(newPos, oldPos);
  7426. camera.position.sub(moveVec);
  7427. this.position.copy(camera.position);
  7428. onProgress && onProgress();
  7429. }, duration, null /* done */, 0, easing.easeInOutSine, null, "zoomInView" /* , info.cancelFun */);
  7430. }
  7431. tranCamera(viewport, info, duration, easeName) {
  7432. viewport.camera = info.midCamera;
  7433. //viewport.camera.matrixWorld = info.endCamera.matrixWorld
  7434. //viewer.setCameraMode(CameraMode.ORTHOGRAPHIC)
  7435. info.midCamera.projectionMatrix.copy(info.startCamera.projectionMatrix);
  7436. var onUpdate = info.onUpdate;
  7437. info.onUpdate = (progress, delta) => {
  7438. lerp.matrix4(info.midCamera.projectionMatrix, info.endCamera.projectionMatrix)(progress);
  7439. onUpdate && onUpdate(progress, delta);
  7440. };
  7441. var callback = info.callback;
  7442. info.callback = () => {
  7443. viewport.camera = info.endCamera;
  7444. viewer.scene.measurements.forEach(e => {
  7445. Potree.Utils.updateVisible(e, 'tranCamera', true);
  7446. });
  7447. this.applyToCamera(viewport.camera);
  7448. viewer.dispatchEvent({
  7449. type: 'camera_changed',
  7450. viewport: viewer.mainViewport,
  7451. changeInfo: {}
  7452. }); //update sprite
  7453. callback && callback();
  7454. };
  7455. //info.forbitCancel = true
  7456. info.camera = info.endCamera;
  7457. if (info.camera.type == "OrthographicCamera") {
  7458. this.moveOrthoCamera(viewport, info, duration, easeName);
  7459. } else {
  7460. this.setView(Object.assign(info, {
  7461. duration
  7462. }));
  7463. }
  7464. }
  7465. }
  7466. ;
  7467. var view = new ExtendView();
  7468. var math = {
  7469. getBaseLog(x, y) {
  7470. //返回以 x 为底 y 的对数(即 logx y) . Math.log 返回一个数的自然对数
  7471. return Math.log(y) / Math.log(x);
  7472. },
  7473. convertVector: {
  7474. ZupToYup: function ZupToYup(e) {
  7475. //navvis -> 4dkk
  7476. return new Vector3(e.x, e.z, -e.y);
  7477. },
  7478. YupToZup: function YupToZup(e) {
  7479. //4dkk -> navvis
  7480. return new Vector3(e.x, -e.z, e.y);
  7481. }
  7482. },
  7483. convertQuaternion: {
  7484. ZupToYup: function ZupToYup(e) {
  7485. //navvis -> 4dkk //不同于convertVisionQuaternion
  7486. var rotation = new Euler(-Math.PI / 2, 0, 0);
  7487. var quaternion = new Quaternion().setFromEuler(rotation);
  7488. return e.clone().premultiply(quaternion);
  7489. //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)))
  7490. },
  7491. YupToZup: function YupToZup(e) {
  7492. //4dkk -> navvis
  7493. var rotation = new Euler(Math.PI / 2, 0, 0);
  7494. var quaternion = new Quaternion().setFromEuler(rotation);
  7495. return e.clone().premultiply(quaternion);
  7496. }
  7497. },
  7498. convertVisionQuaternion: function convertVisionQuaternion(e) {
  7499. return new Quaternion(e.x, e.z, -e.y, e.w).multiply(new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), MathUtils.degToRad(90)));
  7500. },
  7501. invertVisionQuaternion: function invertVisionQuaternion(e) {
  7502. //反转给算法部
  7503. var a = e.clone().multiply(new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), MathUtils.degToRad(-90)));
  7504. return new Quaternion(a.x, -a.z, a.y, a.w);
  7505. },
  7506. //------------
  7507. getVec2Angle: function getVec2Angle(dir1, dir2) {
  7508. return Math.acos(MathUtils.clamp(this.getVec2Cos(dir1, dir2), -1, 1));
  7509. },
  7510. getVec2Cos: function getVec2Cos(dir1, dir2) {
  7511. return dir1.dot(dir2) / dir1.length() / dir2.length();
  7512. },
  7513. getAngle: function getAngle(vec1, vec2) {
  7514. var axis = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'z';
  7515. //带方向的角度 vector3
  7516. if (!vec1.isVector3) {
  7517. vec1 = new Vector3(vec1.x, vec1.y, 0);
  7518. vec2 = new Vector3(vec2.x, vec2.y, 0);
  7519. }
  7520. var angle = vec1.angleTo(vec2);
  7521. var axis_ = vec1.clone().cross(vec2);
  7522. if (typeof axis == 'string') {
  7523. if (axis_[axis] < 0) {
  7524. angle *= -1;
  7525. }
  7526. } else {
  7527. //vector3
  7528. if (axis_.dot(axis) < 0) {
  7529. angle *= -1;
  7530. }
  7531. }
  7532. return angle;
  7533. },
  7534. closeTo: function closeTo(a, b) {
  7535. var precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1e-6;
  7536. var f = (a, b) => {
  7537. return Math.abs(a - b) < precision;
  7538. };
  7539. if (typeof a == 'number') {
  7540. return f(a, b);
  7541. } else {
  7542. var judge = name => {
  7543. if (a[name] == void 0) return true; //有值就判断,没值就不判断
  7544. else return f(a[name], b[name]);
  7545. };
  7546. return judge('x') && judge('y') && judge('z') && judge('w');
  7547. }
  7548. },
  7549. toPrecision: function toPrecision(e, t) {
  7550. //xzw change 保留小数
  7551. var f = function f(e, t) {
  7552. var i = Math.pow(10, t);
  7553. return Math.round(e * i) / i;
  7554. };
  7555. if (e instanceof Array) {
  7556. for (var s = 0; s < e.length; s++) {
  7557. e[s] = f(e[s], t);
  7558. }
  7559. return e;
  7560. } else if (e instanceof Object) {
  7561. for (var s in e) {
  7562. e[s] = f(e[s], t);
  7563. }
  7564. return e;
  7565. } else if (typeof e == 'number') {
  7566. return f(e, t);
  7567. } else {
  7568. return e;
  7569. }
  7570. },
  7571. isEmptyQuaternion: function isEmptyQuaternion(e) {
  7572. return 0 === Math.abs(e.x) && 0 === Math.abs(e.y) && 0 === Math.abs(e.z) && 0 === Math.abs(e.w);
  7573. },
  7574. projectPositionToCanvas: function projectPositionToCanvas(e, t, i) {
  7575. i = i || new Vector3(), i.copy(e);
  7576. var r = .5 * $('#player').width(),
  7577. o = .5 * $('#player').height();
  7578. return i.project(t), i.x = i.x * r + r, i.y = -(i.y * o) + o, i;
  7579. },
  7580. handelPadResize: false,
  7581. /* handelPadding : function () { //去除player左边和上面的宽高,因为pc的player左上有其他element 许钟文
  7582. var pads = [];//记录下来避免反复计算
  7583. var index = [];
  7584. var resetPad = function(){
  7585. pads = [];
  7586. index = [];
  7587. math.handelPadResize = false; //switchview时resized为true
  7588. }
  7589. if(config.isEdit && !config.isMobile){
  7590. window.addEventListener('resize',resetPad);
  7591. }
  7592. return function(x, y, domE){
  7593. if(!config.isEdit || config.isMobile) {
  7594. return {
  7595. x: x,
  7596. y: y
  7597. }
  7598. }
  7599. if(this.handelPadResize)resetPad();
  7600. domE = domE || $('#player')[0];
  7601. var pad;
  7602. var i = index.indexOf(domE);
  7603. if (i == -1){
  7604. index.push(domE);
  7605. pad = {
  7606. x: this.getOffset("left", domE),
  7607. y: this.getOffset("top", domE)
  7608. }
  7609. pads.push(pad)
  7610. }
  7611. else pad = pads[i];
  7612. return {
  7613. x: x - pad.x,
  7614. y: y - pad.y
  7615. }
  7616. }
  7617. }(), */
  7618. getOffset: function getOffset(type, element, parent) {
  7619. //获取元素的边距 许钟文
  7620. var offset = type == "left" ? element.offsetLeft : element.offsetTop;
  7621. if (!parent) parent = $("body")[0];
  7622. while (element = element.offsetParent) {
  7623. if (element == parent) break;
  7624. offset += type == "left" ? element.offsetLeft : element.offsetTop;
  7625. }
  7626. return offset;
  7627. },
  7628. constrainedTurn: function constrainedTurn(e) {
  7629. var t = e % (2 * Math.PI);
  7630. return t = t > Math.PI ? t -= 2 * Math.PI : t < -Math.PI ? t += 2 * Math.PI : t;
  7631. },
  7632. getFOVDotThreshold: function getFOVDotThreshold(e) {
  7633. return Math.cos(MathUtils.degToRad(e / 2));
  7634. },
  7635. transform2DForwardVectorByCubeFace: function transform2DForwardVectorByCubeFace(e, t, i, n) {
  7636. switch (e) {
  7637. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  7638. i.set(1, t.y, t.x);
  7639. break;
  7640. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  7641. i.set(-1, t.y, -t.x);
  7642. break;
  7643. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  7644. i.set(-t.x, 1, -t.y);
  7645. break;
  7646. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  7647. i.set(-t.x, -1, t.y);
  7648. break;
  7649. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  7650. i.set(-t.x, t.y, 1);
  7651. break;
  7652. case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  7653. i.set(t.x, t.y, -1);
  7654. }
  7655. n && i.normalize();
  7656. },
  7657. getFootPoint: function getFootPoint(oldPos, p1, p2, restricInline) {
  7658. //找oldPos在线段p1, p2上的垂足
  7659. /*
  7660. let p1o = new THREE.Vector3().subVectors(o,p1)
  7661. let p1p2 = new THREE.Vector3().subVectors(p2,p1)
  7662. let p1F = p1o.projectOnVector(p1p2)
  7663. return new THREE.Vector3().addVectors(p1,p1F) */ //也可以这样
  7664. if (p1.equals(p2)) return p1.clone();
  7665. var op1 = oldPos.clone().sub(p1);
  7666. var p1p2 = p1.clone().sub(p2);
  7667. var p1p2Len = p1p2.length();
  7668. var leftLen = op1.dot(p1p2) / p1p2Len;
  7669. var pos = p1.clone().add(p1p2.multiplyScalar(leftLen / p1p2Len));
  7670. if (restricInline && pos.clone().sub(p1).dot(pos.clone().sub(p2)) > 0) {
  7671. //foot不在线段上
  7672. if (pos.distanceTo(p1) < pos.distanceTo(p2)) pos = p1.clone();else pos = p2.clone();
  7673. }
  7674. return pos;
  7675. },
  7676. /**
  7677. * 计算多边形的重心
  7678. * @param {*} points
  7679. */
  7680. getCenterOfGravityPoint: function getCenterOfGravityPoint(mPoints) {
  7681. var area = 0.0; //多边形面积
  7682. var Gx = 0.0,
  7683. Gy = 0.0; // 重心的x、y
  7684. for (var i = 1; i <= mPoints.length; i++) {
  7685. var ix = mPoints[i % mPoints.length].x;
  7686. var iy = mPoints[i % mPoints.length].y;
  7687. var nx = mPoints[i - 1].x;
  7688. var ny = mPoints[i - 1].y;
  7689. var temp = (ix * ny - iy * nx) / 2.0;
  7690. area += temp;
  7691. Gx += temp * (ix + nx) / 3.0;
  7692. Gy += temp * (iy + ny) / 3.0;
  7693. }
  7694. Gx = Gx / area;
  7695. Gy = Gy / area;
  7696. return {
  7697. x: Gx,
  7698. y: Gy
  7699. };
  7700. },
  7701. getBound: function getBound(ring) {
  7702. var bound = new Box2();
  7703. for (var j = 0, len = ring.length; j < len; j++) {
  7704. bound.expandByPoint(ring[j]);
  7705. }
  7706. return bound;
  7707. },
  7708. isPointInArea: function isPointInArea(ring, holes, point, ifAtLine) {
  7709. //判断点是否在某个环内, 若传递了holes代表还要不能在内环内
  7710. var bound = this.getBound(ring);
  7711. if (point.x < bound.min.x || point.x > bound.max.x || point.y < bound.min.y || point.y > bound.max.y) return false;
  7712. var inside = false;
  7713. var x = point.x,
  7714. y = point.y;
  7715. for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
  7716. var xi = ring[i].x,
  7717. yi = ring[i].y;
  7718. var xj = ring[j].x,
  7719. yj = ring[j].y;
  7720. if ((xi - x) * (yj - y) == (xi - x) * (yi - y) && x >= Math.min(xi, xj) && x <= Math.max(xi, xj) //xzw add
  7721. && y >= Math.min(yi, yj) && y <= Math.max(yi, yj)) {
  7722. //return !!ifAtLine;//在线段上,则判断为…… (默认在外)
  7723. return {
  7724. atLine: true
  7725. };
  7726. }
  7727. if (yi > y != yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
  7728. inside = !inside;
  7729. }
  7730. }
  7731. if (inside && holes) {
  7732. return !holes.some(ring => this.isPointInArea(ring, null, point, ifAtLine)); //不能存在于任何一个二级内环内
  7733. } else {
  7734. return inside;
  7735. }
  7736. },
  7737. getArea: function getArea(ring) {
  7738. //求面积 顺时针为正 来自three shape
  7739. for (var t = ring.length, i = 0, n = t - 1, r = 0; r < t; n = r++) i += ring[n].x * ring[r].y - ring[r].x * ring[n].y;
  7740. return -.5 * i;
  7741. },
  7742. getVolume: function getVolume(faceArr) {//求三角多面体的体积。和求面积同理都用鞋带计算法 https://blog.csdn.net/weixin_43414513/article/details/123758897
  7743. //问题:怎么确定方向
  7744. //每个三角形的顺序必须是右手螺旋法则指向物体外(外向里看为逆时针),分别为ABC,则每个三角形和原点O构成的三棱锥体积为 (OA cross OB) dot(OC) / 6 . 结果一般朝向原点的为负,反之为正
  7745. },
  7746. isInBetween: function isInBetween(a, b, c, precision) {
  7747. // 如果b几乎等于a或c,返回false.为了避免浮点运行时两值几乎相等,但存在相差0.00000...0001的这种情况出现使用下面方式进行避免
  7748. /* if (Math.abs(a - b) < 0.000001 || Math.abs(b - c) < 0.000001) {
  7749. return false;
  7750. }
  7751. return (a <= b && b <= c) || (c <= b && b <= a);*/
  7752. //更改:如果b和a或c中一个接近 就算在a和c之间
  7753. return a <= b && b <= c || c <= b && b <= a || this.closeTo(a, b, precision) || this.closeTo(b, c, precision);
  7754. },
  7755. ifPointAtLineBound: function ifPointAtLineBound(point, linePoints, precision) {
  7756. //待验证 横线和竖线比较特殊
  7757. return math.isInBetween(linePoints[0].x, point.x, linePoints[1].x, precision) && math.isInBetween(linePoints[0].y, point.y, linePoints[1].y, precision);
  7758. },
  7759. isLineIntersect: function isLineIntersect(line1, line2, notSegment, precision) {
  7760. //线段和线段是否有交点. notSegment代表是直线而不是线段
  7761. var a1 = line1[1].y - line1[0].y;
  7762. var b1 = line1[0].x - line1[1].x;
  7763. var c1 = a1 * line1[0].x + b1 * line1[0].y;
  7764. //转换成一般式: Ax+By = C
  7765. var a2 = line2[1].y - line2[0].y;
  7766. var b2 = line2[0].x - line2[1].x;
  7767. var c2 = a2 * line2[0].x + b2 * line2[0].y;
  7768. // 计算交点
  7769. var d = a1 * b2 - a2 * b1;
  7770. // 当d==0时,两线平行
  7771. if (d == 0) {
  7772. return false;
  7773. } else {
  7774. var x = (b2 * c1 - b1 * c2) / d;
  7775. var y = (a1 * c2 - a2 * c1) / d;
  7776. // 检测交点是否在两条线段上
  7777. /* if (notSegment || (isInBetween(line1[0].x, x, line1[1].x) || isInBetween(line1[0].y, y, line1[1].y)) &&
  7778. (isInBetween(line2[0].x, x, line2[1].x) || isInBetween(line2[0].y, y, line2[1].y))) {
  7779. return {x,y};
  7780. } */
  7781. if (notSegment || math.ifPointAtLineBound({
  7782. x,
  7783. y
  7784. }, line1, precision) && math.ifPointAtLineBound({
  7785. x,
  7786. y
  7787. }, line2, precision)) {
  7788. return {
  7789. x,
  7790. y
  7791. };
  7792. }
  7793. }
  7794. },
  7795. getNormal2d: function getNormal2d() {
  7796. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7797. //获取二维法向量 方向向内
  7798. var x, y, x1, y1;
  7799. //line2d的向量
  7800. if (o.vec) {
  7801. x1 = o.vec.x;
  7802. y1 = o.vec.y;
  7803. } else {
  7804. x1 = o.p1.x - o.p2.x;
  7805. y1 = o.p1.y - o.p2.y;
  7806. }
  7807. //假设法向量的x或y固定为1或-1
  7808. if (y1 != 0) {
  7809. x = 1;
  7810. y = -(x1 * x) / y1;
  7811. } else if (x1 != 0) {
  7812. //y如果为0,正常情况x不会是0
  7813. y = 1;
  7814. x = -(y1 * y) / x1;
  7815. } else {
  7816. console.log("两个点一样");
  7817. return null;
  7818. }
  7819. //判断方向里或者外:
  7820. var vNormal = new Vector3(x, 0, y);
  7821. var vLine = new Vector3(x1, 0, y1);
  7822. var vDir = vNormal.cross(vLine);
  7823. if (vDir.y > 0) {
  7824. x *= -1;
  7825. y *= -1;
  7826. }
  7827. return new Vector2(x, y).normalize();
  7828. },
  7829. getQuaBetween2Vector: function getQuaBetween2Vector(oriVec, newVec, upVec) {
  7830. //获取从oriVec旋转到newVec可以应用的quaternion
  7831. var angle = oriVec.angleTo(newVec);
  7832. var axis = oriVec.clone().cross(newVec).normalize(); //两个up之间
  7833. if (axis.length() == 0) {
  7834. //当夹角为180 或 0 度时,得到的axis为(0,0,0),故使用备用的指定upVec
  7835. return new Quaternion().setFromAxisAngle(upVec, angle);
  7836. }
  7837. return new Quaternion().setFromAxisAngle(axis, angle);
  7838. },
  7839. /*
  7840. getQuaBetween2Vector2 : function(oriVec, newVec ){//not camera
  7841. var _ = (new THREE.Matrix4).lookAt( oriVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
  7842. var aimQua = (new THREE.Quaternion).setFromRotationMatrix(_)
  7843. var _2 = (new THREE.Matrix4).lookAt( newVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
  7844. var aimQua2 = (new THREE.Quaternion).setFromRotationMatrix(_2)
  7845. return aimQua2.multiply(aimQua.clone().inverse())
  7846. } */
  7847. getQuaByAim: function getQuaByAim(aim) {
  7848. var center = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Vector3();
  7849. var forward = new Vector3(0, 1, 0);
  7850. var qua1 = new Quaternion().setFromUnitVectors(forward, aim.clone().sub(center).normalize());
  7851. /* var _ = (new THREE.Matrix4).lookAt(center,aim, new THREE.Vector3(0,1,0));
  7852. let qua2 = (new THREE.Quaternion).setFromRotationMatrix(_);
  7853. let rot1 = new THREE.Euler().setFromQuaternion(qua1)
  7854. let rot2 = new THREE.Euler().setFromQuaternion(qua2) //奇怪,qua2怎么都不对
  7855. console.log(rot1,rot2) */
  7856. return qua1;
  7857. },
  7858. getAimByQua: function getAimByQua(quaternion) {
  7859. var center = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Vector3();
  7860. return new Vector3(0, 0, -1).applyQuaternion(quaternion).add(center);
  7861. },
  7862. getScaleForConstantSize: function () {
  7863. //获得规定二维大小的mesh的scale值。可以避免因camera的projection造成的mesh视觉大小改变。 来源:tag.updateDisc
  7864. var w;
  7865. var i = new Vector3(),
  7866. o = new Vector3(),
  7867. l = new Vector3(),
  7868. c = new Vector3(),
  7869. h = new Vector3();
  7870. return function () {
  7871. var op = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7872. if (op.width2d) w = op.width2d; //如果恒定二维宽度
  7873. else {
  7874. //否则考虑上距离,加一丢丢近大远小的效果
  7875. var currentDis, nearBound, farBound;
  7876. if (op.camera.type == "OrthographicCamera") {
  7877. currentDis = 200 / op.camera.zoom; //(op.camera.right - op.camera.left) / op.camera.zoom
  7878. } else {
  7879. currentDis = op.position.distanceTo(op.camera.position);
  7880. }
  7881. w = op.maxSize - (op.maxSize - op.minSize) * MathUtils.smoothstep(currentDis, op.nearBound, op.farBound);
  7882. //maxSize : mesh要表现的最大像素宽度; nearBound: 最近距离,若比nearBound近,则使用maxSize
  7883. }
  7884. i.copy(op.position).project(op.camera); //tag中心在屏幕上的二维坐标
  7885. o.set(op.resolution.x / 2, op.resolution.y / 2, 1).multiply(i); //转化成px -w/2 到 w/2的范围
  7886. l.set(w / 2, 0, 0).add(o); //加上tag宽度的一半
  7887. c.set(2 / op.resolution.x, 2 / op.resolution.y, 1).multiply(l); //再转回 -1 到 1的范围
  7888. h.copy(c).unproject(op.camera); //再转成三维坐标,求得tag边缘的位置
  7889. var g = h.distanceTo(op.position); //就能得到tag的三维半径
  7890. //这里使用的都是resolution2, 好处是手机端不会太小, 坏处是pc更改网页显示百分比时显示的大小会变(或许可以自己算出设备真实的deviceRatio, 因window.screen是不会改变的),但考虑到用户可以自行调节字大小也许是好的
  7891. return g; //可能NAN 当相机和position重叠时
  7892. };
  7893. }(),
  7894. //W , H, left, top分别是rect的宽、高、左、上
  7895. getCrossPointAtRect: function getCrossPointAtRect(p1, aim, W, H, left, top) {
  7896. //求射线p1-aim在rect边界上的交点,其中aim在rect范围内,p1则不一定(交点在aim这边的延长线上)
  7897. var x, y, borderX;
  7898. var r = (aim.x - p1.x) / (aim.y - p1.y); //根据相似三角形原理先求出这个比值
  7899. var getX = function getX(y) {
  7900. return r * (y - p1.y) + p1.x;
  7901. };
  7902. var getY = function getY(x) {
  7903. return 1 / r * (x - p1.x) + p1.y;
  7904. };
  7905. if (aim.x >= p1.x) {
  7906. borderX = W + left;
  7907. } else {
  7908. borderX = left;
  7909. }
  7910. x = borderX;
  7911. y = getY(x);
  7912. if (y < top || y > top + H) {
  7913. if (y < top) {
  7914. y = top;
  7915. } else {
  7916. y = top + H;
  7917. }
  7918. x = getX(y);
  7919. }
  7920. return new Vector2(x, y);
  7921. },
  7922. getDirFromUV: function getDirFromUV(uv) {
  7923. //获取dir 反向计算 - - 二维转三维比较麻烦
  7924. var dirB; //所求 单位向量
  7925. var y = Math.cos(uv.y * Math.PI); //uv中纵向可以直接确定y, 根据上面getUVfromDir的反向计算
  7926. // 故 uv.y * Math.PI 就是到垂直线(向上)的夹角
  7927. var angle = 2 * Math.PI * uv.x - Math.PI; //x/z代表的是角度
  7928. var axisX, axisZ; //axis为1代表是正,-1是负数
  7929. if (-Math.PI <= angle && angle < 0) {
  7930. axisX = -1; //下半圆
  7931. } else {
  7932. axisX = 1; //上半圆
  7933. }
  7934. if (-Math.PI / 2 <= angle && angle < Math.PI / 2) {
  7935. axisZ = 1; //右半圆
  7936. } else {
  7937. axisZ = -1; //左半圆
  7938. }
  7939. var XDivideZ = Math.tan(angle);
  7940. var z = Math.sqrt((1 - y * y) / (1 + XDivideZ * XDivideZ));
  7941. var x = XDivideZ * z;
  7942. if (z * axisZ < 0) {
  7943. //异号
  7944. z *= -1;
  7945. x *= -1;
  7946. if (x * axisX < 0) {
  7947. // console.log("wrong!!!!!??????????")
  7948. }
  7949. }
  7950. x *= -1; //计算完成后这里不能漏掉 *= -1
  7951. dirB = this.convertVector.YupToZup(new Vector3(x, y, z));
  7952. //理想状态下x和z和anotherDir相同
  7953. return dirB;
  7954. },
  7955. getUVfromDir: function getUVfromDir(dir) {
  7956. //获取UV 同shader里的计算
  7957. var dir = this.convertVector.ZupToYup(dir);
  7958. dir.x *= -1; //计算前这里不能漏掉 *= -1 见shader
  7959. var tx = Math.atan2(dir.x, dir.z) / (Math.PI * 2.0) + 0.5; //atan2(y,x) 返回从 X 轴正向逆时针旋转到点 (x,y) 时经过的角度。区间是-PI 到 PI 之间的值
  7960. var ty = Math.acos(dir.y) / Math.PI;
  7961. return new Vector2(tx, ty);
  7962. //理想状态下tx相同
  7963. },
  7964. getDirByLonLat: function getDirByLonLat(lon, lat) {
  7965. var dir = new Vector3();
  7966. var phi = MathUtils.degToRad(90 - lat);
  7967. var theta = MathUtils.degToRad(lon);
  7968. dir.x = Math.sin(phi) * Math.cos(theta);
  7969. dir.y = Math.cos(phi);
  7970. dir.z = Math.sin(phi) * Math.sin(theta);
  7971. return dir;
  7972. } //0,0 => (1,0,0) 270=>(0,0,-1)
  7973. ,
  7974. projectPointAtPlane: function projectPointAtPlane() {
  7975. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  7976. //获取一个点在一个面上的投影 {facePoints:[a,b,c], point:}
  7977. var plane = new Plane().setFromCoplanarPoints(...o.facePoints);
  7978. return plane.projectPoint(o.point, new Vector3());
  7979. },
  7980. getPolygonsMixedRings: function getPolygonsMixedRings(polygons, onlyGetOutRing) {
  7981. //{points:[vector2,...],holes:[[],[]]}
  7982. var points = [];
  7983. var lines = [];
  7984. var i = 0;
  7985. polygons.forEach(e => points.push(...e.map(a => new Vector2().copy(a))));
  7986. polygons.forEach((ps, j) => {
  7987. var length = ps.length;
  7988. var index = 0;
  7989. while (index < length) {
  7990. lines.push({
  7991. p1: index + i,
  7992. p2: (index + 1) % length + i
  7993. });
  7994. index++;
  7995. }
  7996. i += length;
  7997. });
  7998. points.forEach((p, j) => {
  7999. p.id = j;
  8000. });
  8001. var rings = searchRings({
  8002. points,
  8003. lines,
  8004. onlyGetOutRing
  8005. });
  8006. //console.log(rings)
  8007. rings = rings.filter(e => e.closetParent == void 0); // 子环不加,被外环包含了
  8008. return rings;
  8009. },
  8010. getQuaFromPosAim(position, target) {
  8011. /* let matrix = (new THREE.Matrix4).lookAt(position, target, new THREE.Vector3(0,0,1)) //这里垂直的话会默认给一个右向所以不这么写
  8012. return (new THREE.Quaternion).setFromRotationMatrix(matrix) */
  8013. view.direction = new Vector3().subVectors(target, position);
  8014. return view.quaternion;
  8015. },
  8016. getYawPitchByQua(qua) {
  8017. view.quaternion = qua;
  8018. return {
  8019. yaw: view.yaw,
  8020. pitch: view.pitch
  8021. };
  8022. },
  8023. getBoundByPoints(points, minSize) {
  8024. var bound = new Box3();
  8025. points.forEach(point => {
  8026. bound.expandByPoint(point);
  8027. });
  8028. var center = bound.getCenter(new Vector3());
  8029. if (minSize) {
  8030. var minBound = new Box3().setFromCenterAndSize(center, minSize);
  8031. bound.union(minBound);
  8032. }
  8033. return {
  8034. bounding: bound,
  8035. size: bound.getSize(new Vector3()),
  8036. center
  8037. };
  8038. },
  8039. /* linearClamp(value, x1,x2, y1, y2){//x为bound.min, bound.max
  8040. value = THREE.Math.clamp(value, x1,x2)
  8041. return y1 + ( y2 - y1) * (value - x1) / (x2 - x1)
  8042. } */
  8043. linearClamp(value, xArr, yArr) {
  8044. //xArr需要按顺序从小到大,yArr对应xArr中的值
  8045. var len = xArr.length;
  8046. if (value <= xArr[0]) return yArr[0];
  8047. if (value >= xArr[len - 1]) return yArr[len - 1];
  8048. var i = 0;
  8049. while (++i < len) {
  8050. if (value < xArr[i]) {
  8051. var x1 = xArr[i - 1],
  8052. x2 = xArr[i],
  8053. y1 = yArr[i - 1],
  8054. y2 = yArr[i];
  8055. value = y1 + (y2 - y1) * (value - x1) / (x2 - x1);
  8056. break;
  8057. }
  8058. }
  8059. return value;
  8060. },
  8061. getKelvinFromCelsius(c) {
  8062. //摄氏度->开尔文
  8063. return c + 273.1; //273.15 算法的值是整数然后除以10所以只保留一位小数
  8064. },
  8065. getCelsiusFromKelvin(c) {
  8066. return c - 273.1;
  8067. },
  8068. fromCes(cartesian, getLonlat) {
  8069. var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
  8070. var lng = Cesium.Math.toDegrees(cartographic.longitude);
  8071. var lat = Cesium.Math.toDegrees(cartographic.latitude);
  8072. var height = cartographic.height;
  8073. var loc = new Vector3(lng, lat, height);
  8074. if (getLonlat) return loc;
  8075. return viewer.transform.lonlatToLocal.forward(loc);
  8076. },
  8077. toCes(pos) {
  8078. var xy = [pos.x, pos.y];
  8079. var height = pos.z;
  8080. var deg = viewer.transform.lonlatToLocal.inverse(xy); // toMap.forward(xy);
  8081. var cPos = Cesium.Cartesian3.fromDegrees(...deg, height); //console.log('toCes',cPos,height) //数字过大如e35会崩溃
  8082. return cPos;
  8083. }
  8084. };
  8085. /*
  8086. 如何将若干个点拟合出线段
  8087. // 假设你有一个点数组,每个点表示为一个包含x和y坐标的对象
  8088. const points = [
  8089. { x: 1, y: 2 },
  8090. { x: 2, y: 3 },
  8091. { x: 3, y: 4 },
  8092. { x: 4, y: 5 },
  8093. // ... 更多点
  8094. ];
  8095. // 定义用于计算最小二乘法参数的函数
  8096. function leastSquares( ) {
  8097. let sumX = 0;
  8098. let sumY = 0;
  8099. let sumXY = 0;
  8100. let sumX2 = 0;
  8101. let n = points.length;
  8102. for (const point of points) {
  8103. sumX += point.x;
  8104. sumY += point.y;
  8105. sumXY += point.x * point.y;
  8106. sumX2 += point.x * point.x;
  8107. }
  8108. const k = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); //不知道为何这样算,自己解不出来(使点到直线距离之和平方最小),但测了下似乎是准的
  8109. const b = (sumY - k * sumX) / n;
  8110. return { k, b };
  8111. }
  8112. // 使用上述函数计算拟合直线的参数
  8113. const { k, b } = leastSquares(points);
  8114. // 现在你可以使用这些参数来表示拟合出的线段
  8115. console.log(`拟合线段的方程为: y = ${k}x + ${b}`);
  8116. */
  8117. Potree.math = math;
  8118. function mobileVersion(e, t) {
  8119. //ios的版本
  8120. var i = window.navigator.userAgent,
  8121. n = i.match(e);
  8122. return n = n ? n[1].split(t) : [], {
  8123. major: parseInt(n[0]) || 0,
  8124. minor: parseInt(n[1]) || 0,
  8125. patch: parseInt(n[2]) || 0
  8126. };
  8127. }
  8128. var browser = {
  8129. isFullscreen: function isFullscreen() {
  8130. return document.fullscreenElement || document.mozFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
  8131. },
  8132. supportsFullscreen: function supportsFullscreen() {
  8133. return document.fullscreenEnabled || document.mozFullscreenEnabled || document.mozFullScreenEnabled || document.webkitFullscreenEnabled || document.msFullscreenEnabled;
  8134. },
  8135. isPointerLocked: function isPointerLocked() {
  8136. return document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement;
  8137. },
  8138. requestFullscreen: function requestFullscreen(dom, t) {
  8139. dom.requestFullscreen ? dom.requestFullscreen() : dom.mozRequestFullScreen ? dom.mozRequestFullScreen() : dom.webkitRequestFullscreen ? dom.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT) : dom.msRequestFullscreen && dom.msRequestFullscreen(), t && $(document).on("fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange", browser.requestPointerLock);
  8140. },
  8141. requestPointerLock: function requestPointerLock() {
  8142. var e;
  8143. if (document.fullscreenElement) e = document.fullscreenElement();else if (document.mozFullscreenElement) e = document.mozFullscreenElement();else if (document.mozFullScreenElement) e = document.mozFullScreenElement();else {
  8144. if (!document.webkitFullscreenElement) return;
  8145. e = document.webkitFullscreenElement();
  8146. }
  8147. ;
  8148. e.requestPointerLock = e.requestPointerLock || e.mozRequestPointerLock || e.webkitRequestPointerLock, e.requestPointerLock(), $(document).off("fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange", this);
  8149. },
  8150. exitPointerLock: function exitPointerLock() {
  8151. ;
  8152. document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock, document.exitPointerLock();
  8153. },
  8154. exitFullscreen: function exitFullscreen() {
  8155. document.exitFullscreen ? document.exitFullscreen() : document.msExitFullscreen ? document.msExitFullscreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.webkitExitFullscreen && document.webkitExitFullscreen();
  8156. },
  8157. details: function details() {
  8158. var e = navigator.userAgent.match("(Firefox|Chrome|Safari)/([\\d]+)");
  8159. return e ? {
  8160. name: e[1],
  8161. version: parseInt(e[2]),
  8162. platform: navigator.platform
  8163. } : {};
  8164. },
  8165. is: function is(e) {
  8166. return this.details() && this.details().name === e;
  8167. },
  8168. inIframe: function inIframe() {
  8169. return window.parent !== window;
  8170. },
  8171. aspectRatio: function aspectRatio($elem) {
  8172. $elem = $elem || $("#player");
  8173. var e = $elem.width() / $elem.height();
  8174. return isFinite(e) ? e : 0;
  8175. },
  8176. userAgent: function userAgent() {
  8177. return window.navigator.userAgent;
  8178. },
  8179. isMobile: function isMobile() {
  8180. var e = navigator.userAgent || navigator.vendor || window.opera;
  8181. return /(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(e) || /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(e.substr(0, 4));
  8182. },
  8183. isLandscape: function isLandscape() {
  8184. return this.isMobile && this.aspectRatio() > 1;
  8185. },
  8186. isSmallScreen: function isSmallScreen() {
  8187. var e = screen.width / window.devicePixelRatio;
  8188. return e < 240;
  8189. },
  8190. detectIE: function detectIE() {
  8191. var e = window.navigator.userAgent,
  8192. t = e.indexOf("MSIE ");
  8193. return t !== -1 || !!navigator.userAgent.match(/Trident.*rv\:11\./);
  8194. },
  8195. detectSafari: function detectSafari() {
  8196. var e = window.navigator.userAgent,
  8197. t = e.indexOf("Safari");
  8198. return t !== -1 && !this.detectOpera() && !this.detectChrome(); //xzw add detectOpera
  8199. },
  8200. detectFirefox: function detectFirefox() {
  8201. var e = window.navigator.userAgent;
  8202. return e.indexOf("Firefox") !== -1;
  8203. },
  8204. detectChrome: function detectChrome() {
  8205. var e = window.navigator.userAgent;
  8206. return e.indexOf("Chrome") !== -1 && !this.detectOpera();
  8207. },
  8208. detectOpera: function detectOpera() {
  8209. var e = window.navigator.userAgent;
  8210. return e.indexOf("OPR") !== -1;
  8211. },
  8212. detectIOS: function detectIOS() {
  8213. return this.detectIPhone() || this.detectIPad() || this.detectIPod();
  8214. },
  8215. detectIPad: function detectIPad() {
  8216. var e = window.navigator.userAgent,
  8217. t = /iPad/;
  8218. return t.test(e);
  8219. },
  8220. detectIPod: function detectIPod() {
  8221. var e = window.navigator.userAgent,
  8222. t = /iPod/;
  8223. return t.test(e);
  8224. },
  8225. detectIPhone: function detectIPhone() {
  8226. var e = window.navigator.userAgent,
  8227. t = /iPhone/;
  8228. return t.test(e);
  8229. },
  8230. detectAndroid: function detectAndroid() {
  8231. var e = window.navigator.userAgent;
  8232. return e.indexOf("Android") !== -1;
  8233. },
  8234. detectAndroidMobile: function detectAndroidMobile() {
  8235. var e = window.navigator.userAgent;
  8236. return this.detectAndroid() && e.indexOf("Mobile") !== -1;
  8237. },
  8238. detectSamsungNative: function detectSamsungNative() {
  8239. var e = window.navigator.userAgent;
  8240. return e.indexOf("SM-G900H") !== -1 || e.indexOf("GT-I9500") !== -1 || e.indexOf("SM-N900") !== -1;
  8241. },
  8242. detectSamsungS6: function detectSamsungS6() {
  8243. var e = window.navigator.userAgent;
  8244. return e.indexOf("SM-G92") !== -1;
  8245. },
  8246. /************************************************************徐世廷*************************************************************/
  8247. detectHUAWEI5X: function detectHUAWEI5X() {
  8248. return -1 !== window.navigator.userAgent.indexOf("KIW-TL00H");
  8249. },
  8250. /*******************************************************************************************************************************/
  8251. detectWebVR: function detectWebVR() {
  8252. return !(!window.navigator.getVRDisplays || !window.VRDisplay);
  8253. },
  8254. getVRDisplay: function getVRDisplay() {
  8255. var e = $.Deferred();
  8256. return this.detectWebVR() ? (navigator.getVRDisplays().then(function (t) {
  8257. t.length >= 1 && e.resolve(t[0]), e.reject(null);
  8258. }), e) : e.reject(null);
  8259. },
  8260. iosVersion: function iosVersion() {
  8261. if (!this.detectIOS()) throw new DeviceMismatchException("Did not detect an iDevice");
  8262. var e = /((?:\d+\_?){1,3}) like Mac OS/,
  8263. t = "_";
  8264. return mobileVersion(e, t);
  8265. },
  8266. androidVersion: function androidVersion() {
  8267. if (!this.detectAndroid()) throw new DeviceMismatchException("Did not detect an Android based device");
  8268. var e = /Android ((?:\d+\.?){1,3})/,
  8269. t = ".";
  8270. return mobileVersion(e, t);
  8271. },
  8272. valueFromCookie: function valueFromCookie(e, t) {
  8273. var i = new RegExp(e + "=([0-9a-f]+)(; ?|$)").exec(document.cookie);
  8274. if (!i) return t;
  8275. var n = i[1];
  8276. return "boolean" == typeof t ? "true" === n || "1" === n : "number" == typeof t ? parseFloat(n) : n;
  8277. },
  8278. valueFromHash: function valueFromHash(e, t) {
  8279. var i = new RegExp("[#&?]" + e + "=([^#&?]*)"),
  8280. n = i.exec(window.location.href);
  8281. if (!n) return t;
  8282. var r = n[1];
  8283. return "boolean" == typeof t ? "true" === r || "1" === r : "number" == typeof t ? parseFloat(r) : window.decodeURIComponent(r);
  8284. },
  8285. //-------许钟文:-------------------------------------------------
  8286. getProjectNum: function getProjectNum() {
  8287. //获取场景projectNum
  8288. if (window.__ProjectNum && window.__ProjectNum != "__ProjectNum__") {
  8289. return window.__ProjectNum;
  8290. }
  8291. var number = window.location.href.substring(window.location.href.indexOf("=") + 1);
  8292. if (number.indexOf("&") != -1) {
  8293. number = number.substring(0, number.indexOf("&"));
  8294. }
  8295. if (number.indexOf("#") != -1) {
  8296. number = number.substring(0, number.indexOf("#"));
  8297. }
  8298. return number;
  8299. },
  8300. urlHasValue: function urlHasValue(key, isGetValue) {
  8301. var querys = window.location.search.substr(1).split("&");
  8302. if (isGetValue) {
  8303. for (var i = 0; i < querys.length; i++) {
  8304. var keypair = querys[i].split("=");
  8305. if (keypair.length === 2 && keypair[0] === key) {
  8306. return keypair[1];
  8307. }
  8308. }
  8309. return "";
  8310. } else {
  8311. for (var _i = 0; _i < querys.length; _i++) {
  8312. var _keypair = querys[_i].split("=");
  8313. if (_keypair[0] == key) {
  8314. return true;
  8315. }
  8316. }
  8317. return false;
  8318. }
  8319. },
  8320. /**
  8321. * 获取查询参数的值
  8322. * @param {String} key
  8323. * @returns String
  8324. */
  8325. urlQueryValue(key) {
  8326. return this.urlHasValue(key, true) || "";
  8327. },
  8328. /**
  8329. * 判断是否存在hash
  8330. * @param {String} key
  8331. * @returns Boolean
  8332. */
  8333. urlIsHasHash(key) {
  8334. var querys = window.location.hash.substr(1).replace('/?', '').split("&");
  8335. return querys.includes(key);
  8336. },
  8337. islongPhone: function islongPhone() {
  8338. //是否是刘海全面屏幕 仅仅根据比例判断 - -
  8339. //screen.height == 812 && screen.width == 375)
  8340. var r = screen.height / screen.width; //可能横屏
  8341. return this.isMobile() && (r > 1.99 || r < 0.502512); //18/9=2.165 //???
  8342. },
  8343. detectWeixin: function detectWeixin() {
  8344. //微信 包括PC的微信
  8345. return window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == "micromessenger";
  8346. },
  8347. detectWeixinMiniProgram: function detectWeixinMiniProgram() {
  8348. return window.navigator.userAgent.match("miniProgram");
  8349. },
  8350. detectEdge: function detectEdge() {
  8351. return window.navigator.userAgent.indexOf("Edge") > -1;
  8352. },
  8353. detectApp: function detectApp() {
  8354. return this.urlHasValue("app");
  8355. },
  8356. /**
  8357. * 判断标签页是否切换状态
  8358. */
  8359. isTabHidden: function isTabHidden() {
  8360. var prefixes = ["webkit", "moz", "ms", "o"];
  8361. if ("hidden" in document) return document.hidden;
  8362. for (var i = 0; i < prefixes.length; i++) {
  8363. if (prefixes[i] + "Hidden" in document) return document[prefixes[i] + "Hidden"];
  8364. }
  8365. return false;
  8366. },
  8367. maybeQilin() {
  8368. //可能是银河麒麟桌面系统,webgl容易出bug 2024.10
  8369. return window.navigator.userAgent.toLowerCase().includes('linux');
  8370. }
  8371. };
  8372. WebGLRenderer.prototype.paramThreeToGL = function (e) {
  8373. var t,
  8374. i = this.extensions,
  8375. r = this.getContext();
  8376. //context;
  8377. if (e === RepeatWrapping) return r.REPEAT;
  8378. if (e === ClampToEdgeWrapping) return r.CLAMP_TO_EDGE;
  8379. if (e === MirroredRepeatWrapping) return r.MIRRORED_REPEAT;
  8380. if (e === NearestFilter) return r.NEAREST;
  8381. if (e === NearestMipMapNearestFilter) return r.NEAREST_MIPMAP_NEAREST;
  8382. if (e === NearestMipMapLinearFilter) return r.NEAREST_MIPMAP_LINEAR;
  8383. if (e === LinearFilter) return r.LINEAR;
  8384. if (e === LinearMipMapNearestFilter) return r.LINEAR_MIPMAP_NEAREST;
  8385. if (e === LinearMipMapLinearFilter) return r.LINEAR_MIPMAP_LINEAR;
  8386. if (e === UnsignedByteType) return r.UNSIGNED_BYTE;
  8387. if (e === UnsignedShort4444Type) return r.UNSIGNED_SHORT_4_4_4_4;
  8388. if (e === UnsignedShort5551Type) return r.UNSIGNED_SHORT_5_5_5_1;
  8389. if (e === UnsignedShort565Type) return r.UNSIGNED_SHORT_5_6_5;
  8390. if (e === ByteType) return r.BYTE;
  8391. if (e === ShortType) return r.SHORT;
  8392. if (e === UnsignedShortType) return r.UNSIGNED_SHORT;
  8393. if (e === IntType) return r.INT;
  8394. if (e === UnsignedIntType) return r.UNSIGNED_INT;
  8395. if (e === FloatType) return r.FLOAT;
  8396. if (t = i.get("OES_texture_half_float"), null !== t && e === HalfFloatType) return t.HALF_FLOAT_OES;
  8397. if (e === AlphaFormat) return r.ALPHA;
  8398. if (e === RGBFormat) return r.RGB;
  8399. if (e === RGBAFormat) return r.RGBA;
  8400. if (e === LuminanceFormat) return r.LUMINANCE;
  8401. if (e === LuminanceAlphaFormat) return r.LUMINANCE_ALPHA;
  8402. if (e === AddEquation) return r.FUNC_ADD;
  8403. if (e === SubtractEquation) return r.FUNC_SUBTRACT;
  8404. if (e === ReverseSubtractEquation) return r.FUNC_REVERSE_SUBTRACT;
  8405. if (e === ZeroFactor) return r.ZERO;
  8406. if (e === OneFactor) return r.ONE;
  8407. if (e === SrcColorFactor) return r.SRC_COLOR;
  8408. if (e === OneMinusSrcColorFactor) return r.ONE_MINUS_SRC_COLOR;
  8409. if (e === SrcAlphaFactor) return r.SRC_ALPHA;
  8410. if (e === OneMinusSrcAlphaFactor) return r.ONE_MINUS_SRC_ALPHA;
  8411. if (e === DstAlphaFactor) return r.DST_ALPHA;
  8412. if (e === OneMinusDstAlphaFactor) return r.ONE_MINUS_DST_ALPHA;
  8413. if (e === DstColorFactor) return r.DST_COLOR;
  8414. if (e === OneMinusDstColorFactor) return r.ONE_MINUS_DST_COLOR;
  8415. if (e === SrcAlphaSaturateFactor) return r.SRC_ALPHA_SATURATE;
  8416. if (t = i.get("WEBGL_compressed_texture_s3tc"), null !== t) {
  8417. if (e === RGB_S3TC_DXT1_Format) return t.COMPRESSED_RGB_S3TC_DXT1_EXT;
  8418. if (e === RGBA_S3TC_DXT1_Format$1) return t.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  8419. if (e === RGBA_S3TC_DXT3_Format) return t.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  8420. if (e === RGBA_S3TC_DXT5_Format$1) return t.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  8421. }
  8422. if (t = i.get("WEBGL_compressed_texture_pvrtc"), null !== t) {
  8423. if (e === RGB_PVRTC_4BPPV1_Format) return t.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  8424. if (e === RGB_PVRTC_2BPPV1_Format) return t.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  8425. if (e === RGBA_PVRTC_4BPPV1_Format) return t.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  8426. if (e === RGBA_PVRTC_2BPPV1_Format) return t.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  8427. }
  8428. if (t = i.get("WEBGL_compressed_texture_etc1"), null !== t && e === RGB_ETC1_Format) return t.COMPRESSED_RGB_ETC1_WEBGL;
  8429. if (t = i.get("EXT_blend_minmax"), null !== t) {
  8430. if (e === MinEquation) return t.MIN_EXT;
  8431. if (e === MaxEquation) return t.MAX_EXT;
  8432. }
  8433. return 0;
  8434. };
  8435. EventDispatcher.prototype.addEventListener = function (type, listener) {
  8436. var {
  8437. importance = 0,
  8438. once
  8439. } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  8440. //add importance
  8441. if (this._listeners === undefined) this._listeners = {};
  8442. var listeners = this._listeners;
  8443. if (listeners[type] === undefined) {
  8444. listeners[type] = [];
  8445. }
  8446. /* if(type == 'flyingDone'){
  8447. console.log('addEventListener flyingDone')
  8448. } */
  8449. if (!listeners[type].some(e => e.listener == listener)) {
  8450. listeners[type].push({
  8451. listener,
  8452. importance,
  8453. once
  8454. });
  8455. listeners[type] = listeners[type].sort((e, a) => a.importance - e.importance);
  8456. //add
  8457. }
  8458. };
  8459. EventDispatcher.prototype.hasEventListener = function (type, listener) {
  8460. if (this._listeners === undefined) return false;
  8461. var listeners = this._listeners;
  8462. return listeners[type] !== undefined && listeners[type].some(e => e.listener == listener);
  8463. };
  8464. EventDispatcher.prototype.removeEventListener = function (type, listener) {
  8465. if (this._listeners === undefined) return;
  8466. var listeners = this._listeners;
  8467. var listenerArray = listeners[type];
  8468. if (listenerArray !== undefined) {
  8469. /* const index = listenerArray.indexOf( listener );
  8470. if ( index !== - 1 ) {
  8471. listenerArray.splice( index, 1 );
  8472. } */
  8473. var item = listenerArray.find(e => e.listener == listener);
  8474. item && listenerArray.splice(listenerArray.indexOf(item), 1);
  8475. }
  8476. };
  8477. EventDispatcher.prototype.removeEventListeners = function (type) {
  8478. //add
  8479. if (this._listeners && this._listeners[type] !== undefined) {
  8480. delete this._listeners[type];
  8481. }
  8482. };
  8483. EventDispatcher.prototype.removeAllListeners = function () {
  8484. //add
  8485. this._listeners = {};
  8486. };
  8487. EventDispatcher.prototype.dispatchEvent = function (event) {
  8488. if (typeof event == 'string') {
  8489. //add
  8490. event = {
  8491. type: event
  8492. };
  8493. }
  8494. if (this._listeners === undefined) return;
  8495. var listeners = this._listeners;
  8496. var listenerArray = listeners[event.type];
  8497. if (listenerArray !== undefined) {
  8498. event.target = this;
  8499. // Make a copy, in case listeners are removed while iterating.
  8500. for (var {
  8501. listener,
  8502. once
  8503. } of listenerArray.slice(0)) {
  8504. if (once) {
  8505. this.removeEventListener(event.type, listener);
  8506. }
  8507. var result = listener.call(this, event);
  8508. //add stopContinue
  8509. if (result && result.stopContinue) {
  8510. break;
  8511. }
  8512. }
  8513. }
  8514. };
  8515. EventDispatcher.prototype.traverse = function (callback) {
  8516. var result = callback(this);
  8517. if (result && result.stopContinue) {
  8518. //xzw add
  8519. return;
  8520. }
  8521. var children = this.children;
  8522. if (children) {
  8523. for (var i = 0, l = children.length; i < l; i++) {
  8524. children[i].traverse(callback);
  8525. }
  8526. }
  8527. };
  8528. Quaternion.prototype.toObject = function (e) {
  8529. return {
  8530. x: this.x,
  8531. y: this.y,
  8532. z: this.z,
  8533. w: this.w
  8534. };
  8535. };
  8536. Euler.prototype.toObject = function (addOrder) {
  8537. var euler = {
  8538. x: this.x,
  8539. y: this.y,
  8540. z: this.z
  8541. };
  8542. addOrder && (euler.order = this.order);
  8543. return euler;
  8544. };
  8545. Object3D.prototype.traverse = function (callback, lastResult) {
  8546. var result = callback(this, lastResult);
  8547. //lastResult一般用于收集祖先的visible
  8548. if (result && result.stopContinue) {
  8549. //xzw add
  8550. return;
  8551. }
  8552. var children = this.children;
  8553. for (var i = 0, l = children.length; i < l; i++) {
  8554. children[i] && children[i].traverse(callback, result);
  8555. }
  8556. };
  8557. Shim.FollowRootObject = function (root) {
  8558. Object3D.call(this);
  8559. this.root = root;
  8560. };
  8561. Shim.FollowRootObject.prototype = Object.assign(Object.create(Object3D.prototype), {
  8562. constructor: Shim.FollowRootObject,
  8563. updateMatrixWorld(force) {
  8564. //重写,只为了将root当做parent
  8565. this.scale.set(1 / this.root.scale.x, 1 / this.root.scale.y, 1 / this.root.scale.z);
  8566. //中和模型缩放。无论模型缩放如何都不能改tag大小
  8567. this.updateMatrix();
  8568. this.matrixWorld.multiplyMatrices(this.root.matrixWorld, this.matrix);
  8569. var children = this.children;
  8570. for (var i = 0, l = children.length; i < l; i++) {
  8571. children[i].updateMatrixWorld(force);
  8572. }
  8573. },
  8574. updateWorldMatrix(updateParents, updateChildren) {
  8575. //重写,只为了将root当做parent
  8576. if (updateParents === true && this.root !== null) {
  8577. this.root.updateWorldMatrix(true, false);
  8578. }
  8579. if (this.matrixAutoUpdate) this.updateMatrix();
  8580. this.matrixWorld.multiplyMatrices(this.root.matrixWorld, this.matrix);
  8581. if (updateChildren === true) {
  8582. var children = this.children;
  8583. for (var i = 0, l = children.length; i < l; i++) {
  8584. children[i].updateWorldMatrix(false, true);
  8585. }
  8586. }
  8587. }
  8588. });
  8589. Material.prototype.setValues = function (values) {
  8590. if (values === undefined) return;
  8591. for (var key in values) {
  8592. var newValue = values[key];
  8593. if (newValue === undefined) {
  8594. console.warn('THREE.Material: \'' + key + '\' parameter is undefined.');
  8595. continue;
  8596. }
  8597. // for backward compatability if shading is set in the constructor
  8598. if (key === 'shading') {
  8599. console.warn('THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.');
  8600. this.flatShading = newValue === FlatShading ? true : false;
  8601. continue;
  8602. }
  8603. var currentValue = this[key];
  8604. /* if ( currentValue === undefined ) { //-----主要删了这段,否则很难和 set 一起使用
  8605. //console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
  8606. continue;
  8607. } */
  8608. if (currentValue && currentValue.isColor) {
  8609. currentValue.set(newValue);
  8610. } else if (currentValue && currentValue.isVector3 && newValue && newValue.isVector3) {
  8611. currentValue.copy(newValue);
  8612. } else {
  8613. this[key] = newValue;
  8614. }
  8615. }
  8616. };
  8617. function ascSort$1(a, b) {
  8618. return a.distance - b.distance;
  8619. }
  8620. function intersectObject(object, raycaster, intersects, recursive, ignoreUnvisible) {
  8621. if (ignoreUnvisible && !object.visible) return;
  8622. //add
  8623. if (object.layers.test(raycaster.layers)) {
  8624. object.raycast(raycaster, intersects);
  8625. }
  8626. if (recursive === true) {
  8627. var children = object.children;
  8628. for (var i = 0, l = children.length; i < l; i++) {
  8629. intersectObject(children[i], raycaster, intersects, true, ignoreUnvisible);
  8630. }
  8631. }
  8632. }
  8633. Raycaster.prototype.intersectObject = function (object, recursive, optionalTarget, ignoreUnvisible) {
  8634. var intersects = optionalTarget || [];
  8635. intersectObject(object, this, intersects, recursive, ignoreUnvisible);
  8636. intersects.sort(ascSort$1);
  8637. return intersects;
  8638. };
  8639. Raycaster.prototype.intersectObjects = function (objects, recursive, optionalTarget, ignoreUnvisible) {
  8640. //add ignoreUnvisible 跳过不可见
  8641. var intersects = optionalTarget || [];
  8642. if (Array.isArray(objects) === false) {
  8643. console.warn('THREE.Raycaster.intersectObjects: objects is not an Array.');
  8644. return intersects;
  8645. }
  8646. for (var i = 0, l = objects.length; i < l; i++) {
  8647. intersectObject(objects[i], this, intersects, recursive, ignoreUnvisible);
  8648. }
  8649. intersects.sort(ascSort$1);
  8650. return intersects;
  8651. };
  8652. Object3D.prototype.realVisible = function () {
  8653. var v = true;
  8654. var parent = this;
  8655. var lastParent;
  8656. while (parent) {
  8657. if (parent.visible === false) {
  8658. v = false;
  8659. break;
  8660. }
  8661. lastParent = parent;
  8662. parent = parent.parent;
  8663. }
  8664. if (v && !(lastParent instanceof Scene)) {
  8665. //已被删除
  8666. v = false;
  8667. }
  8668. return v;
  8669. };
  8670. Object3D.prototype.isChildOf = function (rootParent) {
  8671. //是否后代, 包括自身
  8672. var parent = this;
  8673. while (parent) {
  8674. if (parent == rootParent) {
  8675. return true;
  8676. break;
  8677. }
  8678. parent = parent.parent;
  8679. }
  8680. };
  8681. Curve.prototype.getPointAt = function (u, optionalTarget) {
  8682. var t = this.getUtoTmapping(u);
  8683. this.UtoTMapArr && this.UtoTMapArr.push(t);
  8684. //add
  8685. return this.getPoint(t, optionalTarget);
  8686. };
  8687. var _inverseMatrix$3 = /*@__PURE__*/
  8688. new Matrix4();
  8689. var _ray$3 = /*@__PURE__*/
  8690. new Ray();
  8691. var _sphere$6 = /*@__PURE__*/
  8692. new Sphere();
  8693. var _sphereHitAt = /*@__PURE__*/
  8694. new Vector3();
  8695. var _vA$1$1 = /*@__PURE__*/
  8696. new Vector3();
  8697. var _vB$1$1 = /*@__PURE__*/
  8698. new Vector3();
  8699. var _vC$1$1 = /*@__PURE__*/
  8700. new Vector3();
  8701. var _tempA$1 = /*@__PURE__*/
  8702. new Vector3();
  8703. var _morphA$1 = /*@__PURE__*/
  8704. new Vector3();
  8705. var _intersectionPoint$1 = /*@__PURE__*/
  8706. new Vector3();
  8707. var _intersectionPointWorld$1 = /*@__PURE__*/
  8708. new Vector3();
  8709. var _basePosition$1 = /*@__PURE__*/
  8710. new Vector3();
  8711. var _skinIndex$1 = /*@__PURE__*/
  8712. new Vector4();
  8713. var _skinWeight$1 = /*@__PURE__*/
  8714. new Vector4();
  8715. var _vector3 = /*@__PURE__*/
  8716. new Vector3();
  8717. var _matrix4 = /*@__PURE__*/
  8718. new Matrix4();
  8719. var _vertex = /*@__PURE__*/
  8720. new Vector3();
  8721. var _sphere$5 = /*@__PURE__*/
  8722. new Sphere();
  8723. var _inverseMatrix$2$1 = /*@__PURE__*/
  8724. new Matrix4();
  8725. var _ray$2$1 = /*@__PURE__*/
  8726. new Ray();
  8727. SkinnedMesh.prototype.computeBoundingSphere = function () {
  8728. var geometry = this.geometry;
  8729. if (!this.boundingSphere) {
  8730. this.boundingSphere = new Sphere();
  8731. }
  8732. this.boundingSphere.makeEmpty();
  8733. var positionAttribute = geometry.getAttribute('position');
  8734. for (var i = 0; i < positionAttribute.count; i++) {
  8735. this.getVertexPosition(i, _vertex);
  8736. this.boundingSphere.expandByPoint(_vertex);
  8737. }
  8738. };
  8739. SkinnedMesh.prototype.computeBoundingBox = function () {
  8740. var geometry = this.geometry;
  8741. if (!this.boundingBox) {
  8742. this.boundingBox = new Box3();
  8743. }
  8744. this.boundingBox.makeEmpty();
  8745. var positionAttribute = geometry.getAttribute('position');
  8746. for (var i = 0; i < positionAttribute.count; i++) {
  8747. this.getVertexPosition(i, _vertex);
  8748. this.boundingBox.expandByPoint(_vertex);
  8749. }
  8750. };
  8751. SkinnedMesh.prototype.raycast = function (raycaster, intersects) {
  8752. //根据r173重写,因模型大小跟着骨骼走
  8753. var material = this.material;
  8754. var matrixWorld = this.matrixWorld;
  8755. if (material === undefined) return;
  8756. // test with bounding sphere in world space
  8757. if (!this.boundingSphere) this.computeBoundingSphere();
  8758. _sphere$5.copy(this.boundingSphere);
  8759. _sphere$5.applyMatrix4(matrixWorld);
  8760. if (raycaster.ray.intersectsSphere(_sphere$5) === false) return;
  8761. // convert ray to local space of skinned mesh
  8762. _inverseMatrix$2$1.copy(matrixWorld).invert();
  8763. _ray$2$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2$1);
  8764. // test with bounding box in local space
  8765. if (this.boundingBox) {
  8766. if (_ray$2$1.intersectsBox(this.boundingBox) === false) return;
  8767. }
  8768. // test for intersections with geometry
  8769. this._computeIntersections(raycaster, intersects, _ray$2$1);
  8770. };
  8771. SkinnedMesh.prototype.getVertexPosition = function (index, target) {
  8772. //super.getVertexPosition( index, target );
  8773. var geometry = this.geometry;
  8774. var position = geometry.attributes.position;
  8775. var morphPosition = geometry.morphAttributes.position;
  8776. var morphTargetsRelative = geometry.morphTargetsRelative;
  8777. target.fromBufferAttribute(position, index);
  8778. var morphInfluences = this.morphTargetInfluences;
  8779. if (morphPosition && morphInfluences) {
  8780. _morphA$1.set(0, 0, 0);
  8781. for (var i = 0, il = morphPosition.length; i < il; i++) {
  8782. var influence = morphInfluences[i];
  8783. var morphAttribute = morphPosition[i];
  8784. if (influence === 0) continue;
  8785. _tempA$1.fromBufferAttribute(morphAttribute, index);
  8786. if (morphTargetsRelative) {
  8787. _morphA$1.addScaledVector(_tempA$1, influence);
  8788. } else {
  8789. _morphA$1.addScaledVector(_tempA$1.sub(target), influence);
  8790. }
  8791. }
  8792. target.add(_morphA$1);
  8793. }
  8794. this.applyBoneTransform(index, target);
  8795. return target;
  8796. };
  8797. SkinnedMesh.prototype.applyBoneTransform = function (index, vector) {
  8798. var skeleton = this.skeleton;
  8799. var geometry = this.geometry;
  8800. _skinIndex$1.fromBufferAttribute(geometry.attributes.skinIndex, index);
  8801. _skinWeight$1.fromBufferAttribute(geometry.attributes.skinWeight, index);
  8802. _basePosition$1.copy(vector).applyMatrix4(this.bindMatrix);
  8803. vector.set(0, 0, 0);
  8804. for (var i = 0; i < 4; i++) {
  8805. var weight = _skinWeight$1.getComponent(i);
  8806. if (weight !== 0) {
  8807. var boneIndex = _skinIndex$1.getComponent(i);
  8808. _matrix4.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
  8809. vector.addScaledVector(_vector3.copy(_basePosition$1).applyMatrix4(_matrix4), weight);
  8810. }
  8811. }
  8812. return vector.applyMatrix4(this.bindMatrixInverse);
  8813. };
  8814. SkinnedMesh.prototype._computeIntersections = function (raycaster, intersects, rayLocalSpace) {
  8815. var intersection;
  8816. var geometry = this.geometry;
  8817. var material = this.material;
  8818. var index = geometry.index;
  8819. var position = geometry.attributes.position;
  8820. var uv = geometry.attributes.uv;
  8821. var uv1 = geometry.attributes.uv1;
  8822. var normal = geometry.attributes.normal;
  8823. var groups = geometry.groups;
  8824. var drawRange = geometry.drawRange;
  8825. if (index !== null) {
  8826. // indexed buffer geometry
  8827. if (Array.isArray(material)) {
  8828. for (var i = 0, il = groups.length; i < il; i++) {
  8829. var group = groups[i];
  8830. var groupMaterial = material[group.materialIndex];
  8831. var start = Math.max(group.start, drawRange.start);
  8832. var end = Math.min(index.count, Math.min(group.start + group.count, drawRange.start + drawRange.count));
  8833. for (var j = start, jl = end; j < jl; j += 3) {
  8834. var a = index.getX(j);
  8835. var b = index.getX(j + 1);
  8836. var c = index.getX(j + 2);
  8837. intersection = checkGeometryIntersection(this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c);
  8838. if (intersection) {
  8839. intersection.faceIndex = Math.floor(j / 3);
  8840. // triangle number in indexed buffer semantics
  8841. intersection.face.materialIndex = group.materialIndex;
  8842. intersects.push(intersection);
  8843. }
  8844. }
  8845. }
  8846. } else {
  8847. var _start = Math.max(0, drawRange.start);
  8848. var _end = Math.min(index.count, drawRange.start + drawRange.count);
  8849. for (var _i = _start, _il = _end; _i < _il; _i += 3) {
  8850. var _a = index.getX(_i);
  8851. var _b = index.getX(_i + 1);
  8852. var _c = index.getX(_i + 2);
  8853. intersection = checkGeometryIntersection(this, material, raycaster, rayLocalSpace, uv, uv1, normal, _a, _b, _c);
  8854. if (intersection) {
  8855. intersection.faceIndex = Math.floor(_i / 3);
  8856. // triangle number in indexed buffer semantics
  8857. intersects.push(intersection);
  8858. }
  8859. }
  8860. }
  8861. } else if (position !== undefined) {
  8862. // non-indexed buffer geometry
  8863. if (Array.isArray(material)) {
  8864. for (var _i2 = 0, _il2 = groups.length; _i2 < _il2; _i2++) {
  8865. var _group = groups[_i2];
  8866. var _groupMaterial = material[_group.materialIndex];
  8867. var _start2 = Math.max(_group.start, drawRange.start);
  8868. var _end2 = Math.min(position.count, Math.min(_group.start + _group.count, drawRange.start + drawRange.count));
  8869. for (var _j = _start2, _jl = _end2; _j < _jl; _j += 3) {
  8870. var _a2 = _j;
  8871. var _b2 = _j + 1;
  8872. var _c2 = _j + 2;
  8873. intersection = checkGeometryIntersection(this, _groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, _a2, _b2, _c2);
  8874. if (intersection) {
  8875. intersection.faceIndex = Math.floor(_j / 3);
  8876. // triangle number in non-indexed buffer semantics
  8877. intersection.face.materialIndex = _group.materialIndex;
  8878. intersects.push(intersection);
  8879. }
  8880. }
  8881. }
  8882. } else {
  8883. var _start3 = Math.max(0, drawRange.start);
  8884. var _end3 = Math.min(position.count, drawRange.start + drawRange.count);
  8885. for (var _i3 = _start3, _il3 = _end3; _i3 < _il3; _i3 += 3) {
  8886. var _a3 = _i3;
  8887. var _b3 = _i3 + 1;
  8888. var _c3 = _i3 + 2;
  8889. intersection = checkGeometryIntersection(this, material, raycaster, rayLocalSpace, uv, uv1, normal, _a3, _b3, _c3);
  8890. if (intersection) {
  8891. intersection.faceIndex = Math.floor(_i3 / 3);
  8892. // triangle number in non-indexed buffer semantics
  8893. intersects.push(intersection);
  8894. }
  8895. }
  8896. }
  8897. }
  8898. };
  8899. var _v40 = /*@__PURE__*/
  8900. new Vector4();
  8901. var _v41 = /*@__PURE__*/
  8902. new Vector4();
  8903. var _v42 = /*@__PURE__*/
  8904. new Vector4();
  8905. function checkGeometryIntersection(object, material, raycaster, ray, uv, uv1, normal, a, b, c) {
  8906. object.getVertexPosition(a, _vA$1$1);
  8907. object.getVertexPosition(b, _vB$1$1);
  8908. object.getVertexPosition(c, _vC$1$1);
  8909. var intersection = checkIntersection$1(object, material, raycaster, ray, _vA$1$1, _vB$1$1, _vC$1$1, _intersectionPoint$1);
  8910. if (intersection) {
  8911. var barycoord = new Vector3();
  8912. Triangle.getBarycoord(_intersectionPoint$1, _vA$1$1, _vB$1$1, _vC$1$1, barycoord);
  8913. if (uv) {
  8914. intersection.uv = Triangle.getInterpolatedAttribute(uv, a, b, c, barycoord, new Vector2());
  8915. }
  8916. if (uv1) {
  8917. intersection.uv1 = Triangle.getInterpolatedAttribute(uv1, a, b, c, barycoord, new Vector2());
  8918. }
  8919. if (normal) {
  8920. intersection.normal = Triangle.getInterpolatedAttribute(normal, a, b, c, barycoord, new Vector3());
  8921. if (intersection.normal.dot(ray.direction) > 0) {
  8922. intersection.normal.multiplyScalar(-1);
  8923. }
  8924. }
  8925. var face = {
  8926. a: a,
  8927. b: b,
  8928. c: c,
  8929. normal: new Vector3(),
  8930. materialIndex: 0
  8931. };
  8932. Triangle.getNormal(_vA$1$1, _vB$1$1, _vC$1$1, face.normal);
  8933. intersection.face = face;
  8934. intersection.barycoord = barycoord;
  8935. }
  8936. return intersection;
  8937. }
  8938. function checkIntersection$1(object, material, raycaster, ray, pA, pB, pC, point) {
  8939. var intersect;
  8940. if (material.side === BackSide) {
  8941. intersect = ray.intersectTriangle(pC, pB, pA, true, point);
  8942. } else {
  8943. intersect = ray.intersectTriangle(pA, pB, pC, material.side === FrontSide, point);
  8944. }
  8945. if (intersect === null) return null;
  8946. _intersectionPointWorld$1.copy(point);
  8947. _intersectionPointWorld$1.applyMatrix4(object.matrixWorld);
  8948. var distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld$1);
  8949. if (distance < raycaster.near || distance > raycaster.far) return null;
  8950. return {
  8951. distance: distance,
  8952. point: _intersectionPointWorld$1.clone(),
  8953. object: object
  8954. };
  8955. }
  8956. var _v1$6$1 = /*@__PURE__*/
  8957. new Vector3();
  8958. var _v2$3$1 = /*@__PURE__*/
  8959. new Vector3();
  8960. Sphere.prototype.expandByPoint = function (point) {
  8961. if (this.isEmpty()) {
  8962. this.center.copy(point);
  8963. this.radius = 0;
  8964. return this;
  8965. }
  8966. _v1$6$1.subVectors(point, this.center);
  8967. var lengthSq = _v1$6$1.lengthSq();
  8968. if (lengthSq > this.radius * this.radius) {
  8969. // calculate the minimal sphere
  8970. var length = Math.sqrt(lengthSq);
  8971. var delta = (length - this.radius) * 0.5;
  8972. this.center.addScaledVector(_v1$6$1, delta / length);
  8973. this.radius += delta;
  8974. }
  8975. return this;
  8976. };
  8977. /* THREE.Triangle.prototype.getBarycoord( point, target ) {
  8978. return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
  8979. } */
  8980. Triangle.getInterpolatedAttribute = function (attr, i1, i2, i3, barycoord, target) {
  8981. _v40.setScalar(0);
  8982. _v41.setScalar(0);
  8983. _v42.setScalar(0);
  8984. _v40.fromBufferAttribute(attr, i1);
  8985. _v41.fromBufferAttribute(attr, i2);
  8986. _v42.fromBufferAttribute(attr, i3);
  8987. target.setScalar(0);
  8988. target.addScaledVector(_v40, barycoord.x);
  8989. target.addScaledVector(_v41, barycoord.y);
  8990. target.addScaledVector(_v42, barycoord.z);
  8991. return target;
  8992. };
  8993. var _vector$7$1 = new Vector3();
  8994. InterleavedBufferAttribute.prototype.applyNormalMatrix = function (m) {
  8995. for (var i = 0, l = this.count; i < l; i++) {
  8996. _vector$7$1.fromBufferAttribute(this, i);
  8997. _vector$7$1.applyNormalMatrix(m);
  8998. this.setXYZ(i, _vector$7$1.x, _vector$7$1.y, _vector$7$1.z);
  8999. }
  9000. return this;
  9001. };
  9002. Color.prototype.getHSV = function () {
  9003. //or hsb 色相、饱和度、明度(不同于hsl的亮度,只有色相是和hsl一样)代码源于deepseek
  9004. var r = this.r,
  9005. g = this.g,
  9006. b = this.b;
  9007. var max = Math.max(r, g, b);
  9008. var min = Math.min(r, g, b);
  9009. var h,
  9010. s,
  9011. v = max;
  9012. var d = max - min;
  9013. s = max === 0 ? 0 : d / max;
  9014. if (max === min) {
  9015. h = 0;
  9016. // 无色
  9017. } else {
  9018. switch (max) {
  9019. case r:
  9020. h = (g - b) / d + (g < b ? 6 : 0);
  9021. break;
  9022. case g:
  9023. h = (b - r) / d + 2;
  9024. break;
  9025. case b:
  9026. h = (r - g) / d + 4;
  9027. break;
  9028. }
  9029. h /= 6;
  9030. }
  9031. return {
  9032. h: h * 360,
  9033. s: s * 100,
  9034. v: v * 100
  9035. };
  9036. };
  9037. Color.prototype.setHSV = function (h, s, v) {
  9038. h = h % 360;
  9039. s /= 100;
  9040. v /= 100;
  9041. var c = v * s;
  9042. var x = c * (1 - Math.abs(h / 60 % 2 - 1));
  9043. var m = v - c;
  9044. var r, g, b;
  9045. if (0 <= h && h < 60) {
  9046. [r, g, b] = [c, x, 0];
  9047. } else if (60 <= h && h < 120) {
  9048. [r, g, b] = [x, c, 0];
  9049. } else if (120 <= h && h < 180) {
  9050. [r, g, b] = [0, c, x];
  9051. } else if (180 <= h && h < 240) {
  9052. [r, g, b] = [0, x, c];
  9053. } else if (240 <= h && h < 300) {
  9054. [r, g, b] = [x, 0, c];
  9055. } else if (300 <= h && h < 360) {
  9056. [r, g, b] = [c, 0, x];
  9057. }
  9058. return this.setRGB(r + m, g + m, b + m);
  9059. };
  9060. var oldSet = Color.prototype.set;
  9061. Color.prototype.set = function () {
  9062. if (arguments.length >= 3) return this.setRGB.apply(this, arguments);
  9063. return oldSet.apply(this, arguments);
  9064. };
  9065. var MathLight = {};
  9066. MathLight.RADIANS_PER_DEGREE = Math.PI / 180;
  9067. MathLight.DEGREES_PER_RADIAN = 180 / Math.PI;
  9068. MathLight.Vector3 = function (e, t, i) {
  9069. this.x = e || 0, this.y = t || 0, this.z = i || 0;
  9070. };
  9071. MathLight.Matrix4 = function () {
  9072. this.elements = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]), arguments.length > 0 && console.error("MathLight.Matrix4: the constructor no longer reads arguments. use .set() instead.");
  9073. };
  9074. MathLight.Matrix4.prototype = {
  9075. identity: function identity() {
  9076. return this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), this;
  9077. },
  9078. copy: function copy(e) {
  9079. return this.elements.set(e.elements), this;
  9080. },
  9081. applyToVector3: function applyToVector3(e) {
  9082. var t = e.x,
  9083. i = e.y,
  9084. n = e.z,
  9085. r = this.elements;
  9086. return e.x = r[0] * t + r[4] * i + r[8] * n + r[12], e.y = r[1] * t + r[5] * i + r[9] * n + r[13], e.z = r[2] * t + r[6] * i + r[10] * n + r[14], this;
  9087. },
  9088. getInverse: function getInverse(e, t) {
  9089. var i = this.elements,
  9090. n = e.elements,
  9091. r = n[0],
  9092. o = n[1],
  9093. a = n[2],
  9094. s = n[3],
  9095. l = n[4],
  9096. c = n[5],
  9097. h = n[6],
  9098. u = n[7],
  9099. d = n[8],
  9100. p = n[9],
  9101. f = n[10],
  9102. g = n[11],
  9103. m = n[12],
  9104. v = n[13],
  9105. A = n[14],
  9106. y = n[15],
  9107. C = p * A * u - v * f * u + v * h * g - c * A * g - p * h * y + c * f * y,
  9108. I = m * f * u - d * A * u - m * h * g + l * A * g + d * h * y - l * f * y,
  9109. E = d * v * u - m * p * u + m * c * g - l * v * g - d * c * y + l * p * y,
  9110. b = m * p * h - d * v * h - m * c * f + l * v * f + d * c * A - l * p * A,
  9111. w = r * C + o * I + a * E + s * b;
  9112. if (0 === w) {
  9113. var _ = "MathLight.Matrix4.getInverse(): can't invert matrix, determinant is 0";
  9114. if (t) throw new Error(_);
  9115. return console.warn(_), this.identity();
  9116. }
  9117. var T = 1 / w;
  9118. return i[0] = C * T, i[1] = (v * f * s - p * A * s - v * a * g + o * A * g + p * a * y - o * f * y) * T, i[2] = (c * A * s - v * h * s + v * a * u - o * A * u - c * a * y + o * h * y) * T, i[3] = (p * h * s - c * f * s - p * a * u + o * f * u + c * a * g - o * h * g) * T, i[4] = I * T, i[5] = (d * A * s - m * f * s + m * a * g - r * A * g - d * a * y + r * f * y) * T, i[6] = (m * h * s - l * A * s - m * a * u + r * A * u + l * a * y - r * h * y) * T, i[7] = (l * f * s - d * h * s + d * a * u - r * f * u - l * a * g + r * h * g) * T, i[8] = E * T, i[9] = (m * p * s - d * v * s - m * o * g + r * v * g + d * o * y - r * p * y) * T, i[10] = (l * v * s - m * c * s + m * o * u - r * v * u - l * o * y + r * c * y) * T, i[11] = (d * c * s - l * p * s - d * o * u + r * p * u + l * o * g - r * c * g) * T, i[12] = b * T, i[13] = (d * v * a - m * p * a + m * o * f - r * v * f - d * o * A + r * p * A) * T, i[14] = (m * c * a - l * v * a - m * o * h + r * v * h + l * o * A - r * c * A) * T, i[15] = (l * p * a - d * c * a + d * o * h - r * p * h - l * o * f + r * c * f) * T, this;
  9119. },
  9120. makeRotationFromQuaternion: function makeRotationFromQuaternion(e) {
  9121. var t = this.elements,
  9122. i = e.x,
  9123. n = e.y,
  9124. r = e.z,
  9125. o = e.w,
  9126. a = i + i,
  9127. s = n + n,
  9128. l = r + r,
  9129. c = i * a,
  9130. h = i * s,
  9131. u = i * l,
  9132. d = n * s,
  9133. p = n * l,
  9134. f = r * l,
  9135. g = o * a,
  9136. m = o * s,
  9137. v = o * l;
  9138. return t[0] = 1 - (d + f), t[4] = h - v, t[8] = u + m, t[1] = h + v, t[5] = 1 - (c + f), t[9] = p - g, t[2] = u - m, t[6] = p + g, t[10] = 1 - (c + d), t[3] = 0, t[7] = 0, t[11] = 0, t[12] = 0, t[13] = 0, t[14] = 0, t[15] = 1, this;
  9139. }
  9140. };
  9141. MathLight.Quaternion = function (e, t, i, n) {
  9142. this._x = e || 0, this._y = t || 0, this._z = i || 0, this._w = void 0 !== n ? n : 1;
  9143. };
  9144. MathLight.Quaternion.prototype = {
  9145. get x() {
  9146. return this._x;
  9147. },
  9148. set x(e) {
  9149. this._x = e;
  9150. },
  9151. get y() {
  9152. return this._y;
  9153. },
  9154. set y(e) {
  9155. this._y = e;
  9156. },
  9157. get z() {
  9158. return this._z;
  9159. },
  9160. set z(e) {
  9161. this._z = e;
  9162. },
  9163. get w() {
  9164. return this._w;
  9165. },
  9166. set w(e) {
  9167. this._w = e;
  9168. },
  9169. copy: function copy(e) {
  9170. this._x = e.x, this._y = e.y, this._z = e.z, this._w = e.w;
  9171. },
  9172. inverse: function inverse() {
  9173. return this.conjugate().normalize();
  9174. },
  9175. conjugate: function conjugate() {
  9176. return this._x *= -1, this._y *= -1, this._z *= -1, this;
  9177. },
  9178. length: function length() {
  9179. return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
  9180. },
  9181. normalize: function normalize() {
  9182. var e = this.length();
  9183. return 0 === e ? (this._x = 0, this._y = 0, this._z = 0, this._w = 1) : (e = 1 / e, this._x = this._x * e, this._y = this._y * e, this._z = this._z * e, this._w = this._w * e), this;
  9184. },
  9185. setFromAxisAngle: function setFromAxisAngle(e, t) {
  9186. var i = t / 2,
  9187. n = Math.sin(i);
  9188. return this._x = e.x * n, this._y = e.y * n, this._z = e.z * n, this._w = Math.cos(i), this;
  9189. },
  9190. setFromUnitVectors: function () {
  9191. var e,
  9192. t,
  9193. i = 1e-6;
  9194. return function (n, o) {
  9195. return void 0 === e && (e = new MathLight.Vector3()), t = MathLight.dot(n, o) + 1, t < i ? (t = 0, 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), this._x = e.x, this._y = e.y, this._z = e.z, this._w = t, this.normalize();
  9196. };
  9197. }(),
  9198. multiply: function multiply(e) {
  9199. return this.multiplyQuaternions(this, e);
  9200. },
  9201. premultiply: function premultiply(e) {
  9202. return this.multiplyQuaternions(e, this);
  9203. },
  9204. multiplyQuaternions: function multiplyQuaternions(e, t) {
  9205. var i = e._x,
  9206. n = e._y,
  9207. r = e._z,
  9208. o = e._w,
  9209. a = t._x,
  9210. s = t._y,
  9211. l = t._z,
  9212. c = t._w;
  9213. return this._x = i * c + o * a + n * l - r * s, this._y = n * c + o * s + r * a - i * l, this._z = r * c + o * l + i * s - n * a, this._w = o * c - i * a - n * s - r * l, this;
  9214. }
  9215. };
  9216. MathLight.convertWorkshopVector = function (e) {
  9217. return new MathLight.Vector3(-e.x, e.y, e.z);
  9218. };
  9219. MathLight.convertWorkshopQuaternion = function (e) {
  9220. 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));
  9221. };
  9222. MathLight.convertWorkshopOrthoZoom = function (e) {
  9223. //return e === -1 ? -1 : e / 16 * ($('#player').width() / $('#player').height()) / n.workshopApsect
  9224. return e === -1 ? -1 : e * ($("#player").width() / $("#player").height());
  9225. };
  9226. MathLight.convertWorkshopPanoramaQuaternion = function (e) {
  9227. 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));
  9228. };
  9229. MathLight.normalize = function (e) {
  9230. var t = e.x * e.x + e.y * e.y + e.z * e.z,
  9231. i = Math.sqrt(t);
  9232. e.x /= i, e.y /= i, e.z /= i;
  9233. };
  9234. MathLight.dot = function (e, t) {
  9235. return e.x * t.x + e.y * t.y + e.z * t.z;
  9236. };
  9237. MathLight.cross = function (e, t, i) {
  9238. var n = e.x,
  9239. r = e.y,
  9240. o = e.z;
  9241. i.x = r * t.z - o * t.y, i.y = o * t.x - n * t.z, i.z = n * t.y - r * t.x;
  9242. };
  9243. MathLight.setVector = function (e, t, i, n) {
  9244. e.x = t, e.y = i, e.z = n;
  9245. };
  9246. MathLight.copyVector = function (e, t) {
  9247. t.x = e.x, t.y = e.y, t.z = e.z;
  9248. };
  9249. MathLight.addVector = function (e, t) {
  9250. e.x += t.x, e.y += t.y, e.z += t.z;
  9251. };
  9252. MathLight.subVector = function (e, t) {
  9253. e.x -= t.x, e.y -= t.y, e.z -= t.z;
  9254. };
  9255. MathLight.applyQuaternionToVector = function (e, t) {
  9256. var i = t.x,
  9257. n = t.y,
  9258. r = t.z,
  9259. o = e.x,
  9260. a = e.y,
  9261. s = e.z,
  9262. l = e.w,
  9263. c = l * i + a * r - s * n,
  9264. h = l * n + s * i - o * r,
  9265. u = l * r + o * n - a * i,
  9266. d = -o * i - a * n - s * r;
  9267. t.x = c * l + d * -o + h * -s - u * -a, t.y = h * l + d * -a + u * -o - c * -s, t.z = u * l + d * -s + c * -a - h * -o;
  9268. };
  9269. MathLight.angleBetweenVectors = function (e, t) {
  9270. return Math.acos(MathLight.dot(e, t));
  9271. };
  9272. var cameraLight = {
  9273. clampVFOV: function clampVFOV(currentFov, maxHFov, width, height) {
  9274. //限制currentFov, 使之造成的横向fov不大于指定值maxHFov
  9275. var r = cameraLight.getHFOVFromVFOV(currentFov, width, height);
  9276. return r > maxHFov ? cameraLight.getVFOVFromHFOV(maxHFov, width, height) : currentFov;
  9277. },
  9278. getHFOVForCamera: function getHFOVForCamera(camera, getRad) {
  9279. return cameraLight.getHFOVByScreenPrecent(camera.fov, camera.aspect, getRad);
  9280. },
  9281. //add
  9282. getHFOVByScreenPrecent: function getHFOVByScreenPrecent(fov, percent, getRad) {
  9283. //当fov为占比百分百时,percent代表在屏幕上从中心到边缘的占比
  9284. var rad = 2 * Math.atan(percent * Math.tan(fov * MathLight.RADIANS_PER_DEGREE / 2));
  9285. if (getRad) return rad;else return rad * MathLight.DEGREES_PER_RADIAN;
  9286. }
  9287. };
  9288. var XHRFactory = {
  9289. config: {
  9290. withCredentials: false,
  9291. customHeaders: [{
  9292. header: null,
  9293. value: null
  9294. }]
  9295. },
  9296. createXMLHttpRequest: function createXMLHttpRequest() {
  9297. var xhr = new XMLHttpRequest();
  9298. if (this.config.customHeaders && Array.isArray(this.config.customHeaders) && this.config.customHeaders.length > 0) {
  9299. var baseOpen = xhr.open;
  9300. var customHeaders = this.config.customHeaders;
  9301. xhr.open = function () {
  9302. baseOpen.apply(this, [].slice.call(arguments));
  9303. customHeaders.forEach(function (customHeader) {
  9304. if (!!customHeader.header && !!customHeader.value) {
  9305. xhr.setRequestHeader(customHeader.header, customHeader.value);
  9306. }
  9307. });
  9308. };
  9309. }
  9310. return xhr;
  9311. }
  9312. };
  9313. // /**
  9314. class TextSprite$1 extends Object3D {
  9315. //old
  9316. constructor(text) {
  9317. super();
  9318. var texture = new Texture();
  9319. texture.minFilter = LinearFilter;
  9320. texture.magFilter = LinearFilter;
  9321. var spriteMaterial = new SpriteMaterial({
  9322. map: texture,
  9323. depthTest: false,
  9324. depthWrite: false
  9325. });
  9326. this.texture = texture;
  9327. this.material = spriteMaterial;
  9328. //this.material = getRawMaterial(texture);
  9329. this.sprite = new Sprite$1(this.material);
  9330. this.add(this.sprite);
  9331. this.borderThickness = 4;
  9332. this.fontface = 'Arial';
  9333. this.fontsize = 28;
  9334. this.borderColor = {
  9335. r: 0,
  9336. g: 0,
  9337. b: 0,
  9338. a: 1.0
  9339. };
  9340. this.backgroundColor = {
  9341. r: 255,
  9342. g: 255,
  9343. b: 255,
  9344. a: 1.0
  9345. };
  9346. this.textColor = {
  9347. r: 255,
  9348. g: 255,
  9349. b: 255,
  9350. a: 1.0
  9351. };
  9352. this.text = '';
  9353. this.setText(text);
  9354. }
  9355. setText(text) {
  9356. if (this.text !== text) {
  9357. this.text = text;
  9358. this.update();
  9359. }
  9360. }
  9361. setTextColor(color) {
  9362. this.textColor = color;
  9363. this.update();
  9364. }
  9365. setBorderColor(color) {
  9366. this.borderColor = color;
  9367. this.update();
  9368. }
  9369. setBackgroundColor(color) {
  9370. this.backgroundColor = color;
  9371. this.update();
  9372. }
  9373. update() {
  9374. var canvas = document.createElement('canvas');
  9375. var context = canvas.getContext('2d');
  9376. context.font = 'Bold ' + this.fontsize + 'px ' + this.fontface;
  9377. // get size data (height depends only on font size)
  9378. var metrics = context.measureText(this.text);
  9379. var textWidth = metrics.width;
  9380. var margin = 5;
  9381. var spriteWidth = 2 * margin + textWidth + 2 * this.borderThickness;
  9382. var spriteHeight = this.fontsize * 1.4 + 2 * this.borderThickness;
  9383. context.canvas.width = spriteWidth;
  9384. context.canvas.height = spriteHeight;
  9385. context.font = 'Bold ' + this.fontsize + 'px ' + this.fontface;
  9386. // background color
  9387. context.fillStyle = 'rgba(' + this.backgroundColor.r + ',' + this.backgroundColor.g + ',' + this.backgroundColor.b + ',' + this.backgroundColor.a + ')';
  9388. // border color
  9389. context.strokeStyle = 'rgba(' + this.borderColor.r + ',' + this.borderColor.g + ',' + this.borderColor.b + ',' + this.borderColor.a + ')';
  9390. context.lineWidth = this.borderThickness;
  9391. this.roundRect(context, this.borderThickness / 2, this.borderThickness / 2, textWidth + this.borderThickness + 2 * margin, this.fontsize * 1.4 + this.borderThickness, 6);
  9392. // text color
  9393. context.strokeStyle = 'rgba(0, 0, 0, 1.0)';
  9394. context.strokeText(this.text, this.borderThickness + margin, this.fontsize + this.borderThickness);
  9395. context.fillStyle = 'rgba(' + this.textColor.r + ',' + this.textColor.g + ',' + this.textColor.b + ',' + this.textColor.a + ')';
  9396. context.fillText(this.text, this.borderThickness + margin, this.fontsize + this.borderThickness);
  9397. var texture = new Texture(canvas);
  9398. texture.minFilter = LinearFilter;
  9399. texture.magFilter = LinearFilter;
  9400. texture.needsUpdate = true;
  9401. //this.material.needsUpdate = true;
  9402. // { // screen-space sprite
  9403. // let [screenWidth, screenHeight] = [1620, 937];
  9404. // let uniforms = this.sprite.material.uniforms;
  9405. // let aspect = spriteHeight / spriteWidth;
  9406. // let factor = 0.5;
  9407. // let w = spriteWidth / screenWidth;
  9408. // let h = spriteHeight / screenHeight;
  9409. // uniforms.uScale.value = [2 * w, 2 * h];
  9410. // //uniforms.uScale.value = [factor * 1, factor * aspect];
  9411. // this.sprite.material.uniforms.map.value = texture;
  9412. // }
  9413. this.sprite.material.map = texture;
  9414. this.texture = texture;
  9415. this.sprite.scale.set(spriteWidth * 0.01, spriteHeight * 0.01, 1.0);
  9416. }
  9417. roundRect(ctx, x, y, w, h, r) {
  9418. ctx.beginPath();
  9419. ctx.moveTo(x + r, y);
  9420. ctx.lineTo(x + w - r, y);
  9421. ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  9422. ctx.lineTo(x + w, y + h - r);
  9423. ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  9424. ctx.lineTo(x + r, y + h);
  9425. ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  9426. ctx.lineTo(x, y + r);
  9427. ctx.quadraticCurveTo(x, y, x + r, y);
  9428. ctx.closePath();
  9429. ctx.fill();
  9430. ctx.stroke();
  9431. }
  9432. }
  9433. class Volume extends Object3D {
  9434. constructor() {
  9435. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9436. super();
  9437. if (this.constructor.name === "Volume") {
  9438. console.warn("Can't create object of class Volume directly. Use classes BoxVolume or SphereVolume instead.");
  9439. }
  9440. //console.log(this);
  9441. //console.log(this.constructor);
  9442. //console.log(this.constructor.name);
  9443. this._clip = args.clip || false;
  9444. this._visible = true;
  9445. this.showVolumeLabel = true;
  9446. this._modifiable = args.modifiable || true;
  9447. this.label = new TextSprite$1('0');
  9448. this.label.setBorderColor({
  9449. r: 0,
  9450. g: 255,
  9451. b: 0,
  9452. a: 0.0
  9453. });
  9454. this.label.setBackgroundColor({
  9455. r: 0,
  9456. g: 255,
  9457. b: 0,
  9458. a: 0.0
  9459. });
  9460. this.label.material.depthTest = false;
  9461. this.label.material.depthWrite = false;
  9462. this.label.material.transparent = true;
  9463. this.label.position.y -= 0.5;
  9464. this.add(this.label);
  9465. this.label.updateMatrixWorld = () => {
  9466. var volumeWorldPos = new Vector3();
  9467. volumeWorldPos.setFromMatrixPosition(this.matrixWorld);
  9468. this.label.position.copy(volumeWorldPos);
  9469. this.label.updateMatrix();
  9470. this.label.matrixWorld.copy(this.label.matrix);
  9471. this.label.matrixWorldNeedsUpdate = false;
  9472. for (var i = 0, l = this.label.children.length; i < l; i++) {
  9473. this.label.children[i].updateMatrixWorld(true);
  9474. }
  9475. };
  9476. {
  9477. // event listeners
  9478. this.addEventListener('select', e => {});
  9479. this.addEventListener('deselect', e => {});
  9480. }
  9481. }
  9482. get visible() {
  9483. return this._visible;
  9484. }
  9485. set visible(value) {
  9486. if (this._visible !== value) {
  9487. this._visible = value;
  9488. this.dispatchEvent({
  9489. type: "visibility_changed",
  9490. object: this
  9491. });
  9492. }
  9493. }
  9494. getVolume() {
  9495. console.warn("override this in subclass");
  9496. }
  9497. update() {}
  9498. raycast(raycaster, intersects) {}
  9499. get clip() {
  9500. return this._clip;
  9501. }
  9502. set clip(value) {
  9503. if (this._clip !== value) {
  9504. this._clip = value;
  9505. this.update();
  9506. this.dispatchEvent({
  9507. type: "clip_changed",
  9508. object: this
  9509. });
  9510. }
  9511. }
  9512. get modifieable() {
  9513. return this._modifiable;
  9514. }
  9515. set modifieable(value) {
  9516. this._modifiable = value;
  9517. this.update();
  9518. }
  9519. }
  9520. ;
  9521. class BoxVolume extends Volume {
  9522. constructor() {
  9523. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9524. super(args);
  9525. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  9526. this.name = 'box_' + this.constructor.counter;
  9527. var boxGeometry = new BoxGeometry(1, 1, 1);
  9528. boxGeometry.computeBoundingBox();
  9529. var boxFrameGeometry = new Geometry();
  9530. {
  9531. var Vector3$1 = Vector3;
  9532. boxFrameGeometry.vertices.push(
  9533. // bottom
  9534. new Vector3$1(-0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, 0.5),
  9535. // top
  9536. new Vector3$1(-0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, 0.5),
  9537. // sides
  9538. new Vector3$1(-0.5, -0.5, 0.5), new Vector3$1(-0.5, 0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5));
  9539. }
  9540. this.material = new MeshBasicMaterial({
  9541. color: 0x00ff00,
  9542. transparent: true,
  9543. opacity: 0.3,
  9544. depthTest: true,
  9545. depthWrite: false
  9546. });
  9547. this.box = new Mesh(boxGeometry, this.material);
  9548. this.box.geometry.computeBoundingBox();
  9549. this.boundingBox = this.box.geometry.boundingBox;
  9550. this.add(this.box);
  9551. this.frame = new LineSegments(boxFrameGeometry, new LineBasicMaterial({
  9552. color: 0x000000
  9553. }));
  9554. // this.frame.mode = THREE.Lines;
  9555. this.add(this.frame);
  9556. this.update();
  9557. }
  9558. update() {
  9559. this.boundingBox = this.box.geometry.boundingBox;
  9560. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  9561. if (this._clip) {
  9562. this.box.visible = false;
  9563. this.label.visible = false;
  9564. } else {
  9565. this.box.visible = true;
  9566. this.label.visible = this.showVolumeLabel;
  9567. }
  9568. }
  9569. raycast(raycaster, intersects) {
  9570. var is = [];
  9571. this.box.raycast(raycaster, is);
  9572. if (is.length > 0) {
  9573. var I = is[0];
  9574. intersects.push({
  9575. distance: I.distance,
  9576. object: this,
  9577. point: I.point.clone()
  9578. });
  9579. }
  9580. }
  9581. getVolume() {
  9582. return Math.abs(this.scale.x * this.scale.y * this.scale.z);
  9583. }
  9584. }
  9585. ;
  9586. class SphereVolume$1 extends Volume {
  9587. constructor() {
  9588. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  9589. super(args);
  9590. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  9591. this.name = 'sphere_' + this.constructor.counter;
  9592. var sphereGeometry = new SphereGeometry(1, 32, 32);
  9593. sphereGeometry.computeBoundingBox();
  9594. this.material = new MeshBasicMaterial({
  9595. color: 0x00ff00,
  9596. transparent: true,
  9597. opacity: 0.3,
  9598. depthTest: true,
  9599. depthWrite: false
  9600. });
  9601. this.sphere = new Mesh(sphereGeometry, this.material);
  9602. this.sphere.visible = false;
  9603. this.sphere.geometry.computeBoundingBox();
  9604. this.boundingBox = this.sphere.geometry.boundingBox;
  9605. this.add(this.sphere);
  9606. this.label.visible = false;
  9607. var frameGeometry = new Geometry();
  9608. {
  9609. var steps = 64;
  9610. var uSegments = 8;
  9611. var vSegments = 5;
  9612. var r = 1;
  9613. for (var uSegment = 0; uSegment < uSegments; uSegment++) {
  9614. var alpha = uSegment / uSegments * Math.PI * 2;
  9615. var dirx = Math.cos(alpha);
  9616. var diry = Math.sin(alpha);
  9617. for (var i = 0; i <= steps; i++) {
  9618. var v = i / steps * Math.PI * 2;
  9619. var vNext = v + 2 * Math.PI / steps;
  9620. var height = Math.sin(v);
  9621. var xyAmount = Math.cos(v);
  9622. var heightNext = Math.sin(vNext);
  9623. var xyAmountNext = Math.cos(vNext);
  9624. var vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  9625. frameGeometry.vertices.push(vertex);
  9626. var vertexNext = new Vector3(dirx * xyAmountNext, diry * xyAmountNext, heightNext);
  9627. frameGeometry.vertices.push(vertexNext);
  9628. }
  9629. }
  9630. // creates rings at poles, just because it's easier to implement
  9631. for (var vSegment = 0; vSegment <= vSegments + 1; vSegment++) {
  9632. //let height = (vSegment / (vSegments + 1)) * 2 - 1; // -1 to 1
  9633. var uh = vSegment / (vSegments + 1); // -1 to 1
  9634. uh = (1 - uh) * (-Math.PI / 2) + uh * (Math.PI / 2);
  9635. var _height = Math.sin(uh);
  9636. console.log(uh, _height);
  9637. for (var _i = 0; _i <= steps; _i++) {
  9638. var u = _i / steps * Math.PI * 2;
  9639. var uNext = u + 2 * Math.PI / steps;
  9640. var _dirx = Math.cos(u);
  9641. var _diry = Math.sin(u);
  9642. var dirxNext = Math.cos(uNext);
  9643. var diryNext = Math.sin(uNext);
  9644. var _xyAmount = Math.sqrt(1 - _height * _height);
  9645. var _vertex = new Vector3(_dirx * _xyAmount, _diry * _xyAmount, _height);
  9646. frameGeometry.vertices.push(_vertex);
  9647. var _vertexNext = new Vector3(dirxNext * _xyAmount, diryNext * _xyAmount, _height);
  9648. frameGeometry.vertices.push(_vertexNext);
  9649. }
  9650. }
  9651. }
  9652. this.frame = new LineSegments(frameGeometry, new LineBasicMaterial({
  9653. color: 0x000000
  9654. }));
  9655. this.add(this.frame);
  9656. var frameMaterial = new MeshBasicMaterial({
  9657. wireframe: true,
  9658. color: 0x000000
  9659. });
  9660. this.frame = new Mesh(sphereGeometry, frameMaterial);
  9661. //this.add(this.frame);
  9662. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
  9663. // this.frame.mode = THREE.Lines;
  9664. //this.add(this.frame);
  9665. this.update();
  9666. }
  9667. update() {
  9668. this.boundingBox = this.sphere.geometry.boundingBox;
  9669. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  9670. //if (this._clip) {
  9671. // this.sphere.visible = false;
  9672. // this.label.visible = false;
  9673. //} else {
  9674. // this.sphere.visible = true;
  9675. // this.label.visible = this.showVolumeLabel;
  9676. //}
  9677. }
  9678. raycast(raycaster, intersects) {
  9679. var is = [];
  9680. this.sphere.raycast(raycaster, is);
  9681. if (is.length > 0) {
  9682. var I = is[0];
  9683. intersects.push({
  9684. distance: I.distance,
  9685. object: this,
  9686. point: I.point.clone()
  9687. });
  9688. }
  9689. }
  9690. // see https://en.wikipedia.org/wiki/Ellipsoid#Volume
  9691. getVolume() {
  9692. return 4 / 3 * Math.PI * this.scale.x * this.scale.y * this.scale.z;
  9693. }
  9694. }
  9695. ;
  9696. class Profile extends Object3D {
  9697. constructor() {
  9698. super();
  9699. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  9700. this.name = 'Profile_' + this.constructor.counter;
  9701. this.points = [];
  9702. this.spheres = [];
  9703. this.edges = [];
  9704. this.boxes = [];
  9705. this.width = 1;
  9706. this.height = 20;
  9707. this._modifiable = true;
  9708. this.sphereGeometry = new SphereGeometry(0.4, 10, 10);
  9709. this.color = new Color(0xff0000);
  9710. this.lineColor = new Color(0xff0000);
  9711. }
  9712. createSphereMaterial() {
  9713. var sphereMaterial = new MeshLambertMaterial({
  9714. //shading: THREE.SmoothShading,
  9715. color: 0xff0000,
  9716. depthTest: false,
  9717. depthWrite: false
  9718. });
  9719. return sphereMaterial;
  9720. }
  9721. getSegments() {
  9722. var segments = [];
  9723. for (var i = 0; i < this.points.length - 1; i++) {
  9724. var start = this.points[i].clone();
  9725. var end = this.points[i + 1].clone();
  9726. segments.push({
  9727. start: start,
  9728. end: end
  9729. });
  9730. }
  9731. return segments;
  9732. }
  9733. getSegmentMatrices() {
  9734. var segments = this.getSegments();
  9735. var matrices = [];
  9736. for (var segment of segments) {
  9737. var {
  9738. start,
  9739. end
  9740. } = segment;
  9741. var box = new Object3D();
  9742. var length = start.clone().setZ(0).distanceTo(end.clone().setZ(0));
  9743. box.scale.set(length, 10000, this.width);
  9744. box.up.set(0, 0, 1);
  9745. var center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  9746. var diff = new Vector3().subVectors(end, start);
  9747. var target = new Vector3(diff.y, -diff.x, 0);
  9748. box.position.set(0, 0, 0);
  9749. box.lookAt(target);
  9750. box.position.copy(center);
  9751. box.updateMatrixWorld();
  9752. matrices.push(box.matrixWorld);
  9753. }
  9754. return matrices;
  9755. }
  9756. addMarker(point) {
  9757. this.points.push(point);
  9758. var sphere = new Mesh(this.sphereGeometry, this.createSphereMaterial());
  9759. this.add(sphere);
  9760. this.spheres.push(sphere);
  9761. // edges & boxes
  9762. if (this.points.length > 1) {
  9763. var lineGeometry = new Geometry();
  9764. lineGeometry.vertices.push(new Vector3(), new Vector3());
  9765. lineGeometry.colors.push(this.lineColor, this.lineColor, this.lineColor);
  9766. var lineMaterial = new LineBasicMaterial({
  9767. vertexColors: VertexColors,
  9768. linewidth: 2,
  9769. transparent: true,
  9770. opacity: 0.4
  9771. });
  9772. lineMaterial.depthTest = false;
  9773. var edge = new Line(lineGeometry, lineMaterial);
  9774. edge.visible = false;
  9775. this.add(edge);
  9776. this.edges.push(edge);
  9777. var boxGeometry = new BoxGeometry(1, 1, 1);
  9778. var boxMaterial = new MeshBasicMaterial({
  9779. color: 0xff0000,
  9780. transparent: true,
  9781. opacity: 0.2
  9782. });
  9783. var box = new Mesh(boxGeometry, boxMaterial);
  9784. box.visible = false;
  9785. this.add(box);
  9786. this.boxes.push(box);
  9787. }
  9788. {
  9789. // event listeners
  9790. var drag = e => {
  9791. var I = Utils.getMousePointCloudIntersection(e.drag.end, e.viewer.scene.getActiveCamera(), e.viewer, e.viewer.scene.pointclouds);
  9792. if (I) {
  9793. var i = this.spheres.indexOf(e.drag.object);
  9794. if (i !== -1) {
  9795. this.setPosition(i, I.location);
  9796. //this.dispatchEvent({
  9797. // 'type': 'marker_moved',
  9798. // 'profile': this,
  9799. // 'index': i
  9800. //});
  9801. }
  9802. }
  9803. };
  9804. var drop = e => {
  9805. var i = this.spheres.indexOf(e.drag.object);
  9806. if (i !== -1) {
  9807. this.dispatchEvent({
  9808. 'type': 'marker_dropped',
  9809. 'profile': this,
  9810. 'index': i
  9811. });
  9812. }
  9813. };
  9814. var mouseover = e => e.object.material.emissive.setHex(0x888888);
  9815. var mouseleave = e => e.object.material.emissive.setHex(0x000000);
  9816. sphere.addEventListener('drag', drag);
  9817. sphere.addEventListener('drop', drop);
  9818. sphere.addEventListener('mouseover', mouseover);
  9819. sphere.addEventListener('mouseleave', mouseleave);
  9820. }
  9821. var event = {
  9822. type: 'marker_added',
  9823. profile: this,
  9824. sphere: sphere
  9825. };
  9826. this.dispatchEvent(event);
  9827. this.setPosition(this.points.length - 1, point);
  9828. }
  9829. removeMarker(index) {
  9830. this.points.splice(index, 1);
  9831. this.remove(this.spheres[index]);
  9832. var edgeIndex = index === 0 ? 0 : index - 1;
  9833. this.remove(this.edges[edgeIndex]);
  9834. this.edges.splice(edgeIndex, 1);
  9835. this.remove(this.boxes[edgeIndex]);
  9836. this.boxes.splice(edgeIndex, 1);
  9837. this.spheres.splice(index, 1);
  9838. this.update();
  9839. this.dispatchEvent({
  9840. 'type': 'marker_removed',
  9841. 'profile': this
  9842. });
  9843. }
  9844. setPosition(index, position) {
  9845. var point = this.points[index];
  9846. point.copy(position);
  9847. var event = {
  9848. type: 'marker_moved',
  9849. profile: this,
  9850. index: index,
  9851. position: point.clone()
  9852. };
  9853. this.dispatchEvent(event);
  9854. this.update();
  9855. }
  9856. setWidth(width) {
  9857. this.width = width;
  9858. var event = {
  9859. type: 'width_changed',
  9860. profile: this,
  9861. width: width
  9862. };
  9863. this.dispatchEvent(event);
  9864. this.update();
  9865. }
  9866. getWidth() {
  9867. return this.width;
  9868. }
  9869. update() {
  9870. if (this.points.length === 0) {
  9871. return;
  9872. } else if (this.points.length === 1) {
  9873. var point = this.points[0];
  9874. this.spheres[0].position.copy(point);
  9875. return;
  9876. }
  9877. var min = this.points[0].clone();
  9878. var max = this.points[0].clone();
  9879. var centroid = new Vector3();
  9880. var lastIndex = this.points.length - 1;
  9881. for (var i = 0; i <= lastIndex; i++) {
  9882. var _point = this.points[i];
  9883. var sphere = this.spheres[i];
  9884. var leftIndex = i === 0 ? lastIndex : i - 1;
  9885. // let rightIndex = (i === lastIndex) ? 0 : i + 1;
  9886. var leftVertex = this.points[leftIndex];
  9887. // let rightVertex = this.points[rightIndex];
  9888. var leftEdge = this.edges[leftIndex];
  9889. var rightEdge = this.edges[i];
  9890. var leftBox = this.boxes[leftIndex];
  9891. // rightBox = this.boxes[i];
  9892. // let leftEdgeLength = point.distanceTo(leftVertex);
  9893. // let rightEdgeLength = point.distanceTo(rightVertex);
  9894. // let leftEdgeCenter = new THREE.Vector3().addVectors(leftVertex, point).multiplyScalar(0.5);
  9895. // let rightEdgeCenter = new THREE.Vector3().addVectors(point, rightVertex).multiplyScalar(0.5);
  9896. sphere.position.copy(_point);
  9897. if (this._modifiable) {
  9898. sphere.visible = true;
  9899. } else {
  9900. sphere.visible = false;
  9901. }
  9902. if (leftEdge) {
  9903. leftEdge.geometry.vertices[1].copy(_point);
  9904. leftEdge.geometry.verticesNeedUpdate = true;
  9905. leftEdge.geometry.computeBoundingSphere();
  9906. }
  9907. if (rightEdge) {
  9908. rightEdge.geometry.vertices[0].copy(_point);
  9909. rightEdge.geometry.verticesNeedUpdate = true;
  9910. rightEdge.geometry.computeBoundingSphere();
  9911. }
  9912. if (leftBox) {
  9913. var start = leftVertex;
  9914. var end = _point;
  9915. var length = start.clone().setZ(0).distanceTo(end.clone().setZ(0));
  9916. leftBox.scale.set(length, 1000000, this.width);
  9917. leftBox.up.set(0, 0, 1);
  9918. var center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  9919. var diff = new Vector3().subVectors(end, start);
  9920. var target = new Vector3(diff.y, -diff.x, 0);
  9921. leftBox.position.set(0, 0, 0);
  9922. leftBox.lookAt(target);
  9923. leftBox.position.copy(center);
  9924. }
  9925. centroid.add(_point);
  9926. min.min(_point);
  9927. max.max(_point);
  9928. }
  9929. centroid.multiplyScalar(1 / this.points.length);
  9930. for (var _i = 0; _i < this.boxes.length; _i++) {
  9931. var box = this.boxes[_i];
  9932. box.position.z = min.z + (max.z - min.z) / 2;
  9933. }
  9934. }
  9935. raycast(raycaster, intersects) {
  9936. for (var i = 0; i < this.points.length; i++) {
  9937. var sphere = this.spheres[i];
  9938. sphere.raycast(raycaster, intersects);
  9939. }
  9940. // recalculate distances because they are not necessarely correct
  9941. // for scaled objects.
  9942. // see https://github.com/mrdoob/three.js/issues/5827
  9943. // TODO: remove this once the bug has been fixed
  9944. for (var _i2 = 0; _i2 < intersects.length; _i2++) {
  9945. var I = intersects[_i2];
  9946. I.distance = raycaster.ray.origin.distanceTo(I.point);
  9947. }
  9948. intersects.sort(function (a, b) {
  9949. return a.distance - b.distance;
  9950. });
  9951. }
  9952. get modifiable() {
  9953. return this._modifiable;
  9954. }
  9955. set modifiable(value) {
  9956. this._modifiable = value;
  9957. this.update();
  9958. }
  9959. }
  9960. var _box$4 = new Box3();
  9961. var _vector$d = new Vector3();
  9962. class LineSegmentsGeometry extends InstancedBufferGeometry {
  9963. constructor() {
  9964. super();
  9965. this.isLineSegmentsGeometry = true;
  9966. this.type = 'LineSegmentsGeometry';
  9967. var 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];
  9968. var uvs = [-1, 2, 1, 2, -1, 1, 1, 1, -1, -1, 1, -1, -1, -2, 1, -2];
  9969. var index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5];
  9970. this.setIndex(index);
  9971. this.setAttribute('position', new Float32BufferAttribute(positions, 3));
  9972. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
  9973. }
  9974. applyMatrix4(matrix) {
  9975. var start = this.attributes.instanceStart;
  9976. var end = this.attributes.instanceEnd;
  9977. if (start !== undefined) {
  9978. start.applyMatrix4(matrix);
  9979. end.applyMatrix4(matrix);
  9980. start.needsUpdate = true;
  9981. }
  9982. if (this.boundingBox !== null) {
  9983. this.computeBoundingBox();
  9984. }
  9985. if (this.boundingSphere !== null) {
  9986. this.computeBoundingSphere();
  9987. }
  9988. return this;
  9989. }
  9990. setPositions(array) {
  9991. var lineSegments;
  9992. if (array instanceof Float32Array) {
  9993. lineSegments = array;
  9994. } else if (Array.isArray(array)) {
  9995. lineSegments = new Float32Array(array);
  9996. }
  9997. var instanceBuffer = new InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz
  9998. this.setAttribute('instanceStart', new InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz
  9999. this.setAttribute('instanceEnd', new InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz
  10000. //
  10001. this.computeBoundingBox();
  10002. this.computeBoundingSphere();
  10003. return this;
  10004. }
  10005. setColors(array) {
  10006. var colors;
  10007. if (array instanceof Float32Array) {
  10008. colors = array;
  10009. } else if (Array.isArray(array)) {
  10010. colors = new Float32Array(array);
  10011. }
  10012. var instanceColorBuffer = new InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb
  10013. this.setAttribute('instanceColorStart', new InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb
  10014. this.setAttribute('instanceColorEnd', new InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb
  10015. return this;
  10016. }
  10017. fromWireframeGeometry(geometry) {
  10018. this.setPositions(geometry.attributes.position.array);
  10019. return this;
  10020. }
  10021. fromEdgesGeometry(geometry) {
  10022. this.setPositions(geometry.attributes.position.array);
  10023. return this;
  10024. }
  10025. fromMesh(mesh) {
  10026. this.fromWireframeGeometry(new WireframeGeometry(mesh.geometry));
  10027. // set colors, maybe
  10028. return this;
  10029. }
  10030. fromLineSegments(lineSegments) {
  10031. var geometry = lineSegments.geometry;
  10032. this.setPositions(geometry.attributes.position.array); // assumes non-indexed
  10033. // set colors, maybe
  10034. return this;
  10035. }
  10036. computeBoundingBox() {
  10037. if (this.boundingBox === null) {
  10038. this.boundingBox = new Box3();
  10039. }
  10040. var start = this.attributes.instanceStart;
  10041. var end = this.attributes.instanceEnd;
  10042. if (start !== undefined && end !== undefined) {
  10043. this.boundingBox.setFromBufferAttribute(start);
  10044. _box$4.setFromBufferAttribute(end);
  10045. this.boundingBox.union(_box$4);
  10046. }
  10047. }
  10048. computeBoundingSphere() {
  10049. if (this.boundingSphere === null) {
  10050. this.boundingSphere = new Sphere();
  10051. }
  10052. if (this.boundingBox === null) {
  10053. this.computeBoundingBox();
  10054. }
  10055. var start = this.attributes.instanceStart;
  10056. var end = this.attributes.instanceEnd;
  10057. if (start !== undefined && end !== undefined) {
  10058. var center = this.boundingSphere.center;
  10059. this.boundingBox.getCenter(center);
  10060. var maxRadiusSq = 0;
  10061. for (var i = 0, il = start.count; i < il; i++) {
  10062. _vector$d.fromBufferAttribute(start, i);
  10063. maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$d));
  10064. _vector$d.fromBufferAttribute(end, i);
  10065. maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$d));
  10066. }
  10067. this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
  10068. if (isNaN(this.boundingSphere.radius)) {
  10069. console.error('THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this);
  10070. }
  10071. }
  10072. }
  10073. toJSON() {
  10074. // todo
  10075. }
  10076. applyMatrix(matrix) {
  10077. console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().');
  10078. return this.applyMatrix4(matrix);
  10079. }
  10080. }
  10081. /**
  10082. * parameters = {
  10083. * color: <hex>,
  10084. * lineWidth: <float>,
  10085. * dashed: <boolean>,
  10086. * dashScale: <float>,
  10087. * dashSize: <float>,
  10088. * dashOffset: <float>,
  10089. * gapSize: <float>,
  10090. * resolution: <Vector2>, // to be set by renderer
  10091. * }
  10092. */
  10093. UniformsLib.line = {
  10094. /*
  10095. worldUnits: { value: 1 },
  10096. lineWidth: { value: 1 },
  10097. resolution: { value: new Vector2( 1, 1 ) },
  10098. dashOffset: { value: 0 },
  10099. dashScale: { value: 1 },
  10100. dashSize: { value: 1 },
  10101. gapSize: { value: 1 } // todo FIX - maybe change to totalSize
  10102. */
  10103. worldUnits: {
  10104. value: 1
  10105. },
  10106. lineWidth: {
  10107. value: 1
  10108. },
  10109. resolution: {
  10110. value: new Vector2(1, 1)
  10111. },
  10112. viewportOffset: {
  10113. value: new Vector2(0, 0)
  10114. },
  10115. //left, top
  10116. devicePixelRatio: {
  10117. value: window.devicePixelRatio
  10118. },
  10119. dashScale: {
  10120. value: 1
  10121. },
  10122. dashSize: {
  10123. value: 1
  10124. },
  10125. dashOffset: {
  10126. value: 0
  10127. },
  10128. gapSize: {
  10129. value: 1
  10130. },
  10131. opacity: {
  10132. value: 1
  10133. },
  10134. backColor: {
  10135. type: 'v3',
  10136. value: new Color("#ddd")
  10137. },
  10138. clipDistance: {
  10139. type: 'f',
  10140. value: 4
  10141. },
  10142. //消失距离
  10143. occlusionDistance: {
  10144. type: 'f',
  10145. value: 1
  10146. },
  10147. //变为backColor距离
  10148. maxClipFactor: {
  10149. type: 'f',
  10150. value: 1
  10151. },
  10152. //0-1
  10153. maxOcclusionFactor: {
  10154. type: 'f',
  10155. value: 1
  10156. },
  10157. //0-1
  10158. depthTexture: {
  10159. value: null
  10160. },
  10161. nearPlane: {
  10162. value: 0.1
  10163. },
  10164. farPlane: {
  10165. value: 100000
  10166. },
  10167. //uUseOrthographicCamera:{ type: "b", value: false },
  10168. fadeFar: {
  10169. value: 10
  10170. } //渐变消失
  10171. };
  10172. ShaderLib['line'] = {
  10173. uniforms: UniformsUtils.merge([UniformsLib.common, UniformsLib.fog, UniformsLib.line]),
  10174. vertexShader: /* glsl */"\n\t\t#include <common>\n\t\t#include <color_pars_vertex>\n\t\t#include <fog_pars_vertex>\n\t\t#include <logdepthbuf_pars_vertex>\n\t\t#include <clipping_planes_pars_vertex>\n\n\t\tuniform float lineWidth;\n\t\tuniform vec2 resolution;\n uniform float devicePixelRatio; //add\n \n \n\t\tattribute vec3 instanceStart;\n\t\tattribute vec3 instanceEnd;\n\n\t\tattribute vec3 instanceColorStart;\n\t\tattribute vec3 instanceColorEnd;\n\n\t\t#ifdef WORLD_UNITS\n\n\t\t\tvarying vec4 worldPos;\n\t\t\tvarying vec3 worldStart;\n\t\t\tvarying vec3 worldEnd;\n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tvarying vec2 vUv;\n\n\t\t\t#endif\n\n\t\t#else\n\n\t\t\tvarying vec2 vUv;\n\n\t\t#endif\n\n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashScale;\n\t\t\tattribute float instanceDistanceStart;\n\t\t\tattribute float instanceDistanceEnd;\n\t\t\tvarying float vLineDistance;\n\n\t\t#endif\n\n\t\tvoid trimSegment( const in vec4 start, inout vec4 end ) {\n\n\t\t\t// trim end segment so it terminates between the camera plane and the near plane\n\n\t\t\t// conservative estimate of the near plane\n\t\t\tfloat a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column\n\t\t\tfloat b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column\n\t\t\tfloat nearEstimate = - 0.5 * b / a;\n\n\t\t\tfloat alpha = ( nearEstimate - start.z ) / ( end.z - start.z );\n\n\t\t\tend.xyz = mix( start.xyz, end.xyz, alpha );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\t#ifdef USE_COLOR\n\n\t\t\t\tvColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;\n\n\t\t\t#endif\n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tvLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;\n\t\t\t\tvUv = uv;\n\n\t\t\t#endif\n\n\t\t\tfloat aspect = resolution.x / resolution.y;\n\n\t\t\t// camera space\n\t\t\tvec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );\n\t\t\tvec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );\n\n\t\t\t#ifdef WORLD_UNITS\n\n\t\t\t\tworldStart = start.xyz;\n\t\t\t\tworldEnd = end.xyz;\n\n\t\t\t#else\n\n\t\t\t\tvUv = uv;\n\n\t\t\t#endif\n\n\t\t\t// special case for perspective projection, and segments that terminate either in, or behind, the camera plane\n\t\t\t// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space\n\t\t\t// but we need to perform ndc-space calculations in the shader, so we must address this issue directly\n\t\t\t// perhaps there is a more elegant solution -- WestLangley\n\n\t\t\tbool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column\n\n\t\t\tif ( perspective ) {\n\n\t\t\t\tif ( start.z < 0.0 && end.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( start, end );\n\n\t\t\t\t} else if ( end.z < 0.0 && start.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( end, start );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// clip space\n\t\t\tvec4 clipStart = projectionMatrix * start;\n\t\t\tvec4 clipEnd = projectionMatrix * end;\n\n\t\t\t// ndc space\n\t\t\tvec3 ndcStart = clipStart.xyz / clipStart.w;\n\t\t\tvec3 ndcEnd = clipEnd.xyz / clipEnd.w;\n\n\t\t\t// direction\n\t\t\tvec2 dir = ndcEnd.xy - ndcStart.xy;\n\n\t\t\t// account for clip-space aspect ratio\n\t\t\tdir.x *= aspect;\n\t\t\tdir = normalize( dir );\n\n\t\t\t#ifdef WORLD_UNITS\n\n\t\t\t\t// get the offset direction as perpendicular to the view vector\n\t\t\t\tvec3 worldDir = normalize( end.xyz - start.xyz );\n\t\t\t\tvec3 offset;\n\t\t\t\tif ( position.y < 0.5 ) {\n\n\t\t\t\t\toffset = normalize( cross( start.xyz, worldDir ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\toffset = normalize( cross( end.xyz, worldDir ) );\n\n\t\t\t\t}\n\n\t\t\t\t// sign flip\n\t\t\t\tif ( position.x < 0.0 ) offset *= - 1.0;\n\n\t\t\t\tfloat forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) );\n\n\t\t\t\t// don't extend the line if we're rendering dashes because we\n\t\t\t\t// won't be rendering the endcaps\n\t\t\t\t#ifndef USE_DASH\n\n\t\t\t\t\t// extend the line bounds to encompass endcaps\n\t\t\t\t\tstart.xyz += - worldDir * lineWidth * 0.5;\n\t\t\t\t\tend.xyz += worldDir * lineWidth * 0.5;\n\n\t\t\t\t\t// shift the position of the quad so it hugs the forward edge of the line\n\t\t\t\t\toffset.xy -= dir * forwardOffset;\n\t\t\t\t\toffset.z += 0.5;\n\n\t\t\t\t#endif\n\n\t\t\t\t// endcaps\n\t\t\t\tif ( position.y > 1.0 || position.y < 0.0 ) {\n\n\t\t\t\t\toffset.xy += dir * 2.0 * forwardOffset;\n\n\t\t\t\t}\n\n\t\t\t\t// adjust for lineWidth\n\t\t\t\toffset *= lineWidth * 0.5;\n\n\t\t\t\t// set the world position\n\t\t\t\tworldPos = ( position.y < 0.5 ) ? start : end;\n\t\t\t\tworldPos.xyz += offset;\n\n\t\t\t\t// project the worldpos\n\t\t\t\tvec4 clip = projectionMatrix * worldPos;\n\n\t\t\t\t// shift the depth of the projected points so the line\n\t\t\t\t// segments overlap neatly\n\t\t\t\tvec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;\n\t\t\t\tclip.z = clipPose.z * clip.w;\n\n\t\t\t#else\n\n\t\t\t\tvec2 offset = vec2( dir.y, - dir.x );\n\t\t\t\t// undo aspect ratio adjustment\n\t\t\t\tdir.x /= aspect;\n\t\t\t\toffset.x /= aspect;\n\n\t\t\t\t// sign flip\n\t\t\t\tif ( position.x < 0.0 ) offset *= - 1.0;\n\n\t\t\t\t// endcaps\n\t\t\t\tif ( position.y < 0.0 ) {\n\n\t\t\t\t\toffset += - dir;\n\n\t\t\t\t} else if ( position.y > 1.0 ) {\n\n\t\t\t\t\toffset += dir;\n\n\t\t\t\t}\n\n\t\t\t\t// adjust for lineWidth\n\t\t\t\toffset *= lineWidth;\n\n\t\t\t\t// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...\n\t\t\t\toffset /= resolution.y; //* devicePixelRatio;\n\n\t\t\t\t// select end\n\t\t\t\tvec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;\n\n\t\t\t\t// back to clip space\n\t\t\t\toffset *= clip.w;\n\n\t\t\t\tclip.xy += offset;\n\n\t\t\t#endif\n\n\t\t\tgl_Position = clip;\n\n\t\t\tvec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation\n\n\t\t\t#include <logdepthbuf_vertex>\n\t\t\t#include <clipping_planes_vertex>\n\t\t\t#include <fog_vertex>\n\n\t\t}\n\t\t",
  10175. fragmentShader: /* glsl */"\n\t\tuniform vec3 diffuse;\n\t\tuniform float opacity;\n\t\tuniform float lineWidth;\n uniform bool uUseOrthographicCamera; \n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashOffset;\n\t\t\tuniform float dashSize;\n\t\t\tuniform float gapSize; \n\t\t#endif\n \n //\u52A0\n #if defined(GL_EXT_frag_depth) && defined(useDepth) \n uniform sampler2D depthTexture;\n \n uniform vec2 resolution;\n uniform vec2 viewportOffset;\n uniform vec3 backColor;\n uniform float occlusionDistance;\n uniform float clipDistance;\n uniform float maxClipFactor;\n uniform float maxOcclusionFactor; \n #endif\n #if defined(FadeFar)\n uniform float fadeFar;\n #endif\n \n\n\t\tvarying float vLineDistance;\n\n\t\t#ifdef WORLD_UNITS\n\n\t\t\tvarying vec4 worldPos;\n\t\t\tvarying vec3 worldStart;\n\t\t\tvarying vec3 worldEnd;\n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tvarying vec2 vUv;\n\n\t\t\t#endif\n\n\t\t#else\n\n\t\t\tvarying vec2 vUv;\n\n\t\t#endif\n\n\t\t#include <common>\n\t\t#include <color_pars_fragment>\n\t\t#include <fog_pars_fragment>\n\t\t#include <logdepthbuf_pars_fragment>\n\t\t#include <clipping_planes_pars_fragment>\n\n\n #if defined(GL_EXT_frag_depth) && defined(useDepth) || defined(FadeFar) \n uniform float nearPlane;\n uniform float farPlane;\n float convertToLinear(float zValue)\n {\n //if(uUseOrthographicCamera){\n // return zValue*(farPlane-nearPlane)+nearPlane;\n //}else{ \n float z = zValue * 2.0 - 1.0;\n return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));\n //} \n }\n #endif\n\n\n\n\t\tvec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {\n\n\t\t\tfloat mua;\n\t\t\tfloat mub;\n\n\t\t\tvec3 p13 = p1 - p3;\n\t\t\tvec3 p43 = p4 - p3;\n\n\t\t\tvec3 p21 = p2 - p1;\n\n\t\t\tfloat d1343 = dot( p13, p43 );\n\t\t\tfloat d4321 = dot( p43, p21 );\n\t\t\tfloat d1321 = dot( p13, p21 );\n\t\t\tfloat d4343 = dot( p43, p43 );\n\t\t\tfloat d2121 = dot( p21, p21 );\n\n\t\t\tfloat denom = d2121 * d4343 - d4321 * d4321;\n\n\t\t\tfloat numer = d1343 * d4321 - d1321 * d4343;\n\n\t\t\tmua = numer / denom;\n\t\t\tmua = clamp( mua, 0.0, 1.0 );\n\t\t\tmub = ( d1343 + d4321 * ( mua ) ) / d4343;\n\t\t\tmub = clamp( mub, 0.0, 1.0 );\n\n\t\t\treturn vec2( mua, mub );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\t#include <clipping_planes_fragment>\n\n\t\t\t/*#ifdef USE_DASH\n\n\t\t\t\tif ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps\n\n\t\t\t\tif ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX\n\n\t\t\t#endif*/\n \n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tif ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps\n \n \n bool unvisible = mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize;\n //\u52A0\n #ifdef DASH_with_depth\n \n #else \n if (unvisible) discard; // todo - FIX\n #endif\n\t\t\t#endif\n \n\n\t\t\tfloat alpha = opacity;\n\n\t\t\t#ifdef WORLD_UNITS\n\n\t\t\t\t// Find the closest points on the view ray and the line segment\n\t\t\t\tvec3 rayEnd = normalize( worldPos.xyz ) * 1e5;\n\t\t\t\tvec3 lineDir = worldEnd - worldStart;\n\t\t\t\tvec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd );\n\n\t\t\t\tvec3 p1 = worldStart + lineDir * params.x;\n\t\t\t\tvec3 p2 = rayEnd * params.y;\n\t\t\t\tvec3 delta = p1 - p2;\n\t\t\t\tfloat len = length( delta );\n\t\t\t\tfloat norm = len / lineWidth;\n\n\t\t\t\t#ifndef USE_DASH\n\n\t\t\t\t\t#ifdef USE_ALPHA_TO_COVERAGE\n\n\t\t\t\t\t\tfloat dnorm = fwidth( norm );\n\t\t\t\t\t\talpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm );\n\n\t\t\t\t\t#else\n\n\t\t\t\t\t\tif ( norm > 0.5 ) {\n\n\t\t\t\t\t\t\tdiscard;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t#endif\n\n\t\t\t\t#endif\n\n\t\t\t#else\n\n\t\t\t\t#ifdef USE_ALPHA_TO_COVERAGE\n\n\t\t\t\t\t// artifacts appear on some hardware if a derivative is taken within a conditional\n\t\t\t\t\tfloat a = vUv.x;\n\t\t\t\t\tfloat b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;\n\t\t\t\t\tfloat len2 = a * a + b * b;\n\t\t\t\t\tfloat dlen = fwidth( len2 );\n\n\t\t\t\t\tif ( abs( vUv.y ) > 1.0 ) {\n\n\t\t\t\t\t\talpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 );\n\n\t\t\t\t\t}\n\n\t\t\t\t#else\n\n\t\t\t\t\tif ( abs( vUv.y ) > 1.0 ) {\n\n\t\t\t\t\t\tfloat a = vUv.x;\n\t\t\t\t\t\tfloat b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;\n\t\t\t\t\t\tfloat len2 = a * a + b * b;\n\n\t\t\t\t\t\tif ( len2 > 1.0 ) discard;\n\n\t\t\t\t\t}\n\n\t\t\t\t#endif\n\n\t\t\t#endif\n\n\t\t\tvec4 diffuseColor = vec4( diffuse, alpha );\n\n\n //\u52A0\n #if defined(GL_EXT_frag_depth) && defined(useDepth) || defined(FadeFar) \n \n float fragDepth = convertToLinear(gl_FragCoord.z);\n #if defined(FadeFar) \n float fadeOutFar = fadeFar * 1.3; //\u5B8C\u5168\u6D88\u5931\u8DDD\u79BB\n if(fragDepth > fadeOutFar){\n discard;\n }else if(fragDepth > fadeFar){\n alpha *= (fadeOutFar - fragDepth) / (fadeOutFar - fadeFar);\n diffuseColor.a = alpha;\n } \n #endif\n \n #if defined(GL_EXT_frag_depth) && defined(useDepth)\n \n float mixFactor = 0.0;\n float clipFactor = 0.0;\n //gl_FragCoord\u5927\u5C0F\u4E3A viewport client\u5927\u5C0F \n vec2 depthTxtCoords = vec2(gl_FragCoord.x - viewportOffset.x, gl_FragCoord.y - viewportOffset.y) / resolution;\n\n float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);\n\n float delta = fragDepth - textureDepth;\n\n if (delta > 0.0)\n {\n \n mixFactor = clamp(delta / occlusionDistance, 0.0, maxOcclusionFactor);\n clipFactor = clamp(delta / clipDistance, 0.0, maxClipFactor);\n }\n \n if (clipFactor == 1.0)\n {\n discard;\n }\n \n vec4 backColor_ = vec4(backColor, alpha /* opacity */); //vec4(0.8,0.8,0.8, 0.8*opacity);\n \n #ifdef DASH_with_depth \n // \u53EA\u5728\u88AB\u906E\u4F4F\u7684\u90E8\u5206\u663E\u793A\u865A\u7EBF, \u6240\u4EE5\u82E5\u540C\u65F6\u662F\u865A\u7EBF\u4E0D\u53EF\u89C1\u90E8\u5206\u548C\u88AB\u906E\u4F4F\u65F6\uFF0C a\u4E3A0\n if(unvisible) backColor_.a = 0.0;\n #endif \n \n //vec4 diffuseColor = vec4(mix(diffuse, backColor_, mixFactor), opacity*(1.0 - clipFactor));\n \n diffuseColor = mix(diffuseColor, backColor_ , mixFactor); \n \n float r = pow(1.0 - clipFactor, 3.0); //\u66F4\u900F\u660E\u4E9B \n diffuseColor.a *= r; \n \n #endif\n #endif\n\n\n\t\t\t#include <logdepthbuf_fragment>\n\t\t\t#include <color_fragment>\n\n\t\t\t//gl_FragColor = vec4( diffuseColor.rgb, alpha );\n\t\t\tgl_FragColor = diffuseColor;\n\t\t\t#include <tonemapping_fragment>\n\t\t\t#include <encodings_fragment>\n\t\t\t#include <fog_fragment>\n\t\t\t#include <premultiplied_alpha_fragment>\n\n\t\t}\n\t\t"
  10176. };
  10177. class LineMaterial extends ShaderMaterial {
  10178. constructor(parameters) {
  10179. var {
  10180. vs,
  10181. fs
  10182. } = Potree.Common.changeShaderToWebgl2(ShaderLib['line'].vertexShader, ShaderLib['line'].fragmentShader, 'ShaderMaterial');
  10183. super({
  10184. type: 'LineMaterial',
  10185. uniforms: UniformsUtils.clone(ShaderLib['line'].uniforms),
  10186. vertexShader: vs,
  10187. fragmentShader: fs,
  10188. clipping: true // required for clipping support
  10189. });
  10190. this.isLineMaterial = true;
  10191. this.lineWidth_ = 0;
  10192. this.supportExtDepth = parameters.supportExtDepth;
  10193. this.depthTestWhenPick = false; //pick时是否识别点云等
  10194. if (parameters.color) {
  10195. this.color = new Color(parameters.color);
  10196. }
  10197. if (parameters.backColor) {
  10198. this.uniforms.backColor.value = new Color(parameters.backColor);
  10199. }
  10200. if (parameters.clipDistance) {
  10201. this.uniforms.clipDistance.value = parameters.clipDistance;
  10202. }
  10203. if (parameters.occlusionDistance) {
  10204. this.uniforms.occlusionDistance.value = parameters.occlusionDistance;
  10205. }
  10206. if (parameters.maxClipFactor) {
  10207. this.uniforms.maxClipFactor.value = parameters.maxClipFactor;
  10208. }
  10209. Object.defineProperties(this, {
  10210. color: {
  10211. enumerable: true,
  10212. get: function get() {
  10213. return this.uniforms.diffuse.value;
  10214. },
  10215. set: function set(value) {
  10216. this.uniforms.diffuse.value = value;
  10217. }
  10218. },
  10219. worldUnits: {
  10220. enumerable: true,
  10221. get: function get() {
  10222. return 'WORLD_UNITS' in this.defines;
  10223. },
  10224. set: function set(value) {
  10225. if (value === true) {
  10226. this.defines.WORLD_UNITS = '';
  10227. } else {
  10228. delete this.defines.WORLD_UNITS;
  10229. }
  10230. }
  10231. },
  10232. lineWidth: {
  10233. enumerable: true,
  10234. get: function get() {
  10235. return this.lineWidth_; //this.uniforms.lineWidth.value;
  10236. },
  10237. set: function set(value) {
  10238. this.uniforms.lineWidth.value = value * window.devicePixelRatio;
  10239. this.lineWidth_ = value;
  10240. }
  10241. },
  10242. dashed: {
  10243. enumerable: true,
  10244. get: function get() {
  10245. return Boolean('USE_DASH' in this.defines);
  10246. },
  10247. set(value) {
  10248. if (Boolean(value) !== Boolean('USE_DASH' in this.defines)) {
  10249. this.needsUpdate = true;
  10250. }
  10251. if (value === true) {
  10252. this.defines.USE_DASH = '';
  10253. } else {
  10254. delete this.defines.USE_DASH;
  10255. }
  10256. }
  10257. },
  10258. dashScale: {
  10259. enumerable: true,
  10260. get: function get() {
  10261. return this.uniforms.dashScale.value;
  10262. },
  10263. set: function set(value) {
  10264. this.uniforms.dashScale.value = value;
  10265. }
  10266. },
  10267. dashSize: {
  10268. enumerable: true,
  10269. get: function get() {
  10270. return this.uniforms.dashSize.value;
  10271. },
  10272. set: function set(value) {
  10273. this.uniforms.dashSize.value = value;
  10274. }
  10275. },
  10276. dashOffset: {
  10277. enumerable: true,
  10278. get: function get() {
  10279. return this.uniforms.dashOffset.value;
  10280. },
  10281. set: function set(value) {
  10282. this.uniforms.dashOffset.value = value;
  10283. }
  10284. },
  10285. gapSize: {
  10286. enumerable: true,
  10287. get: function get() {
  10288. return this.uniforms.gapSize.value;
  10289. },
  10290. set: function set(value) {
  10291. this.uniforms.gapSize.value = value;
  10292. }
  10293. },
  10294. opacity: {
  10295. enumerable: true,
  10296. get: function get() {
  10297. return this.uniforms.opacity.value;
  10298. },
  10299. set: function set(value) {
  10300. this.uniforms.opacity.value = value;
  10301. }
  10302. },
  10303. resolution: {
  10304. enumerable: true,
  10305. get: function get() {
  10306. return this.uniforms.resolution.value;
  10307. },
  10308. set: function set(value) {
  10309. this.uniforms.resolution.value.copy(value);
  10310. }
  10311. },
  10312. alphaToCoverage: {
  10313. enumerable: true,
  10314. get: function get() {
  10315. return Boolean('USE_ALPHA_TO_COVERAGE' in this.defines);
  10316. },
  10317. set: function set(value) {
  10318. if (Boolean(value) !== Boolean('USE_ALPHA_TO_COVERAGE' in this.defines)) {
  10319. this.needsUpdate = true;
  10320. }
  10321. if (value === true) {
  10322. this.defines.USE_ALPHA_TO_COVERAGE = '';
  10323. this.extensions.derivatives = true;
  10324. } else {
  10325. delete this.defines.USE_ALPHA_TO_COVERAGE;
  10326. this.extensions.derivatives = false;
  10327. }
  10328. }
  10329. },
  10330. dashWithDepth: {
  10331. //add
  10332. enumerable: true,
  10333. get: function get() {
  10334. return 'DASH_with_depth' in this.defines;
  10335. },
  10336. set: function set(value) {
  10337. value = value && !!this.supportExtDepth;
  10338. if (value != this.dashWithDepth) {
  10339. if (value) {
  10340. this.defines.DASH_with_depth = '';
  10341. } else {
  10342. delete this.defines.DASH_with_depth;
  10343. }
  10344. this.needsUpdate = true;
  10345. }
  10346. }
  10347. }
  10348. });
  10349. this.events = {
  10350. setSize: e => {
  10351. //如果出现横条状的异常,往往是viewportOffset出错 //地图不需要
  10352. var viewport = e.viewport;
  10353. //console.log(viewport.name, viewport.resolution2)
  10354. this.uniforms.resolution.value.copy(viewport.resolution2);
  10355. this.uniforms.devicePixelRatio.value = window.devicePixelRatio;
  10356. this.lineWidth = this.lineWidth_; //update
  10357. if (!this.realUseDepth || !e.viewport) return;
  10358. var viewportOffset = viewport.offset || new THREE.Vector2();
  10359. this.uniforms.viewportOffset.value.copy(viewportOffset);
  10360. },
  10361. render: e => {
  10362. //before render 如果有大于两个viewport的话,不同viewport用不同的depthTex
  10363. this.useDepth && this.updateDepthParams(e);
  10364. var viewport = e.viewport || viewer.mainViewport;
  10365. if (viewport != this.lastViewport) {
  10366. //当mapViewer要渲染测量线后,就需要变viewport
  10367. this.events.setSize({
  10368. viewport
  10369. });
  10370. }
  10371. this.lastViewport = viewport;
  10372. }
  10373. };
  10374. this.setValues(parameters);
  10375. var viewport = viewer.mainViewport;
  10376. this.events.setSize({
  10377. viewport
  10378. });
  10379. viewer.addEventListener('resize', this.events.setSize);
  10380. viewer.addEventListener("render.begin", this.events.render);
  10381. }
  10382. get useDepth() {
  10383. return this.useDepth_;
  10384. }
  10385. set useDepth(value) {
  10386. value = value && this.supportExtDepth; //如果不支持 EXT_DEPTH 的话会失效
  10387. if (this.useDepth_ != value) {
  10388. this.setRealDepth(value);
  10389. this.useDepth_ = value;
  10390. }
  10391. }
  10392. setRealDepth(useDepth, viewport) {
  10393. //确实使用到depthTex
  10394. if (this.realUseDepth != useDepth) {
  10395. if (useDepth) {
  10396. this.defines.useDepth = '';
  10397. } else {
  10398. delete this.defines.useDepth;
  10399. }
  10400. this.realUseDepth = useDepth;
  10401. if (this.autoDepthTest) this.depthWrite = this.depthTest = !useDepth; //如果useDepth = false,使用原始的depthTest
  10402. this.needsUpdate = true;
  10403. if (!viewport) viewport = viewer.mainViewport; //暂时这么设置
  10404. useDepth && this.events.setSize({
  10405. viewport
  10406. });
  10407. }
  10408. }
  10409. set fadeFar(far) {
  10410. var needsUpdate = !this.fadeFar != !far; //null为全部范围可见
  10411. //console.log('fadeFar needsUpdate', needsUpdate)
  10412. if (far) {
  10413. this.defines.FadeFar = true;
  10414. this.uniforms.fadeFar.value = far;
  10415. } else {
  10416. delete this.defines.FadeFar;
  10417. }
  10418. needsUpdate && (this.needsUpdate = true);
  10419. }
  10420. get fadeFar() {
  10421. return 'FadeFar' in this.defines && this.uniforms.fadeFar.value;
  10422. }
  10423. updateDepthParams() {
  10424. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  10425. var viewport = e.viewport || viewer.mainViewport;
  10426. var camera = viewport.camera;
  10427. var hasDepth = this.useDepth && camera.isPerspectiveCamera && (Potree.settings.pointEnableRT || Potree.settings.displayMode == 'showPanos' || viewer.useEDL);
  10428. this.setRealDepth(hasDepth, viewport);
  10429. if (hasDepth) {
  10430. this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture; //其实只赋值一次就行
  10431. }
  10432. //hasDepth or FadeFar:
  10433. this.uniforms.nearPlane.value = camera.near;
  10434. this.uniforms.farPlane.value = camera.far;
  10435. //this.uniforms.uUseOrthographicCamera.value = !camera.isPerspectiveCamera
  10436. }
  10437. }
  10438. var _start$2 = new Vector3();
  10439. var _end$2 = new Vector3();
  10440. var _start4 = new Vector4();
  10441. var _end4 = new Vector4();
  10442. var _ssOrigin = new Vector4();
  10443. var _ssOrigin3 = new Vector3();
  10444. var _mvMatrix = new Matrix4();
  10445. var _line = new Line3();
  10446. var _closestPoint = new Vector3();
  10447. var _box$5 = new Box3();
  10448. var _sphere$4 = new Sphere();
  10449. var _clipToWorldVector = new Vector4();
  10450. var _ray$4, _instanceStart, _instanceEnd, _lineWidth;
  10451. // Returns the margin required to expand by in world space given the distance from the camera,
  10452. // line width, resolution, and camera projection
  10453. function getWorldSpaceHalfWidth(camera, distance, resolution) {
  10454. // transform into clip space, adjust the x and y values by the pixel width offset, then
  10455. // transform back into world space to get world offset. Note clip space is [-1, 1] so full
  10456. // width does not need to be halved.
  10457. _clipToWorldVector.set(0, 0, -distance, 1.0).applyMatrix4(camera.projectionMatrix);
  10458. _clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w);
  10459. _clipToWorldVector.x = _lineWidth / resolution.width;
  10460. _clipToWorldVector.y = _lineWidth / resolution.height;
  10461. _clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse);
  10462. _clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w);
  10463. return Math.abs(Math.max(_clipToWorldVector.x, _clipToWorldVector.y));
  10464. }
  10465. function raycastWorldUnits(lineSegments, intersects) {
  10466. for (var i = 0, l = _instanceStart.count; i < l; i++) {
  10467. _line.start.fromBufferAttribute(_instanceStart, i);
  10468. _line.end.fromBufferAttribute(_instanceEnd, i);
  10469. var pointOnLine = new Vector3();
  10470. var point = new Vector3();
  10471. _ray$4.distanceSqToSegment(_line.start, _line.end, point, pointOnLine);
  10472. var isInside = point.distanceTo(pointOnLine) < _lineWidth * 0.5;
  10473. if (isInside) {
  10474. intersects.push({
  10475. point,
  10476. pointOnLine,
  10477. distance: _ray$4.origin.distanceTo(point),
  10478. object: lineSegments,
  10479. face: null,
  10480. faceIndex: i,
  10481. uv: null,
  10482. uv2: null
  10483. });
  10484. }
  10485. }
  10486. }
  10487. function raycastScreenSpace(lineSegments, camera, intersects) {
  10488. var projectionMatrix = camera.projectionMatrix;
  10489. var material = lineSegments.material;
  10490. var resolution = material.resolution;
  10491. var matrixWorld = lineSegments.matrixWorld;
  10492. var geometry = lineSegments.geometry;
  10493. var instanceStart = geometry.attributes.instanceStart;
  10494. var instanceEnd = geometry.attributes.instanceEnd;
  10495. var near = -camera.near;
  10496. //
  10497. // pick a point 1 unit out along the ray to avoid the ray origin
  10498. // sitting at the camera origin which will cause "w" to be 0 when
  10499. // applying the projection matrix.
  10500. _ray$4.at(1, _ssOrigin);
  10501. // ndc space [ - 1.0, 1.0 ]
  10502. _ssOrigin.w = 1;
  10503. _ssOrigin.applyMatrix4(camera.matrixWorldInverse);
  10504. _ssOrigin.applyMatrix4(projectionMatrix);
  10505. _ssOrigin.multiplyScalar(1 / _ssOrigin.w);
  10506. // screen space
  10507. _ssOrigin.x *= resolution.x / 2;
  10508. _ssOrigin.y *= resolution.y / 2;
  10509. _ssOrigin.z = 0;
  10510. _ssOrigin3.copy(_ssOrigin);
  10511. _mvMatrix.multiplyMatrices(camera.matrixWorldInverse, matrixWorld);
  10512. for (var i = 0, l = instanceStart.count; i < l; i++) {
  10513. _start4.fromBufferAttribute(instanceStart, i);
  10514. _end4.fromBufferAttribute(instanceEnd, i);
  10515. _start4.w = 1;
  10516. _end4.w = 1;
  10517. // camera space
  10518. _start4.applyMatrix4(_mvMatrix);
  10519. _end4.applyMatrix4(_mvMatrix);
  10520. // skip the segment if it's entirely behind the camera
  10521. var isBehindCameraNear = _start4.z > near && _end4.z > near;
  10522. if (isBehindCameraNear) {
  10523. continue;
  10524. }
  10525. // trim the segment if it extends behind camera near
  10526. if (_start4.z > near) {
  10527. var deltaDist = _start4.z - _end4.z;
  10528. var t = (_start4.z - near) / deltaDist;
  10529. _start4.lerp(_end4, t);
  10530. } else if (_end4.z > near) {
  10531. var _deltaDist = _end4.z - _start4.z;
  10532. var _t = (_end4.z - near) / _deltaDist;
  10533. _end4.lerp(_start4, _t);
  10534. }
  10535. // clip space
  10536. _start4.applyMatrix4(projectionMatrix);
  10537. _end4.applyMatrix4(projectionMatrix);
  10538. // ndc space [ - 1.0, 1.0 ]
  10539. _start4.multiplyScalar(1 / _start4.w);
  10540. _end4.multiplyScalar(1 / _end4.w);
  10541. // screen space
  10542. _start4.x *= resolution.x / 2;
  10543. _start4.y *= resolution.y / 2;
  10544. _end4.x *= resolution.x / 2;
  10545. _end4.y *= resolution.y / 2;
  10546. // create 2d segment
  10547. _line.start.copy(_start4);
  10548. _line.start.z = 0;
  10549. _line.end.copy(_end4);
  10550. _line.end.z = 0;
  10551. // get closest point on ray to segment
  10552. var param = _line.closestPointToPointParameter(_ssOrigin3, true);
  10553. _line.at(param, _closestPoint);
  10554. // check if the intersection point is within clip space
  10555. var zPos = MathUtils.lerp(_start4.z, _end4.z, param);
  10556. var isInClipSpace = zPos >= -1 && zPos <= 1;
  10557. var isInside = _ssOrigin3.distanceTo(_closestPoint) < _lineWidth * 0.5;
  10558. if (isInClipSpace && isInside) {
  10559. _line.start.fromBufferAttribute(instanceStart, i);
  10560. _line.end.fromBufferAttribute(instanceEnd, i);
  10561. _line.start.applyMatrix4(matrixWorld);
  10562. _line.end.applyMatrix4(matrixWorld);
  10563. var pointOnLine = new Vector3();
  10564. var point = new Vector3();
  10565. _ray$4.distanceSqToSegment(_line.start, _line.end, point, pointOnLine);
  10566. intersects.push({
  10567. point: point,
  10568. pointOnLine: pointOnLine,
  10569. distance: _ray$4.origin.distanceTo(point),
  10570. object: lineSegments,
  10571. face: null,
  10572. faceIndex: i,
  10573. uv: null,
  10574. uv2: null
  10575. });
  10576. }
  10577. }
  10578. }
  10579. class LineSegments2 extends Mesh {
  10580. constructor() {
  10581. var geometry = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new LineSegmentsGeometry();
  10582. var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new LineMaterial({
  10583. color: Math.random() * 0xffffff
  10584. });
  10585. super(geometry, material);
  10586. this.isLineSegments2 = true;
  10587. this.type = 'LineSegments2';
  10588. }
  10589. // for backwards-compatibility, but could be a method of LineSegmentsGeometry...
  10590. computeLineDistances() {
  10591. var geometry = this.geometry;
  10592. var instanceStart = geometry.attributes.instanceStart;
  10593. var instanceEnd = geometry.attributes.instanceEnd;
  10594. var lineDistances = new Float32Array(2 * instanceStart.count);
  10595. for (var i = 0, j = 0, l = instanceStart.count; i < l; i++, j += 2) {
  10596. _start$2.fromBufferAttribute(instanceStart, i);
  10597. _end$2.fromBufferAttribute(instanceEnd, i);
  10598. lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1];
  10599. lineDistances[j + 1] = lineDistances[j] + _start$2.distanceTo(_end$2);
  10600. }
  10601. var instanceDistanceBuffer = new InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1
  10602. geometry.setAttribute('instanceDistanceStart', new InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0
  10603. geometry.setAttribute('instanceDistanceEnd', new InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1
  10604. return this;
  10605. }
  10606. raycast(raycaster, intersects) {
  10607. var worldUnits = this.material.worldUnits;
  10608. var camera = raycaster.camera;
  10609. if (camera === null && !worldUnits) {
  10610. console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.');
  10611. }
  10612. var threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0;
  10613. _ray$4 = raycaster.ray;
  10614. var matrixWorld = this.matrixWorld;
  10615. var geometry = this.geometry;
  10616. var material = this.material;
  10617. _lineWidth = material.lineWidth + threshold;
  10618. _instanceStart = geometry.attributes.instanceStart;
  10619. _instanceEnd = geometry.attributes.instanceEnd;
  10620. // check if we intersect the sphere bounds
  10621. if (geometry.boundingSphere === null) {
  10622. geometry.computeBoundingSphere();
  10623. }
  10624. _sphere$4.copy(geometry.boundingSphere).applyMatrix4(matrixWorld);
  10625. // increase the sphere bounds by the worst case line screen space width
  10626. var sphereMargin;
  10627. if (worldUnits) {
  10628. sphereMargin = _lineWidth * 0.5;
  10629. } else {
  10630. var distanceToSphere = Math.max(camera.near, _sphere$4.distanceToPoint(_ray$4.origin));
  10631. sphereMargin = getWorldSpaceHalfWidth(camera, distanceToSphere, material.resolution);
  10632. }
  10633. _sphere$4.radius += sphereMargin;
  10634. if (_ray$4.intersectsSphere(_sphere$4) === false) {
  10635. return;
  10636. }
  10637. // check if we intersect the box bounds
  10638. if (geometry.boundingBox === null) {
  10639. geometry.computeBoundingBox();
  10640. }
  10641. _box$5.copy(geometry.boundingBox).applyMatrix4(matrixWorld);
  10642. // increase the box bounds by the worst case line width
  10643. var boxMargin;
  10644. if (worldUnits) {
  10645. boxMargin = _lineWidth * 0.5;
  10646. } else {
  10647. var distanceToBox = Math.max(camera.near, _box$5.distanceToPoint(_ray$4.origin));
  10648. boxMargin = getWorldSpaceHalfWidth(camera, distanceToBox, material.resolution);
  10649. }
  10650. _box$5.expandByScalar(boxMargin);
  10651. if (_ray$4.intersectsBox(_box$5) === false) {
  10652. return;
  10653. }
  10654. if (worldUnits) {
  10655. raycastWorldUnits(this, intersects);
  10656. } else {
  10657. raycastScreenSpace(this, camera, intersects);
  10658. }
  10659. }
  10660. }
  10661. class LineGeometry extends LineSegmentsGeometry {
  10662. constructor() {
  10663. super();
  10664. this.isLineGeometry = true;
  10665. this.type = 'LineGeometry';
  10666. }
  10667. setPositions(array) {
  10668. //见potree.shim.js
  10669. // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format
  10670. var length = array.length - 3;
  10671. var points = new Float32Array(2 * length);
  10672. for (var i = 0; i < length; i += 3) {
  10673. points[2 * i] = array[i];
  10674. points[2 * i + 1] = array[i + 1];
  10675. points[2 * i + 2] = array[i + 2];
  10676. points[2 * i + 3] = array[i + 3];
  10677. points[2 * i + 4] = array[i + 4];
  10678. points[2 * i + 5] = array[i + 5];
  10679. }
  10680. super.setPositions(points);
  10681. return this;
  10682. }
  10683. setColors(array) {
  10684. // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format
  10685. var length = array.length - 3;
  10686. var colors = new Float32Array(2 * length);
  10687. for (var i = 0; i < length; i += 3) {
  10688. colors[2 * i] = array[i];
  10689. colors[2 * i + 1] = array[i + 1];
  10690. colors[2 * i + 2] = array[i + 2];
  10691. colors[2 * i + 3] = array[i + 3];
  10692. colors[2 * i + 4] = array[i + 4];
  10693. colors[2 * i + 5] = array[i + 5];
  10694. }
  10695. super.setColors(colors);
  10696. return this;
  10697. }
  10698. fromLine(line) {
  10699. var geometry = line.geometry;
  10700. this.setPositions(geometry.attributes.position.array); // assumes non-indexed
  10701. // set colors, maybe
  10702. return this;
  10703. }
  10704. }
  10705. class Line2 extends LineSegments2 {
  10706. constructor() {
  10707. var geometry = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new LineGeometry();
  10708. var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new LineMaterial({
  10709. color: Math.random() * 0xffffff
  10710. });
  10711. super(geometry, material);
  10712. this.isLine2 = true;
  10713. this.type = 'Line2';
  10714. }
  10715. }
  10716. //old
  10717. function createHeightLine() {
  10718. var lineGeometry = new LineGeometry();
  10719. lineGeometry.setPositions([0, 0, 0, 0, 0, 0]);
  10720. var lineMaterial = new LineMaterial({
  10721. color: 0x00ff00,
  10722. dashSize: 5,
  10723. gapSize: 2,
  10724. linewidth: 2,
  10725. resolution: new Vector2(1000, 1000)
  10726. });
  10727. lineMaterial.depthTest = false;
  10728. var heightEdge = new Line2(lineGeometry, lineMaterial);
  10729. heightEdge.visible = false;
  10730. //this.add(this.heightEdge);
  10731. return heightEdge;
  10732. }
  10733. function createHeightLabel() {
  10734. var heightLabel = new TextSprite$1('');
  10735. heightLabel.setTextColor({
  10736. r: 140,
  10737. g: 250,
  10738. b: 140,
  10739. a: 1.0
  10740. });
  10741. heightLabel.setBorderColor({
  10742. r: 0,
  10743. g: 0,
  10744. b: 0,
  10745. a: 1.0
  10746. });
  10747. heightLabel.setBackgroundColor({
  10748. r: 0,
  10749. g: 0,
  10750. b: 0,
  10751. a: 1.0
  10752. });
  10753. heightLabel.fontsize = 16;
  10754. heightLabel.material.depthTest = false;
  10755. heightLabel.material.opacity = 1;
  10756. heightLabel.visible = false;
  10757. return heightLabel;
  10758. }
  10759. function createAreaLabel() {
  10760. var areaLabel = new TextSprite$1('');
  10761. areaLabel.setTextColor({
  10762. r: 140,
  10763. g: 250,
  10764. b: 140,
  10765. a: 1.0
  10766. });
  10767. areaLabel.setBorderColor({
  10768. r: 0,
  10769. g: 0,
  10770. b: 0,
  10771. a: 1.0
  10772. });
  10773. areaLabel.setBackgroundColor({
  10774. r: 0,
  10775. g: 0,
  10776. b: 0,
  10777. a: 1.0
  10778. });
  10779. areaLabel.fontsize = 16;
  10780. areaLabel.material.depthTest = false;
  10781. areaLabel.material.opacity = 1;
  10782. areaLabel.visible = false;
  10783. return areaLabel;
  10784. }
  10785. function createCircleRadiusLabel() {
  10786. var circleRadiusLabel = new TextSprite$1("");
  10787. circleRadiusLabel.setTextColor({
  10788. r: 140,
  10789. g: 250,
  10790. b: 140,
  10791. a: 1.0
  10792. });
  10793. circleRadiusLabel.setBorderColor({
  10794. r: 0,
  10795. g: 0,
  10796. b: 0,
  10797. a: 1.0
  10798. });
  10799. circleRadiusLabel.setBackgroundColor({
  10800. r: 0,
  10801. g: 0,
  10802. b: 0,
  10803. a: 1.0
  10804. });
  10805. circleRadiusLabel.fontsize = 16;
  10806. circleRadiusLabel.material.depthTest = false;
  10807. circleRadiusLabel.material.opacity = 1;
  10808. circleRadiusLabel.visible = false;
  10809. return circleRadiusLabel;
  10810. }
  10811. function createCircleRadiusLine() {
  10812. var lineGeometry = new LineGeometry();
  10813. lineGeometry.setPositions([0, 0, 0, 0, 0, 0]);
  10814. var lineMaterial = new LineMaterial({
  10815. color: 0xff0000,
  10816. linewidth: 2,
  10817. resolution: new Vector2(1000, 1000),
  10818. gapSize: 1,
  10819. dashed: true
  10820. });
  10821. lineMaterial.depthTest = false;
  10822. var circleRadiusLine = new Line2(lineGeometry, lineMaterial);
  10823. circleRadiusLine.visible = false;
  10824. return circleRadiusLine;
  10825. }
  10826. function createCircleLine() {
  10827. var coordinates = [];
  10828. var n = 128;
  10829. for (var i = 0; i <= n; i++) {
  10830. var u0 = 2 * Math.PI * (i / n);
  10831. var u1 = 2 * Math.PI * (i + 1) / n;
  10832. var p0 = new Vector3(Math.cos(u0), Math.sin(u0), 0);
  10833. var p1 = new Vector3(Math.cos(u1), Math.sin(u1), 0);
  10834. coordinates.push(...p0.toArray(), ...p1.toArray());
  10835. }
  10836. var geometry = new LineGeometry();
  10837. geometry.setPositions(coordinates);
  10838. var material = new LineMaterial({
  10839. color: 0xff0000,
  10840. dashSize: 5,
  10841. gapSize: 2,
  10842. linewidth: 2,
  10843. resolution: new Vector2(1000, 1000)
  10844. });
  10845. material.depthTest = false;
  10846. var circleLine = new Line2(geometry, material);
  10847. circleLine.visible = false;
  10848. circleLine.computeLineDistances();
  10849. return circleLine;
  10850. }
  10851. function createCircleCenter() {
  10852. var sg = new SphereGeometry(1, 32, 32);
  10853. var sm = new MeshNormalMaterial();
  10854. var circleCenter = new Mesh(sg, sm);
  10855. circleCenter.visible = false;
  10856. return circleCenter;
  10857. }
  10858. function createLine() {
  10859. var geometry = new LineGeometry();
  10860. geometry.setPositions([0, 0, 0, 0, 0, 0]);
  10861. var material = new LineMaterial({
  10862. color: 0xff0000,
  10863. linewidth: 2,
  10864. resolution: new Vector2(1000, 1000),
  10865. gapSize: 1,
  10866. dashed: true
  10867. });
  10868. material.depthTest = false;
  10869. var line = new Line2(geometry, material);
  10870. return line;
  10871. }
  10872. function createCircle() {
  10873. var coordinates = [];
  10874. var n = 128;
  10875. for (var i = 0; i <= n; i++) {
  10876. var u0 = 2 * Math.PI * (i / n);
  10877. var u1 = 2 * Math.PI * (i + 1) / n;
  10878. var p0 = new Vector3(Math.cos(u0), Math.sin(u0), 0);
  10879. var p1 = new Vector3(Math.cos(u1), Math.sin(u1), 0);
  10880. coordinates.push(...p0.toArray(), ...p1.toArray());
  10881. }
  10882. var geometry = new LineGeometry();
  10883. geometry.setPositions(coordinates);
  10884. var material = new LineMaterial({
  10885. color: 0xff0000,
  10886. dashSize: 5,
  10887. gapSize: 2,
  10888. linewidth: 2,
  10889. resolution: new Vector2(1000, 1000)
  10890. });
  10891. material.depthTest = false;
  10892. var line = new Line2(geometry, material);
  10893. line.computeLineDistances();
  10894. return line;
  10895. }
  10896. function createAzimuth() {
  10897. var azimuth = {
  10898. label: null,
  10899. center: null,
  10900. target: null,
  10901. north: null,
  10902. centerToNorth: null,
  10903. centerToTarget: null,
  10904. centerToTargetground: null,
  10905. targetgroundToTarget: null,
  10906. circle: null,
  10907. node: null
  10908. };
  10909. var sg = new SphereGeometry(1, 32, 32);
  10910. var sm = new MeshNormalMaterial();
  10911. {
  10912. var label = new TextSprite$1("");
  10913. label.setTextColor({
  10914. r: 140,
  10915. g: 250,
  10916. b: 140,
  10917. a: 1.0
  10918. });
  10919. label.setBorderColor({
  10920. r: 0,
  10921. g: 0,
  10922. b: 0,
  10923. a: 1.0
  10924. });
  10925. label.setBackgroundColor({
  10926. r: 0,
  10927. g: 0,
  10928. b: 0,
  10929. a: 1.0
  10930. });
  10931. label.fontsize = 16;
  10932. label.material.depthTest = false;
  10933. label.material.opacity = 1;
  10934. azimuth.label = label;
  10935. }
  10936. azimuth.center = new Mesh(sg, sm);
  10937. azimuth.target = new Mesh(sg, sm);
  10938. azimuth.north = new Mesh(sg, sm);
  10939. azimuth.centerToNorth = createLine();
  10940. azimuth.centerToTarget = createLine();
  10941. azimuth.centerToTargetground = createLine();
  10942. azimuth.targetgroundToTarget = createLine();
  10943. azimuth.circle = createCircle();
  10944. azimuth.node = new Object3D();
  10945. azimuth.node.add(azimuth.centerToNorth, azimuth.centerToTarget, azimuth.centerToTargetground, azimuth.targetgroundToTarget, azimuth.circle, azimuth.label, azimuth.center, azimuth.target, azimuth.north);
  10946. return azimuth;
  10947. }
  10948. class Measure extends Object3D {
  10949. constructor() {
  10950. super();
  10951. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  10952. this.name = 'Measure_' + this.constructor.counter;
  10953. this.points = [];
  10954. this._showDistances = true;
  10955. this._showCoordinates = false;
  10956. this._showArea = false;
  10957. this._closed = true;
  10958. this._showAngles = false;
  10959. this._showCircle = false;
  10960. this._showHeight = false;
  10961. this._showEdges = true;
  10962. this._showAzimuth = false;
  10963. this.maxMarkers = Number.MAX_SAFE_INTEGER;
  10964. this.sphereGeometry = new SphereGeometry(0.4, 10, 10);
  10965. this.color = new Color(0xff0000);
  10966. this.spheres = [];
  10967. this.edges = [];
  10968. this.sphereLabels = [];
  10969. this.edgeLabels = [];
  10970. this.angleLabels = [];
  10971. this.coordinateLabels = [];
  10972. this.heightEdge = createHeightLine();
  10973. this.heightLabel = createHeightLabel();
  10974. this.areaLabel = createAreaLabel();
  10975. this.circleRadiusLabel = createCircleRadiusLabel();
  10976. this.circleRadiusLine = createCircleRadiusLine();
  10977. this.circleLine = createCircleLine();
  10978. this.circleCenter = createCircleCenter();
  10979. this.azimuth = createAzimuth();
  10980. this.add(this.heightEdge);
  10981. this.add(this.heightLabel);
  10982. this.add(this.areaLabel);
  10983. this.add(this.circleRadiusLabel);
  10984. this.add(this.circleRadiusLine);
  10985. this.add(this.circleLine);
  10986. this.add(this.circleCenter);
  10987. this.add(this.azimuth.node);
  10988. }
  10989. createSphereMaterial() {
  10990. var sphereMaterial = new MeshLambertMaterial({
  10991. //shading: THREE.SmoothShading,
  10992. color: this.color,
  10993. depthTest: false,
  10994. depthWrite: false
  10995. });
  10996. return sphereMaterial;
  10997. }
  10998. addMarker(point) {
  10999. if (point.x != null) {
  11000. point = {
  11001. position: point
  11002. };
  11003. } else if (point instanceof Array) {
  11004. point = {
  11005. position: new Vector3(...point)
  11006. };
  11007. }
  11008. this.points.push(point);
  11009. // sphere
  11010. var sphere = new Mesh(this.sphereGeometry, this.createSphereMaterial());
  11011. this.add(sphere);
  11012. this.spheres.push(sphere);
  11013. {
  11014. // edges
  11015. var lineGeometry = new LineGeometry();
  11016. lineGeometry.setPositions([0, 0, 0, 0, 0, 0]);
  11017. var lineMaterial = new LineMaterial({
  11018. color: 0xff0000,
  11019. linewidth: 2,
  11020. resolution: new Vector2(1000, 1000)
  11021. });
  11022. lineMaterial.depthTest = false;
  11023. var edge = new Line2(lineGeometry, lineMaterial);
  11024. edge.visible = true;
  11025. this.add(edge);
  11026. this.edges.push(edge);
  11027. }
  11028. {
  11029. // edge labels
  11030. var edgeLabel = new TextSprite$1();
  11031. edgeLabel.setBorderColor({
  11032. r: 0,
  11033. g: 0,
  11034. b: 0,
  11035. a: 1.0
  11036. });
  11037. edgeLabel.setBackgroundColor({
  11038. r: 0,
  11039. g: 0,
  11040. b: 0,
  11041. a: 1.0
  11042. });
  11043. edgeLabel.material.depthTest = false;
  11044. edgeLabel.visible = false;
  11045. edgeLabel.fontsize = 16;
  11046. this.edgeLabels.push(edgeLabel);
  11047. this.add(edgeLabel);
  11048. }
  11049. {
  11050. // angle labels
  11051. var angleLabel = new TextSprite$1();
  11052. angleLabel.setBorderColor({
  11053. r: 0,
  11054. g: 0,
  11055. b: 0,
  11056. a: 1.0
  11057. });
  11058. angleLabel.setBackgroundColor({
  11059. r: 0,
  11060. g: 0,
  11061. b: 0,
  11062. a: 1.0
  11063. });
  11064. angleLabel.fontsize = 16;
  11065. angleLabel.material.depthTest = false;
  11066. angleLabel.material.opacity = 1;
  11067. angleLabel.visible = false;
  11068. this.angleLabels.push(angleLabel);
  11069. this.add(angleLabel);
  11070. }
  11071. {
  11072. // coordinate labels
  11073. var coordinateLabel = new TextSprite$1();
  11074. coordinateLabel.setBorderColor({
  11075. r: 0,
  11076. g: 0,
  11077. b: 0,
  11078. a: 1.0
  11079. });
  11080. coordinateLabel.setBackgroundColor({
  11081. r: 0,
  11082. g: 0,
  11083. b: 0,
  11084. a: 1.0
  11085. });
  11086. coordinateLabel.fontsize = 16;
  11087. coordinateLabel.material.depthTest = false;
  11088. coordinateLabel.material.opacity = 1;
  11089. coordinateLabel.visible = false;
  11090. this.coordinateLabels.push(coordinateLabel);
  11091. this.add(coordinateLabel);
  11092. }
  11093. {
  11094. // Event Listeners
  11095. var drag = e => {
  11096. var I = Utils.getMousePointCloudIntersection(e.drag.end, e.viewer.scene.getActiveCamera(), e.viewer, e.viewer.scene.pointclouds, {
  11097. pickClipped: true
  11098. });
  11099. if (I) {
  11100. var i = this.spheres.indexOf(e.drag.object);
  11101. if (i !== -1) {
  11102. var _point = this.points[i];
  11103. // loop through current keys and cleanup ones that will be orphaned
  11104. for (var key of Object.keys(_point)) {
  11105. if (!I.point[key]) {
  11106. delete _point[key];
  11107. }
  11108. }
  11109. for (var _key of Object.keys(I.point).filter(e => e !== 'position')) {
  11110. _point[_key] = I.point[_key];
  11111. }
  11112. this.setPosition(i, I.location);
  11113. }
  11114. }
  11115. };
  11116. var drop = e => {
  11117. var i = this.spheres.indexOf(e.drag.object);
  11118. if (i !== -1) {
  11119. this.dispatchEvent({
  11120. 'type': 'marker_dropped',
  11121. 'measurement': this,
  11122. 'index': i
  11123. });
  11124. }
  11125. };
  11126. var mouseover = e => e.object.material.emissive.setHex(0x888888);
  11127. var mouseleave = e => e.object.material.emissive.setHex(0x000000);
  11128. sphere.addEventListener('drag', drag);
  11129. sphere.addEventListener('drop', drop);
  11130. sphere.addEventListener('mouseover', mouseover);
  11131. sphere.addEventListener('mouseleave', mouseleave);
  11132. }
  11133. var event = {
  11134. type: 'marker_added',
  11135. measurement: this,
  11136. sphere: sphere
  11137. };
  11138. this.dispatchEvent(event);
  11139. this.setMarker(this.points.length - 1, point);
  11140. }
  11141. removeMarker(index) {
  11142. this.points.splice(index, 1);
  11143. this.remove(this.spheres[index]);
  11144. var edgeIndex = index === 0 ? 0 : index - 1;
  11145. this.remove(this.edges[edgeIndex]);
  11146. this.edges.splice(edgeIndex, 1);
  11147. this.remove(this.edgeLabels[edgeIndex]);
  11148. this.edgeLabels.splice(edgeIndex, 1);
  11149. this.coordinateLabels.splice(index, 1);
  11150. this.remove(this.angleLabels[index]);
  11151. this.angleLabels.splice(index, 1);
  11152. this.spheres.splice(index, 1);
  11153. this.update();
  11154. this.dispatchEvent({
  11155. type: 'marker_removed',
  11156. measurement: this
  11157. });
  11158. }
  11159. setMarker(index, point) {
  11160. this.points[index] = point;
  11161. var event = {
  11162. type: 'marker_moved',
  11163. measure: this,
  11164. index: index,
  11165. position: point.position.clone()
  11166. };
  11167. this.dispatchEvent(event);
  11168. this.update();
  11169. }
  11170. setPosition(index, position) {
  11171. var point = this.points[index];
  11172. point.position.copy(position);
  11173. var event = {
  11174. type: 'marker_moved',
  11175. measure: this,
  11176. index: index,
  11177. position: position.clone()
  11178. };
  11179. this.dispatchEvent(event);
  11180. this.update();
  11181. }
  11182. getArea() {
  11183. var area = 0;
  11184. var j = this.points.length - 1;
  11185. for (var i = 0; i < this.points.length; i++) {
  11186. var p1 = this.points[i].position;
  11187. var p2 = this.points[j].position;
  11188. area += (p2.x + p1.x) * (p1.y - p2.y);
  11189. j = i;
  11190. }
  11191. return Math.abs(area / 2);
  11192. }
  11193. getTotalDistance() {
  11194. if (this.points.length === 0) {
  11195. return 0;
  11196. }
  11197. var distance = 0;
  11198. for (var i = 1; i < this.points.length; i++) {
  11199. var prev = this.points[i - 1].position;
  11200. var curr = this.points[i].position;
  11201. var d = prev.distanceTo(curr);
  11202. distance += d;
  11203. }
  11204. if (this.closed && this.points.length > 1) {
  11205. var first = this.points[0].position;
  11206. var last = this.points[this.points.length - 1].position;
  11207. var _d = last.distanceTo(first);
  11208. distance += _d;
  11209. }
  11210. return distance;
  11211. }
  11212. getAngleBetweenLines(cornerPoint, point1, point2) {
  11213. var v1 = new Vector3().subVectors(point1.position, cornerPoint.position);
  11214. var v2 = new Vector3().subVectors(point2.position, cornerPoint.position);
  11215. // avoid the error printed by threejs if denominator is 0
  11216. var denominator = Math.sqrt(v1.lengthSq() * v2.lengthSq());
  11217. if (denominator === 0) {
  11218. return 0;
  11219. } else {
  11220. return v1.angleTo(v2);
  11221. }
  11222. }
  11223. getAngle(index) {
  11224. if (this.points.length < 3 || index >= this.points.length) {
  11225. return 0;
  11226. }
  11227. var previous = index === 0 ? this.points[this.points.length - 1] : this.points[index - 1];
  11228. var point = this.points[index];
  11229. var next = this.points[(index + 1) % this.points.length];
  11230. return this.getAngleBetweenLines(point, previous, next);
  11231. }
  11232. // updateAzimuth(){
  11233. // // if(this.points.length !== 2){
  11234. // // return;
  11235. // // }
  11236. // // const azimuth = this.azimuth;
  11237. // // const [p0, p1] = this.points;
  11238. // // const r = p0.position.distanceTo(p1.position);
  11239. // }
  11240. update() {
  11241. if (this.points.length === 0) {
  11242. return;
  11243. } else if (this.points.length === 1) {
  11244. var point = this.points[0];
  11245. var position = point.position;
  11246. this.spheres[0].position.copy(position);
  11247. {
  11248. // coordinate labels
  11249. var coordinateLabel = this.coordinateLabels[0];
  11250. var msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  11251. coordinateLabel.setText(msg);
  11252. coordinateLabel.visible = this.showCoordinates;
  11253. }
  11254. return;
  11255. }
  11256. var lastIndex = this.points.length - 1;
  11257. var centroid = new Vector3();
  11258. for (var i = 0; i <= lastIndex; i++) {
  11259. var _point2 = this.points[i];
  11260. centroid.add(_point2.position);
  11261. }
  11262. centroid.divideScalar(this.points.length);
  11263. for (var _i = 0; _i <= lastIndex; _i++) {
  11264. var index = _i;
  11265. var nextIndex = _i + 1 > lastIndex ? 0 : _i + 1;
  11266. var previousIndex = _i === 0 ? lastIndex : _i - 1;
  11267. var _point3 = this.points[index];
  11268. var nextPoint = this.points[nextIndex];
  11269. var previousPoint = this.points[previousIndex];
  11270. var sphere = this.spheres[index];
  11271. // spheres
  11272. sphere.position.copy(_point3.position);
  11273. sphere.material.color = this.color;
  11274. {
  11275. // edges
  11276. var edge = this.edges[index];
  11277. edge.material.color = this.color;
  11278. edge.position.copy(_point3.position);
  11279. edge.geometry.setPositions([0, 0, 0, ...nextPoint.position.clone().sub(_point3.position).toArray()]);
  11280. edge.geometry.verticesNeedUpdate = true;
  11281. edge.geometry.computeBoundingSphere();
  11282. edge.computeLineDistances();
  11283. edge.visible = index < lastIndex || this.closed;
  11284. if (!this.showEdges) {
  11285. edge.visible = false;
  11286. }
  11287. }
  11288. {
  11289. // edge labels
  11290. var edgeLabel = this.edgeLabels[_i];
  11291. var center = new Vector3().add(_point3.position);
  11292. center.add(nextPoint.position);
  11293. center = center.multiplyScalar(0.5);
  11294. var distance = _point3.position.distanceTo(nextPoint.position);
  11295. edgeLabel.position.copy(center);
  11296. var suffix = "";
  11297. if (this.lengthUnit != null && this.lengthUnitDisplay != null) {
  11298. distance = distance / this.lengthUnit.unitspermeter * this.lengthUnitDisplay.unitspermeter; //convert to meters then to the display unit
  11299. suffix = this.lengthUnitDisplay.code;
  11300. }
  11301. var txtLength = Utils.addCommas(distance.toFixed(2));
  11302. edgeLabel.setText("".concat(txtLength, " ").concat(suffix));
  11303. edgeLabel.visible = this.showDistances && (index < lastIndex || this.closed) && this.points.length >= 2 && distance > 0;
  11304. }
  11305. {
  11306. // angle labels
  11307. var angleLabel = this.angleLabels[_i];
  11308. var angle = this.getAngleBetweenLines(_point3, previousPoint, nextPoint);
  11309. var dir = nextPoint.position.clone().sub(previousPoint.position);
  11310. dir.multiplyScalar(0.5);
  11311. dir = previousPoint.position.clone().add(dir).sub(_point3.position).normalize();
  11312. var dist = Math.min(_point3.position.distanceTo(previousPoint.position), _point3.position.distanceTo(nextPoint.position));
  11313. dist = dist / 9;
  11314. var labelPos = _point3.position.clone().add(dir.multiplyScalar(dist));
  11315. angleLabel.position.copy(labelPos);
  11316. var _msg = Utils.addCommas((angle * (180.0 / Math.PI)).toFixed(1)) + '\u00B0';
  11317. angleLabel.setText(_msg);
  11318. angleLabel.visible = this.showAngles && (index < lastIndex || this.closed) && this.points.length >= 3 && angle > 0;
  11319. }
  11320. }
  11321. {
  11322. // update height stuff
  11323. var heightEdge = this.heightEdge;
  11324. heightEdge.visible = this.showHeight;
  11325. this.heightLabel.visible = this.showHeight;
  11326. if (this.showHeight) {
  11327. var sorted = this.points.slice().sort((a, b) => a.position.z - b.position.z);
  11328. var lowPoint = sorted[0].position.clone();
  11329. var highPoint = sorted[sorted.length - 1].position.clone();
  11330. var min = lowPoint.z;
  11331. var max = highPoint.z;
  11332. var height = max - min;
  11333. var start = new Vector3(highPoint.x, highPoint.y, min);
  11334. var end = new Vector3(highPoint.x, highPoint.y, max);
  11335. heightEdge.position.copy(lowPoint);
  11336. heightEdge.geometry.setPositions([0, 0, 0, ...start.clone().sub(lowPoint).toArray(), ...start.clone().sub(lowPoint).toArray(), ...end.clone().sub(lowPoint).toArray()]);
  11337. heightEdge.geometry.verticesNeedUpdate = true;
  11338. // heightEdge.geometry.computeLineDistances();
  11339. // heightEdge.geometry.lineDistancesNeedUpdate = true;
  11340. heightEdge.geometry.computeBoundingSphere();
  11341. heightEdge.computeLineDistances();
  11342. // heightEdge.material.dashSize = height / 40;
  11343. // heightEdge.material.gapSize = height / 40;
  11344. var heightLabelPosition = start.clone().add(end).multiplyScalar(0.5);
  11345. this.heightLabel.position.copy(heightLabelPosition);
  11346. var _suffix = "";
  11347. if (this.lengthUnit != null && this.lengthUnitDisplay != null) {
  11348. height = height / this.lengthUnit.unitspermeter * this.lengthUnitDisplay.unitspermeter; //convert to meters then to the display unit
  11349. _suffix = this.lengthUnitDisplay.code;
  11350. }
  11351. var txtHeight = Utils.addCommas(height.toFixed(2));
  11352. var _msg2 = "".concat(txtHeight, " ").concat(_suffix);
  11353. this.heightLabel.setText(_msg2);
  11354. }
  11355. }
  11356. {
  11357. // update circle stuff
  11358. var circleRadiusLabel = this.circleRadiusLabel;
  11359. var circleRadiusLine = this.circleRadiusLine;
  11360. var circleLine = this.circleLine;
  11361. var circleCenter = this.circleCenter;
  11362. var circleOkay = this.points.length === 3;
  11363. circleRadiusLabel.visible = this.showCircle && circleOkay;
  11364. circleRadiusLine.visible = this.showCircle && circleOkay;
  11365. circleLine.visible = this.showCircle && circleOkay;
  11366. circleCenter.visible = this.showCircle && circleOkay;
  11367. if (this.showCircle && circleOkay) {
  11368. var A = this.points[0].position;
  11369. var B = this.points[1].position;
  11370. var C = this.points[2].position;
  11371. var AB = B.clone().sub(A);
  11372. var AC = C.clone().sub(A);
  11373. var N = AC.clone().cross(AB).normalize();
  11374. var _center = Potree.Utils.computeCircleCenter(A, B, C);
  11375. var radius = _center.distanceTo(A);
  11376. var scale = radius / 20;
  11377. circleCenter.position.copy(_center);
  11378. circleCenter.scale.set(scale, scale, scale);
  11379. //circleRadiusLine.geometry.vertices[0].set(0, 0, 0);
  11380. //circleRadiusLine.geometry.vertices[1].copy(B.clone().sub(center));
  11381. circleRadiusLine.geometry.setPositions([0, 0, 0, ...B.clone().sub(_center).toArray()]);
  11382. circleRadiusLine.geometry.verticesNeedUpdate = true;
  11383. circleRadiusLine.geometry.computeBoundingSphere();
  11384. circleRadiusLine.position.copy(_center);
  11385. circleRadiusLine.computeLineDistances();
  11386. var target = _center.clone().add(N);
  11387. circleLine.position.copy(_center);
  11388. circleLine.scale.set(radius, radius, radius);
  11389. circleLine.lookAt(target);
  11390. circleRadiusLabel.visible = true;
  11391. circleRadiusLabel.position.copy(_center.clone().add(B).multiplyScalar(0.5));
  11392. circleRadiusLabel.setText("".concat(radius.toFixed(3)));
  11393. }
  11394. }
  11395. {
  11396. // update area label
  11397. this.areaLabel.position.copy(centroid);
  11398. this.areaLabel.visible = this.showArea && this.points.length >= 3;
  11399. var area = this.getArea();
  11400. var _suffix2 = "";
  11401. if (this.lengthUnit != null && this.lengthUnitDisplay != null) {
  11402. area = area / Math.pow(this.lengthUnit.unitspermeter, 2) * Math.pow(this.lengthUnitDisplay.unitspermeter, 2); //convert to square meters then to the square display unit
  11403. _suffix2 = this.lengthUnitDisplay.code;
  11404. }
  11405. var txtArea = Utils.addCommas(area.toFixed(1));
  11406. var _msg3 = "".concat(txtArea, " ").concat(_suffix2, "\xB2");
  11407. this.areaLabel.setText(_msg3);
  11408. }
  11409. // this.updateAzimuth();
  11410. }
  11411. raycast(raycaster, intersects) {
  11412. for (var i = 0; i < this.points.length; i++) {
  11413. var sphere = this.spheres[i];
  11414. sphere.raycast(raycaster, intersects);
  11415. }
  11416. // recalculate distances because they are not necessarely correct
  11417. // for scaled objects.
  11418. // see https://github.com/mrdoob/three.js/issues/5827
  11419. // TODO: remove this once the bug has been fixed
  11420. for (var _i2 = 0; _i2 < intersects.length; _i2++) {
  11421. var I = intersects[_i2];
  11422. I.distance = raycaster.ray.origin.distanceTo(I.point);
  11423. }
  11424. intersects.sort(function (a, b) {
  11425. return a.distance - b.distance;
  11426. });
  11427. }
  11428. get showCoordinates() {
  11429. return this._showCoordinates;
  11430. }
  11431. set showCoordinates(value) {
  11432. this._showCoordinates = value;
  11433. this.update();
  11434. }
  11435. get showAngles() {
  11436. return this._showAngles;
  11437. }
  11438. set showAngles(value) {
  11439. this._showAngles = value;
  11440. this.update();
  11441. }
  11442. get showCircle() {
  11443. return this._showCircle;
  11444. }
  11445. set showCircle(value) {
  11446. this._showCircle = value;
  11447. this.update();
  11448. }
  11449. get showAzimuth() {
  11450. return this._showAzimuth;
  11451. }
  11452. set showAzimuth(value) {
  11453. this._showAzimuth = value;
  11454. this.update();
  11455. }
  11456. get showEdges() {
  11457. return this._showEdges;
  11458. }
  11459. set showEdges(value) {
  11460. this._showEdges = value;
  11461. this.update();
  11462. }
  11463. get showHeight() {
  11464. return this._showHeight;
  11465. }
  11466. set showHeight(value) {
  11467. this._showHeight = value;
  11468. this.update();
  11469. }
  11470. get showArea() {
  11471. return this._showArea;
  11472. }
  11473. set showArea(value) {
  11474. this._showArea = value;
  11475. this.update();
  11476. }
  11477. get closed() {
  11478. return this._closed;
  11479. }
  11480. set closed(value) {
  11481. this._closed = value;
  11482. this.update();
  11483. }
  11484. get showDistances() {
  11485. return this._showDistances;
  11486. }
  11487. set showDistances(value) {
  11488. this._showDistances = value;
  11489. this.update();
  11490. }
  11491. }
  11492. class PolygonClipVolume extends Object3D {
  11493. constructor(camera) {
  11494. super();
  11495. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  11496. this.name = "polygon_clip_volume_" + this.constructor.counter;
  11497. this.camera = camera.clone();
  11498. this.camera.rotation.set(...camera.rotation.toArray()); // [r85] workaround because camera.clone() doesn't work on rotation
  11499. this.camera.rotation.order = camera.rotation.order;
  11500. this.camera.updateMatrixWorld();
  11501. this.camera.updateProjectionMatrix();
  11502. this.camera.matrixWorldInverse.copy(this.camera.matrixWorld).invert();
  11503. this.viewMatrix = this.camera.matrixWorldInverse.clone();
  11504. this.projMatrix = this.camera.projectionMatrix.clone();
  11505. // projected markers
  11506. this.markers = [];
  11507. this.initialized = false;
  11508. }
  11509. addMarker() {
  11510. var marker = new Mesh();
  11511. var cancel;
  11512. var drag = e => {
  11513. var size = e.viewer.renderer.getSize(new Vector2());
  11514. var projectedPos = new Vector3(2.0 * (e.drag.end.x / size.width) - 1.0, -2.0 * (e.drag.end.y / size.height) + 1.0, 0);
  11515. marker.position.copy(projectedPos);
  11516. };
  11517. var drop = e => {
  11518. cancel();
  11519. };
  11520. cancel = e => {
  11521. marker.removeEventListener("drag", drag);
  11522. marker.removeEventListener("drop", drop);
  11523. };
  11524. marker.addEventListener("drag", drag);
  11525. marker.addEventListener("drop", drop);
  11526. this.markers.push(marker);
  11527. }
  11528. removeLastMarker() {
  11529. if (this.markers.length > 0) {
  11530. this.markers.splice(this.markers.length - 1, 1);
  11531. }
  11532. }
  11533. }
  11534. ;
  11535. class Utils {
  11536. static async loadShapefileFeatures(file, callback) {
  11537. var features = [];
  11538. var handleFinish = () => {
  11539. callback(features);
  11540. };
  11541. var source = await shapefile.open(file);
  11542. while (true) {
  11543. var result = await source.read();
  11544. if (result.done) {
  11545. handleFinish();
  11546. break;
  11547. }
  11548. if (result.value && result.value.type === 'Feature' && result.value.geometry !== undefined) {
  11549. features.push(result.value);
  11550. }
  11551. }
  11552. }
  11553. static toString(value) {
  11554. if (value.x != null) {
  11555. return value.x.toFixed(2) + ', ' + value.y.toFixed(2) + ', ' + value.z.toFixed(2);
  11556. } else {
  11557. return '' + value + '';
  11558. }
  11559. }
  11560. static normalizeURL(url) {
  11561. var u = new URL(url);
  11562. return u.protocol + '//' + u.hostname + u.pathname.replace(/\/+/g, '/');
  11563. }
  11564. static pathExists(url) {
  11565. var req = XHRFactory.createXMLHttpRequest();
  11566. req.open('GET', url, false);
  11567. req.send(null);
  11568. if (req.status !== 200) {
  11569. return false;
  11570. }
  11571. return true;
  11572. }
  11573. static debugSphere(parent, position, scale, color) {
  11574. var geometry = new SphereGeometry(1, 8, 8);
  11575. var material;
  11576. if (color !== undefined) {
  11577. material = new MeshBasicMaterial({
  11578. color: color
  11579. });
  11580. } else {
  11581. material = new MeshNormalMaterial();
  11582. }
  11583. var sphere = new Mesh(geometry, material);
  11584. sphere.position.copy(position);
  11585. sphere.scale.set(scale, scale, scale);
  11586. parent.add(sphere);
  11587. return sphere;
  11588. }
  11589. static debugLine(parent, start, end, color) {
  11590. var material = new LineBasicMaterial({
  11591. color: color
  11592. });
  11593. var geometry = new Geometry();
  11594. var p1 = new Vector3(0, 0, 0);
  11595. var p2 = end.clone().sub(start);
  11596. geometry.vertices.push(p1, p2);
  11597. var tl = new Line(geometry, material);
  11598. tl.position.copy(start);
  11599. parent.add(tl);
  11600. var line = {
  11601. node: tl,
  11602. set: (start, end) => {
  11603. geometry.vertices[0].copy(start);
  11604. geometry.vertices[1].copy(end);
  11605. geometry.verticesNeedUpdate = true;
  11606. }
  11607. };
  11608. return line;
  11609. }
  11610. static debugCircle(parent, center, radius, normal, color) {
  11611. var material = new LineBasicMaterial({
  11612. color: color
  11613. });
  11614. var geometry = new Geometry();
  11615. var n = 32;
  11616. for (var i = 0; i <= n; i++) {
  11617. var u0 = 2 * Math.PI * (i / n);
  11618. var u1 = 2 * Math.PI * (i + 1) / n;
  11619. var p0 = new Vector3(Math.cos(u0), Math.sin(u0), 0);
  11620. var p1 = new Vector3(Math.cos(u1), Math.sin(u1), 0);
  11621. geometry.vertices.push(p0, p1);
  11622. }
  11623. var tl = new Line(geometry, material);
  11624. tl.position.copy(center);
  11625. tl.scale.set(radius, radius, radius);
  11626. parent.add(tl);
  11627. }
  11628. static debugBox(parent, box) {
  11629. var transform = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Matrix4();
  11630. var color = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0xFFFF00;
  11631. var vertices = [[box.min.x, box.min.y, box.min.z], [box.min.x, box.min.y, box.max.z], [box.min.x, box.max.y, box.min.z], [box.min.x, box.max.y, box.max.z], [box.max.x, box.min.y, box.min.z], [box.max.x, box.min.y, box.max.z], [box.max.x, box.max.y, box.min.z], [box.max.x, box.max.y, box.max.z]].map(v => new Vector3(...v));
  11632. var edges = [[0, 4], [4, 5], [5, 1], [1, 0], [2, 6], [6, 7], [7, 3], [3, 2], [0, 2], [4, 6], [5, 7], [1, 3]];
  11633. var center = box.getCenter(new Vector3());
  11634. var centroids = [{
  11635. position: [box.min.x, center.y, center.z],
  11636. color: 0xFF0000
  11637. }, {
  11638. position: [box.max.x, center.y, center.z],
  11639. color: 0x880000
  11640. }, {
  11641. position: [center.x, box.min.y, center.z],
  11642. color: 0x00FF00
  11643. }, {
  11644. position: [center.x, box.max.y, center.z],
  11645. color: 0x008800
  11646. }, {
  11647. position: [center.x, center.y, box.min.z],
  11648. color: 0x0000FF
  11649. }, {
  11650. position: [center.x, center.y, box.max.z],
  11651. color: 0x000088
  11652. }];
  11653. for (var vertex of vertices) {
  11654. var pos = vertex.clone().applyMatrix4(transform);
  11655. Utils.debugSphere(parent, pos, 0.1, 0xFF0000);
  11656. }
  11657. for (var edge of edges) {
  11658. var start = vertices[edge[0]].clone().applyMatrix4(transform);
  11659. var end = vertices[edge[1]].clone().applyMatrix4(transform);
  11660. Utils.debugLine(parent, start, end, color);
  11661. }
  11662. for (var centroid of centroids) {
  11663. var _pos = new Vector3(...centroid.position).applyMatrix4(transform);
  11664. Utils.debugSphere(parent, _pos, 0.1, centroid.color);
  11665. }
  11666. }
  11667. static debugPlane(parent, plane) {
  11668. var size = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
  11669. var color = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0x0000FF;
  11670. var planehelper = new PlaneHelper(plane, size, color);
  11671. parent.add(planehelper);
  11672. }
  11673. /**
  11674. * adapted from mhluska at https://github.com/mrdoob/three.js/issues/1561
  11675. */
  11676. static computeTransformedBoundingBox(box, transform) {
  11677. var vertices = [new Vector3(box.min.x, box.min.y, box.min.z).applyMatrix4(transform), new Vector3(box.min.x, box.min.y, box.min.z).applyMatrix4(transform), new Vector3(box.max.x, box.min.y, box.min.z).applyMatrix4(transform), new Vector3(box.min.x, box.max.y, box.min.z).applyMatrix4(transform), new Vector3(box.min.x, box.min.y, box.max.z).applyMatrix4(transform), new Vector3(box.min.x, box.max.y, box.max.z).applyMatrix4(transform), new Vector3(box.max.x, box.max.y, box.min.z).applyMatrix4(transform), new Vector3(box.max.x, box.min.y, box.max.z).applyMatrix4(transform), new Vector3(box.max.x, box.max.y, box.max.z).applyMatrix4(transform)];
  11678. var boundingBox = new Box3();
  11679. boundingBox.setFromPoints(vertices);
  11680. return boundingBox;
  11681. }
  11682. //感觉就是bound.applyMatrix4(transform)
  11683. /**
  11684. * add separators to large numbers
  11685. *
  11686. * @param nStr
  11687. * @returns
  11688. */
  11689. static addCommas(nStr) {
  11690. nStr += '';
  11691. var x = nStr.split('.');
  11692. var x1 = x[0];
  11693. var x2 = x.length > 1 ? '.' + x[1] : '';
  11694. var rgx = /(\d+)(\d{3})/;
  11695. while (rgx.test(x1)) {
  11696. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  11697. }
  11698. return x1 + x2;
  11699. }
  11700. static removeCommas(str) {
  11701. return str.replace(/,/g, '');
  11702. }
  11703. /**
  11704. * create worker from a string
  11705. *
  11706. * code from http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string
  11707. */
  11708. static createWorker(code) {
  11709. var blob = new Blob([code], {
  11710. type: 'application/javascript'
  11711. });
  11712. var worker = new Worker(URL.createObjectURL(blob));
  11713. return worker;
  11714. }
  11715. static moveTo(scene, endPosition, endTarget) {
  11716. var view = scene.view;
  11717. var camera = scene.getActiveCamera();
  11718. var animationDuration = 500;
  11719. var easing = TWEEN.Easing.Quartic.Out;
  11720. {
  11721. // animate camera position
  11722. var tween = new TWEEN.Tween(view.position).to(endPosition, animationDuration);
  11723. tween.easing(easing);
  11724. tween.start();
  11725. }
  11726. {
  11727. // animate camera target
  11728. var camTargetDistance = camera.position.distanceTo(endTarget);
  11729. var target = new Vector3().addVectors(camera.position, camera.getWorldDirection(new Vector3()).clone().multiplyScalar(camTargetDistance));
  11730. var _tween = new TWEEN.Tween(target).to(endTarget, animationDuration);
  11731. _tween.easing(easing);
  11732. _tween.onUpdate(() => {
  11733. view.lookAt(target);
  11734. });
  11735. _tween.onComplete(() => {
  11736. view.lookAt(target);
  11737. });
  11738. _tween.start();
  11739. }
  11740. }
  11741. static loadSkybox(path) {
  11742. var parent = new Object3D("skybox_root");
  11743. var camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
  11744. camera.up.set(0, 0, 1);
  11745. var scene = new Scene();
  11746. var format = '.jpg';
  11747. var urls = [path + 'px' + format, path + 'nx' + format, path + 'py' + format, path + 'ny' + format, path + 'pz' + format, path + 'nz' + format];
  11748. var materialArray = [];
  11749. {
  11750. var _loop = function _loop() {
  11751. var material = new MeshBasicMaterial({
  11752. map: null,
  11753. side: BackSide,
  11754. depthTest: false,
  11755. depthWrite: false,
  11756. color: 0x424556
  11757. });
  11758. materialArray.push(material);
  11759. var loader = new TextureLoader();
  11760. loader.load(urls[i], function loaded(texture) {
  11761. material.map = texture;
  11762. material.needsUpdate = true;
  11763. material.color.setHex(0xffffff);
  11764. }, function progress(xhr) {
  11765. // console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
  11766. }, function error(xhr) {
  11767. console.log('An error happened', xhr);
  11768. });
  11769. };
  11770. for (var i = 0; i < 6; i++) {
  11771. _loop();
  11772. }
  11773. }
  11774. var skyGeometry = new BoxGeometry(700, 700, 700);
  11775. var skybox = new Mesh(skyGeometry, materialArray);
  11776. scene.add(skybox);
  11777. scene.traverse(n => n.frustumCulled = false);
  11778. // z up
  11779. scene.rotation.x = Math.PI / 2;
  11780. parent.children.push(camera);
  11781. camera.parent = parent;
  11782. return {
  11783. camera,
  11784. scene,
  11785. parent
  11786. };
  11787. }
  11788. static createGrid(width, length, spacing, color) {
  11789. var material = new LineBasicMaterial({
  11790. color: color || 0x888888
  11791. });
  11792. var geometry = new Geometry();
  11793. for (var i = 0; i <= length; i++) {
  11794. geometry.vertices.push(new Vector3(-(spacing * width) / 2, i * spacing - spacing * length / 2, 0));
  11795. geometry.vertices.push(new Vector3(+(spacing * width) / 2, i * spacing - spacing * length / 2, 0));
  11796. }
  11797. for (var _i = 0; _i <= width; _i++) {
  11798. geometry.vertices.push(new Vector3(_i * spacing - spacing * width / 2, -(spacing * length) / 2, 0));
  11799. geometry.vertices.push(new Vector3(_i * spacing - spacing * width / 2, +(spacing * length) / 2, 0));
  11800. }
  11801. var line = new LineSegments(geometry, material, LinePieces);
  11802. line.receiveShadow = true;
  11803. return line;
  11804. }
  11805. static createBackgroundTexture(width, height) {
  11806. function gauss(x, y) {
  11807. return 1 / (2 * Math.PI) * Math.exp(-(x * x + y * y) / 2);
  11808. }
  11809. ;
  11810. // map.magFilter = THREE.NearestFilter;
  11811. var size = width * height;
  11812. var data = new Uint8Array(3 * size);
  11813. var chroma = [1, 1.5, 1.7];
  11814. var max = gauss(0, 0);
  11815. for (var x = 0; x < width; x++) {
  11816. for (var y = 0; y < height; y++) {
  11817. var u = 2 * (x / width) - 1;
  11818. var v = 2 * (y / height) - 1;
  11819. var i = x + width * y;
  11820. var d = gauss(2 * u, 2 * v) / max;
  11821. var r = (Math.random() + Math.random() + Math.random()) / 3;
  11822. r = (d * 0.5 + 0.5) * r * 0.03;
  11823. r = r * 0.4;
  11824. // d = Math.pow(d, 0.6);
  11825. data[3 * i + 0] = 255 * (d / 15 + 0.05 + r) * chroma[0];
  11826. data[3 * i + 1] = 255 * (d / 15 + 0.05 + r) * chroma[1];
  11827. data[3 * i + 2] = 255 * (d / 15 + 0.05 + r) * chroma[2];
  11828. }
  11829. }
  11830. var texture = new DataTexture(data, width, height, RGBFormat);
  11831. texture.needsUpdate = true;
  11832. return texture;
  11833. }
  11834. static getMousePointCloudIntersection(mouse, camera, viewer, pointclouds) {
  11835. var params = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  11836. var renderer = viewer.renderer;
  11837. var nmouse = {
  11838. x: mouse.x / renderer.domElement.clientWidth * 2 - 1,
  11839. y: -(mouse.y / renderer.domElement.clientHeight) * 2 + 1
  11840. };
  11841. var pickParams = {};
  11842. if (params.pickClipped) {
  11843. pickParams.pickClipped = params.pickClipped;
  11844. }
  11845. pickParams.x = mouse.x;
  11846. pickParams.y = renderer.domElement.clientHeight - mouse.y;
  11847. var raycaster = new Raycaster();
  11848. raycaster.setFromCamera(nmouse, camera);
  11849. var ray = raycaster.ray;
  11850. var selectedPointcloud = null;
  11851. var closestDistance = Infinity;
  11852. var closestIntersection = null;
  11853. var closestPoint = null;
  11854. for (var pointcloud of pointclouds) {
  11855. var point = pointcloud.pick(viewer, camera, ray, pickParams);
  11856. if (!point) {
  11857. continue;
  11858. }
  11859. var distance = camera.position.distanceTo(point.position);
  11860. if (distance < closestDistance) {
  11861. closestDistance = distance;
  11862. selectedPointcloud = pointcloud;
  11863. closestIntersection = point.position;
  11864. closestPoint = point;
  11865. }
  11866. }
  11867. if (selectedPointcloud) {
  11868. return {
  11869. location: closestIntersection,
  11870. distance: closestDistance,
  11871. pointcloud: selectedPointcloud,
  11872. point: closestPoint
  11873. };
  11874. } else {
  11875. return null;
  11876. }
  11877. }
  11878. static pixelsArrayToImage(pixels, width, height) {
  11879. var canvas = document.createElement('canvas');
  11880. canvas.width = width;
  11881. canvas.height = height;
  11882. var context = canvas.getContext('2d');
  11883. pixels = new pixels.constructor(pixels);
  11884. for (var i = 0; i < pixels.length; i++) {
  11885. pixels[i * 4 + 3] = 255;
  11886. }
  11887. var imageData = context.createImageData(width, height);
  11888. imageData.data.set(pixels);
  11889. context.putImageData(imageData, 0, 0);
  11890. var img = new Image();
  11891. img.src = canvas.toDataURL();
  11892. // img.style.transform = "scaleY(-1)";
  11893. return img;
  11894. }
  11895. static pixelsArrayToDataUrl(pixels, width, height) {
  11896. var canvas = document.createElement('canvas');
  11897. canvas.width = width;
  11898. canvas.height = height;
  11899. var context = canvas.getContext('2d');
  11900. pixels = new pixels.constructor(pixels);
  11901. for (var i = 0; i < pixels.length; i++) {
  11902. pixels[i * 4 + 3] = 255;
  11903. }
  11904. var imageData = context.createImageData(width, height);
  11905. imageData.data.set(pixels);
  11906. context.putImageData(imageData, 0, 0);
  11907. var dataURL = canvas.toDataURL();
  11908. return dataURL;
  11909. }
  11910. static pixelsArrayToCanvas(pixels, width, height) {
  11911. var canvas = document.createElement('canvas');
  11912. canvas.width = width;
  11913. canvas.height = height;
  11914. var context = canvas.getContext('2d');
  11915. pixels = new pixels.constructor(pixels);
  11916. //for (let i = 0; i < pixels.length; i++) {
  11917. // pixels[i * 4 + 3] = 255;
  11918. //}
  11919. // flip vertically
  11920. var bytesPerLine = width * 4;
  11921. for (var i = 0; i < parseInt(height / 2); i++) {
  11922. var j = height - i - 1;
  11923. var lineI = pixels.slice(i * bytesPerLine, i * bytesPerLine + bytesPerLine);
  11924. var lineJ = pixels.slice(j * bytesPerLine, j * bytesPerLine + bytesPerLine);
  11925. pixels.set(lineJ, i * bytesPerLine);
  11926. pixels.set(lineI, j * bytesPerLine);
  11927. }
  11928. var imageData = context.createImageData(width, height);
  11929. imageData.data.set(pixels);
  11930. context.putImageData(imageData, 0, 0);
  11931. return canvas;
  11932. }
  11933. static removeListeners(dispatcher, type) {
  11934. if (dispatcher._listeners === undefined) {
  11935. return;
  11936. }
  11937. if (dispatcher._listeners[type]) {
  11938. delete dispatcher._listeners[type];
  11939. }
  11940. }
  11941. static mouseToRay(mouse, camera, width, height) {
  11942. var normalizedMouse = {
  11943. x: mouse.x / width * 2 - 1,
  11944. y: -(mouse.y / height) * 2 + 1
  11945. };
  11946. var vector = new Vector3(normalizedMouse.x, normalizedMouse.y, 0.5);
  11947. var origin = camera.position.clone();
  11948. vector.unproject(camera);
  11949. var direction = new Vector3().subVectors(vector, origin).normalize();
  11950. var ray = new Ray(origin, direction);
  11951. return ray;
  11952. }
  11953. static projectedRadius(radius, camera, distance, screenWidth, screenHeight) {
  11954. if (camera instanceof OrthographicCamera) {
  11955. return Utils.projectedRadiusOrtho(radius, camera.projectionMatrix, screenWidth, screenHeight);
  11956. } else if (camera instanceof PerspectiveCamera) {
  11957. return Utils.projectedRadiusPerspective(radius, camera.fov * Math.PI / 180, distance, screenHeight);
  11958. } else {
  11959. throw new Error("invalid parameters");
  11960. }
  11961. }
  11962. static projectedRadiusPerspective(radius, fov, distance, screenHeight) {
  11963. var projFactor = 1 / Math.tan(fov / 2) / distance;
  11964. projFactor = projFactor * screenHeight / 2;
  11965. return radius * projFactor;
  11966. }
  11967. static projectedRadiusOrtho(radius, proj, screenWidth, screenHeight) {
  11968. var p1 = new Vector4(0);
  11969. var p2 = new Vector4(radius);
  11970. p1.applyMatrix4(proj);
  11971. p2.applyMatrix4(proj);
  11972. p1 = new Vector3(p1.x, p1.y, p1.z);
  11973. p2 = new Vector3(p2.x, p2.y, p2.z);
  11974. p1.x = (p1.x + 1.0) * 0.5 * screenWidth;
  11975. p1.y = (p1.y + 1.0) * 0.5 * screenHeight;
  11976. p2.x = (p2.x + 1.0) * 0.5 * screenWidth;
  11977. p2.y = (p2.y + 1.0) * 0.5 * screenHeight;
  11978. return p1.distanceTo(p2);
  11979. }
  11980. static topView(camera, node) {
  11981. camera.position.set(0, 1, 0);
  11982. camera.rotation.set(-Math.PI / 2, 0, 0);
  11983. camera.zoomTo(node, 1);
  11984. }
  11985. static frontView(camera, node) {
  11986. camera.position.set(0, 0, 1);
  11987. camera.rotation.set(0, 0, 0);
  11988. camera.zoomTo(node, 1);
  11989. }
  11990. static leftView(camera, node) {
  11991. camera.position.set(-1, 0, 0);
  11992. camera.rotation.set(0, -Math.PI / 2, 0);
  11993. camera.zoomTo(node, 1);
  11994. }
  11995. static rightView(camera, node) {
  11996. camera.position.set(1, 0, 0);
  11997. camera.rotation.set(0, Math.PI / 2, 0);
  11998. camera.zoomTo(node, 1);
  11999. }
  12000. static findClosestGpsTime(target, viewer) {
  12001. var start = performance.now();
  12002. var nodes = [];
  12003. for (var pc of viewer.scene.pointclouds) {
  12004. nodes.push(pc.root);
  12005. for (var child of pc.root.children) {
  12006. if (child) {
  12007. nodes.push(child);
  12008. }
  12009. }
  12010. }
  12011. var closestNode = null;
  12012. var closestIndex = Infinity;
  12013. var closestDistance = Infinity;
  12014. var closestValue = 0;
  12015. for (var node of nodes) {
  12016. var isOkay = node.geometryNode != null && node.geometryNode.geometry != null && node.sceneNode != null;
  12017. if (!isOkay) {
  12018. continue;
  12019. }
  12020. var _geometry = node.geometryNode.geometry;
  12021. var gpsTime = _geometry.attributes["gps-time"];
  12022. var range = gpsTime.potree.range;
  12023. for (var i = 0; i < gpsTime.array.length; i++) {
  12024. var value = gpsTime.array[i];
  12025. value = value * (range[1] - range[0]) + range[0];
  12026. var distance = Math.abs(target - value);
  12027. if (distance < closestDistance) {
  12028. closestIndex = i;
  12029. closestDistance = distance;
  12030. closestValue = value;
  12031. closestNode = node;
  12032. //console.log("found a closer one: " + value);
  12033. }
  12034. }
  12035. }
  12036. var geometry = closestNode.geometryNode.geometry;
  12037. var position = new Vector3(geometry.attributes.position.array[3 * closestIndex + 0], geometry.attributes.position.array[3 * closestIndex + 1], geometry.attributes.position.array[3 * closestIndex + 2]);
  12038. position.applyMatrix4(closestNode.sceneNode.matrixWorld);
  12039. var end = performance.now();
  12040. var duration = end - start;
  12041. console.log("duration: ".concat(duration.toFixed(3), "ms"));
  12042. return {
  12043. node: closestNode,
  12044. index: closestIndex,
  12045. position: position
  12046. };
  12047. }
  12048. /**
  12049. *
  12050. * 0: no intersection
  12051. * 1: intersection
  12052. * 2: fully inside
  12053. */
  12054. static frustumSphereIntersection(frustum, sphere) {
  12055. var planes = frustum.planes;
  12056. var center = sphere.center;
  12057. var negRadius = -sphere.radius;
  12058. var minDistance = Number.MAX_VALUE;
  12059. for (var i = 0; i < 6; i++) {
  12060. var distance = planes[i].distanceToPoint(center);
  12061. if (distance < negRadius) {
  12062. return 0;
  12063. }
  12064. minDistance = Math.min(minDistance, distance);
  12065. }
  12066. return minDistance >= sphere.radius ? 2 : 1;
  12067. }
  12068. // code taken from three.js
  12069. // ImageUtils - generateDataTexture()
  12070. static generateDataTexture(width, height, color) {
  12071. var size = width * height;
  12072. var data = new Uint8Array(4 * width * height);
  12073. var r = Math.floor(color.r * 255);
  12074. var g = Math.floor(color.g * 255);
  12075. var b = Math.floor(color.b * 255);
  12076. for (var i = 0; i < size; i++) {
  12077. data[i * 3] = r;
  12078. data[i * 3 + 1] = g;
  12079. data[i * 3 + 2] = b;
  12080. }
  12081. var texture = new DataTexture(data, width, height, RGBAFormat);
  12082. texture.needsUpdate = true;
  12083. texture.magFilter = NearestFilter;
  12084. return texture;
  12085. }
  12086. // from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
  12087. static getParameterByName(name) {
  12088. name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
  12089. var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
  12090. var results = regex.exec(document.location.search);
  12091. return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, ' '));
  12092. }
  12093. static setParameter(name, value) {
  12094. // value = encodeURIComponent(value);
  12095. name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
  12096. var regex = new RegExp('([\\?&])(' + name + '=([^&#]*))');
  12097. var results = regex.exec(document.location.search);
  12098. var url = window.location.href;
  12099. if (results === null) {
  12100. if (window.location.search.length === 0) {
  12101. url = url + '?';
  12102. } else {
  12103. url = url + '&';
  12104. }
  12105. url = url + name + '=' + value;
  12106. } else {
  12107. var newValue = name + '=' + value;
  12108. url = url.replace(results[2], newValue);
  12109. }
  12110. window.history.replaceState({}, '', url);
  12111. }
  12112. static createChildAABB(aabb, index) {
  12113. var min = aabb.min.clone();
  12114. var max = aabb.max.clone();
  12115. var size = new Vector3().subVectors(max, min);
  12116. if ((index & 0b0001) > 0) {
  12117. min.z += size.z / 2;
  12118. } else {
  12119. max.z -= size.z / 2;
  12120. }
  12121. if ((index & 0b0010) > 0) {
  12122. min.y += size.y / 2;
  12123. } else {
  12124. max.y -= size.y / 2;
  12125. }
  12126. if ((index & 0b0100) > 0) {
  12127. min.x += size.x / 2;
  12128. } else {
  12129. max.x -= size.x / 2;
  12130. }
  12131. return new Box3(min, max);
  12132. }
  12133. // see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
  12134. static clipboardCopy(text) {
  12135. var textArea = document.createElement("textarea");
  12136. textArea.style.position = 'fixed';
  12137. textArea.style.top = 0;
  12138. textArea.style.left = 0;
  12139. textArea.style.width = '2em';
  12140. textArea.style.height = '2em';
  12141. textArea.style.padding = 0;
  12142. textArea.style.border = 'none';
  12143. textArea.style.outline = 'none';
  12144. textArea.style.boxShadow = 'none';
  12145. textArea.style.background = 'transparent';
  12146. textArea.value = text;
  12147. document.body.appendChild(textArea);
  12148. textArea.select();
  12149. try {
  12150. var success = document.execCommand('copy');
  12151. if (success) {
  12152. console.log("copied text to clipboard");
  12153. } else {
  12154. console.log("copy to clipboard failed");
  12155. }
  12156. } catch (err) {
  12157. console.log("error while trying to copy to clipboard");
  12158. }
  12159. document.body.removeChild(textArea);
  12160. }
  12161. static getMeasurementIcon(measurement) {
  12162. if (measurement instanceof Measure) {
  12163. if (measurement.showDistances && !measurement.showArea && !measurement.showAngles) {
  12164. return "".concat(Potree.resourcePath, "/icons/distance.svg");
  12165. } else if (measurement.showDistances && measurement.showArea && !measurement.showAngles) {
  12166. return "".concat(Potree.resourcePath, "/icons/area.svg");
  12167. } else if (measurement.maxMarkers === 1) {
  12168. return "".concat(Potree.resourcePath, "/icons/point.svg");
  12169. } else if (!measurement.showDistances && !measurement.showArea && measurement.showAngles) {
  12170. return "".concat(Potree.resourcePath, "/icons/angle.png");
  12171. } else if (measurement.showHeight) {
  12172. return "".concat(Potree.resourcePath, "/icons/height.svg");
  12173. } else {
  12174. return "".concat(Potree.resourcePath, "/icons/distance.svg");
  12175. }
  12176. } else if (measurement instanceof Profile) {
  12177. return "".concat(Potree.resourcePath, "/icons/profile.svg");
  12178. } else if (measurement instanceof Volume) {
  12179. return "".concat(Potree.resourcePath, "/icons/volume.svg");
  12180. } else if (measurement instanceof PolygonClipVolume) {
  12181. return "".concat(Potree.resourcePath, "/icons/clip-polygon.svg");
  12182. }
  12183. }
  12184. static lineToLineIntersection(P0, P1, P2, P3) {
  12185. var P = [P0, P1, P2, P3];
  12186. var d = (m, n, o, p) => {
  12187. var result = (P[m].x - P[n].x) * (P[o].x - P[p].x) + (P[m].y - P[n].y) * (P[o].y - P[p].y) + (P[m].z - P[n].z) * (P[o].z - P[p].z);
  12188. return result;
  12189. };
  12190. var mua = (d(0, 2, 3, 2) * d(3, 2, 1, 0) - d(0, 2, 1, 0) * d(3, 2, 3, 2)
  12191. /**-----------------------------------------------------------------**/) / (d(1, 0, 1, 0) * d(3, 2, 3, 2) - d(3, 2, 1, 0) * d(3, 2, 1, 0));
  12192. var mub = (d(0, 2, 3, 2) + mua * d(3, 2, 1, 0)
  12193. /**--------------------------------------**/) / d(3, 2, 3, 2);
  12194. var P01 = P1.clone().sub(P0);
  12195. var P23 = P3.clone().sub(P2);
  12196. var Pa = P0.clone().add(P01.multiplyScalar(mua));
  12197. var Pb = P2.clone().add(P23.multiplyScalar(mub));
  12198. var center = Pa.clone().add(Pb).multiplyScalar(0.5);
  12199. return center;
  12200. }
  12201. static computeCircleCenter(A, B, C) {
  12202. var AB = B.clone().sub(A);
  12203. var AC = C.clone().sub(A);
  12204. var N = AC.clone().cross(AB).normalize();
  12205. var ab_dir = AB.clone().cross(N).normalize();
  12206. var ac_dir = AC.clone().cross(N).normalize();
  12207. var ab_origin = A.clone().add(B).multiplyScalar(0.5);
  12208. var ac_origin = A.clone().add(C).multiplyScalar(0.5);
  12209. var P0 = ab_origin;
  12210. var P1 = ab_origin.clone().add(ab_dir);
  12211. var P2 = ac_origin;
  12212. var P3 = ac_origin.clone().add(ac_dir);
  12213. var center = Utils.lineToLineIntersection(P0, P1, P2, P3);
  12214. return center;
  12215. // Potree.Utils.debugLine(viewer.scene.scene, P0, P1, 0x00ff00);
  12216. // Potree.Utils.debugLine(viewer.scene.scene, P2, P3, 0x0000ff);
  12217. // Potree.Utils.debugSphere(viewer.scene.scene, center, 0.03, 0xff00ff);
  12218. // const radius = center.distanceTo(A);
  12219. // Potree.Utils.debugCircle(viewer.scene.scene, center, radius, new THREE.Vector3(0, 0, 1), 0xff00ff);
  12220. }
  12221. static getNorthVec(p1, distance, projection) {
  12222. if (projection) {
  12223. // if there is a projection, transform coordinates to WGS84
  12224. // and compute angle to north there
  12225. proj4.defs("pointcloud", projection);
  12226. var transform = proj4("pointcloud", "WGS84");
  12227. var llP1 = transform.forward(p1.toArray());
  12228. var llP2 = transform.forward([p1.x, p1.y + distance]);
  12229. var polarRadius = Math.sqrt((llP2[0] - llP1[0]) ** 2 + (llP2[1] - llP1[1]) ** 2);
  12230. llP2 = [llP1[0], llP1[1] + polarRadius];
  12231. var northVec = transform.inverse(llP2);
  12232. return new Vector3(...northVec, p1.z).sub(p1);
  12233. } else {
  12234. // if there is no projection, assume [0, 1, 0] as north direction
  12235. var vec = new Vector3(0, 1, 0).multiplyScalar(distance);
  12236. return vec;
  12237. }
  12238. }
  12239. static computeAzimuth(p1, p2, projection) {
  12240. var azimuth = 0;
  12241. if (projection) {
  12242. // if there is a projection, transform coordinates to WGS84
  12243. // and compute angle to north there
  12244. var transform;
  12245. if (projection.includes('EPSG')) {
  12246. transform = proj4(projection, "WGS84");
  12247. } else {
  12248. proj4.defs("pointcloud", projection);
  12249. transform = proj4("pointcloud", "WGS84");
  12250. }
  12251. var llP1 = transform.forward(p1.toArray());
  12252. var llP2 = transform.forward(p2.toArray());
  12253. var dir = [llP2[0] - llP1[0], llP2[1] - llP1[1]];
  12254. azimuth = Math.atan2(dir[1], dir[0]) - Math.PI / 2;
  12255. } else {
  12256. // if there is no projection, assume [0, 1, 0] as north direction
  12257. var _dir = [p2.x - p1.x, p2.y - p1.y];
  12258. azimuth = Math.atan2(_dir[1], _dir[0]) - Math.PI / 2;
  12259. }
  12260. // make clockwise
  12261. azimuth = -azimuth;
  12262. return azimuth;
  12263. }
  12264. static async loadScript(url) {
  12265. return new Promise(resolve => {
  12266. var element = document.getElementById(url);
  12267. if (element) {
  12268. resolve();
  12269. } else {
  12270. var script = document.createElement("script");
  12271. script.id = url;
  12272. script.onload = () => {
  12273. resolve();
  12274. };
  12275. script.src = url;
  12276. document.body.appendChild(script);
  12277. }
  12278. });
  12279. }
  12280. static createSvgGradient(scheme) {
  12281. // this is what we are creating:
  12282. //
  12283. //<svg width="1em" height="3em" xmlns="http://www.w3.org/2000/svg">
  12284. // <defs>
  12285. // <linearGradient id="gradientID" gradientTransform="rotate(90)">
  12286. // <stop offset="0%" stop-color="rgb(93, 78, 162)" />
  12287. // ...
  12288. // <stop offset="100%" stop-color="rgb(157, 0, 65)" />
  12289. // </linearGradient>
  12290. // </defs>
  12291. //
  12292. // <rect width="100%" height="100%" fill="url('#myGradient')" stroke="black" stroke-width="0.1em"/>
  12293. //</svg>
  12294. var gradientId = "".concat(Math.random(), "_").concat(Date.now());
  12295. var svgn = "http://www.w3.org/2000/svg";
  12296. var svg = document.createElementNS(svgn, "svg");
  12297. svg.setAttributeNS(null, "width", "2em");
  12298. svg.setAttributeNS(null, "height", "3em");
  12299. {
  12300. // <defs>
  12301. var defs = document.createElementNS(svgn, "defs");
  12302. var linearGradient = document.createElementNS(svgn, "linearGradient");
  12303. linearGradient.setAttributeNS(null, "id", gradientId);
  12304. linearGradient.setAttributeNS(null, "gradientTransform", "rotate(90)");
  12305. for (var i = scheme.length - 1; i >= 0; i--) {
  12306. var stopVal = scheme[i];
  12307. var percent = parseInt(100 - stopVal[0] * 100);
  12308. var [r, g, b] = stopVal[1].toArray().map(v => parseInt(v * 255));
  12309. var stop = document.createElementNS(svgn, "stop");
  12310. stop.setAttributeNS(null, "offset", "".concat(percent, "%"));
  12311. stop.setAttributeNS(null, "stop-color", "rgb(".concat(r, ", ").concat(g, ", ").concat(b, ")"));
  12312. linearGradient.appendChild(stop);
  12313. }
  12314. defs.appendChild(linearGradient);
  12315. svg.appendChild(defs);
  12316. }
  12317. var rect = document.createElementNS(svgn, "rect");
  12318. rect.setAttributeNS(null, "width", "100%");
  12319. rect.setAttributeNS(null, "height", "100%");
  12320. rect.setAttributeNS(null, "fill", "url(\"#".concat(gradientId, "\")"));
  12321. rect.setAttributeNS(null, "stroke", "black");
  12322. rect.setAttributeNS(null, "stroke-width", "0.1em");
  12323. svg.appendChild(rect);
  12324. return svg;
  12325. }
  12326. static async waitAny(promises) {
  12327. return new Promise(resolve => {
  12328. promises.map(promise => {
  12329. promise.then(() => {
  12330. resolve();
  12331. });
  12332. });
  12333. });
  12334. }
  12335. }
  12336. Utils.screenPass = new function () {
  12337. this.screenScene = new Scene();
  12338. this.screenQuad = new Mesh(new PlaneBufferGeometry(2, 2, 1));
  12339. this.screenQuad.material.depthTest = true;
  12340. this.screenQuad.material.depthWrite = true;
  12341. this.screenQuad.material.transparent = true;
  12342. this.screenScene.add(this.screenQuad);
  12343. this.camera = new Camera();
  12344. this.render = function (renderer, material, target) {
  12345. this.screenQuad.material = material;
  12346. if (typeof target === 'undefined') {
  12347. renderer.render(this.screenScene, this.camera);
  12348. } else {
  12349. renderer.render(this.screenScene, this.camera, target);
  12350. }
  12351. };
  12352. }();
  12353. class Version {
  12354. constructor(version) {
  12355. this.version = version;
  12356. var vmLength = version.indexOf('.') === -1 ? version.length : version.indexOf('.');
  12357. this.versionMajor = parseInt(version.substr(0, vmLength));
  12358. this.versionMinor = parseInt(version.substr(vmLength + 1));
  12359. if (this.versionMinor.length === 0) {
  12360. this.versionMinor = 0;
  12361. }
  12362. }
  12363. newerThan(version) {
  12364. var v = new Version(version);
  12365. if (this.versionMajor > v.versionMajor) {
  12366. return true;
  12367. } else if (this.versionMajor === v.versionMajor && this.versionMinor > v.versionMinor) {
  12368. return true;
  12369. } else {
  12370. return false;
  12371. }
  12372. }
  12373. equalOrHigher(version) {
  12374. var v = new Version(version);
  12375. if (this.versionMajor > v.versionMajor) {
  12376. return true;
  12377. } else if (this.versionMajor === v.versionMajor && this.versionMinor >= v.versionMinor) {
  12378. return true;
  12379. } else {
  12380. return false;
  12381. }
  12382. }
  12383. upTo(version) {
  12384. return !this.newerThan(version);
  12385. }
  12386. }
  12387. //加载 解析点云
  12388. class BinaryLoader {
  12389. constructor(version, boundingBox, scale) {
  12390. if (typeof version === 'string') {
  12391. this.version = new Version(version);
  12392. } else {
  12393. this.version = version;
  12394. }
  12395. this.boundingBox = boundingBox;
  12396. this.scale = scale;
  12397. }
  12398. load(node) {
  12399. if (node.loaded) {
  12400. return;
  12401. }
  12402. var url = node.getURL();
  12403. if (this.version.equalOrHigher('1.4')) {
  12404. url += '.bin';
  12405. }
  12406. var xhr = XHRFactory.createXMLHttpRequest();
  12407. xhr.open('GET', url, true);
  12408. xhr.responseType = 'arraybuffer';
  12409. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  12410. xhr.onreadystatechange = () => {
  12411. if (xhr.readyState === 4) {
  12412. if ((xhr.status === 200 || xhr.status === 0) && xhr.response !== null) {
  12413. var buffer = xhr.response;
  12414. this.parse(node, buffer);
  12415. } else {
  12416. //console.error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  12417. throw new Error("Failed to load file! HTTP status: ".concat(xhr.status, ", file: ").concat(url));
  12418. }
  12419. }
  12420. };
  12421. try {
  12422. xhr.send(null);
  12423. } catch (e) {
  12424. console.log('fehler beim laden der punktwolke: ' + e);
  12425. }
  12426. }
  12427. parse(node, buffer, callback) {
  12428. var pointAttributes = node.pcoGeometry.pointAttributes; //定义自cloud.js
  12429. var numPoints = buffer.byteLength / node.pcoGeometry.pointAttributes.byteSize;
  12430. if (this.version.upTo('1.5')) {
  12431. node.numPoints = numPoints;
  12432. }
  12433. var workerPath = Potree.scriptPath + '/workers/BinaryDecoderWorker.js';
  12434. var worker = Potree.workerPool.getWorker(workerPath);
  12435. worker.onmessage = function (e) {
  12436. var data = e.data;
  12437. var buffers = data.attributeBuffers;
  12438. var tightBoundingBox = new Box3(new Vector3().fromArray(data.tightBoundingBox.min), new Vector3().fromArray(data.tightBoundingBox.max));
  12439. Potree.workerPool.returnWorker(workerPath, worker);
  12440. var geometry = new BufferGeometry();
  12441. for (var property in buffers) {
  12442. var _buffer = buffers[property].buffer;
  12443. var batchAttribute = buffers[property].attribute;
  12444. if (property === "POSITION_CARTESIAN") {
  12445. geometry.setAttribute('position', new BufferAttribute(new Float32Array(_buffer), 3));
  12446. } else if (property === "centersFloat") {
  12447. //add
  12448. geometry.setAttribute("centersFloat", new BufferAttribute(new Float32Array(_buffer), 4));
  12449. } else if (property === "centersInt") {
  12450. //add
  12451. geometry.setAttribute("centersInt", new BufferAttribute(new Int32Array(_buffer), 4));
  12452. } else if (property === "rgba") {
  12453. geometry.setAttribute("rgba", new BufferAttribute(new Uint8Array(_buffer), 4, true));
  12454. } else if (property === "NORMAL_SPHEREMAPPED") {
  12455. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(_buffer), 3));
  12456. } else if (property === "NORMAL_OCT16") {
  12457. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(_buffer), 3));
  12458. } else if (property === "NORMAL") {
  12459. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(_buffer), 3));
  12460. } else if (property === "INDICES") {
  12461. var bufferAttribute = new BufferAttribute(new Uint8Array(_buffer), 4);
  12462. bufferAttribute.normalized = true;
  12463. geometry.setAttribute('indices', bufferAttribute);
  12464. } else if (property === "SPACING") {
  12465. var _bufferAttribute = new BufferAttribute(new Float32Array(_buffer), 1);
  12466. geometry.setAttribute('spacing', _bufferAttribute);
  12467. } else if (property === "IR" || property === "TEMP") {
  12468. //温度
  12469. var _bufferAttribute2 = new BufferAttribute(new Float32Array(_buffer), 1);
  12470. _bufferAttribute2.tempRange = batchAttribute.range;
  12471. geometry.setAttribute(property.toLowerCase(), _bufferAttribute2);
  12472. } else if (property === "SEG") {
  12473. //分类
  12474. var _bufferAttribute3 = new BufferAttribute(new Float32Array(_buffer), 1);
  12475. geometry.setAttribute('classification', _bufferAttribute3);
  12476. } else if (property === "covs") {
  12477. //add
  12478. var _bufferAttribute4 = new BufferAttribute(new Float32Array(_buffer), 6);
  12479. geometry.setAttribute('covs', _bufferAttribute4);
  12480. } /* else if(property != 'GS3D'){//改
  12481. //geometry.setAttribute("rgba", new THREE.BufferAttribute(new Uint8Array(buffer), 4, true));
  12482. const bufferAttribute = new THREE.BufferAttribute(new Float32Array(buffer), 1);
  12483. bufferAttribute.potree = {
  12484. offset: buffers[property].offset,
  12485. scale: buffers[property].scale,
  12486. preciseBuffer: buffers[property].preciseBuffer,
  12487. range: batchAttribute.range,
  12488. };
  12489. geometry.setAttribute(property, bufferAttribute);
  12490. const attribute = pointAttributes.attributes.find(a => a.name === batchAttribute.name);
  12491. attribute.range[0] = Math.min(attribute.range[0], batchAttribute.range[0]);
  12492. attribute.range[1] = Math.max(attribute.range[1], batchAttribute.range[1]);
  12493. if(node.getLevel() === 0){
  12494. attribute.initialRange = batchAttribute.range;
  12495. }
  12496. } */
  12497. }
  12498. tightBoundingBox.max.sub(tightBoundingBox.min);
  12499. tightBoundingBox.min.set(0, 0, 0);
  12500. var numPoints = e.data.buffer.byteLength / pointAttributes.byteSize;
  12501. node.numPoints = numPoints;
  12502. node.geometry = geometry;
  12503. node.mean = new Vector3(...data.mean);
  12504. node.tightBoundingBox = tightBoundingBox;
  12505. node.loaded = true;
  12506. node.loading = false;
  12507. node.estimatedSpacing = data.estimatedSpacing;
  12508. Potree.numNodesLoading--;
  12509. callback(); //add
  12510. };
  12511. var message = {
  12512. buffer: buffer,
  12513. pointAttributes: pointAttributes,
  12514. version: this.version.version,
  12515. min: [node.boundingBox.min.x, node.boundingBox.min.y, node.boundingBox.min.z],
  12516. offset: [node.pcoGeometry.offset.x, node.pcoGeometry.offset.y, node.pcoGeometry.offset.z],
  12517. scale: this.scale,
  12518. spacing: node.spacing,
  12519. hasChildren: node.hasChildren,
  12520. name: node.name
  12521. };
  12522. worker.postMessage(message, [message.buffer]);
  12523. }
  12524. }
  12525. var ftCanvas = document.createElement('canvas');
  12526. var Features = function () {
  12527. var gl = ftCanvas.getContext('webgl') || ftCanvas.getContext('experimental-webgl');
  12528. if (gl === null) {
  12529. return {};
  12530. }
  12531. // -- code taken from THREE.WebGLRenderer --
  12532. var _vertexShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);
  12533. var _vertexShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);
  12534. // Unused: let _vertexShaderPrecisionLowpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
  12535. var _fragmentShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
  12536. var _fragmentShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);
  12537. // Unused: let _fragmentShaderPrecisionLowpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT);
  12538. var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
  12539. var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
  12540. // -----------------------------------------
  12541. var precision;
  12542. if (highpAvailable) {
  12543. precision = 'highp';
  12544. } else if (mediumpAvailable) {
  12545. precision = 'mediump';
  12546. } else {
  12547. precision = 'lowp';
  12548. }
  12549. return {
  12550. SHADER_INTERPOLATION: {
  12551. isSupported: function isSupported() {
  12552. var supported = true;
  12553. supported = supported && gl.getExtension('EXT_frag_depth');
  12554. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  12555. return supported;
  12556. }
  12557. },
  12558. SHADER_SPLATS: {
  12559. isSupported: function isSupported() {
  12560. var supported = true;
  12561. supported = supported && gl.getExtension('EXT_frag_depth');
  12562. supported = supported && gl.getExtension('OES_texture_float');
  12563. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  12564. return supported;
  12565. }
  12566. },
  12567. SHADER_EDL: {
  12568. isSupported: function isSupported() {
  12569. var supported = true;
  12570. supported = supported && (gl.getExtension('EXT_frag_depth') || Potree.settings.isWebgl2); //麒麟系统firefox支持webgl2但这里用webgl1的content得不到EXT_frag_depth
  12571. supported = supported && gl.getExtension('OES_texture_float');
  12572. supported = supported && gl.getParameter(gl.MAX_VARYING_VECTORS) >= 8;
  12573. //supported = supported || (gl instanceof WebGL2RenderingContext);
  12574. return supported;
  12575. }
  12576. },
  12577. //WEBGL2: {
  12578. // isSupported: function(){
  12579. // return typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext;
  12580. // }
  12581. //},
  12582. precision: precision
  12583. };
  12584. }();
  12585. /**
  12586. * Some types of possible point attribute data formats
  12587. *
  12588. * @class
  12589. */
  12590. var PointAttributeTypes = {
  12591. DATA_TYPE_DOUBLE: {
  12592. ordinal: 0,
  12593. name: "double",
  12594. size: 8
  12595. },
  12596. DATA_TYPE_FLOAT: {
  12597. ordinal: 1,
  12598. name: "float",
  12599. size: 4
  12600. },
  12601. DATA_TYPE_INT8: {
  12602. ordinal: 2,
  12603. name: "int8",
  12604. size: 1
  12605. },
  12606. DATA_TYPE_UINT8: {
  12607. ordinal: 3,
  12608. name: "uint8",
  12609. size: 1
  12610. },
  12611. DATA_TYPE_INT16: {
  12612. ordinal: 4,
  12613. name: "int16",
  12614. size: 2
  12615. },
  12616. DATA_TYPE_UINT16: {
  12617. ordinal: 5,
  12618. name: "uint16",
  12619. size: 2
  12620. },
  12621. DATA_TYPE_INT32: {
  12622. ordinal: 6,
  12623. name: "int32",
  12624. size: 4
  12625. },
  12626. DATA_TYPE_UINT32: {
  12627. ordinal: 7,
  12628. name: "uint32",
  12629. size: 4
  12630. },
  12631. DATA_TYPE_INT64: {
  12632. ordinal: 8,
  12633. name: "int64",
  12634. size: 8
  12635. },
  12636. DATA_TYPE_UINT64: {
  12637. ordinal: 9,
  12638. name: "uint64",
  12639. size: 8
  12640. }
  12641. };
  12642. var i$1 = 0;
  12643. for (var obj in PointAttributeTypes) {
  12644. PointAttributeTypes[i$1] = PointAttributeTypes[obj];
  12645. i$1++;
  12646. }
  12647. class PointAttribute {
  12648. constructor(name, type, numElements) {
  12649. this.name = name;
  12650. this.type = type;
  12651. this.numElements = numElements;
  12652. this.byteSize = this.numElements * this.type.size;
  12653. this.description = "";
  12654. this.range = [Infinity, -Infinity];
  12655. }
  12656. }
  12657. ;
  12658. PointAttribute.POSITION_CARTESIAN = new PointAttribute("POSITION_CARTESIAN", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  12659. PointAttribute.RGBA_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 4);
  12660. PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
  12661. PointAttribute.RGB_PACKED = new PointAttribute("COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 3);
  12662. PointAttribute.NORMAL_FLOATS = new PointAttribute("NORMAL_FLOATS", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  12663. PointAttribute.INTENSITY = new PointAttribute("INTENSITY", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  12664. PointAttribute.CLASSIFICATION = new PointAttribute("CLASSIFICATION", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  12665. PointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute("NORMAL_SPHEREMAPPED", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  12666. PointAttribute.NORMAL_OCT16 = new PointAttribute("NORMAL_OCT16", PointAttributeTypes.DATA_TYPE_UINT8, 2);
  12667. PointAttribute.NORMAL = new PointAttribute("NORMAL", PointAttributeTypes.DATA_TYPE_FLOAT, 3);
  12668. PointAttribute.RETURN_NUMBER = new PointAttribute("RETURN_NUMBER", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  12669. PointAttribute.NUMBER_OF_RETURNS = new PointAttribute("NUMBER_OF_RETURNS", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  12670. PointAttribute.SOURCE_ID = new PointAttribute("SOURCE_ID", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  12671. PointAttribute.INDICES = new PointAttribute("INDICES", PointAttributeTypes.DATA_TYPE_UINT32, 1);
  12672. PointAttribute.SPACING = new PointAttribute("SPACING", PointAttributeTypes.DATA_TYPE_FLOAT, 1);
  12673. PointAttribute.GPS_TIME = new PointAttribute("GPS_TIME", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
  12674. class PointAttributes {
  12675. constructor(pointAttributes) {
  12676. this.attributes = [];
  12677. this.byteSize = 0;
  12678. this.size = 0;
  12679. this.vectors = [];
  12680. if (pointAttributes != null) {
  12681. for (var _i = 0; _i < pointAttributes.length; _i++) {
  12682. var pointAttributeName = pointAttributes[_i];
  12683. var pointAttribute = PointAttribute[pointAttributeName];
  12684. this.attributes.push(pointAttribute);
  12685. this.byteSize += pointAttribute.byteSize;
  12686. this.size++;
  12687. }
  12688. }
  12689. }
  12690. add(pointAttribute) {
  12691. this.attributes.push(pointAttribute);
  12692. this.byteSize += pointAttribute.byteSize;
  12693. this.size++;
  12694. }
  12695. addVector(vector) {
  12696. this.vectors.push(vector);
  12697. }
  12698. hasNormals() {
  12699. for (var name in this.attributes) {
  12700. var pointAttribute = this.attributes[name];
  12701. if (pointAttribute === PointAttribute.NORMAL_SPHEREMAPPED || pointAttribute === PointAttribute.NORMAL_FLOATS || pointAttribute === PointAttribute.NORMAL || pointAttribute === PointAttribute.NORMAL_OCT16) {
  12702. return true;
  12703. }
  12704. }
  12705. return false;
  12706. }
  12707. }
  12708. class Points$1 {
  12709. constructor() {
  12710. this.boundingBox = new Box3();
  12711. this.numPoints = 0;
  12712. this.data = {};
  12713. }
  12714. add(points) {
  12715. var currentSize = this.numPoints;
  12716. var additionalSize = points.numPoints;
  12717. var newSize = currentSize + additionalSize;
  12718. var thisAttributes = Object.keys(this.data);
  12719. var otherAttributes = Object.keys(points.data);
  12720. var attributes = new Set([...thisAttributes, ...otherAttributes]);
  12721. for (var attribute of attributes) {
  12722. if (thisAttributes.includes(attribute) && otherAttributes.includes(attribute)) {
  12723. // attribute in both, merge
  12724. var Type = this.data[attribute].constructor;
  12725. var merged = new Type(this.data[attribute].length + points.data[attribute].length);
  12726. merged.set(this.data[attribute], 0);
  12727. merged.set(points.data[attribute], this.data[attribute].length);
  12728. this.data[attribute] = merged;
  12729. } else if (thisAttributes.includes(attribute) && !otherAttributes.includes(attribute)) {
  12730. // attribute only in this; take over this and expand to new size
  12731. var elementsPerPoint = this.data[attribute].length / this.numPoints;
  12732. var _Type = this.data[attribute].constructor;
  12733. var expanded = new _Type(elementsPerPoint * newSize);
  12734. expanded.set(this.data[attribute], 0);
  12735. this.data[attribute] = expanded;
  12736. } else if (!thisAttributes.includes(attribute) && otherAttributes.includes(attribute)) {
  12737. // attribute only in points to be added; take over new points and expand to new size
  12738. var _elementsPerPoint = points.data[attribute].length / points.numPoints;
  12739. var _Type2 = points.data[attribute].constructor;
  12740. var _expanded = new _Type2(_elementsPerPoint * newSize);
  12741. _expanded.set(points.data[attribute], _elementsPerPoint * currentSize);
  12742. this.data[attribute] = _expanded;
  12743. }
  12744. }
  12745. this.numPoints = newSize;
  12746. this.boundingBox.union(points.boundingBox);
  12747. }
  12748. }
  12749. class CSVExporter {
  12750. static toString(points) {
  12751. var string = '';
  12752. var attributes = Object.keys(points.data).filter(a => a !== 'normal').sort((a, b) => {
  12753. if (a === 'position') return -1;
  12754. if (b === 'position') return 1;
  12755. if (a === 'rgba') return -1;
  12756. if (b === 'rgba') return 1;
  12757. });
  12758. var headerValues = [];
  12759. for (var attribute of attributes) {
  12760. var itemSize = points.data[attribute].length / points.numPoints;
  12761. if (attribute === 'position') {
  12762. headerValues = headerValues.concat(['x', 'y', 'z']);
  12763. } else if (attribute === 'rgba') {
  12764. headerValues = headerValues.concat(['r', 'g', 'b', 'a']);
  12765. } else if (itemSize > 1) {
  12766. for (var i = 0; i < itemSize; i++) {
  12767. headerValues.push("".concat(attribute, "_").concat(i));
  12768. }
  12769. } else {
  12770. headerValues.push(attribute);
  12771. }
  12772. }
  12773. string = headerValues.join(', ') + '\n';
  12774. for (var _i = 0; _i < points.numPoints; _i++) {
  12775. var values = [];
  12776. for (var _attribute of attributes) {
  12777. var _itemSize = points.data[_attribute].length / points.numPoints;
  12778. var value = points.data[_attribute].subarray(_itemSize * _i, _itemSize * _i + _itemSize).join(', ');
  12779. values.push(value);
  12780. }
  12781. string += values.join(', ') + '\n';
  12782. }
  12783. return string;
  12784. }
  12785. }
  12786. ;
  12787. class LASExporter {
  12788. static toLAS(points) {
  12789. // TODO Unused: let string = '';
  12790. var boundingBox = points.boundingBox;
  12791. var offset = boundingBox.min.clone();
  12792. var diagonal = boundingBox.min.distanceTo(boundingBox.max);
  12793. var scale = new Vector3(0.001, 0.001, 0.001);
  12794. if (diagonal > 1000 * 1000) {
  12795. scale = new Vector3(0.01, 0.01, 0.01);
  12796. } else {
  12797. scale = new Vector3(0.001, 0.001, 0.001);
  12798. }
  12799. var setString = function setString(string, offset, buffer) {
  12800. var view = new Uint8Array(buffer);
  12801. for (var i = 0; i < string.length; i++) {
  12802. var charCode = string.charCodeAt(i);
  12803. view[offset + i] = charCode;
  12804. }
  12805. };
  12806. var buffer = new ArrayBuffer(227 + 28 * points.numPoints);
  12807. var view = new DataView(buffer);
  12808. var u8View = new Uint8Array(buffer);
  12809. // let u16View = new Uint16Array(buffer);
  12810. setString('LASF', 0, buffer);
  12811. u8View[24] = 1;
  12812. u8View[25] = 2;
  12813. // system identifier o:26 l:32
  12814. // generating software o:58 l:32
  12815. setString('Potree 1.7', 58, buffer);
  12816. // file creation day of year o:90 l:2
  12817. // file creation year o:92 l:2
  12818. // header size o:94 l:2
  12819. view.setUint16(94, 227, true);
  12820. // offset to point data o:96 l:4
  12821. view.setUint32(96, 227, true);
  12822. // number of letiable length records o:100 l:4
  12823. // point data record format 104 1
  12824. u8View[104] = 2;
  12825. // point data record length 105 2
  12826. view.setUint16(105, 28, true);
  12827. // number of point records 107 4
  12828. view.setUint32(107, points.numPoints, true);
  12829. // number of points by return 111 20
  12830. // x scale factor 131 8
  12831. view.setFloat64(131, scale.x, true);
  12832. // y scale factor 139 8
  12833. view.setFloat64(139, scale.y, true);
  12834. // z scale factor 147 8
  12835. view.setFloat64(147, scale.z, true);
  12836. // x offset 155 8
  12837. view.setFloat64(155, offset.x, true);
  12838. // y offset 163 8
  12839. view.setFloat64(163, offset.y, true);
  12840. // z offset 171 8
  12841. view.setFloat64(171, offset.z, true);
  12842. // max x 179 8
  12843. view.setFloat64(179, boundingBox.max.x, true);
  12844. // min x 187 8
  12845. view.setFloat64(187, boundingBox.min.x, true);
  12846. // max y 195 8
  12847. view.setFloat64(195, boundingBox.max.y, true);
  12848. // min y 203 8
  12849. view.setFloat64(203, boundingBox.min.y, true);
  12850. // max z 211 8
  12851. view.setFloat64(211, boundingBox.max.z, true);
  12852. // min z 219 8
  12853. view.setFloat64(219, boundingBox.min.z, true);
  12854. var boffset = 227;
  12855. for (var i = 0; i < points.numPoints; i++) {
  12856. var px = points.data.position[3 * i + 0];
  12857. var py = points.data.position[3 * i + 1];
  12858. var pz = points.data.position[3 * i + 2];
  12859. var ux = parseInt((px - offset.x) / scale.x);
  12860. var uy = parseInt((py - offset.y) / scale.y);
  12861. var uz = parseInt((pz - offset.z) / scale.z);
  12862. view.setUint32(boffset + 0, ux, true);
  12863. view.setUint32(boffset + 4, uy, true);
  12864. view.setUint32(boffset + 8, uz, true);
  12865. if (points.data.intensity) {
  12866. view.setUint16(boffset + 12, points.data.intensity[i], true);
  12867. }
  12868. var rt = 0;
  12869. if (points.data.returnNumber) {
  12870. rt += points.data.returnNumber[i];
  12871. }
  12872. if (points.data.numberOfReturns) {
  12873. rt += points.data.numberOfReturns[i] << 3;
  12874. }
  12875. view.setUint8(boffset + 14, rt);
  12876. if (points.data.classification) {
  12877. view.setUint8(boffset + 15, points.data.classification[i]);
  12878. }
  12879. // scan angle rank
  12880. // user data
  12881. // point source id
  12882. if (points.data.pointSourceID) {
  12883. view.setUint16(boffset + 18, points.data.pointSourceID[i]);
  12884. }
  12885. if (points.data.rgba) {
  12886. var rgba = points.data.rgba;
  12887. view.setUint16(boffset + 20, rgba[4 * i + 0] * 255, true);
  12888. view.setUint16(boffset + 22, rgba[4 * i + 1] * 255, true);
  12889. view.setUint16(boffset + 24, rgba[4 * i + 2] * 255, true);
  12890. }
  12891. boffset += 28;
  12892. }
  12893. return buffer;
  12894. }
  12895. }
  12896. /**
  12897. * @author mrdoob / http://mrdoob.com/ https://github.com/mrdoob/eventdispatcher.js
  12898. *
  12899. * with slight modifications by mschuetz, http://potree.org
  12900. *
  12901. */
  12902. // The MIT License
  12903. //
  12904. // Copyright (c) 2011 Mr.doob
  12905. //
  12906. // Permission is hereby granted, free of charge, to any person obtaining a copy
  12907. // of this software and associated documentation files (the "Software"), to deal
  12908. // in the Software without restriction, including without limitation the rights
  12909. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12910. // copies of the Software, and to permit persons to whom the Software is
  12911. // furnished to do so, subject to the following conditions:
  12912. //
  12913. // The above copyright notice and this permission notice shall be included in
  12914. // all copies or substantial portions of the Software.
  12915. //
  12916. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12917. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12918. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  12919. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  12920. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  12921. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  12922. // THE SOFTWARE.
  12923. class EventDispatcher$1 {
  12924. constructor() {
  12925. this._listeners = {};
  12926. }
  12927. addEventListener(type, listener) {
  12928. var listeners = this._listeners;
  12929. if (listeners[type] === undefined) {
  12930. listeners[type] = [];
  12931. }
  12932. if (listeners[type].indexOf(listener) === -1) {
  12933. listeners[type].push(listener);
  12934. }
  12935. }
  12936. hasEventListener(type, listener) {
  12937. var listeners = this._listeners;
  12938. return listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1;
  12939. }
  12940. removeEventListener(type, listener) {
  12941. var listeners = this._listeners;
  12942. var listenerArray = listeners[type];
  12943. if (listenerArray !== undefined) {
  12944. var index = listenerArray.indexOf(listener);
  12945. if (index !== -1) {
  12946. listenerArray.splice(index, 1);
  12947. }
  12948. }
  12949. }
  12950. removeEventListeners(type) {
  12951. if (this._listeners[type] !== undefined) {
  12952. delete this._listeners[type];
  12953. }
  12954. }
  12955. dispatchEvent(event) {
  12956. var listeners = this._listeners;
  12957. var listenerArray = listeners[event.type];
  12958. if (listenerArray !== undefined) {
  12959. event.target = this;
  12960. for (var listener of listenerArray.slice(0)) {
  12961. listener.call(this, event);
  12962. }
  12963. }
  12964. }
  12965. }
  12966. class PointCloudTreeNode extends EventDispatcher$1 {
  12967. constructor() {
  12968. super();
  12969. this.needsTransformUpdate = true;
  12970. }
  12971. getChildren() {
  12972. throw new Error('override function');
  12973. }
  12974. getBoundingBox() {
  12975. throw new Error('override function');
  12976. }
  12977. isLoaded() {
  12978. throw new Error('override function');
  12979. }
  12980. isGeometryNode() {
  12981. throw new Error('override function');
  12982. }
  12983. isTreeNode() {
  12984. throw new Error('override function');
  12985. }
  12986. getLevel() {
  12987. throw new Error('override function');
  12988. }
  12989. getBoundingSphere() {
  12990. throw new Error('override function');
  12991. }
  12992. }
  12993. ;
  12994. class PointCloudTree extends Object3D {
  12995. constructor() {
  12996. super();
  12997. //this.spriteGroup = new THREE.Object3D //add
  12998. }
  12999. initialized() {
  13000. return this.root !== null;
  13001. }
  13002. }
  13003. ;
  13004. class PointCloudOctreeGeometry {
  13005. constructor() {
  13006. this.url = null;
  13007. this.octreeDir = null;
  13008. this.spacing = 0;
  13009. this.boundingBox = null;
  13010. this.root = null;
  13011. this.nodes = null;
  13012. this.pointAttributes = null;
  13013. this.hierarchyStepSize = -1;
  13014. this.loader = null;
  13015. }
  13016. }
  13017. class PointCloudOctreeGeometryNode extends PointCloudTreeNode {
  13018. constructor(name, pcoGeometry, boundingBox) {
  13019. super();
  13020. this.id = PointCloudOctreeGeometryNode.IDCount++;
  13021. this.name = name;
  13022. this.index = parseInt(name.charAt(name.length - 1));
  13023. this.pcoGeometry = pcoGeometry;
  13024. this.geometry = null;
  13025. this.boundingBox = boundingBox;
  13026. this.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  13027. this.children = {};
  13028. this.numPoints = 0;
  13029. this.level = null;
  13030. this.loaded = false;
  13031. this.oneTimeDisposeHandlers = [];
  13032. }
  13033. isGeometryNode() {
  13034. return true;
  13035. }
  13036. getLevel() {
  13037. return this.level;
  13038. }
  13039. isTreeNode() {
  13040. return false;
  13041. }
  13042. isLoaded() {
  13043. return this.loaded;
  13044. }
  13045. getBoundingSphere() {
  13046. return this.boundingSphere;
  13047. }
  13048. getBoundingBox() {
  13049. return this.boundingBox;
  13050. }
  13051. getChildren() {
  13052. var children = [];
  13053. for (var i = 0; i < 8; i++) {
  13054. if (this.children[i]) {
  13055. children.push(this.children[i]);
  13056. }
  13057. }
  13058. return children;
  13059. }
  13060. getBoundingBox() {
  13061. return this.boundingBox;
  13062. }
  13063. getURL() {
  13064. var url = '';
  13065. var version = this.pcoGeometry.loader.version;
  13066. if (version.equalOrHigher('1.5')) {
  13067. url = this.pcoGeometry.octreeDir + '/' + this.getHierarchyPath() + '/' + this.name;
  13068. } else if (version.equalOrHigher('1.4')) {
  13069. url = this.pcoGeometry.octreeDir + '/' + this.name;
  13070. } else if (version.upTo('1.3')) {
  13071. url = this.pcoGeometry.octreeDir + '/' + this.name;
  13072. }
  13073. return url;
  13074. }
  13075. getHierarchyPath() {
  13076. var path = 'r/';
  13077. var hierarchyStepSize = this.pcoGeometry.hierarchyStepSize;
  13078. var indices = this.name.substr(1);
  13079. var numParts = Math.floor(indices.length / hierarchyStepSize);
  13080. for (var i = 0; i < numParts; i++) {
  13081. path += indices.substr(i * hierarchyStepSize, hierarchyStepSize) + '/';
  13082. }
  13083. path = path.slice(0, -1);
  13084. return path;
  13085. }
  13086. addChild(child) {
  13087. this.children[child.index] = child;
  13088. child.parent = this;
  13089. }
  13090. load() {
  13091. if (this.loading === true || this.loaded === true || Potree.numNodesLoading >= Potree.maxNodesLoading) {
  13092. return;
  13093. }
  13094. this.loading = true;
  13095. Potree.numNodesLoading++;
  13096. if (this.pcoGeometry.loader.version.equalOrHigher('1.5')) {
  13097. if (this.level % this.pcoGeometry.hierarchyStepSize === 0 && this.hasChildren) {
  13098. this.loadHierachyThenPoints();
  13099. } else {
  13100. this.loadPoints();
  13101. }
  13102. } else {
  13103. this.pcoGeometry.dispatchEvent({
  13104. type: 'updateNodeMaxLevel',
  13105. level: this.level
  13106. }); //add
  13107. this.loadPoints();
  13108. }
  13109. }
  13110. loadPoints() {
  13111. this.pcoGeometry.loader.load(this);
  13112. }
  13113. loadHierachyThenPoints() {
  13114. var node = this;
  13115. // load hierarchy
  13116. var callback = function callback(node, hbuffer) {
  13117. var tStart = performance.now();
  13118. var view = new DataView(hbuffer);
  13119. var stack = [];
  13120. var children = view.getUint8(0);
  13121. var numPoints = view.getUint32(1, true);
  13122. node.numPoints = numPoints;
  13123. stack.push({
  13124. children: children,
  13125. numPoints: numPoints,
  13126. name: node.name
  13127. });
  13128. var decoded = [];
  13129. var offset = 5;
  13130. while (stack.length > 0) {
  13131. var snode = stack.shift();
  13132. var mask = 1;
  13133. for (var i = 0; i < 8; i++) {
  13134. if ((snode.children & mask) !== 0) {
  13135. var childName = snode.name + i;
  13136. var childChildren = view.getUint8(offset);
  13137. var childNumPoints = view.getUint32(offset + 1, true);
  13138. stack.push({
  13139. children: childChildren,
  13140. numPoints: childNumPoints,
  13141. name: childName
  13142. });
  13143. decoded.push({
  13144. children: childChildren,
  13145. numPoints: childNumPoints,
  13146. name: childName
  13147. });
  13148. offset += 5;
  13149. }
  13150. mask = mask * 2;
  13151. }
  13152. if (offset === hbuffer.byteLength) {
  13153. break;
  13154. }
  13155. }
  13156. // console.log(decoded);
  13157. var nodes = {};
  13158. nodes[node.name] = node;
  13159. var pco = node.pcoGeometry;
  13160. for (var _i = 0; _i < decoded.length; _i++) {
  13161. var name = decoded[_i].name;
  13162. var decodedNumPoints = decoded[_i].numPoints;
  13163. var index = parseInt(name.charAt(name.length - 1));
  13164. var parentName = name.substring(0, name.length - 1);
  13165. var parentNode = nodes[parentName];
  13166. var level = name.length - 1;
  13167. var boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  13168. var currentNode = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  13169. currentNode.level = level;
  13170. currentNode.numPoints = decodedNumPoints;
  13171. currentNode.hasChildren = decoded[_i].children > 0;
  13172. currentNode.spacing = pco.spacing / Math.pow(2, level);
  13173. parentNode.addChild(currentNode);
  13174. nodes[name] = currentNode;
  13175. }
  13176. var duration = performance.now() - tStart;
  13177. if (duration > 5) {
  13178. var msg = "duration: ".concat(duration, "ms, numNodes: ").concat(decoded.length);
  13179. console.log(msg);
  13180. }
  13181. node.loadPoints();
  13182. };
  13183. if (node.level % node.pcoGeometry.hierarchyStepSize === 0) {
  13184. // let hurl = node.pcoGeometry.octreeDir + "/../hierarchy/" + node.name + ".hrc";
  13185. var hurl = node.pcoGeometry.octreeDir + '/' + node.getHierarchyPath() + '/' + node.name + '.hrc';
  13186. var xhr = XHRFactory.createXMLHttpRequest();
  13187. xhr.open('GET', hurl, true);
  13188. xhr.responseType = 'arraybuffer';
  13189. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  13190. xhr.onreadystatechange = () => {
  13191. if (xhr.readyState === 4) {
  13192. if (xhr.status === 200 || xhr.status === 0) {
  13193. var hbuffer = xhr.response;
  13194. callback(node, hbuffer);
  13195. } else {
  13196. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + hurl);
  13197. Potree.numNodesLoading--;
  13198. }
  13199. }
  13200. };
  13201. try {
  13202. xhr.send(null);
  13203. } catch (e) {
  13204. console.log('fehler beim laden der punktwolke: ' + e);
  13205. }
  13206. }
  13207. }
  13208. getNumPoints() {
  13209. return this.numPoints;
  13210. }
  13211. dispose() {
  13212. if (this.geometry && this.parent != null) {
  13213. this.geometry.dispose();
  13214. this.geometry = null;
  13215. this.loaded = false;
  13216. this.dispatchEvent({
  13217. type: 'dispose'
  13218. });
  13219. for (var i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  13220. var handler = this.oneTimeDisposeHandlers[i];
  13221. handler();
  13222. }
  13223. this.oneTimeDisposeHandlers = [];
  13224. }
  13225. }
  13226. }
  13227. PointCloudOctreeGeometryNode.IDCount = 0;
  13228. // -------------------------------------------
  13229. // to get a ready to use gradient array from a chroma.js gradient:
  13230. // http://gka.github.io/chroma.js/
  13231. // -------------------------------------------
  13232. //
  13233. // let stops = [];
  13234. // for(let i = 0; i <= 10; i++){
  13235. // let range = chroma.scale(['yellow', 'navy']).mode('lch').domain([10,0])(i)._rgb
  13236. // .slice(0, 3)
  13237. // .map(v => (v / 255).toFixed(4))
  13238. // .join(", ");
  13239. //
  13240. // let line = `[${i / 10}, new THREE.Color(${range})],`;
  13241. //
  13242. // stops.push(line);
  13243. // }
  13244. // stops.join("\n");
  13245. //
  13246. //
  13247. //
  13248. // -------------------------------------------
  13249. // to get a ready to use gradient array from matplotlib:
  13250. // -------------------------------------------
  13251. // import matplotlib.pyplot as plt
  13252. // import matplotlib.colors as colors
  13253. //
  13254. // norm = colors.Normalize(vmin=0,vmax=1)
  13255. // cmap = plt.cm.viridis
  13256. //
  13257. // for i in range(0,11):
  13258. // u = i / 10
  13259. // rgb = cmap(norm(u))[0:3]
  13260. // rgb = ["{0:.3f}".format(v) for v in rgb]
  13261. // rgb = "[" + str(u) + ", new THREE.Color(" + ", ".join(rgb) + ")],"
  13262. // print(rgb)
  13263. var Gradients = {
  13264. // From chroma spectral http://gka.github.io/chroma.js/
  13265. SPECTRAL: [[0, new Color(0.3686, 0.3098, 0.6353)], [0.1, new Color(0.1961, 0.5333, 0.7412)], [0.2, new Color(0.4000, 0.7608, 0.6471)], [0.3, new Color(0.6706, 0.8667, 0.6431)], [0.4, new Color(0.9020, 0.9608, 0.5961)], [0.5, new Color(1.0000, 1.0000, 0.7490)], [0.6, new Color(0.9961, 0.8784, 0.5451)], [0.7, new Color(0.9922, 0.6824, 0.3804)], [0.8, new Color(0.9569, 0.4275, 0.2627)], [0.9, new Color(0.8353, 0.2431, 0.3098)], [1, new Color(0.6196, 0.0039, 0.2588)]],
  13266. PLASMA: [[0.0, new Color(0.241, 0.015, 0.610)], [0.1, new Color(0.387, 0.001, 0.654)], [0.2, new Color(0.524, 0.025, 0.653)], [0.3, new Color(0.651, 0.125, 0.596)], [0.4, new Color(0.752, 0.227, 0.513)], [0.5, new Color(0.837, 0.329, 0.431)], [0.6, new Color(0.907, 0.435, 0.353)], [0.7, new Color(0.963, 0.554, 0.272)], [0.8, new Color(0.992, 0.681, 0.195)], [0.9, new Color(0.987, 0.822, 0.144)], [1.0, new Color(0.940, 0.975, 0.131)]],
  13267. YELLOW_GREEN: [[0, new Color(0.1647, 0.2824, 0.3451)], [0.1, new Color(0.1338, 0.3555, 0.4227)], [0.2, new Color(0.0610, 0.4319, 0.4864)], [0.3, new Color(0.0000, 0.5099, 0.5319)], [0.4, new Color(0.0000, 0.5881, 0.5569)], [0.5, new Color(0.1370, 0.6650, 0.5614)], [0.6, new Color(0.2906, 0.7395, 0.5477)], [0.7, new Color(0.4453, 0.8099, 0.5201)], [0.8, new Color(0.6102, 0.8748, 0.4850)], [0.9, new Color(0.7883, 0.9323, 0.4514)], [1, new Color(0.9804, 0.9804, 0.4314)]],
  13268. VIRIDIS: [[0.0, new Color(0.267, 0.005, 0.329)], [0.1, new Color(0.283, 0.141, 0.458)], [0.2, new Color(0.254, 0.265, 0.530)], [0.3, new Color(0.207, 0.372, 0.553)], [0.4, new Color(0.164, 0.471, 0.558)], [0.5, new Color(0.128, 0.567, 0.551)], [0.6, new Color(0.135, 0.659, 0.518)], [0.7, new Color(0.267, 0.749, 0.441)], [0.8, new Color(0.478, 0.821, 0.318)], [0.9, new Color(0.741, 0.873, 0.150)], [1.0, new Color(0.993, 0.906, 0.144)]],
  13269. INFERNO: [[0.0, new Color(0.077, 0.042, 0.206)], [0.1, new Color(0.225, 0.036, 0.388)], [0.2, new Color(0.373, 0.074, 0.432)], [0.3, new Color(0.522, 0.128, 0.420)], [0.4, new Color(0.665, 0.182, 0.370)], [0.5, new Color(0.797, 0.255, 0.287)], [0.6, new Color(0.902, 0.364, 0.184)], [0.7, new Color(0.969, 0.516, 0.063)], [0.8, new Color(0.988, 0.683, 0.072)], [0.9, new Color(0.961, 0.859, 0.298)], [1.0, new Color(0.988, 0.998, 0.645)]],
  13270. GRAYSCALE: [[0, new Color(0, 0, 0)], [1, new Color(1, 1, 1)]],
  13271. // 16 samples of the TURBU color scheme
  13272. // values taken from: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
  13273. // original file licensed under Apache-2.0
  13274. TURBO: [[0.00, new Color(0.18995, 0.07176, 0.23217)], [0.07, new Color(0.25107, 0.25237, 0.63374)], [0.13, new Color(0.27628, 0.42118, 0.89123)], [0.20, new Color(0.25862, 0.57958, 0.99876)], [0.27, new Color(0.15844, 0.73551, 0.92305)], [0.33, new Color(0.09267, 0.86554, 0.7623)], [0.40, new Color(0.19659, 0.94901, 0.59466)], [0.47, new Color(0.42778, 0.99419, 0.38575)], [0.53, new Color(0.64362, 0.98999, 0.23356)], [0.60, new Color(0.80473, 0.92452, 0.20459)], [0.67, new Color(0.93301, 0.81236, 0.22667)], [0.73, new Color(0.99314, 0.67408, 0.20348)], [0.80, new Color(0.9836, 0.49291, 0.12849)], [0.87, new Color(0.92105, 0.31489, 0.05475)], [0.93, new Color(0.81608, 0.18462, 0.01809)], [1.00, new Color(0.66449, 0.08436, 0.00424)]],
  13275. RAINBOW: [
  13276. // 火灾
  13277. [0, new Color(0.278, 0, 0.714)], [1 / 6, new Color(0, 0, 1)], [2 / 6, new Color(0, 1, 1)], [3 / 6, new Color(0, 1, 0)], [4 / 6, new Color(1, 1, 0)], [5 / 6, new Color(1, 0.64, 0)], [1, new Color(1, 0, 0)]],
  13278. CONTOUR: [[0.00, new Color(0, 0, 0)], [0.03, new Color(0, 0, 0)], [0.04, new Color(1, 1, 1)], [1.00, new Color(1, 1, 1)]],
  13279. ir: [
  13280. //红外
  13281. [0, new Color('#000000')], [1 / 5, new Color('#230463')], [2 / 5, new Color('#80068B')], [3 / 5, new Color('#F49107')], [4 / 5, new Color('#FAD725')], [1, new Color('#FFFFFF')]]
  13282. };
  13283. var Shaders = {};
  13284. Shaders["pointcloud_new.vs"] = "\nprecision highp float;\nprecision highp int;\n \n#define PI 3.141592653589793\n\n\n\n\n#if defined(usePanoMap) \n \n uniform samplerCube pano0Map; //\u968F\u4FBF\u8BBE\u7F6E\u4E00\u4E2AsamplerCube\u53BB\u4F7F\u7528\u90FD\u4F1A\u8BA9\u70B9\u4E91\u6D88\u5931\n uniform samplerCube pano1Map;\n \n uniform float progress;\n uniform float easeInOutRatio;\n\n \n uniform vec3 pano0Position;\n uniform mat4 pano0Matrix; \n uniform vec3 pano1Position;\n uniform mat4 pano1Matrix;\n /*\n varying vec3 vWorldPosition0;\n varying vec3 vWorldPosition1;\n */\n#endif \n\n\n\n\n \n\n//--------------\n\n\n\n\n\nattribute vec3 position;\nattribute vec3 color;\nattribute float intensity;\nattribute float classification; //attribute float classification;\nattribute float returnNumber;\nattribute float numberOfReturns;\nattribute float pointSourceID;\nattribute vec4 indices; //\u6BCF\u4E2A\u70B9\u7684index\nattribute float spacing;\nattribute float gpsTime;\nattribute vec3 normal;\nattribute float aExtra;\n\nattribute float ir; //\u7EA2\u5916\u6E29\u5EA6 \u5F00\u5C14\u6587 \nattribute float temp; //\u706B\u707EAI\u6E29\u5EA6 \u5F00\u5C14\u6587 \n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat4 uViewInv;\n\n//uniform float uScreenWidth;\n//uniform float uScreenHeight;\nuniform vec2 resolution;\n\n\nuniform float fov;\nuniform float near;\nuniform float far;\n\n\n\n\nuniform bool uDebug;\n\nuniform bool uUseOrthographicCamera;\nuniform float uOrthoWidth;\nuniform float uOrthoHeight;\n\n#define CLIPTASK_NONE 0\n#define CLIPTASK_HIGHLIGHT 1\n#define CLIPTASK_SHOW_INSIDE 2\n#define CLIPTASK_SHOW_OUTSIDE 3\n\n#define CLIPMETHOD_INSIDE_ANY 0\n#define CLIPMETHOD_INSIDE_ALL 1\n\n//\u6700\u5916\u5C42\u88C1\u526A\uFF08\u4E0B\u8F7D\uFF09\n#if defined(bigClipInBox)\n\tuniform mat4 clipBoxBig_in;\n#endif\n//\u5185\u5C42\u88C1\u526A\n#if defined(num_in_clipboxes) && num_in_clipboxes > 0\n\tuniform mat4 clipBoxes_in[num_in_clipboxes];\n#endif\n#if defined(num_out_clipboxes) && num_out_clipboxes > 0\n\tuniform mat4 clipBoxes_out[num_out_clipboxes];\n#endif\n\n\n#if defined(num_clipspheres) && num_clipspheres > 0\n\tuniform mat4 uClipSpheres[num_clipspheres];\n#endif\n\n \n#if defined(num_highlightBox) && num_highlightBox > 0\n uniform mat4 boxes_highlight[num_highlightBox]; \n#endif \n\t\t \n\n#if defined(num_prism) && num_prism > 0\n uniform mat3 prismList[num_prism];\n uniform vec2 prismPoints[prismPointCountSum]; \n#endif \n\n#if defined(showBaseHeight) \n uniform sampler2D baseHeightAreaMap ;\n uniform vec2 baseHeightBoundZ;\n uniform vec4 baseHeightBoundXY; \n#endif \n\nuniform float size;\nuniform float minSize;\nuniform float maxSize; \nuniform float orthoMaxSize;//add\n\n\nuniform float uPCIndex;\nuniform float uOctreeSpacing;\nuniform float uNodeSpacing;\nuniform float uOctreeSize;\nuniform vec3 uBBSize;\nuniform float uLevel;\nuniform float levelPercent;//add\nuniform float uVNStart;\nuniform bool uIsLeafNode;\n\nuniform vec3 uColor;\nuniform float uOpacity; \nvarying float vOpacity; //add\n\n\n\nuniform vec2 elevationRange;\nuniform vec2 intensityRange;\n\nuniform vec2 uFilterReturnNumberRange;\nuniform vec2 uFilterNumberOfReturnsRange;\nuniform vec2 uFilterPointSourceIDClipRange;\nuniform vec2 uFilterGPSTimeClipRange;\n//uniform float ufilterByNormalThreshold; \n\nuniform float uGpsScale;\nuniform float uGpsOffset;\n\nuniform vec2 uNormalizedGpsBufferRange;\n\nuniform vec3 uIntensity_gbc;\nuniform vec3 uRGB_gbc;\nuniform vec3 uExtra_gbc;\n\nuniform float uTransition;\nuniform float wRGB;\nuniform float wIntensity;\nuniform float wElevation;\nuniform float wClassification;\nuniform float wReturnNumber;\nuniform float wSourceID;\n\nuniform vec2 uExtraNormalizedRange;\nuniform vec2 uExtraRange;\nuniform float uExtraScale;\nuniform float uExtraOffset;\n\nuniform vec3 uShadowColor;\n\nuniform sampler2D visibleNodes;\nuniform sampler2D gradient;\nuniform sampler2D classificationLUT;\n\n#if defined(color_type_matcap)\nuniform sampler2D matcapTextureUniform;\n#endif\nuniform bool backfaceCulling;\n\n#if defined(num_shadowmaps) && num_shadowmaps > 0\nuniform sampler2D uShadowMap[num_shadowmaps];\nuniform mat4 uShadowWorldView[num_shadowmaps];\nuniform mat4 uShadowProj[num_shadowmaps];\n#endif\n \nuniform vec2 temperRange;\n \n\nvarying vec3\tvColor;\nvarying float\tvLogDepth;\nvarying vec3\tvViewPosition;\nvarying float \tvRadius;\nvarying float \tvPointSize;\n\n \n\nfloat Round(float number){\n\treturn floor(number + 0.5);\n}\n\n// \n// ### ######## ### ######## ######## #### ## ## ######## ###### #### ######## ######## ###### \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## ######## ## ## ## ## ###### ###### ## ## ###### ###### \n// ######### ## ## ######### ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ######## ## ## ## ## #### ### ######## ###### #### ######## ######## ###### \n// \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\n\n// ---------------------\n// OCTREE\n// ---------------------\n\n#if (defined(adaptive_point_size) || defined(color_type_level_of_detail)) && defined(tree_type_octree)\n/**\n * number of 1-bits up to inclusive index position\n * number is treated as if it were an integer in the range 0-255\n *\n */\nint numberOfOnes(int number, int index){\n\tint numOnes = 0;\n\tint tmp = 128;\n\tfor(int i = 7; i >= 0; i--){\n\t\t\n\t\tif(number >= tmp){\n\t\t\tnumber = number - tmp;\n\n\t\t\tif(i <= index){\n\t\t\t\tnumOnes++;\n\t\t\t}\n\t\t}\n\t\t\n\t\ttmp = tmp / 2;\n\t}\n\n\treturn numOnes;\n}\n\n\n/**\n * checks whether the bit at index is 1\n * number is treated as if it were an integer in the range 0-255\n *\n */\nbool isBitSet(int number, int index){\n\n\t// weird multi else if due to lack of proper array, int and bitwise support in WebGL 1.0\n\tint powi = 1;\n\tif(index == 0){\n\t\tpowi = 1;\n\t}else if(index == 1){\n\t\tpowi = 2;\n\t}else if(index == 2){\n\t\tpowi = 4;\n\t}else if(index == 3){\n\t\tpowi = 8;\n\t}else if(index == 4){\n\t\tpowi = 16;\n\t}else if(index == 5){\n\t\tpowi = 32;\n\t}else if(index == 6){\n\t\tpowi = 64;\n\t}else if(index == 7){\n\t\tpowi = 128;\n\t}else{\n\t\treturn false;\n\t}\n\n\tint ndp = number / powi;\n\n\treturn mod(float(ndp), 2.0) != 0.0;\n}\n\n\n/**\n * find the LOD at the point position\n */\nfloat getLOD(){//////we use this\n\t \n\tvec3 offset = vec3(0.0, 0.0, 0.0);\n\tint iOffset = int(uVNStart);\n\tfloat depth = uLevel;\n\tfor(float i = 0.0; i <= 30.0; i++){\n\t\tfloat nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);\n\t\t\n\t\tvec3 index3d = (position-offset) / nodeSizeAtLevel;\n\t\tindex3d = floor(index3d + 0.5);\n\t\tint index = int(Round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));\n\t\t\n\t\tvec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));\n\t\tint mask = int(Round(value.r * 255.0));\n\n\t\tif(isBitSet(mask, index)){\n\t\t\t// there are more visible child nodes at this position\n\t\t\tint advanceG = int(Round(value.g * 255.0)) * 256;\n\t\t\tint advanceB = int(Round(value.b * 255.0));\n\t\t\tint advanceChild = numberOfOnes(mask, index - 1);\n\t\t\tint advance = advanceG + advanceB + advanceChild;\n\n\t\t\tiOffset = iOffset + advance;\n\t\t\t\n\t\t\tdepth++;\n\t\t}else{\n\t\t\t// no more visible child nodes at this position\n\t\t\t//return value.a * 255.0;\n\n\t\t\tfloat lodOffset = (255.0 * value.a) / 10.0 - 10.0;\n\n\t\t\treturn depth + lodOffset;\n\t\t}\n\t\t\n\t\toffset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;\n\t}\n\t\t\n\treturn depth;\n}\n\nfloat getSpacing(){\n\tvec3 offset = vec3(0.0, 0.0, 0.0);\n\tint iOffset = int(uVNStart);\n\tfloat depth = uLevel;\n\tfloat spacing = uNodeSpacing;\n\tfor(float i = 0.0; i <= 30.0; i++){\n\t\tfloat nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);\n\t\t\n\t\tvec3 index3d = (position-offset) / nodeSizeAtLevel;\n\t\tindex3d = floor(index3d + 0.5);\n\t\tint index = int(Round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));\n\t\t\n\t\tvec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));\n\t\tint mask = int(Round(value.r * 255.0));\n\t\tfloat spacingFactor = value.a;\n\n\t\tif(i > 0.0){\n\t\t\tspacing = spacing / (255.0 * spacingFactor);\n\t\t}\n\t\t\n\n\t\tif(isBitSet(mask, index)){\n\t\t\t// there are more visible child nodes at this position\n\t\t\tint advanceG = int(Round(value.g * 255.0)) * 256;\n\t\t\tint advanceB = int(Round(value.b * 255.0));\n\t\t\tint advanceChild = numberOfOnes(mask, index - 1);\n\t\t\tint advance = advanceG + advanceB + advanceChild;\n\n\t\t\tiOffset = iOffset + advance;\n\n\t\t\t//spacing = spacing / (255.0 * spacingFactor);\n\t\t\t//spacing = spacing / 3.0;\n\t\t\t\n\t\t\tdepth++;\n\t\t}else{\n\t\t\t// no more visible child nodes at this position\n\t\t\treturn spacing;\n\t\t}\n\t\t\n\t\toffset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;\n\t}\n\t\t\n\treturn spacing;\n}\n\nfloat getPointSizeAttenuation(){\n\treturn pow(2.0, getLOD());\n}\n\n\n#endif\n\n\n// ---------------------\n// KD-TREE\n// ---------------------\n\n#if (defined(adaptive_point_size) || defined(color_type_level_of_detail)) && defined(tree_type_kdtree)\n\nfloat getLOD(){\n\tvec3 offset = vec3(0.0, 0.0, 0.0);\n\tfloat iOffset = 0.0;\n\tfloat depth = 0.0;\n\t\t\n\t\t\n\tvec3 size = uBBSize;\t\n\tvec3 pos = position;\n\t\t\n\tfor(float i = 0.0; i <= 1000.0; i++){\n\t\t\n\t\tvec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));\n\t\t\n\t\tint children = int(value.r * 255.0);\n\t\tfloat next = value.g * 255.0;\n\t\tint split = int(value.b * 255.0);\n\t\t\n\t\tif(next == 0.0){\n\t\t \treturn depth;\n\t\t}\n\t\t\n\t\tvec3 splitv = vec3(0.0, 0.0, 0.0);\n\t\tif(split == 1){\n\t\t\tsplitv.x = 1.0;\n\t\t}else if(split == 2){\n\t\t \tsplitv.y = 1.0;\n\t\t}else if(split == 4){\n\t\t \tsplitv.z = 1.0;\n\t\t}\n\t\t\n\t\tiOffset = iOffset + next;\n\t\t\n\t\tfloat factor = length(pos * splitv / size);\n\t\tif(factor < 0.5){\n\t\t\t// left\n\t\tif(children == 0 || children == 2){\n\t\t\t\treturn depth;\n\t\t\t}\n\t\t}else{\n\t\t\t// right\n\t\t\tpos = pos - size * splitv * 0.5;\n\t\t\tif(children == 0 || children == 1){\n\t\t\t\treturn depth;\n\t\t\t}\n\t\t\tif(children == 3){\n\t\t\t\tiOffset = iOffset + 1.0;\n\t\t\t}\n\t\t}\n\t\tsize = size * ((1.0 - (splitv + 1.0) / 2.0) + 0.5);\n\t\t\n\t\tdepth++;\n\t}\n\t\t\n\t\t\n\treturn depth;\t\n}\n\nfloat getPointSizeAttenuation(){\n\treturn 0.5 * pow(1.3, getLOD());\n}\n\n#endif\n\n\n\n// \n// ### ######## ######## ######## #### ######## ## ## ######## ######## ###### \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ######## ## ######## ## ## ## ###### ###### \n// ######### ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## \n// ## ## ## ## ## ## #### ######## ####### ## ######## ###### \n// \n\n\n\n// formula adapted from: http://www.dfstudios.co.uk/articles/programming/image-programming-algorithms/image-processing-algorithms-part-5-contrast-adjustment/\nfloat getContrastFactor(float contrast){\n\treturn (1.0158730158730156 * (contrast + 1.0)) / (1.0158730158730156 - contrast);\n}\n\nvec3 getRGB(){\n\tvec3 rgb = color;\n\t\n\trgb = pow(rgb, vec3(uRGB_gbc.x));\n\trgb = rgb + uRGB_gbc.y;\n\trgb = (rgb - 0.5) * getContrastFactor(uRGB_gbc.z) + 0.5;\n\trgb = clamp(rgb, 0.0, 1.0);\n\n\treturn rgb;\n}\n\nfloat getIntensity(){\n\tfloat w = (intensity - intensityRange.x) / (intensityRange.y - intensityRange.x);\n\tw = pow(w, uIntensity_gbc.x);\n\tw = w + uIntensity_gbc.y;\n\tw = (w - 0.5) * getContrastFactor(uIntensity_gbc.z) + 0.5;\n\tw = clamp(w, 0.0, 1.0);\n\n\treturn w;\n}\n\nvec3 getGpsTime(){\n\n\tfloat w = (gpsTime + uGpsOffset) * uGpsScale;\n\n\n\tvec3 c = texture2D(gradient, vec2(w, 1.0 - w)).rgb;\n\n\n\t// vec2 r = uNormalizedGpsBufferRange;\n\t// float w = gpsTime * (r.y - r.x) + r.x;\n\t// w = clamp(w, 0.0, 1.0);\n\t// vec3 c = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\t\n\treturn c;\n}\n\nvec3 getElevation(vec4 world){ \n\tfloat w = (world.z - elevationRange.x) / (elevationRange.y - elevationRange.x);\n\tvec3 cElevation = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\treturn cElevation;\n}\n\n\nvec3 getTemperature(){ //xzw add \n\n float temperature = 0.0;\n \n #if defined color_type_ir \n temperature = ir;\n #else\n temperature = temp;\n #endif\n\tfloat w = (temperature - temperRange.x) / (temperRange.y - temperRange.x);\n w = clamp(w,0.0,1.0);\n\tvec3 c = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\treturn c;\n}\n\n\nvec4 getClassification(){\n\tvec2 uv = vec2(float(classification) / 255.0, 0.5);\n\tvec4 classColor = texture2D(classificationLUT, uv);\n\t\n\treturn classColor;\n}\n\nvec3 getReturns(){\n\n\t// 0b 00_000_111\n\tfloat rn = mod(returnNumber, 8.0);\n\t// 0b 00_111_000\n\tfloat nr = mod(returnNumber / 8.0, 8.0);\n\n\tif(nr <= 1.0){\n\t\treturn vec3(1.0, 0.0, 0.0);\n\t}else{\n\t\treturn vec3(0.0, 1.0, 0.0);\n\t}\n\n\t// return vec3(nr / 4.0, 0.0, 0.0);\n\n\t// if(nr == 1.0){\n\t// \treturn vec3(1.0, 1.0, 0.0);\n\t// }else{\n\t// \tif(rn == 1.0){\n\t// \t\treturn vec3(1.0, 0.0, 0.0);\n\t// \t}else if(rn == nr){\n\t// \t\treturn vec3(0.0, 0.0, 1.0);\n\t// \t}else{\n\t// \t\treturn vec3(0.0, 1.0, 0.0);\n\t// \t}\n\t// }\n\n\t// if(numberOfReturns == 1.0){\n\t// \treturn vec3(1.0, 1.0, 0.0);\n\t// }else{\n\t// \tif(returnNumber == 1.0){\n\t// \t\treturn vec3(1.0, 0.0, 0.0);\n\t// \t}else if(returnNumber == numberOfReturns){\n\t// \t\treturn vec3(0.0, 0.0, 1.0);\n\t// \t}else{\n\t// \t\treturn vec3(0.0, 1.0, 0.0);\n\t// \t}\n\t// }\n}\n\nvec3 getReturnNumber(){\n\tif(numberOfReturns == 1.0){\n\t\treturn vec3(1.0, 1.0, 0.0);\n\t}else{\n\t\tif(returnNumber == 1.0){\n\t\t\treturn vec3(1.0, 0.0, 0.0);\n\t\t}else if(returnNumber == numberOfReturns){\n\t\t\treturn vec3(0.0, 0.0, 1.0);\n\t\t}else{\n\t\t\treturn vec3(0.0, 1.0, 0.0);\n\t\t}\n\t}\n}\n\nvec3 getNumberOfReturns(){\n\tfloat value = numberOfReturns;\n\n\tfloat w = value / 6.0;\n\n\tvec3 color = texture2D(gradient, vec2(w, 1.0 - w)).rgb;\n\n\treturn color;\n}\n\nvec3 getSourceID(){\n\tfloat w = mod(pointSourceID, 10.0) / 10.0;\n\treturn texture2D(gradient, vec2(w,1.0 - w)).rgb;\n}\n\nvec3 getCompositeColor(vec4 world){\n\tvec3 c;\n\tfloat w;\n\n\tc += wRGB * getRGB();\n\tw += wRGB;\n\t\n\tc += wIntensity * getIntensity() * vec3(1.0, 1.0, 1.0);\n\tw += wIntensity;\n\t\n\tc += wElevation * getElevation(world);\n\tw += wElevation;\n\t\n\tc += wReturnNumber * getReturnNumber();\n\tw += wReturnNumber;\n\t\n\tc += wSourceID * getSourceID();\n\tw += wSourceID;\n\t\n\tvec4 cl = wClassification * getClassification();\n\tc += cl.a * cl.rgb;\n\tw += wClassification * cl.a;\n\n\tc = c / w;\n\t\n\tif(w == 0.0){\n\t\t//c = color;\n\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t}\n\t\n\treturn c;\n}\n\n\nvec3 getNormal(){\n\t//vec3 n_hsv = vec3( modelMatrix * vec4( normal, 0.0 )) * 0.5 + 0.5; // (n_world.xyz + vec3(1.,1.,1.)) / 2.;\n\tvec3 n_view = normalize( vec3(modelViewMatrix * vec4( normal, 0.0 )) );\n\treturn n_view;\n}\nbool applyBackfaceCulling() {\n\t// Black not facing vertices / Backface culling\n \n\tvec3 e = normalize(vec3(modelViewMatrix * vec4( position, 1. )));\n\tvec3 n = getNormal(); // normalize( vec3(modelViewMatrix * vec4( normal, 0.0 )) );\n\n\tif((uUseOrthographicCamera && n.z <= 0.) || (!uUseOrthographicCamera && dot( n, e ) >= 0.)) { \n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n#if defined(color_type_matcap)\n// Matcap Material\nvec3 getMatcap(){ \n\tvec3 eye = normalize( vec3( modelViewMatrix * vec4( position, 1. ) ) ); \n\tif(uUseOrthographicCamera) { \n\t\teye = vec3(0., 0., -1.);\n\t}\n\tvec3 r_en = reflect( eye, getNormal() ); // or r_en = e - 2. * dot( n, e ) * n;\n\tfloat m = 2. * sqrt(pow( r_en.x, 2. ) + pow( r_en.y, 2. ) + pow( r_en.z + 1., 2. ));\n\tvec2 vN = r_en.xy / m + .5;\n\treturn texture2D(matcapTextureUniform, vN).rgb; \n}\n#endif\n\nvec3 getExtra(){\n\n\tfloat w = (aExtra + uExtraOffset) * uExtraScale;\n\tw = clamp(w, 0.0, 1.0);\n\n\tvec3 color = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\n\t// vec2 r = uExtraNormalizedRange;\n\n\t// float w = aExtra * (r.y - r.x) + r.x;\n\n\t// w = (w - uExtraRange.x) / (uExtraRange.y - uExtraRange.x);\n\n\t// w = clamp(w, 0.0, 1.0);\n\n\t// vec3 color = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\n\treturn color;\n}\n\nvec3 getColor(vec4 world){\n\tvec3 color;\n\t\n\t#ifdef color_type_rgba\n\t\tcolor = getRGB();\n \n \n\t#elif defined color_type_height || defined color_type_elevation\n\t\tcolor = getElevation(world);\n\t#elif defined color_type_rgb_height\n\t\tvec3 cHeight = getElevation();\n\t\tcolor = (1.0 - uTransition) * getRGB() + uTransition * cHeight;\n #elif defined color_type_ir || defined color_type_temp // add\n color = getTemperature();\n\t#elif defined color_type_depth\n\t\tfloat linearDepth = gl_Position.w;\n\t\tfloat expDepth = (gl_Position.z / gl_Position.w) * 0.5 + 0.5;\n\t\tcolor = vec3(linearDepth, expDepth, 0.0);\n\t\t//color = vec3(1.0, 0.5, 0.3);\n\t#elif defined color_type_intensity\n\t\tfloat w = getIntensity();\n\t\tcolor = vec3(w, w, w);\n\t#elif defined color_type_gps_time\n\t\tcolor = getGpsTime();\n\t#elif defined color_type_intensity_gradient\n\t\tfloat w = getIntensity();\n\t\tcolor = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\t#elif defined color_type_color\n\t\tcolor = uColor;\n\t#elif defined color_type_level_of_detail\n\t\tfloat depth = getLOD();\n\t\tfloat w = depth / 10.0;\n\t\tcolor = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\t#elif defined color_type_indices\n\t\tcolor = indices.rgb;\n\t#elif defined color_type_classification //xzw change \n\t\tvec4 cl = getClassification(); \n vec3 originC = getRGB();\n float blendRatio = 0.5;\n float classAlpha = cl.a * blendRatio; \n\t\tcolor = cl.rgb * classAlpha + originC * (1.0-classAlpha); //mix with old rgba\n\t#elif defined color_type_return_number\n\t\tcolor = getReturnNumber();\n\t#elif defined color_type_returns\n\t\tcolor = getReturns();\n\t#elif defined color_type_number_of_returns\n\t\tcolor = getNumberOfReturns();\n\t#elif defined color_type_source_id\n\t\tcolor = getSourceID();\n\t#elif defined color_type_point_source_id\n\t\tcolor = getSourceID();\n\t#elif defined color_type_normal\n\t\tcolor = (modelMatrix * vec4(normal, 0.0)).xyz;\n\t#elif defined color_type_phong\n\t\tcolor = color;\n\t#elif defined color_type_composite\n\t\tcolor = getCompositeColor(world);\n\t#elif defined color_type_matcap\n\t\tcolor = getMatcap();\n\t#elif defined color_type_heightCpt //add\n color = vec3(0.0,0.0,0.0);\n #else\n\t\tcolor = getExtra();\n\t#endif\n\t\n\tif (backfaceCulling && applyBackfaceCulling()){\n //color = vec3(0.);\n }\n //applyBackfaceCulling\u76F4\u63A5\u8FD4\u56DEfalse\u6216\u8005\u6CE8\u91CAcolor = vec3(0.);\u90FD\u6CA1\u95EE\u9898\n\treturn color;\n}\n\nfloat getPointSize(){\n\tfloat pointSize = 1.0;\n\tfloat maxSize_ = maxSize;\n\tfloat slope = tan(fov / 2.0);\n\tfloat projFactor = -0.5 * resolution.y / (slope * vViewPosition.z);\n \n \n \n /*\n\tfloat scale = length(\n\t\tmodelViewMatrix * vec4(0, 0, 0, 1) - \n\t\tmodelViewMatrix * vec4(uOctreeSpacing, 0, 0, 1)\n\t) / uOctreeSpacing;\n \n\tprojFactor = projFactor * scale;\n\t*/\n \n \n\tfloat r = uOctreeSpacing * 1.7;\n\t//vRadius = r;\n \n \n\t#if defined fixed_point_size\n\t\tpointSize = size;\n\t#elif defined attenuated_point_size\n\t\tif(uUseOrthographicCamera){ \n pointSize = size / uOrthoWidth * resolution.x; //\u6539\u6210\u8FD1\u4F3Cadaptive_point_size\u6839\u636E\u7A97\u53E3\u7F29\u653E\u3002\u5176\u5B9E\u5C31\u662Fsize * zoom (size\u5355\u4F4D\u8F6C\u5316\u4E3A\u7C73\uFF0C\u5982size\u4E3A1\u4EE3\u8868\u4E00\u4E2A\u70B9\u4E91\u5728\u573A\u666F\u4E2D1\u7C73\u5BBD,zoom\u4EE3\u88681px=1/zoom\u7C73)\n maxSize_ = orthoMaxSize; //for panoEditor, when zoom in, need more details, rather than always same size\n\n\t\t}else{ //\u8FD1\u5927\u8FDC\u5C0F\uFF0C\u6A21\u62DF\u771F\u5B9Emesh\uFF0C\u8FB9\u7F18\u653E\u5927\n\t\t\t//pointSize = size * spacing * projFactor; //spacing\u662Fattribute \u4E3A\u7A7A \u5982\u679C\u6709\u8FD9\u4E2A\u503C\u5C31\u80FD\u66F4\u81EA\u9002\u5E94\u586B\u8865\n //pointSize = size * uOctreeSpacing * projFactor / 18.0; //\u76F4\u63A5\u7528cloud\u7684spacing\u91CC\uFF0C\u4E0D\u8FC7\u56E0\u4E3A\u90FD\u4E00\u6837\u6240\u4EE5\u53EF\u80FD\u6CA1\u6709\u4EC0\u4E48\u610F\u4E49\n\t\t\t//pointSize = pointSize * projFactor;\n pointSize = size * projFactor ;\n\t\t}\n \n\t#elif defined adaptive_point_size\n\t\tif(uUseOrthographicCamera) {\n\t\t\tfloat worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();\n\t\t\tpointSize = (worldSpaceSize / uOrthoWidth) * resolution.x; //uScreenWidth;\n maxSize_ = orthoMaxSize;\n\t\t} else {\n\t\t\tfloat worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();\n\t\t\tpointSize = worldSpaceSize * projFactor;\n\t\t}\n \n\t#endif\n\n\tpointSize = max(minSize, pointSize);\n\tpointSize = min(maxSize_, pointSize);\n\t\n\tvRadius = pointSize / projFactor;\n\n\treturn pointSize;\n} \n\n\nbool insideBox(mat4 clipBox, vec4 worldPos){//add\n vec4 clipPosition = clipBox * worldPos;\n bool inside = -0.5 <= clipPosition.x && clipPosition.x <= 0.5;\n inside = inside && -0.5 <= clipPosition.y && clipPosition.y <= 0.5;\n inside = inside && -0.5 <= clipPosition.z && clipPosition.z <= 0.5;\n\n return inside;\n}\n\n\n\n#if defined(color_type_heightCpt)\n vec3 percentToByte(float num){\n //\u8F93\u51FA\u662F0-1\uFF0C shader\u7CBE\u5EA6\u4E0D\u591F\uFF0C\u53EA\u591F\u5B583\u4E2A\u6570\n float a = 1.0;\n float result[4];\n for(int i=0;i<3;i++){\n a = i == 2 ? a/255.0 : a / 256.0 ; \n //\u5206\u6210256\u4EFD\uFF0C\u5176\u4E2D255\u4EFD\u7ED9\u5F53\u524D\u4F4D\u7F6E\uFF0C\u6700\u540E\u4E00\u4EFD\u7ED9\u540E\u4E00\u4E2A\u4F4D\u7F6E\uFF0C\u800C\u5230\u4E86\u6700\u540E\u4E00\u4E2A\u4F4D\u7F6E\u65F6\u6CA1\u6709\u4E0B\u4E00\u4E2A\u4F4D\u7F6E\u4E86\u6240\u4EE5\u53EA\u5206\u6210255\u4EFD\n if(num > a){\n float c = num / a;\n float r = floor(c);\n r = min(255.0, r);\n result[i] = r;\n num -= r * a;\n }else{\n result[i] = 0.0;\n }\n } \n return vec3(result[0]/255.0, result[1]/255.0,result[2]/255.0); \n \n //\u9664\u4EE5\u591A\u5C11255\u8FD8\u662F256? \u53C2\u8003uPCIndex / 255.0 \u5E94\u8BE5\u662F255\n } \n#endif\n\n \n\n#if defined(num_prism) && num_prism > 0\n \n \n int insidePrism(mat3 prismInfo, int pointIndexStart, vec4 worldPos){//\u662F\u5426\u5728\u68F1\u67F1\u91CC \n \n float zMin = prismInfo[0][0];\n float zMid = prismInfo[0][1];\n float zMax = prismInfo[0][2]; \n float xMin = prismInfo[1][0];\n float xMax = prismInfo[1][1];\n float yMin = prismInfo[1][2];\n float yMax = prismInfo[2][0]; \n\n int pointCount = int(Round(prismInfo[2][1]));\n \n if( worldPos.x < xMin || worldPos.x > xMax || worldPos.y < yMin || worldPos.y > yMax)return 0;\n #ifndef showBaseHeight\n if( worldPos.z < zMin || worldPos.z > zMax) return 0;\n #endif\n \n \n bool inside = false;\n \n int j=pointCount-1;\n \n for(int i=0; i<prism_maxPointsCount; i++){\n if(i>=pointCount)break;\n float xi = prismPoints[i+pointIndexStart].x, yi = prismPoints[i+pointIndexStart].y, xj = prismPoints[j+pointIndexStart].x, yj = prismPoints[j+pointIndexStart].y;\n\n if(((yi > worldPos.y) != (yj > worldPos.y)) && (worldPos.x < (xj - xi) * (worldPos.y - yi) / (yj - yi) + xi)){\n inside = !inside;\n }\n j=i; \n }\n \n if(inside){\n #ifdef showBaseHeight\n return 1;\n #else \n #ifdef color_type_heightCpt \n vColor = percentToByte((worldPos.z - zMin) / (zMax - zMin)); \n #endif \n #endif\n \n return worldPos.z < zMid ? 1 : 2;\n }else return 0; \n } \n \n#endif\n\n#ifdef showBaseHeight\n float byteToFloat(vec3 color){ \n float percent = 0.0;\n float a = 1.0; \n for(int i=0;i<3;i++){\n a = i == 2 ? a/255.0 : a/256.0; \n percent += a * color[i] ;\n }\n return percent * 255.0 ; \n } \n \n#endif\n\n\n \n\n\nvoid doClipping(vec4 world){\n\n\t/*{ \n\t\tvec4 cl = getClassification(); \n\t\tif(cl.a == 0.0){\n\t\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}*/\n\n\t#if defined(clip_return_number_enabled)\n\t{ // return number filter\n\t\tvec2 range = uFilterReturnNumberRange;\n\t\tif(returnNumber < range.x || returnNumber > range.y){\n\t\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}\n\t#endif\n\n\t#if defined(clip_number_of_returns_enabled)\n\t{ // number of return filter\n\t\tvec2 range = uFilterNumberOfReturnsRange;\n\t\tif(numberOfReturns < range.x || numberOfReturns > range.y){\n\t\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}\n\t#endif\n\n\t#if defined(clip_gps_enabled)\n\t{ // GPS time filter\n\t\tfloat time = (gpsTime + uGpsOffset) * uGpsScale;\n\t\tvec2 range = uFilterGPSTimeClipRange;\n\n\t\tif(time < range.x || time > range.y){\n\t\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}\n\t#endif\n\n\t#if defined(clip_point_source_id_enabled)\n\t{ // point source id filter\n\t\tvec2 range = uFilterPointSourceIDClipRange;\n\t\tif(pointSourceID < range.x || pointSourceID > range.y){\n\t\t\tgl_Position = vec4(100.0, 100.0, 100.0, 0.0);\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}\n\t#endif\n\n\t \n\n\n //\u603B\u5171\u4E09\u79CDbox : \u6700\u5916\u5C42\u53EF\u89C1\u3001\u5185\u5C42\u53EF\u89C1\u548C\u4E0D\u53EF\u89C1(\u5916\u5C42\u53EF\u89C1\u548C\u5185\u5C42\u53EF\u89C1\u662F\u4EA4\u96C6\uFF0C\u5185\u5C42\u53EF\u89C1\u548C\u5185\u5C42\u4E0D\u53EF\u89C1\u662F\u5E76\u96C6)\n \n #if defined(bigClipInBox) \n if(!insideBox(clipBoxBig_in, world)){ \n gl_Position = vec4(100.0, 100.0, 100.0, 1.0);\n return;;\n } \n #endif \n \n #if defined(num_in_clipboxes) && num_in_clipboxes > 0\n //\u5F53\u6709\u53EF\u89C1box\u65F6\uFF0C\u9700\u8981\u5728\u4EFB\u4E00\u53EF\u89C1box\u5185\u624D\u53EF\u89C1\n bool visi1 = false;\n\t\tfor(int i = 0; i < num_in_clipboxes; i++){ \n if(insideBox(clipBoxes_in[i], world)){\n visi1 = true;\n break;\n } \n\t\t}\n if(!visi1){\n gl_Position = vec4(100.0, 100.0, 100.0, 1.0);\n return;\n }\n\t#endif\n\n\n #if defined(num_out_clipboxes) && num_out_clipboxes > 0\n //\u5F53\u6709\u4E0D\u53EF\u89C1box\u65F6\uFF0C\u4E0D\u5728\u6240\u6709\u4E0D\u53EF\u89C1box\u5185\u624D\u53EF\u89C1\n bool visi2 = true;\n\t\tfor(int i = 0; i < num_out_clipboxes; i++){ \n if(insideBox(clipBoxes_out[i], world)){\n visi2 = false;\n break;\n } \n\t\t}\n if(!visi2){\n gl_Position = vec4(100.0, 100.0, 100.0, 1.0);\n return;\n }\n\t#endif \n \n \n #if defined(num_highlightBox) && num_highlightBox > 0\n //\u5F53\u6709\u9AD8\u4EAEbox\u65F6\uFF0C\u9700\u8981\u5728\u4EFB\u4E00\u53EF\u89C1\u9AD8\u4EAE\u5185\u90FD\u9AD8\u5BBD\n bool highlight = false;\n\t\tfor(int i = 0; i < num_highlightBox; i++){ \n if(insideBox(boxes_highlight[i], world)){\n highlight = true;\n break;\n } \n\t\t}\n if(highlight){\n vColor.r += 0.5; \n }\n\t#endif\n \n \n \n int highlight_ = 0; \n \n #if defined(num_prism) && num_prism > 0 \n //\u57FA\u4E8Eprism\u68F1\u67F1\u7684\u571F\u65B9\u91CF\u663E\u793A\u6216\u8BA1\u7B97\n \n int pointIndexStart = 0;\n\t\tfor(int i = 0; i < num_prism; i++){ \n highlight_ = insidePrism(prismList[i], pointIndexStart, world);\n \n if(highlight_>0){ \n #if !defined(showBaseHeight) && !defined(color_type_heightCpt)\n if(highlight_ == 1){\n vColor.r += 0.5; \n }else if(highlight_ == 2){\n vColor.g += 0.5;\n }\n #endif\n \n break;\n }\n \n \n pointIndexStart += int(Round(prismList[i][2][1])); \n\t\t} \n \n #ifdef color_type_heightCpt \n if(highlight_==0){ \n gl_Position = vec4(100.0, 100.0, 100.0, 1.0); //unvisible\n return;\n }\n #endif \n \n\t#endif\n \n \n \n \n #ifdef showBaseHeight\n //\u57FA\u4E8E\u6A21\u578B\u7684\u571F\u65B9\u91CF\u663E\u793A\u6216\u8BA1\u7B97\n bool outsidePrism = false;\n #if defined(num_prism) && num_prism > 0//\u9AD8\u4EAE\u4EA4\u96C6\n if( highlight_ == 0 ){\n outsidePrism = true;\n }\n #endif \n \n if(!outsidePrism){\n \n float zMin = baseHeightBoundZ.x; \n float zMax = baseHeightBoundZ.y; \n float xMin = baseHeightBoundXY.x;\n float xMax = baseHeightBoundXY.y;\n float yMin = baseHeightBoundXY.z;\n float yMax = baseHeightBoundXY.w; \n \n bool inside = false;\n if(world.z < zMin || world.z > zMax || world.x < xMin || world.x > xMax || world.y < yMin || world.y > yMax){\n inside = false;\n }else{\n vec2 uv = vec2((world.x - xMin) / (xMax - xMin), (world.y - yMin) / (yMax - yMin) );\n \n vec4 color = texture2D(baseHeightAreaMap,uv);\n //\u6297\u952F\u9F7F\u5F85\u5199\n \n \n if(color.a==1.0){ \n \n float currentHeight = (world.z - zMin) / (zMax - zMin) ; \n \n #ifdef color_type_heightCpt\n /*float diff = currentHeight - baseHeight;\n if(diff<0.0){\n diff = -diff;\n vOpacity = 0.5;//\u9700\u8981\u900F\u660E\u901A\u9053\uFF0C\u5BB9\u6613\u51FA\u9519\n }else{\n vOpacity = 1.0;\n }\n vColor = percentToByte(diff); \n */ \n vColor = percentToByte(currentHeight);\n //vColor = color.rgb;\n vOpacity = 1.0;\n \n #else\n //vColor = color.rgb;\n float baseHeight = byteToFloat(color.rgb);\n if(currentHeight > baseHeight){\n vColor.g += 0.5; \n }else{\n vColor.r += 0.5; \n }\n #endif\n \n inside = true;\n }else{\n inside = false;\n }\n \n \n \n } \n \n if(inside == false){\n #ifdef color_type_heightCpt\n gl_Position = vec4(100.0, 100.0, 100.0, 1.0); //unvisible\n return;\n #endif\n }\n \n }\n\t#endif\n}\n\n\n\n// \n// ## ## ### #### ## ## \n// ### ### ## ## ## ### ## \n// #### #### ## ## ## #### ## \n// ## ### ## ## ## ## ## ## ## \n// ## ## ######### ## ## #### \n// ## ## ## ## ## ## ### \n// ## ## ## ## #### ## ## \n//\n\n\nvec2 getSamplerCoord( vec3 direction ) \n{\n direction = normalize(direction);\n float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;\n float ty=acos(direction.z)/PI;\n\n return vec2(tx,ty);\n} \n\nvec3 transformAxis( vec3 direction ) //navvis->4dkk\n{\n float y = direction.y;\n direction.y = direction.z;\n direction.z = -y;\n return direction;\n}\n\nvoid main() {\n //bool filtered_by_normal = false; \n float normalZ = 0.0;\n\n\n\n #ifdef use_filter_by_normal\n /*if(abs(getNormal().z) > 0.4) { //ufilterByNormalThreshold \u6682\u5B9A 3\n\t\t\t// Move point outside clip space space to discard it.\n\t\t\t//gl_Position = vec4(0.0, 0.0, 2.0, 1.0); //gl_Position\u7684\u53EF\u89C6\u533A\u57DF\u662F x,y,z\u90FD\u662F[-1,1] \n //return;\n //filtered_by_normal = true; //\u6807\u8BB0\u4E00\u4E0B\u3002\u4E0D\u76F4\u63A5\u4E0D\u7ED8\u5236\uFF0C\u56E0\u4E3A\u6709\u7684\u6CD5\u7EBF\u90FD\u662F\u5782\u76F4\u5411\u4E0A\n \n\t\t}*/\n \n normalZ = abs(getNormal().z);\n #endif\n \n \n vec4 worldPos = modelMatrix * vec4(position, 1.0); \n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 ); //vec4 mvPosition = viewMatrix * worldPos;\n vViewPosition = mvPosition.xyz;\n gl_Position = projectionMatrix * mvPosition;\n vLogDepth = log2(-mvPosition.z);\n \n \n \n // COLOR\n //\u52A0-------------------\n #if defined(usePanoMap)\n \n vec3 positionLocalToPanoCenter0 = worldPos.xyz - pano0Position;\n vec3 vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz; \n vWorldPosition0.x *= -1.0;\n vWorldPosition0 = transformAxis(vWorldPosition0);\n \n vec3 positionLocalToPanoCenter1 = worldPos.xyz - pano1Position;\n vec3 vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz; \n vWorldPosition1.x *= -1.0;\n vWorldPosition1 = transformAxis(vWorldPosition1);\n \n /*\n vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);\n vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz); \n vec4 colorFromPano0 = texture2D(pano0Map,samplerCoord0);\n vec4 colorFromPano1 = texture2D(pano1Map,samplerCoord1);\n */\n \n \n \n \n vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);\n vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);\n\n vColor = mix(colorFromPano0,colorFromPano1,progress).xyz; \n\n \n //float easeInOutRatio = 0.0; //\u7F13\u51B2\uFF0C\u6E10\u53D8\u70B9\u4E91\u5230\u8D34\u56FE\u7684\u989C\u8272 \n if(progress < easeInOutRatio){\n float easeProgress = (easeInOutRatio - progress) / easeInOutRatio;\n vec3 vColor1 = getColor(worldPos);\n vColor = mix(vColor,vColor1,easeProgress); \n }else if(progress > 1.0 - easeInOutRatio){ \n float easeProgress = (progress - (1.0 - easeInOutRatio) ) / easeInOutRatio;\n vec3 vColor1 = getColor(worldPos);\n vColor = mix(vColor,vColor1,easeProgress); \n }\n \n\n #else\n \n vColor = getColor(worldPos);\n \n #endif\n \n \n //------------------- \n \n if(uOpacity>=1.0 || uUseOrthographicCamera){ \n vOpacity = uOpacity; \n \n \n if(uOpacity<1.0){ //uUseOrthographicCamera \n //\u9632\u6B62\u7F29\u5C0F\u540E\u70B9\u4E91\u51E0\u4E4E\u770B\u4E0D\u89C1 \n vOpacity *= 4.0-3.0 * levelPercent; \n \n }\n \n }else{ //#ifdef attenuated_opacity zoom\u4E0D\u4F1A\u6539\u53D8z \u6240\u4EE5\u8FD9\u5E76\u4E0D\u662F\u7528\u5728\u5206\u5C4F\u65F6\u5019\u7684\n float v = -gl_Position.z-1.0 ; // \u8303\u56F4\u4ECE-2\u52300\uFF0C e\u7684-2\u52300\u6B21\u65B9\u7684\u8303\u56F4\u662F0.818\u52301 \n //vOpacity = uOpacity * exp(v/ (levelPercent * 20.0 ) ); \n \n //\u8FD1\u5904\u52A0\u6DF1\uFF0C\u8FDC\u5904\u53D8\u6DE1 gl_Position.z\u4F3C\u4E4E\u671D\u5411\u5C4F\u5E55\u91CC\u4E3A\u6B63\n float r = clamp( pow(1.1, v/10.0 ), 0.1, 1.0 ); //\u9664\u4EE5\u7684\u6570\u5B57\u8D8A\u5927\uFF0C\u8FD1\u9AD8\u8FDC\u4F4E\u7684\u7A0B\u5EA6\u8D8A\u5C0F\uFF0C\u8303\u56F4\u8D8A\u957F\u3002 \u7A0B\u5EA6\u592A\u9AD8\u8FDC\u5904\u5355\u8584\u7684\u533A\u57DF\u770B\u4E0D\u89C1 pow\u7684\u5E95\u6570\u8D8A\u5927\u6539\u53D8\u7387\u8D8A\u5927\n vOpacity = uOpacity * r ;\n \n \n } \n \n vOpacity *= max(0.3, pow((1.0 - normalZ),5.0));//\u5782\u76F4\u671D\u76F8\u673A\u65F6\u964D\u4F4E\u900F\u660E\u5EA6 \n //vOpacity = clamp(vOpacity, 0.0, 1.0); \n\n\n\n // POINT SIZE\n float pointSize = getPointSize();\n \n gl_PointSize = pointSize;\n vPointSize = pointSize;\n\n \n \n \n \n\n // only for \"replacing\" approaches\n // if(getLOD() != uLevel){\n // \tgl_Position = vec4(10.0, 10.0, 10.0, 1.0);\n // }\n\n\n #if defined hq_depth_pass\n float originalDepth = gl_Position.w;\n float adjustedDepth = originalDepth + 2.0 * vRadius;\n float adjust = adjustedDepth / originalDepth;\n\n mvPosition.xyz = mvPosition.xyz * adjust;\n gl_Position = projectionMatrix * mvPosition;\n #endif\n\n\n // CLIPPING\n doClipping(worldPos);\n\n #if defined(num_clipspheres) && num_clipspheres > 0\n for(int i = 0; i < num_clipspheres; i++){\n vec4 sphereLocal = uClipSpheres[i] * mvPosition;\n\n float distance = length(sphereLocal.xyz);\n\n if(distance < 1.0){\n float w = distance;\n vec3 cGradient = texture2D(gradient, vec2(w, 1.0 - w)).rgb;\n \n vColor = cGradient;\n //vColor = cGradient * 0.7 + vColor * 0.3;\n }\n }\n #endif\n\n #if defined(num_shadowmaps) && num_shadowmaps > 0\n\n const float sm_near = 0.1;\n const float sm_far = 10000.0;\n\n for(int i = 0; i < num_shadowmaps; i++){\n vec3 viewPos = (uShadowWorldView[i] * vec4(position, 1.0)).xyz;\n float distanceToLight = abs(viewPos.z);\n \n vec4 projPos = uShadowProj[i] * uShadowWorldView[i] * vec4(position, 1);\n vec3 nc = projPos.xyz / projPos.w;\n \n float u = nc.x * 0.5 + 0.5;\n float v = nc.y * 0.5 + 0.5;\n\n vec2 sampleStep = vec2(1.0 / (2.0*1024.0), 1.0 / (2.0*1024.0)) * 1.5;\n vec2 sampleLocations[9];\n sampleLocations[0] = vec2(0.0, 0.0);\n sampleLocations[1] = sampleStep;\n sampleLocations[2] = -sampleStep;\n sampleLocations[3] = vec2(sampleStep.x, -sampleStep.y);\n sampleLocations[4] = vec2(-sampleStep.x, sampleStep.y);\n\n sampleLocations[5] = vec2(0.0, sampleStep.y);\n sampleLocations[6] = vec2(0.0, -sampleStep.y);\n sampleLocations[7] = vec2(sampleStep.x, 0.0);\n sampleLocations[8] = vec2(-sampleStep.x, 0.0);\n\n float visibleSamples = 0.0;\n float numSamples = 0.0;\n\n float bias = vRadius * 2.0;\n\n for(int j = 0; j < 9; j++){\n vec4 depthMapValue = texture2D(uShadowMap[i], vec2(u, v) + sampleLocations[j]);\n\n float linearDepthFromSM = depthMapValue.x + bias;\n float linearDepthFromViewer = distanceToLight;\n\n if(linearDepthFromSM > linearDepthFromViewer){\n visibleSamples += 1.0;\n }\n\n numSamples += 1.0;\n }\n\n float visibility = visibleSamples / numSamples;\n\n 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){\n //vColor = vec3(0.0, 0.0, 0.2);\n }else{\n //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);\n vColor = vColor * visibility + vColor * uShadowColor * (1.0 - visibility);\n }\n\n\n }\n\n #endif\n\n \n \n}\n";
  13285. Shaders["pointcloud_new.fs"] = "\n#if defined paraboloid_point_shape\n\t#extension GL_EXT_frag_depth : enable\n#endif\n#define PI 3.141592653589793\n\n\n\nprecision highp float;\nprecision highp int;\n\n/*\n#if defined(usePanoMap) \n \n uniform samplerCube pano0Map; //\u968F\u4FBF\u8BBE\u7F6E\u4E00\u4E2AsamplerCube\u53BB\u4F7F\u7528\u90FD\u4F1A\u8BA9\u70B9\u4E91\u6D88\u5931\n uniform samplerCube pano1Map;\n \n uniform float progress;\n uniform float easeInOutRatio;\n\n \n uniform vec3 pano0Position;\n uniform mat4 pano0Matrix; \n uniform vec3 pano1Position;\n uniform mat4 pano1Matrix;\n varying vec3 vWorldPosition0;\n varying vec3 vWorldPosition1;\n\n#endif \n*/\n\n\n\n//------------\n\n\n\n\n\nuniform mat4 viewMatrix;\nuniform mat4 uViewInv;\nuniform mat4 uProjInv;\nuniform vec3 cameraPosition;\n\n\nuniform mat4 projectionMatrix;\n//uniform float uOpacity;\nvarying float vOpacity; //add\n\nuniform float blendHardness;\nuniform float blendDepthSupplement;\nuniform float fov;\nuniform float uSpacing;\nuniform float near;\nuniform float far;\nuniform float uPCIndex;\nuniform float uScreenWidth;\nuniform float uScreenHeight;\n\nvarying vec3\tvColor;\nvarying float\tvLogDepth;\nvarying vec3\tvViewPosition;\nvarying float\tvRadius;\nvarying float \tvPointSize;\nvarying vec3 \tvPosition;\n\n\nfloat specularStrength = 1.0;\n\n\nvec2 getSamplerCoord( vec3 direction ) \n{\n direction = normalize(direction);\n float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;\n float ty=acos(direction.z)/PI;\n\n return vec2(tx,ty);\n} \n\n\n\n\nvoid main() {\n\n vec3 color = vColor; \n\t \n \n /*#if defined(usePanoMap) //\u52A0 \u7ECF\u6D4B\u8BD5\uFF0C\u5373\u4F7F\u5168\u90E8\u5199\u5728fragment\u91CC\u4E5F\u662F\u65E0\u8BBApointsize\u591A\u5927\u90FD\u662F\u4E00\u4E2A\u70B9\u4E00\u4E2A\u989C\u8272\uFF0C\u6240\u4EE5\u5E72\u8106\u5199\u5728vectex\u91CC\n \n \n vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);\n vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);\n \n color = mix(colorFromPano0,colorFromPano1,progress).xyz; \n \n \n //float easeInOutRatio = 0.0; //\u7F13\u51B2\uFF0C\u6E10\u53D8\u70B9\u4E91\u5230\u8D34\u56FE\u7684\u989C\u8272 \n if(progress < easeInOutRatio){\n float easeProgress = (easeInOutRatio - progress) / easeInOutRatio; \n color = mix(color,vColor,easeProgress); \n }else if(progress > 1.0 - easeInOutRatio){ \n float easeProgress = (progress - (1.0 - easeInOutRatio) ) / easeInOutRatio; \n color = mix(color,vColor,easeProgress); \n }\n \n \n #else \n color = vColor;\n #endif*/\n \n \n \n\tfloat depth = gl_FragCoord.z;\n\n\t#if defined(circle_point_shape) || defined(paraboloid_point_shape) \n\t\tfloat u = 2.0 * gl_PointCoord.x - 1.0;\n\t\tfloat v = 2.0 * gl_PointCoord.y - 1.0;\n\t#endif\n\t\n\t#if defined(circle_point_shape) \n\t\tfloat cc = u*u + v*v;\n\t\tif(cc > 1.0){\n\t\t\tdiscard;\n\t\t}\n\t#endif\n\t\n\n \n\n\t\n \n #if defined color_type_indices //pick point recognize\n\t\tgl_FragColor = vec4(color, uPCIndex / 255.0); //uPCIndex : node Index\n\t#else\n\t\tgl_FragColor = vec4(color, vOpacity);\n\t#endif\n \n \n \n \n \n \n \n \n\n\t#if defined paraboloid_point_shape\n\t\tfloat wi = 0.0 - ( u*u + v*v);\n\t\tvec4 pos = vec4(vViewPosition, 1.0);\n\t\tpos.z += wi * vRadius;\n\t\tfloat linearDepth = -pos.z;\n\t\tpos = projectionMatrix * pos;\n\t\tpos = pos / pos.w;\n\t\tfloat expDepth = pos.z;\n\t\tdepth = (pos.z + 1.0) / 2.0;\n\t\tgl_FragDepthEXT = depth;\n\t\tgl_FragDepthEXT = clamp(gl_FragDepthEXT, 0.0, 1.0); //add\n \n \n\t\t#if defined(color_type_depth)\n\t\t\tcolor.r = linearDepth;\n\t\t\tcolor.g = expDepth;\n\t\t#endif\n\t\t\n\t\t#if defined(use_edl)\n\t\t\tgl_FragColor.a = log2(linearDepth);\n\t\t#endif\n\t\t\n\t#else\n\t\t#if defined(use_edl)\n\t\t\tgl_FragColor.a = vLogDepth;\n\t\t#endif\n\t#endif\n\n\t#if defined(weighted_splats)\n\t\tfloat distance = 2.0 * length(gl_PointCoord.xy - 0.5);\n\t\tfloat weight = max(0.0, 1.0 - distance);\n\t\tweight = pow(weight, 1.5);\n\n\t\tgl_FragColor.a = weight;\n\t\tgl_FragColor.xyz = gl_FragColor.xyz * weight;\n\t#endif\n\n\t//gl_FragColor = vec4(0.0, 0.7, 0.0, 1.0);\n\t\n}\n\n\n";
  13286. Shaders["pointcloud_sm.vs"] = "\nprecision mediump float;\nprecision mediump int;\n\nattribute vec3 position;\nattribute vec3 color;\n\nuniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\n\nuniform float uScreenWidth;\nuniform float uScreenHeight;\nuniform float near;\nuniform float far;\n\nuniform float uSpacing;\nuniform float uOctreeSize;\nuniform float uLevel;\nuniform float uVNStart;\n\nuniform sampler2D visibleNodes;\n\nvarying float vLinearDepth;\nvarying vec3 vColor;\n\n#define PI 3.141592653589793\n\n\n\n// ---------------------\n// OCTREE\n// ---------------------\n\n#if defined(adaptive_point_size)\n/**\n * number of 1-bits up to inclusive index position\n * number is treated as if it were an integer in the range 0-255\n *\n */\nfloat numberOfOnes(float number, float index){\n\tfloat tmp = mod(number, pow(2.0, index + 1.0));\n\tfloat numOnes = 0.0;\n\tfor(float i = 0.0; i < 8.0; i++){\n\t\tif(mod(tmp, 2.0) != 0.0){\n\t\t\tnumOnes++;\n\t\t}\n\t\ttmp = floor(tmp / 2.0);\n\t}\n\treturn numOnes;\n}\n\n\n/**\n * checks whether the bit at index is 1\n * number is treated as if it were an integer in the range 0-255\n *\n */\nbool isBitSet(float number, float index){\n\treturn mod(floor(number / pow(2.0, index)), 2.0) != 0.0;\n}\n\n\n/**\n * find the LOD at the point position\n */\nfloat getLOD(){\n\t\n\tvec3 offset = vec3(0.0, 0.0, 0.0);\n\tfloat iOffset = uVNStart;\n\tfloat depth = uLevel;\n\tfor(float i = 0.0; i <= 30.0; i++){\n\t\tfloat nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);\n\t\t\n\t\tvec3 index3d = (position-offset) / nodeSizeAtLevel;\n\t\tindex3d = floor(index3d + 0.5);\n\t\tfloat index = 4.0 * index3d.x + 2.0 * index3d.y + index3d.z;\n\t\t\n\t\tvec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));\n\t\tfloat mask = value.r * 255.0;\n\t\tif(isBitSet(mask, index)){\n\t\t\t// there are more visible child nodes at this position\n\t\t\tiOffset = iOffset + value.g * 255.0 * 256.0 + value.b * 255.0 + numberOfOnes(mask, index - 1.0);\n\t\t\tdepth++;\n\t\t}else{\n\t\t\t// no more visible child nodes at this position\n\t\t\treturn depth;\n\t\t}\n\t\t\n\t\toffset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;\n\t}\n\t\t\n\treturn depth;\n}\n\n#endif\n\nfloat getPointSize(){\n\tfloat pointSize = 1.0;\n\t\n\tfloat slope = tan(fov / 2.0);\n\tfloat projFactor = -0.5 * uScreenHeight / (slope * vViewPosition.z);\n\t\n\tfloat r = uOctreeSpacing * 1.5;\n\tvRadius = r;\n\t#if defined fixed_point_size\n\t\tpointSize = size;\n\t#elif defined attenuated_point_size\n\t\tif(uUseOrthographicCamera){\n\t\t\tpointSize = size;\t\t\t\n\t\t}else{\n\t\t\tpointSize = pointSize * projFactor;\n\t\t}\n\t#elif defined adaptive_point_size\n\t\tif(uUseOrthographicCamera) {\n\t\t\tfloat worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();\n\t\t\tpointSize = (worldSpaceSize / uOrthoWidth) * uScreenWidth;\n\t\t} else {\n\t\t\tfloat worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();\n\t\t\tpointSize = worldSpaceSize * projFactor;\n\t\t}\n\t#endif\n\n\tpointSize = max(minSize, pointSize);\n\tpointSize = min(maxSize, pointSize);\n\t\n\tvRadius = pointSize / projFactor;\n\n\treturn pointSize;\n}\n\n\nvoid main() {\n\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tvLinearDepth = gl_Position.w;\n\n\tfloat pointSize = getPointSize();\n\tgl_PointSize = pointSize;\n\n}\n";
  13287. Shaders["pointcloud_sm.fs"] = "\nprecision mediump float;\nprecision mediump int;\n\nvarying vec3 vColor;\nvarying float vLinearDepth;\n\nvoid main() {\n\n\t//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\t//gl_FragColor = vec4(vColor, 1.0);\n\t//gl_FragColor = vec4(vLinearDepth, pow(vLinearDepth, 2.0), 0.0, 1.0);\n\tgl_FragColor = vec4(vLinearDepth, vLinearDepth / 30.0, vLinearDepth / 30.0, 1.0);\n\t\n}\n\n\n";
  13288. Shaders["normalize.vs"] = "\nprecision mediump float;\nprecision mediump int;\n\nattribute vec3 position;\nattribute vec2 uv;\n\nuniform mat4 projectionMatrix;\nuniform mat4 modelViewMatrix;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);\n}";
  13289. Shaders["normalize.fs"] = "\n#extension GL_EXT_frag_depth : enable\n\nprecision mediump float;\nprecision mediump int;\n\nuniform sampler2D uWeightMap;\nuniform sampler2D uDepthMap;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tfloat depth = texture2D(uDepthMap, vUv).r;\n\t\n\tif(depth >= 1.0){\n\t\tdiscard;\n\t}\n\n\tgl_FragColor = vec4(depth, 1.0, 0.0, 1.0);\n\n\tvec4 color = texture2D(uWeightMap, vUv); \n\tcolor = color / color.w;\n\t\n\tgl_FragColor = vec4(color.xyz, 1.0); \n\t\n\tgl_FragDepthEXT = depth;\n\n\n}";
  13290. Shaders["normalize_and_edl.fs"] = "\n#extension GL_EXT_frag_depth : enable\n\n// \n// adapted from the EDL shader code from Christian Boucheny in cloud compare:\n// https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL\n//\n\nprecision mediump float;\nprecision mediump int;\n\nuniform sampler2D uWeightMap;\nuniform sampler2D uEDLMap;\nuniform sampler2D uDepthMap;\n\nuniform float screenWidth;\nuniform float screenHeight;\nuniform vec2 neighbours[NEIGHBOUR_COUNT];\nuniform float edlStrength;\nuniform float radius;\n\nvarying vec2 vUv;\n\nfloat response(float depth){\n\tvec2 uvRadius = radius / vec2(screenWidth, screenHeight);\n\t\n\tfloat sum = 0.0;\n\t\n\tfor(int i = 0; i < NEIGHBOUR_COUNT; i++){\n\t\tvec2 uvNeighbor = vUv + uvRadius * neighbours[i];\n\t\t\n\t\tfloat neighbourDepth = texture2D(uEDLMap, uvNeighbor).a;\n\n\t\tif(neighbourDepth != 0.0){\n\t\t\tif(depth == 0.0){\n\t\t\t\tsum += 100.0;\n\t\t\t}else{\n\t\t\t\tsum += max(0.0, depth - neighbourDepth);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn sum / float(NEIGHBOUR_COUNT);\n}\n\nvoid main() {\n\n\tfloat edlDepth = texture2D(uEDLMap, vUv).a;\n\tfloat res = response(edlDepth);\n\tfloat shade = exp(-res * 300.0 * edlStrength);\n\n\tfloat depth = texture2D(uDepthMap, vUv).r;\n\tif(depth >= 1.0 && res == 0.0){\n\t\tdiscard;\n\t}\n\t\n\tvec4 color = texture2D(uWeightMap, vUv); \n\tcolor = color / color.w;\n\tcolor = color * shade;\n\n\tgl_FragColor = vec4(color.xyz, 1.0); \n\n\tgl_FragDepthEXT = depth;\n}";
  13291. Shaders["edl_new.vs"] = "\nprecision mediump float;\nprecision mediump int;\n\nattribute vec3 position;\nattribute vec2 uv;\n\nuniform mat4 projectionMatrix;\nuniform mat4 modelViewMatrix;\n\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\t\n\tvec4 mvPosition = modelViewMatrix * vec4(position,1.0);\n\n\tgl_Position = projectionMatrix * mvPosition;\n}";
  13292. Shaders["edl_new.fs"] = "\n#extension GL_EXT_frag_depth : enable\n\n// \n// adapted from the EDL shader code from Christian Boucheny in cloud compare:\n// https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL\n//\n\nprecision mediump float;\nprecision mediump int;\n\n//uniform float screenWidth;\n//uniform float screenHeight;\nuniform vec2 resolution;\n\n\nuniform vec2 neighbours[NEIGHBOUR_COUNT];\nuniform float edlStrength;\nuniform float radius;\nuniform float opacity;\n\n//uniform float uNear;\n//uniform float uFar;\n\nuniform mat4 uProj;\n\nuniform sampler2D uEDLColor;\nuniform sampler2D uEDLDepth;\n\nvarying vec2 vUv;\n\nuniform int useEDL;\n\nfloat response(float depth){\n\tvec2 uvRadius = radius / resolution; //vec2(screenWidth, screenHeight);\n\t\n\tfloat sum = 0.0;\n\t\n\tfor(int i = 0; i < NEIGHBOUR_COUNT; i++){\n\t\tvec2 uvNeighbor = vUv + uvRadius * neighbours[i];\n\t\t//\u83B7\u53D6\u5468\u56F4\u516B\u4E2A\u683C\u5B50\u7684\u503C\n\t\tfloat neighbourDepth = texture2D(uEDLColor, uvNeighbor).a;\n\t\tneighbourDepth = (neighbourDepth == 1.0) ? 0.0 : neighbourDepth;\n\n\t\tif(neighbourDepth != 0.0){\n\t\t\t //if(depth == 0.0){\n\t\t\t //\tsum += 100.0;\n\t\t\t //}else{\n\t\t\t\tsum += max(0.0, depth - neighbourDepth); //\u83B7\u53D6\u5DEE\u503C\n\t\t\t //}\n\t\t}\n\t}\n\t\n\treturn sum / float(NEIGHBOUR_COUNT);\n}\n\nvoid main(){\n\tvec4 cEDL = texture2D(uEDLColor, vUv);\n\t\n\tfloat depth = cEDL.a;\n\tdepth = (depth == 1.0) ? 0.0 : depth;\n \n if(depth == 0.0){ //\u53BB\u6389\u8FD9\u53E5\u5C31\u80FD\u5728\u65E0\u70B9\u4E91\u50CF\u7D20\u7684\u5730\u65B9\u6E32\u67D3outline\uFF0C\u4F46\u4F1A\u906E\u4F4F\u5176\u4ED6mesh\n\t\tdiscard;\n\t}\n \n \n if(useEDL == 1){\n float res = response(depth); \n float shade = exp(-res * 300.0 * edlStrength); //\u81EA\u7136\u5E38\u6570e\u4E3A\u5E95\u7684\u6307\u6570\u51FD\u6570 \n const float min = 0.2; //add \u4F7F\u8FB9\u7F18\u8272\u53D8\u6D45 \u8303\u56F4\u4ECE0-1 \u53D8\u4E3Amin-1\n shade = shade * (1.0-min) + min;\n gl_FragColor = vec4(cEDL.rgb * shade, opacity); \n }else{//\u52A0 \u4E0D\u6539\u989C\u8272\u7684\u60C5\u51B5 \n gl_FragColor = vec4(cEDL.rgb, opacity);\n } \n //\u6CE8\u610F\uFF0CedlStrength\u8D8A\u5F3A\uFF0C\u5728\u76F8\u540Cdepth\u7684\u53E0\u653E\u7684\u70B9\u4E91\u95F4\u7684\u8F6E\u5ED3\u7EBF\u989C\u8272\u8D8A\u6DF1\n //\u4F5C\u7528\uFF1A\u52FE\u52D2\u8FB9\u7F18\uFF0C\u5F3A\u5316\u6DF1\u5EA6\u5DEE\u5F02\uFF0C\u6A21\u62DF\u9634\u5F71\uFF0C\u52A0\u5F3A\u7ED3\u6784\u7ACB\u4F53\u611F\n \n { // write regular hyperbolic depth values to depth buffer \u4FEE\u6539\u6DF1\u5EA6\n float dl = pow(2.0, depth);\n\n vec4 dp = uProj * vec4(0.0, 0.0, -dl, 1.0);\n float pz = dp.z / dp.w;\n float fragDepth = (pz + 1.0) / 2.0;\n\n gl_FragDepthEXT = fragDepth;\n }\n\t\n}\n";
  13293. Shaders["blur.vs"] = "\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);\n}";
  13294. Shaders["blur.fs"] = "\nuniform mat4 projectionMatrix;\n\nuniform float screenWidth;\nuniform float screenHeight;\nuniform float near;\nuniform float far;\n\nuniform sampler2D map;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tfloat dx = 1.0 / screenWidth;\n\tfloat dy = 1.0 / screenHeight;\n\n\tvec3 color = vec3(0.0, 0.0, 0.0);\n\tcolor += texture2D(map, vUv + vec2(-dx, -dy)).rgb;\n\tcolor += texture2D(map, vUv + vec2( 0, -dy)).rgb;\n\tcolor += texture2D(map, vUv + vec2(+dx, -dy)).rgb;\n\tcolor += texture2D(map, vUv + vec2(-dx, 0)).rgb;\n\tcolor += texture2D(map, vUv + vec2( 0, 0)).rgb;\n\tcolor += texture2D(map, vUv + vec2(+dx, 0)).rgb;\n\tcolor += texture2D(map, vUv + vec2(-dx, dy)).rgb;\n\tcolor += texture2D(map, vUv + vec2( 0, dy)).rgb;\n\tcolor += texture2D(map, vUv + vec2(+dx, dy)).rgb;\n\n\tcolor = color / 9.0;\n\t\n\tgl_FragColor = vec4(color, 1.0);\n}";
  13295. Shaders["depthBasic.vs"] = "\n \n#if defined use_map \n varying vec2 vUv;\n \n #ifdef UV_Transform \n uniform mat3 uvTransform;\n #endif\n#endif \n\nvoid main() {\n #if defined use_map \n #ifdef UV_Transform \n vUv = ( uvTransform * vec3( uv, 1 ) ).xy; //include <uv_vertex> \n #else\n vUv = uv;\n #endif\n #endif\n \n \n vec4 mvPosition = vec4(position, 1.0);\n \n //add instanceMesh\n #ifdef USE_INSTANCING \n mvPosition = instanceMatrix * mvPosition;\n #endif\n \n gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n} \n ";
  13296. Shaders["depthBasic.fs"] = "\nuniform float opacity;\n//uniform float mapScale;\nuniform vec3 baseColor;\n\n\n\n\n\n#if defined use_map\n varying vec2 vUv;\n uniform sampler2D map; \n uniform vec3 mapColor;\n \n vec4 applyMapColor(vec4 color){ \n vec2 uv = vUv;\n /*if(mapScale != 1.0){ \n uv = (vUv - 0.5) / mapScale + 0.5; \n if(uv.x > 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0){\n //color = vec4(0.0,0.0,0.0,0.0);\n discard;\n } \n }*/\n vec4 colorFromMap = texture2D(map, uv);\n \n #if defined mapOverlay\n //\u8D34\u56FE\u53E0\u52A0\u5728\u57FA\u7840\u8272\u4E0A\uFF0C\u800C\u975E\u76F8\u4E58\n colorFromMap.rgb *= mapColor;\n color = color * (1.0-colorFromMap.a) + colorFromMap;\n #else\n color *= colorFromMap;\n \n #endif\n \n return color;\n }\n#endif\n \n\n#if defined(GL_EXT_frag_depth) && defined(useDepth)\n //\u4F3C\u4E4E\u901A\u8FC7gl.getExtension('EXT_frag_depth')\u5F97\u5230\u7684GL_EXT_frag_depth\n \n uniform sampler2D depthTexture;\n \n uniform vec2 resolution;\n uniform vec2 viewportOffset; // viewportOffset \u8303\u56F4\u4ECE0-\u6574\u4E2A\u753B\u5E03\u7684\u50CF\u7D20\n uniform vec3 backColor;\n uniform float occlusionDistance;\n uniform float clipDistance;\n uniform float startClipDis;\n uniform float startOcclusDis;\n uniform float maxClipFactor;\n uniform float maxOcclusionFactor;\n //uniform bool uUseOrthographicCamera; \n\n \n#endif \n\n#if defined(GL_EXT_frag_depth) && defined(useDepth) || defined(FadeFar) \n uniform float nearPlane;\n uniform float farPlane; \n float convertToLinear(float zValue){\n //if(uUseOrthographicCamera){\n // return zValue*(farPlane-nearPlane)+nearPlane;\n //}else{ \n float z = zValue * 2.0 - 1.0;\n return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));\n //} \n } \n#endif\n\n#if defined(FadeFar)\n uniform float fadeFar;\n#endif\n//#include <clipping_planes_pars_fragment>\n \nvoid main() {\n //#include <clipping_planes_fragment>\n \n vec4 color = vec4(baseColor, opacity);\n \n \n \n #if defined(GL_EXT_frag_depth) && defined(useDepth) || defined(FadeFar) \n \n float fragDepth = convertToLinear(gl_FragCoord.z);\n \n #if defined(FadeFar) \n float fadeOutFar = fadeFar * 1.3; //\u5B8C\u5168\u6D88\u5931\u8DDD\u79BB\n if(fragDepth > fadeOutFar){\n discard;\n }else if(fragDepth > fadeFar){\n color.a *= (fadeOutFar - fragDepth) / (fadeOutFar - fadeFar);\n \n } \n #endif\n \n \n float mixFactor = 0.0;\n float clipFactor = 0.0;\n \n #if defined(GL_EXT_frag_depth) && defined(useDepth)\n \n vec2 depthTxtCoords = vec2(gl_FragCoord.x-viewportOffset.x, gl_FragCoord.y - viewportOffset.y) / resolution;\n //gl_FragCoord\u5927\u5C0F\u4E3A viewport client\u5927\u5C0F \n \n float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);\n\n \n float delta = fragDepth - textureDepth;\n\n if (delta > 0.0)//\u5DEE\u8DDD\n {\n // occlusionDistance and clipDistance define the width of the respective zones and\n // mixFactor and clipFactor express the interpolation between the two colors depending on the position\n // of the current fragment withing those zones.\n \n mixFactor = clamp((delta - startOcclusDis) / (occlusionDistance - startOcclusDis), 0.0, maxOcclusionFactor);\n clipFactor = clamp((delta - startClipDis) / (clipDistance - startClipDis), 0.0, maxClipFactor);\n \n \n } \n #endif\n \n \n // If the fragment is totally transparent, don't bother drawing it\n if (clipFactor == 1.0)\n {\n discard;\n }else{\n \n #if defined use_map\n color = applyMapColor(color); \n #endif\n \n #if defined(GL_EXT_frag_depth) && defined(useDepth)\n float r = pow(1.0 - clipFactor, 3.0); //\u66F4\u900F\u660E\u4E9B \n color = vec4(mix(color.rgb, backColor, mixFactor), color.a * r);\n #endif \n }\n \n \n #else\n #if defined use_map\n color = applyMapColor(color); \n #endif \n #endif\n \n gl_FragColor = color;\n \n}\n";
  13297. Shaders["copyCubeMap.vs"] = "varying vec3 vWorldPos;\nvec3 transformAxis( vec3 direction ) //navvis->4dkk\n{\n float y = direction.y;\n direction.y = direction.z;\n direction.z = -y;\n return direction;\n}\nvoid main() {\n vWorldPos = vec3(-position.x, -position.y, position.z);\n //vWorldPos = transformAxis(vWorldPos);\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n} \n ";
  13298. Shaders["copyCubeMap.fs"] = "varying vec3 vWorldPos;\nuniform float alpha;\nuniform samplerCube tDiffuse;\n\n\nvoid main() {\n vec4 texColor = textureCube(tDiffuse, vWorldPos);\n gl_FragColor = vec4(texColor.rgb, texColor.a * alpha);\n} \n ";
  13299. Shaders["basicTextured.vs"] = " \n//#include <skinning_pars_vertex>\n \nvarying vec2 vUv;\n\n\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n \n /*#include <begin_vertex> \n #include <skinbase_vertex> \n #include <skinning_vertex>*/\n} \n ";
  13300. Shaders["basicTextured.fs"] = "varying vec2 vUv;\nuniform float opacity;\n \n\n#ifdef HasMap\n uniform sampler2D map; \n#endif\n#ifdef HasColor\n uniform vec3 color;\n#endif\n\nvoid main() {\n vec4 color_;\n #ifdef HasColor\n color_ = vec4(color, opacity); \n #else\n color_ = vec4(1.0,1.0,1.0, opacity);\n #endif\n \n #ifdef HasMap\n vec4 texColor = texture2D(map, vUv); \n gl_FragColor = texColor * color_;\n \n /*#ifdef InverseColor\n bool inverse = false; //gl_FragColor.r < 0.3 || gl_FragColor.g < 0.3 || gl_FragColor.b < 0.3 ||\n \n //\u6DF1\u8272\u5B57\u548C\u767D\u8272\u5730\u9762\u8981\u53CD\u8F6C\n \n if(gl_FragColor.r > 0.9 && gl_FragColor.g > 0.9 && gl_FragColor.b > 0.9){\n //gl_FragColor.r = 1.0 - gl_FragColor.r;\n //gl_FragColor.g = 1.0 - gl_FragColor.g;\n //gl_FragColor.b = 1.0 - gl_FragColor.b; \n gl_FragColor = vec4(0.07,0.22, 0.5,1.0);\n }else{//\u6D77\u548C\u8349\u576A\u989C\u8272\u52A0\u6DF1\n \n gl_FragColor = texColor * vec4(0.3,0.5,0.7,1.0);\n } \n \n #endif*/\n \n #else\n gl_FragColor = color_;\n #endif\n \n \n}\n";
  13301. Shaders["skybox.vs"] = "uniform mat4 matrix; \nvarying vec3 vWorldPosition;\n\n\n\nvoid main() \n{ \n \n vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz ; // - cameraPosition; \n vWorldPosition = (vec4(vWorldPosition, 1.0) * matrix).xyz;\n vWorldPosition.x *= -1.0;\n\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
  13302. Shaders["skybox.fs"] = "varying vec3 vWorldPosition;\nuniform sampler2D tDiffuse; \n\n#define PI 3.141592653 \n\n/*vec2 getSamplerCoord( vec3 direction ) \n{\n direction = normalize(direction);\n float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;\n float ty=acos(direction.y)/PI;\n\n return vec2(tx,ty);\n}*/\nvec2 getSamplerCoord( vec3 direction ) \n{\n direction = normalize(direction);\n float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;\n float ty=acos(direction.z)/PI;\n\n return vec2(tx,ty);\n} \nvoid main() \n{\n vec2 samplerCoord = getSamplerCoord(vWorldPosition);\n vec4 color = texture2D(tDiffuse, samplerCoord);\n //gl_FragColor = RGBEToLinear( color ); //\u5BF9\u4E8Ehdr\u5FC5\u987B\u52A0\u8FD9\u4E00\u53E5\uFF0C\u5426\u5219\u6548\u679C\u5F88\u5947\u602A\u3002copy\u81EAmeshBasicMaterial\u91CC\u7684mat_fragment\u7684mapTexelToLinear\u51FD\u6570\uFF0C\u53EA\u8981\u6709map\u5C31\u4F1A\u4F7F\u7528\u8BE5\u51FD\u6570\n gl_FragColor = color;\n //#include <tonemapping_fragment>\n //////#include <encodings_fragment>\n\n} \n";
  13303. var ClassificationScheme = {
  13304. DEFAULT: {
  13305. 0: {
  13306. visible: true,
  13307. name: 'never classified',
  13308. color: [0.5, 0.5, 0.5, 1.0]
  13309. },
  13310. 1: {
  13311. visible: true,
  13312. name: 'unclassified',
  13313. color: [0.5, 0.5, 0.5, 1.0]
  13314. },
  13315. 2: {
  13316. visible: true,
  13317. name: 'ground',
  13318. color: [0.63, 0.32, 0.18, 1.0]
  13319. },
  13320. 3: {
  13321. visible: true,
  13322. name: 'low vegetation',
  13323. color: [0.0, 1.0, 0.0, 1.0]
  13324. },
  13325. 4: {
  13326. visible: true,
  13327. name: 'medium vegetation',
  13328. color: [0.0, 0.8, 0.0, 1.0]
  13329. },
  13330. 5: {
  13331. visible: true,
  13332. name: 'high vegetation',
  13333. color: [0.0, 0.6, 0.0, 1.0]
  13334. },
  13335. 6: {
  13336. visible: true,
  13337. name: 'building',
  13338. color: [1.0, 0.66, 0.0, 1.0]
  13339. },
  13340. 7: {
  13341. visible: true,
  13342. name: 'low point(noise)',
  13343. color: [1.0, 0.0, 1.0, 1.0]
  13344. },
  13345. 8: {
  13346. visible: true,
  13347. name: 'key-point',
  13348. color: [1.0, 0.0, 0.0, 1.0]
  13349. },
  13350. 9: {
  13351. visible: true,
  13352. name: 'water',
  13353. color: [0.0, 0.0, 1.0, 1.0]
  13354. },
  13355. 12: {
  13356. visible: true,
  13357. name: 'overlap',
  13358. color: [1.0, 1.0, 0.0, 1.0]
  13359. },
  13360. DEFAULT: {
  13361. visible: true,
  13362. name: 'default',
  13363. color: [0.3, 0.6, 0.6, 0.5]
  13364. }
  13365. },
  13366. user: {
  13367. //add on 2025
  13368. 1: {
  13369. visible: true,
  13370. name: 'concrete',
  13371. color: '#CCCCCC'
  13372. },
  13373. //混凝土
  13374. 2: {
  13375. visible: true,
  13376. name: 'wood',
  13377. color: '#47FF53'
  13378. },
  13379. 3: {
  13380. visible: true,
  13381. name: 'metal',
  13382. color: '#FFD633'
  13383. },
  13384. 4: {
  13385. visible: true,
  13386. name: 'glass',
  13387. color: '#1C6BFF'
  13388. },
  13389. 5: {
  13390. visible: true,
  13391. name: 'plastic',
  13392. color: '#47FFFF'
  13393. },
  13394. 6: {
  13395. visible: true,
  13396. name: 'electric_wire',
  13397. color: '#FF3939'
  13398. }
  13399. }
  13400. };
  13401. Object.defineProperty(ClassificationScheme, 'RANDOM', {
  13402. get: function get() {
  13403. var scheme = {};
  13404. for (var i = 0; i <= 255; i++) {
  13405. scheme[i] = new Vector4(Math.random(), Math.random(), Math.random());
  13406. }
  13407. scheme["DEFAULT"] = new Vector4(Math.random(), Math.random(), Math.random());
  13408. return scheme;
  13409. }
  13410. });
  13411. class EnumItem {
  13412. constructor(object) {
  13413. for (var key of Object.keys(object)) {
  13414. this[key] = object[key];
  13415. }
  13416. }
  13417. inspect() {
  13418. return "Enum(".concat(this.name, ": ").concat(this.value, ")");
  13419. }
  13420. }
  13421. ;
  13422. class Enum {
  13423. constructor(object) {
  13424. this.object = object;
  13425. for (var key of Object.keys(object)) {
  13426. var value = object[key];
  13427. if (typeof value === "object") {
  13428. value.name = key;
  13429. } else {
  13430. value = {
  13431. name: key,
  13432. value: value
  13433. };
  13434. }
  13435. this[key] = new EnumItem(value);
  13436. }
  13437. }
  13438. fromValue(value) {
  13439. for (var key of Object.keys(this.object)) {
  13440. if (this[key].value === value) {
  13441. return this[key];
  13442. }
  13443. }
  13444. throw new Error("No enum for value: ".concat(value));
  13445. }
  13446. }
  13447. ;
  13448. var CameraMode = {
  13449. ORTHOGRAPHIC: 0,
  13450. PERSPECTIVE: 1,
  13451. VR: 2
  13452. };
  13453. var ClipTask = {
  13454. NONE: 0,
  13455. HIGHLIGHT: 1,
  13456. SHOW_INSIDE: 2,
  13457. SHOW_OUTSIDE: 3
  13458. };
  13459. var ClipMethod = {
  13460. INSIDE_ANY: 0,
  13461. INSIDE_ALL: 1
  13462. };
  13463. var ElevationGradientRepeat = {
  13464. CLAMP: 0,
  13465. REPEAT: 1,
  13466. MIRRORED_REPEAT: 2
  13467. };
  13468. var MOUSE$1 = {
  13469. LEFT: 0b0001,
  13470. RIGHT: 0b0010,
  13471. MIDDLE: 0b0100
  13472. };
  13473. var PointSizeType = {
  13474. FIXED: 0,
  13475. ATTENUATED: 1,
  13476. ADAPTIVE: 2
  13477. };
  13478. var PointShape$1 = {
  13479. SQUARE: 0,
  13480. CIRCLE: 1,
  13481. PARABOLOID: 2
  13482. };
  13483. var TreeType = {
  13484. OCTREE: 0,
  13485. KDTREE: 1
  13486. };
  13487. var LengthUnits = {
  13488. METER: {
  13489. code: 'm',
  13490. unitspermeter: 1.0
  13491. },
  13492. FEET: {
  13493. code: 'ft',
  13494. unitspermeter: 3.28084
  13495. },
  13496. INCH: {
  13497. code: '\u2033',
  13498. unitspermeter: 39.3701
  13499. }
  13500. };
  13501. //
  13502. // how to calculate the radius of a projected sphere in screen space
  13503. // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
  13504. // http://stackoverflow.com/questions/3717226/radius-of-projected-sphere
  13505. //
  13506. class PointCloudMaterial$1 extends RawShaderMaterial {
  13507. //base
  13508. constructor() {
  13509. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  13510. super();
  13511. this.visibleNodesTexture = Utils.generateDataTexture(2048, 1, new Color(0xffffff));
  13512. this.visibleNodesTexture.minFilter = NearestFilter;
  13513. this.visibleNodesTexture.magFilter = NearestFilter;
  13514. var getValid = (a, b) => {
  13515. if (a !== undefined) {
  13516. return a;
  13517. } else {
  13518. return b;
  13519. }
  13520. };
  13521. var pointSize = getValid(parameters.size, 1.0);
  13522. var minSize = getValid(parameters.minSize, 2.0);
  13523. var maxSize = getValid(parameters.maxSize, 50.0);
  13524. var treeType = getValid(parameters.treeType, TreeType.OCTREE);
  13525. this._pointSizeType = PointSizeType.FIXED;
  13526. this._shape = PointShape$1.SQUARE;
  13527. this._useClipBox = false;
  13528. this.clipBoxes = [];
  13529. this.clipPolygons = [];
  13530. this._weighted = false;
  13531. this._gradient = Gradients.SPECTRAL;
  13532. this.gradientTexture = PointCloudMaterial$1.generateGradientTexture(this._gradient);
  13533. //this._matcap = "matcap.jpg";
  13534. //this.matcapTexture = PointCloudMaterial.generateMatcapTexture(this._matcap);
  13535. this.lights = false;
  13536. this.fog = false;
  13537. this._treeType = treeType;
  13538. this._useEDL = false;
  13539. this.defines = new Map();
  13540. this.ranges = new Map();
  13541. this._activeAttributeName = null;
  13542. this._defaultIntensityRangeChanged = false;
  13543. this._defaultElevationRangeChanged = false;
  13544. {
  13545. var [width, height] = [256, 1];
  13546. var data = new Uint8Array(width * 4);
  13547. var texture = new DataTexture(data, width, height, RGBAFormat);
  13548. texture.magFilter = NearestFilter;
  13549. texture.needsUpdate = true;
  13550. this.classificationTexture = texture;
  13551. }
  13552. this.attributes = {
  13553. position: {
  13554. type: 'fv',
  13555. value: []
  13556. },
  13557. color: {
  13558. type: 'fv',
  13559. value: []
  13560. },
  13561. normal: {
  13562. type: 'fv',
  13563. value: []
  13564. },
  13565. intensity: {
  13566. type: 'f',
  13567. value: []
  13568. },
  13569. classification: {
  13570. type: 'f',
  13571. value: []
  13572. },
  13573. returnNumber: {
  13574. type: 'f',
  13575. value: []
  13576. },
  13577. numberOfReturns: {
  13578. type: 'f',
  13579. value: []
  13580. },
  13581. pointSourceID: {
  13582. type: 'f',
  13583. value: []
  13584. },
  13585. indices: {
  13586. type: 'fv',
  13587. value: []
  13588. }
  13589. };
  13590. this.uniforms = {
  13591. level: {
  13592. type: "f",
  13593. value: 0.0
  13594. },
  13595. vnStart: {
  13596. type: "f",
  13597. value: 0.0
  13598. },
  13599. spacing: {
  13600. type: "f",
  13601. value: 1.0
  13602. },
  13603. blendHardness: {
  13604. type: "f",
  13605. value: 2.0
  13606. },
  13607. blendDepthSupplement: {
  13608. type: "f",
  13609. value: 0.0
  13610. },
  13611. fov: {
  13612. type: "f",
  13613. value: 1.0
  13614. },
  13615. screenWidth: {
  13616. type: "f",
  13617. value: 1.0
  13618. },
  13619. screenHeight: {
  13620. type: "f",
  13621. value: 1.0
  13622. },
  13623. near: {
  13624. type: "f",
  13625. value: 0.1
  13626. },
  13627. far: {
  13628. type: "f",
  13629. value: 1.0
  13630. },
  13631. uColor: {
  13632. type: "c",
  13633. value: new Color(0xffffff)
  13634. },
  13635. uOpacity: {
  13636. type: "f",
  13637. value: 1.0
  13638. },
  13639. size: {
  13640. type: "f",
  13641. value: pointSize
  13642. },
  13643. minSize: {
  13644. type: "f",
  13645. value: minSize
  13646. },
  13647. maxSize: {
  13648. type: "f",
  13649. value: maxSize
  13650. },
  13651. octreeSize: {
  13652. type: "f",
  13653. value: 0
  13654. },
  13655. bbSize: {
  13656. type: "fv",
  13657. value: [0, 0, 0]
  13658. },
  13659. elevationRange: {
  13660. type: "2fv",
  13661. value: [0, 0]
  13662. },
  13663. clipBoxCount: {
  13664. type: "f",
  13665. value: 0
  13666. },
  13667. //clipSphereCount: { type: "f", value: 0 },
  13668. clipPolygonCount: {
  13669. type: "i",
  13670. value: 0
  13671. },
  13672. clipBoxes: {
  13673. type: "Matrix4fv",
  13674. value: []
  13675. },
  13676. //clipSpheres: { type: "Matrix4fv", value: [] },
  13677. clipPolygons: {
  13678. type: "3fv",
  13679. value: []
  13680. },
  13681. clipPolygonVCount: {
  13682. type: "iv",
  13683. value: []
  13684. },
  13685. clipPolygonVP: {
  13686. type: "Matrix4fv",
  13687. value: []
  13688. },
  13689. visibleNodes: {
  13690. type: "t",
  13691. value: this.visibleNodesTexture
  13692. },
  13693. pcIndex: {
  13694. type: "f",
  13695. value: 0
  13696. },
  13697. gradient: {
  13698. type: "t",
  13699. value: this.gradientTexture
  13700. },
  13701. classificationLUT: {
  13702. type: "t",
  13703. value: this.classificationTexture
  13704. },
  13705. uHQDepthMap: {
  13706. type: "t",
  13707. value: null
  13708. },
  13709. toModel: {
  13710. type: "Matrix4f",
  13711. value: []
  13712. },
  13713. diffuse: {
  13714. type: "fv",
  13715. value: [1, 1, 1]
  13716. },
  13717. transition: {
  13718. type: "f",
  13719. value: 0.5
  13720. },
  13721. intensityRange: {
  13722. type: "fv",
  13723. value: [Infinity, -Infinity]
  13724. },
  13725. intensity_gbc: {
  13726. type: "fv",
  13727. value: [1, 0, 0]
  13728. },
  13729. uRGB_gbc: {
  13730. type: "fv",
  13731. value: [1, 0, 0]
  13732. },
  13733. // intensityGamma: { type: "f", value: 1 },
  13734. // intensityContrast: { type: "f", value: 0 },
  13735. // intensityBrightness:{ type: "f", value: 0 },
  13736. // rgbGamma: { type: "f", value: 1 },
  13737. // rgbContrast: { type: "f", value: 0 },
  13738. // rgbBrightness: { type: "f", value: 0 },
  13739. wRGB: {
  13740. type: "f",
  13741. value: 1
  13742. },
  13743. wIntensity: {
  13744. type: "f",
  13745. value: 0
  13746. },
  13747. wElevation: {
  13748. type: "f",
  13749. value: 0
  13750. },
  13751. wClassification: {
  13752. type: "f",
  13753. value: 0
  13754. },
  13755. wReturnNumber: {
  13756. type: "f",
  13757. value: 0
  13758. },
  13759. wSourceID: {
  13760. type: "f",
  13761. value: 0
  13762. },
  13763. useOrthographicCamera: {
  13764. type: "b",
  13765. value: false
  13766. },
  13767. elevationGradientRepat: {
  13768. type: "i",
  13769. value: ElevationGradientRepeat.CLAMP
  13770. },
  13771. clipTask: {
  13772. type: "i",
  13773. value: 1
  13774. },
  13775. clipMethod: {
  13776. type: "i",
  13777. value: 1
  13778. },
  13779. uShadowColor: {
  13780. type: "3fv",
  13781. value: [0, 0, 0]
  13782. },
  13783. uExtraScale: {
  13784. type: "f",
  13785. value: 1
  13786. },
  13787. uExtraOffset: {
  13788. type: "f",
  13789. value: 0
  13790. },
  13791. uExtraRange: {
  13792. type: "2fv",
  13793. value: [0, 1]
  13794. },
  13795. uExtraGammaBrightContr: {
  13796. type: "3fv",
  13797. value: [1, 0, 0]
  13798. },
  13799. uFilterReturnNumberRange: {
  13800. type: "fv",
  13801. value: [0, 7]
  13802. },
  13803. uFilterNumberOfReturnsRange: {
  13804. type: "fv",
  13805. value: [0, 7]
  13806. },
  13807. uFilterGPSTimeClipRange: {
  13808. type: "fv",
  13809. value: [0, 7]
  13810. },
  13811. uFilterPointSourceIDClipRange: {
  13812. type: "fv",
  13813. value: [0, 65535]
  13814. },
  13815. //matcapTextureUniform: { type: "t", value: this.matcapTexture },
  13816. backfaceCulling: {
  13817. type: "b",
  13818. value: false
  13819. }
  13820. };
  13821. this.classification = ClassificationScheme.DEFAULT;
  13822. this.defaultAttributeValues.normal = [0, 0, 0];
  13823. this.defaultAttributeValues.classification = [0, 0, 0];
  13824. this.defaultAttributeValues.indices = [0, 0, 0, 0];
  13825. this.vertexShader = Shaders['pointcloud.vs'];
  13826. this.fragmentShader = Shaders['pointcloud.fs'];
  13827. this.vertexColors = VertexColors;
  13828. this.updateShaderSource();
  13829. }
  13830. setDefine(key, value) {
  13831. if (value !== undefined && value !== null) {
  13832. if (this.defines.get(key) !== value) {
  13833. this.defines.set(key, value);
  13834. this.updateShaderSource();
  13835. }
  13836. } else {
  13837. this.removeDefine(key);
  13838. }
  13839. }
  13840. removeDefine(key) {
  13841. this.defines.delete(key);
  13842. }
  13843. updateShaderSource() {
  13844. var vs = Shaders['pointcloud.vs'];
  13845. var fs = Shaders['pointcloud.fs'];
  13846. var definesString = this.getDefines();
  13847. var vsVersionIndex = vs.indexOf("#version ");
  13848. var fsVersionIndex = fs.indexOf("#version ");
  13849. if (vsVersionIndex >= 0) {
  13850. vs = vs.replace(/(#version .*)/, "$1\n".concat(definesString));
  13851. } else {
  13852. vs = "".concat(definesString, "\n").concat(vs);
  13853. }
  13854. if (fsVersionIndex >= 0) {
  13855. fs = fs.replace(/(#version .*)/, "$1\n".concat(definesString));
  13856. } else {
  13857. fs = "".concat(definesString, "\n").concat(fs);
  13858. }
  13859. this.vertexShader = vs;
  13860. this.fragmentShader = fs;
  13861. if (this.opacity === 1.0) {
  13862. this.blending = NoBlending;
  13863. this.transparent = false;
  13864. this.depthTest = true;
  13865. this.depthWrite = true;
  13866. this.depthFunc = LessEqualDepth;
  13867. } else if (this.opacity < 1.0 && !this.useEDL) {
  13868. this.blending = AdditiveBlending;
  13869. this.transparent = true;
  13870. this.depthTest = false;
  13871. this.depthWrite = true;
  13872. this.depthFunc = AlwaysDepth;
  13873. }
  13874. if (this.weighted) {
  13875. this.blending = AdditiveBlending;
  13876. this.transparent = true;
  13877. this.depthTest = true;
  13878. this.depthWrite = false;
  13879. }
  13880. this.needsUpdate = true;
  13881. }
  13882. getDefines() {
  13883. var defines = [];
  13884. if (this.pointSizeType === PointSizeType.FIXED) {
  13885. defines.push('#define fixed_point_size');
  13886. } else if (this.pointSizeType === PointSizeType.ATTENUATED) {
  13887. defines.push('#define attenuated_point_size');
  13888. } else if (this.pointSizeType === PointSizeType.ADAPTIVE) {
  13889. defines.push('#define adaptive_point_size');
  13890. }
  13891. if (this.shape === PointShape$1.SQUARE) {
  13892. defines.push('#define square_point_shape');
  13893. } else if (this.shape === PointShape$1.CIRCLE) {
  13894. defines.push('#define circle_point_shape');
  13895. } else if (this.shape === PointShape$1.PARABOLOID) {
  13896. defines.push('#define paraboloid_point_shape');
  13897. }
  13898. if (this._useEDL) {
  13899. defines.push('#define use_edl');
  13900. }
  13901. if (this.activeAttributeName) {
  13902. var attributeName = this.activeAttributeName.replace(/[^a-zA-Z0-9]/g, '_');
  13903. defines.push("#define color_type_".concat(attributeName));
  13904. }
  13905. if (this._treeType === TreeType.OCTREE) {
  13906. defines.push('#define tree_type_octree');
  13907. } else if (this._treeType === TreeType.KDTREE) {
  13908. defines.push('#define tree_type_kdtree');
  13909. }
  13910. if (this.weighted) {
  13911. defines.push('#define weighted_splats');
  13912. }
  13913. for (var [key, value] of this.defines) {
  13914. defines.push(value);
  13915. }
  13916. return defines.join("\n");
  13917. }
  13918. setClipBoxes(clipBoxes) {
  13919. if (!clipBoxes) {
  13920. return;
  13921. }
  13922. var doUpdate = this.clipBoxes.length !== clipBoxes.length && (clipBoxes.length === 0 || this.clipBoxes.length === 0);
  13923. this.uniforms.clipBoxCount.value = this.clipBoxes.length;
  13924. this.clipBoxes = clipBoxes;
  13925. if (doUpdate) {
  13926. this.updateShaderSource();
  13927. }
  13928. this.uniforms.clipBoxes.value = new Float32Array(this.clipBoxes.length * 16);
  13929. for (var i = 0; i < this.clipBoxes.length; i++) {
  13930. var box = clipBoxes[i];
  13931. this.uniforms.clipBoxes.value.set(box.inverse.elements, 16 * i);
  13932. }
  13933. for (var _i = 0; _i < this.uniforms.clipBoxes.value.length; _i++) {
  13934. if (Number.isNaN(this.uniforms.clipBoxes.value[_i])) {
  13935. this.uniforms.clipBoxes.value[_i] = Infinity;
  13936. }
  13937. }
  13938. }
  13939. setClipPolygons(clipPolygons, maxPolygonVertices) {
  13940. if (!clipPolygons) {
  13941. return;
  13942. }
  13943. this.clipPolygons = clipPolygons;
  13944. var doUpdate = this.clipPolygons.length !== clipPolygons.length;
  13945. if (doUpdate) {
  13946. this.updateShaderSource();
  13947. }
  13948. }
  13949. get gradient() {
  13950. return this._gradient;
  13951. }
  13952. set gradient(value) {
  13953. //海拔贴图
  13954. if (this._gradient !== value) {
  13955. this._gradient = value;
  13956. this.gradientTexture = PointCloudMaterial$1.generateGradientTexture(this._gradient);
  13957. this.uniforms.gradient.value = this.gradientTexture;
  13958. }
  13959. }
  13960. /* get matcap(){
  13961. return this._matcap;
  13962. }
  13963. set matcap (value) {
  13964. if (this._matcap !== value) {
  13965. this._matcap = value;
  13966. this.matcapTexture = Potree.PointCloudMaterial.generateMatcapTexture(this._matcap);
  13967. this.uniforms.matcapTextureUniform.value = this.matcapTexture;
  13968. }
  13969. } */
  13970. get useOrthographicCamera() {
  13971. return this.uniforms.useOrthographicCamera.value;
  13972. }
  13973. set useOrthographicCamera(value) {
  13974. if (this.uniforms.useOrthographicCamera.value !== value) {
  13975. this.uniforms.useOrthographicCamera.value = value;
  13976. }
  13977. }
  13978. get backfaceCulling() {
  13979. return this.uniforms.backfaceCulling.value;
  13980. }
  13981. set backfaceCulling(value) {
  13982. if (this.uniforms.backfaceCulling.value !== value) {
  13983. this.uniforms.backfaceCulling.value = value;
  13984. this.dispatchEvent({
  13985. type: 'backface_changed',
  13986. target: this
  13987. });
  13988. }
  13989. }
  13990. recomputeClassification() {
  13991. var classification = this.classification;
  13992. var data = this.classificationTexture.image.data;
  13993. if (!classification) return;
  13994. var width = 256;
  13995. var black = [1, 1, 1, 1]; //1111
  13996. var valuesChanged = false;
  13997. for (var i = 0; i < width; i++) {
  13998. var color = void 0;
  13999. var visible = true;
  14000. if (classification[i]) {
  14001. color = classification[i].color;
  14002. visible = classification[i].visible;
  14003. } else if (classification[i % 32]) {
  14004. color = classification[i % 32].color;
  14005. visible = classification[i % 32].visible;
  14006. } else if (classification.DEFAULT) {
  14007. color = classification.DEFAULT.color;
  14008. visible = classification.DEFAULT.visible;
  14009. } else {
  14010. color = black;
  14011. }
  14012. var r = parseInt(255 * color[0]);
  14013. var g = parseInt(255 * color[1]);
  14014. var b = parseInt(255 * color[2]);
  14015. var a = visible ? parseInt(255 * color[3]) : 0;
  14016. if (data[4 * i + 0] !== r) {
  14017. data[4 * i + 0] = r;
  14018. valuesChanged = true;
  14019. }
  14020. if (data[4 * i + 1] !== g) {
  14021. data[4 * i + 1] = g;
  14022. valuesChanged = true;
  14023. }
  14024. if (data[4 * i + 2] !== b) {
  14025. data[4 * i + 2] = b;
  14026. valuesChanged = true;
  14027. }
  14028. if (data[4 * i + 3] !== a) {
  14029. data[4 * i + 3] = a;
  14030. valuesChanged = true;
  14031. }
  14032. }
  14033. if (valuesChanged) {
  14034. this.classificationTexture.needsUpdate = true;
  14035. this.dispatchEvent({
  14036. type: 'material_property_changed',
  14037. target: this
  14038. });
  14039. }
  14040. }
  14041. get spacing() {
  14042. return this.uniforms.spacing.value;
  14043. }
  14044. set spacing(value) {
  14045. if (this.uniforms.spacing.value !== value) {
  14046. // 即 uOctreeSpacing 来自cloud.js里
  14047. this.uniforms.spacing.value = value;
  14048. }
  14049. }
  14050. get useClipBox() {
  14051. return this._useClipBox;
  14052. }
  14053. set useClipBox(value) {
  14054. if (this._useClipBox !== value) {
  14055. this._useClipBox = value;
  14056. this.updateShaderSource();
  14057. }
  14058. }
  14059. get clipTask() {
  14060. return this.uniforms.clipTask.value;
  14061. }
  14062. set clipTask(mode) {
  14063. this.uniforms.clipTask.value = mode;
  14064. }
  14065. get elevationGradientRepat() {
  14066. return this.uniforms.elevationGradientRepat.value;
  14067. }
  14068. set elevationGradientRepat(mode) {
  14069. this.uniforms.elevationGradientRepat.value = mode;
  14070. }
  14071. get clipMethod() {
  14072. return this.uniforms.clipMethod.value;
  14073. }
  14074. set clipMethod(mode) {
  14075. this.uniforms.clipMethod.value = mode;
  14076. }
  14077. get weighted() {
  14078. return this._weighted;
  14079. }
  14080. set weighted(value) {
  14081. if (this._weighted !== value) {
  14082. this._weighted = value;
  14083. this.updateShaderSource();
  14084. }
  14085. }
  14086. get fov() {
  14087. return this.uniforms.fov.value;
  14088. }
  14089. set fov(value) {
  14090. if (this.uniforms.fov.value !== value) {
  14091. this.uniforms.fov.value = value;
  14092. // this.updateShaderSource();
  14093. }
  14094. }
  14095. get screenWidth() {
  14096. return this.uniforms.screenWidth.value;
  14097. }
  14098. set screenWidth(value) {
  14099. if (this.uniforms.screenWidth.value !== value) {
  14100. this.uniforms.screenWidth.value = value;
  14101. // this.updateShaderSource();
  14102. }
  14103. }
  14104. get screenHeight() {
  14105. return this.uniforms.screenHeight.value;
  14106. }
  14107. set screenHeight(value) {
  14108. if (this.uniforms.screenHeight.value !== value) {
  14109. this.uniforms.screenHeight.value = value;
  14110. // this.updateShaderSource();
  14111. }
  14112. }
  14113. get near() {
  14114. return this.uniforms.near.value;
  14115. }
  14116. set near(value) {
  14117. if (this.uniforms.near.value !== value) {
  14118. this.uniforms.near.value = value;
  14119. }
  14120. }
  14121. get far() {
  14122. return this.uniforms.far.value;
  14123. }
  14124. set far(value) {
  14125. if (this.uniforms.far.value !== value) {
  14126. this.uniforms.far.value = value;
  14127. }
  14128. }
  14129. get opacity() {
  14130. return this.uniforms.uOpacity.value;
  14131. }
  14132. set opacity(value) {
  14133. if (this.uniforms && this.uniforms.uOpacity) {
  14134. if (this.uniforms.uOpacity.value !== value) {
  14135. this.uniforms.uOpacity.value = value;
  14136. this.updateShaderSource();
  14137. this.dispatchEvent({
  14138. type: 'opacity_changed',
  14139. target: this
  14140. });
  14141. this.dispatchEvent({
  14142. type: 'material_property_changed',
  14143. target: this
  14144. });
  14145. }
  14146. }
  14147. }
  14148. get activeAttributeName() {
  14149. return this._activeAttributeName;
  14150. }
  14151. set activeAttributeName(value) {
  14152. if (this._activeAttributeName !== value) {
  14153. //console.error('_activeAttributeName!!!!!!!',value)
  14154. this._activeAttributeName = value;
  14155. this.updateShaderSource();
  14156. this.dispatchEvent({
  14157. type: 'active_attribute_changed',
  14158. target: this
  14159. });
  14160. this.dispatchEvent({
  14161. type: 'material_property_changed',
  14162. target: this
  14163. });
  14164. }
  14165. }
  14166. get pointSizeType() {
  14167. return this._pointSizeType;
  14168. }
  14169. set pointSizeType(value) {
  14170. if (this._pointSizeType !== value) {
  14171. this._pointSizeType = value;
  14172. this.updateShaderSource(); //这句表明这个属性频繁更改会卡顿
  14173. this.dispatchEvent({
  14174. type: 'point_size_type_changed',
  14175. target: this
  14176. });
  14177. this.dispatchEvent({
  14178. type: 'material_property_changed',
  14179. target: this
  14180. });
  14181. }
  14182. }
  14183. get useEDL() {
  14184. return this._useEDL;
  14185. }
  14186. set useEDL(value) {
  14187. if (this._useEDL !== value) {
  14188. this._useEDL = value;
  14189. this.updateShaderSource();
  14190. }
  14191. }
  14192. get color() {
  14193. return this.uniforms.uColor.value;
  14194. }
  14195. set color(value) {
  14196. if (!this.uniforms.uColor.value.equals(value)) {
  14197. this.uniforms.uColor.value.copy(value);
  14198. this.dispatchEvent({
  14199. type: 'color_changed',
  14200. target: this
  14201. });
  14202. this.dispatchEvent({
  14203. type: 'material_property_changed',
  14204. target: this
  14205. });
  14206. }
  14207. }
  14208. get shape() {
  14209. return this._shape;
  14210. }
  14211. set shape(value) {
  14212. if (this._shape !== value) {
  14213. this._shape = value;
  14214. this.updateShaderSource();
  14215. this.dispatchEvent({
  14216. type: 'point_shape_changed',
  14217. target: this
  14218. });
  14219. this.dispatchEvent({
  14220. type: 'material_property_changed',
  14221. target: this
  14222. });
  14223. }
  14224. }
  14225. get treeType() {
  14226. return this._treeType;
  14227. }
  14228. set treeType(value) {
  14229. if (this._treeType !== value) {
  14230. this._treeType = value;
  14231. this.updateShaderSource();
  14232. }
  14233. }
  14234. get bbSize() {
  14235. return this.uniforms.bbSize.value;
  14236. }
  14237. set bbSize(value) {
  14238. this.uniforms.bbSize.value = value;
  14239. }
  14240. get size() {
  14241. return this.uniforms.size.value;
  14242. }
  14243. set size(value) {
  14244. if (this.uniforms.size.value !== value) {
  14245. this.uniforms.size.value = value;
  14246. this.dispatchEvent({
  14247. type: 'point_size_changed',
  14248. target: this
  14249. });
  14250. this.dispatchEvent({
  14251. type: 'material_property_changed',
  14252. target: this
  14253. });
  14254. }
  14255. }
  14256. get minSize() {
  14257. return this.uniforms.minSize.value;
  14258. }
  14259. set minSize(value) {
  14260. if (this.uniforms.minSize.value !== value) {
  14261. this.uniforms.minSize.value = value;
  14262. this.dispatchEvent({
  14263. type: 'point_size_changed',
  14264. target: this
  14265. });
  14266. this.dispatchEvent({
  14267. type: 'material_property_changed',
  14268. target: this
  14269. });
  14270. }
  14271. }
  14272. get elevationRange() {
  14273. return this.uniforms.elevationRange.value;
  14274. }
  14275. set elevationRange(value) {
  14276. var changed = this.uniforms.elevationRange.value[0] !== value[0] || this.uniforms.elevationRange.value[1] !== value[1];
  14277. if (changed) {
  14278. this.uniforms.elevationRange.value = value;
  14279. this._defaultElevationRangeChanged = true;
  14280. this.dispatchEvent({
  14281. type: 'material_property_changed',
  14282. target: this
  14283. });
  14284. }
  14285. }
  14286. get heightMin() {
  14287. return this.uniforms.elevationRange.value[0];
  14288. }
  14289. set heightMin(value) {
  14290. this.elevationRange = [value, this.elevationRange[1]];
  14291. }
  14292. get heightMax() {
  14293. return this.uniforms.elevationRange.value[1];
  14294. }
  14295. set heightMax(value) {
  14296. this.elevationRange = [this.elevationRange[0], value];
  14297. }
  14298. get transition() {
  14299. return this.uniforms.transition.value;
  14300. }
  14301. set transition(value) {
  14302. this.uniforms.transition.value = value;
  14303. }
  14304. get intensityRange() {
  14305. return this.uniforms.intensityRange.value;
  14306. }
  14307. set intensityRange(value) {
  14308. if (!(value instanceof Array && value.length === 2)) {
  14309. return;
  14310. }
  14311. if (value[0] === this.uniforms.intensityRange.value[0] && value[1] === this.uniforms.intensityRange.value[1]) {
  14312. return;
  14313. }
  14314. this.uniforms.intensityRange.value = value;
  14315. this._defaultIntensityRangeChanged = true;
  14316. this.dispatchEvent({
  14317. type: 'material_property_changed',
  14318. target: this
  14319. });
  14320. }
  14321. get intensityGamma() {
  14322. return this.uniforms.intensity_gbc.value[0];
  14323. }
  14324. set intensityGamma(value) {
  14325. if (this.uniforms.intensity_gbc.value[0] !== value) {
  14326. this.uniforms.intensity_gbc.value[0] = value;
  14327. this.dispatchEvent({
  14328. type: 'material_property_changed',
  14329. target: this
  14330. });
  14331. }
  14332. }
  14333. get intensityContrast() {
  14334. return this.uniforms.intensity_gbc.value[2];
  14335. }
  14336. set intensityContrast(value) {
  14337. if (this.uniforms.intensity_gbc.value[2] !== value) {
  14338. this.uniforms.intensity_gbc.value[2] = value;
  14339. this.dispatchEvent({
  14340. type: 'material_property_changed',
  14341. target: this
  14342. });
  14343. }
  14344. }
  14345. get intensityBrightness() {
  14346. return this.uniforms.intensity_gbc.value[1];
  14347. }
  14348. set intensityBrightness(value) {
  14349. if (this.uniforms.intensity_gbc.value[1] !== value) {
  14350. this.uniforms.intensity_gbc.value[1] = value;
  14351. this.dispatchEvent({
  14352. type: 'material_property_changed',
  14353. target: this
  14354. });
  14355. }
  14356. }
  14357. get rgbGamma() {
  14358. return this.uniforms.uRGB_gbc.value[0];
  14359. }
  14360. set rgbGamma(value) {
  14361. if (this.uniforms.uRGB_gbc.value[0] !== value) {
  14362. this.uniforms.uRGB_gbc.value[0] = value;
  14363. this.dispatchEvent({
  14364. type: 'material_property_changed',
  14365. target: this
  14366. });
  14367. }
  14368. }
  14369. get rgbContrast() {
  14370. return this.uniforms.uRGB_gbc.value[2];
  14371. }
  14372. set rgbContrast(value) {
  14373. if (this.uniforms.uRGB_gbc.value[2] !== value) {
  14374. this.uniforms.uRGB_gbc.value[2] = value;
  14375. this.dispatchEvent({
  14376. type: 'material_property_changed',
  14377. target: this
  14378. });
  14379. }
  14380. }
  14381. get rgbBrightness() {
  14382. return this.uniforms.uRGB_gbc.value[1];
  14383. }
  14384. set rgbBrightness(value) {
  14385. if (this.uniforms.uRGB_gbc.value[1] !== value) {
  14386. this.uniforms.uRGB_gbc.value[1] = value;
  14387. this.dispatchEvent({
  14388. type: 'material_property_changed',
  14389. target: this
  14390. });
  14391. }
  14392. }
  14393. get extraGamma() {
  14394. return this.uniforms.uExtraGammaBrightContr.value[0];
  14395. }
  14396. set extraGamma(value) {
  14397. if (this.uniforms.uExtraGammaBrightContr.value[0] !== value) {
  14398. this.uniforms.uExtraGammaBrightContr.value[0] = value;
  14399. this.dispatchEvent({
  14400. type: 'material_property_changed',
  14401. target: this
  14402. });
  14403. }
  14404. }
  14405. get extraBrightness() {
  14406. return this.uniforms.uExtraGammaBrightContr.value[1];
  14407. }
  14408. set extraBrightness(value) {
  14409. if (this.uniforms.uExtraGammaBrightContr.value[1] !== value) {
  14410. this.uniforms.uExtraGammaBrightContr.value[1] = value;
  14411. this.dispatchEvent({
  14412. type: 'material_property_changed',
  14413. target: this
  14414. });
  14415. }
  14416. }
  14417. get extraContrast() {
  14418. return this.uniforms.uExtraGammaBrightContr.value[2];
  14419. }
  14420. set extraContrast(value) {
  14421. if (this.uniforms.uExtraGammaBrightContr.value[2] !== value) {
  14422. this.uniforms.uExtraGammaBrightContr.value[2] = value;
  14423. this.dispatchEvent({
  14424. type: 'material_property_changed',
  14425. target: this
  14426. });
  14427. }
  14428. }
  14429. getRange(attributeName) {
  14430. return this.ranges.get(attributeName);
  14431. }
  14432. setRange(attributeName, newRange) {
  14433. var rangeChanged = false;
  14434. var oldRange = this.ranges.get(attributeName);
  14435. if (oldRange != null && newRange != null) {
  14436. rangeChanged = oldRange[0] !== newRange[0] || oldRange[1] !== newRange[1];
  14437. } else {
  14438. rangeChanged = true;
  14439. }
  14440. this.ranges.set(attributeName, newRange);
  14441. if (rangeChanged) {
  14442. this.dispatchEvent({
  14443. type: 'material_property_changed',
  14444. target: this
  14445. });
  14446. }
  14447. }
  14448. get extraRange() {
  14449. return this.uniforms.uExtraRange.value;
  14450. }
  14451. set extraRange(value) {
  14452. if (!(value instanceof Array && value.length === 2)) {
  14453. return;
  14454. }
  14455. if (value[0] === this.uniforms.uExtraRange.value[0] && value[1] === this.uniforms.uExtraRange.value[1]) {
  14456. return;
  14457. }
  14458. this.uniforms.uExtraRange.value = value;
  14459. this._defaultExtraRangeChanged = true;
  14460. this.dispatchEvent({
  14461. type: 'material_property_changed',
  14462. target: this
  14463. });
  14464. }
  14465. get weightRGB() {
  14466. return this.uniforms.wRGB.value;
  14467. }
  14468. set weightRGB(value) {
  14469. if (this.uniforms.wRGB.value !== value) {
  14470. this.uniforms.wRGB.value = value;
  14471. this.dispatchEvent({
  14472. type: 'material_property_changed',
  14473. target: this
  14474. });
  14475. }
  14476. }
  14477. get weightIntensity() {
  14478. return this.uniforms.wIntensity.value;
  14479. }
  14480. set weightIntensity(value) {
  14481. if (this.uniforms.wIntensity.value !== value) {
  14482. this.uniforms.wIntensity.value = value;
  14483. this.dispatchEvent({
  14484. type: 'material_property_changed',
  14485. target: this
  14486. });
  14487. }
  14488. }
  14489. get weightElevation() {
  14490. return this.uniforms.wElevation.value;
  14491. }
  14492. set weightElevation(value) {
  14493. if (this.uniforms.wElevation.value !== value) {
  14494. this.uniforms.wElevation.value = value;
  14495. this.dispatchEvent({
  14496. type: 'material_property_changed',
  14497. target: this
  14498. });
  14499. }
  14500. }
  14501. get weightClassification() {
  14502. return this.uniforms.wClassification.value;
  14503. }
  14504. set weightClassification(value) {
  14505. if (this.uniforms.wClassification.value !== value) {
  14506. this.uniforms.wClassification.value = value;
  14507. this.dispatchEvent({
  14508. type: 'material_property_changed',
  14509. target: this
  14510. });
  14511. }
  14512. }
  14513. get weightReturnNumber() {
  14514. return this.uniforms.wReturnNumber.value;
  14515. }
  14516. set weightReturnNumber(value) {
  14517. if (this.uniforms.wReturnNumber.value !== value) {
  14518. this.uniforms.wReturnNumber.value = value;
  14519. this.dispatchEvent({
  14520. type: 'material_property_changed',
  14521. target: this
  14522. });
  14523. }
  14524. }
  14525. get weightSourceID() {
  14526. return this.uniforms.wSourceID.value;
  14527. }
  14528. set weightSourceID(value) {
  14529. if (this.uniforms.wSourceID.value !== value) {
  14530. this.uniforms.wSourceID.value = value;
  14531. this.dispatchEvent({
  14532. type: 'material_property_changed',
  14533. target: this
  14534. });
  14535. }
  14536. }
  14537. static generateGradientTexture(gradient) {
  14538. var size = 64;
  14539. // create canvas
  14540. var canvas = document.createElement('canvas');
  14541. canvas.width = size;
  14542. canvas.height = size;
  14543. // get context
  14544. var context = canvas.getContext('2d');
  14545. // draw gradient
  14546. context.rect(0, 0, size, size);
  14547. var ctxGradient = context.createLinearGradient(0, 0, size, size);
  14548. for (var i = 0; i < gradient.length; i++) {
  14549. var step = gradient[i];
  14550. ctxGradient.addColorStop(step[0], '#' + step[1].getHexString());
  14551. }
  14552. context.fillStyle = ctxGradient;
  14553. context.fill();
  14554. //let texture = new THREE.Texture(canvas);
  14555. var texture = new CanvasTexture(canvas);
  14556. texture.needsUpdate = true;
  14557. texture.minFilter = LinearFilter;
  14558. texture.wrap = RepeatWrapping;
  14559. texture.repeat = 2;
  14560. // textureImage = texture.image;
  14561. return texture;
  14562. }
  14563. static generateMatcapTexture(matcap) {
  14564. var url = new URL(Potree.resourcePath + "/textures/matcap/" + matcap).href;
  14565. var texture = new TextureLoader().load(url);
  14566. texture.magFilter = texture.minFilter = LinearFilter;
  14567. texture.needsUpdate = true;
  14568. // 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
  14569. // Switch matcap texture on the fly : viewer.scene.pointclouds[0].material.matcap = 'matcap1.jpg';
  14570. // 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
  14571. return texture;
  14572. }
  14573. disableEvents() {
  14574. if (this._hiddenListeners === undefined) {
  14575. this._hiddenListeners = this._listeners;
  14576. this._listeners = {};
  14577. }
  14578. }
  14579. enableEvents() {
  14580. this._listeners = this._hiddenListeners;
  14581. this._hiddenListeners = undefined;
  14582. }
  14583. } // copyFrom(from){
  14584. // var a = 10;
  14585. // for(let name of Object.keys(this.uniforms)){
  14586. // this.uniforms[name].value = from.uniforms[name].value;
  14587. // }
  14588. // }
  14589. // copy(from){
  14590. // this.copyFrom(from);
  14591. // }
  14592. //见ExtendPointCloudOctree
  14593. class PointCloudOctreeNode extends PointCloudTreeNode {
  14594. constructor() {
  14595. super();
  14596. //this.children = {};
  14597. this.children = [];
  14598. this.sceneNode = null;
  14599. this.octree = null;
  14600. }
  14601. getNumPoints() {
  14602. return this.geometryNode.numPoints;
  14603. }
  14604. isLoaded() {
  14605. return true;
  14606. }
  14607. isTreeNode() {
  14608. return true;
  14609. }
  14610. isGeometryNode() {
  14611. return false;
  14612. }
  14613. getLevel() {
  14614. return this.geometryNode.level;
  14615. }
  14616. getBoundingSphere() {
  14617. return this.geometryNode.boundingSphere;
  14618. }
  14619. getBoundingBox() {
  14620. return this.geometryNode.boundingBox;
  14621. }
  14622. getChildren() {
  14623. var children = [];
  14624. for (var i = 0; i < 8; i++) {
  14625. if (this.children[i]) {
  14626. children.push(this.children[i]);
  14627. }
  14628. }
  14629. return children;
  14630. }
  14631. getPointsInBox(boxNode) {
  14632. if (!this.sceneNode) {
  14633. return null;
  14634. }
  14635. var buffer = this.geometryNode.buffer;
  14636. var posOffset = buffer.offset("position");
  14637. var stride = buffer.stride;
  14638. var view = new DataView(buffer.data);
  14639. var worldToBox = boxNode.matrixWorld.clone().invert();
  14640. var objectToBox = new Matrix4().multiplyMatrices(worldToBox, this.sceneNode.matrixWorld);
  14641. var inBox = [];
  14642. var pos = new Vector4();
  14643. for (var i = 0; i < buffer.numElements; i++) {
  14644. var x = view.getFloat32(i * stride + posOffset + 0, true);
  14645. var y = view.getFloat32(i * stride + posOffset + 4, true);
  14646. var z = view.getFloat32(i * stride + posOffset + 8, true);
  14647. pos.set(x, y, z, 1);
  14648. pos.applyMatrix4(objectToBox);
  14649. if (-0.5 < pos.x && pos.x < 0.5) {
  14650. if (-0.5 < pos.y && pos.y < 0.5) {
  14651. if (-0.5 < pos.z && pos.z < 0.5) {
  14652. pos.set(x, y, z, 1).applyMatrix4(this.sceneNode.matrixWorld);
  14653. inBox.push(new Vector3(pos.x, pos.y, pos.z));
  14654. }
  14655. }
  14656. }
  14657. }
  14658. return inBox;
  14659. }
  14660. get name() {
  14661. return this.geometryNode.name;
  14662. }
  14663. }
  14664. ;
  14665. class PointCloudOctree extends PointCloudTree {
  14666. //base
  14667. constructor(geometry, material) {
  14668. var _this2;
  14669. super();
  14670. _this2 = this;
  14671. this.pointBudget = Infinity; //一直是这个值
  14672. this.pcoGeometry = geometry;
  14673. this.boundingBox = this.pcoGeometry.boundingBox;
  14674. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  14675. this.material = material || new PointCloudMaterial$1();
  14676. this.visiblePointsTarget = 2 * 1000 * 1000;
  14677. this.minimumNodePixelSize = 150;
  14678. this.level = 0;
  14679. this.position.copy(geometry.offset);
  14680. this.updateMatrix();
  14681. {
  14682. var priorityQueue = ["rgba", "rgb", "intensity", "classification"];
  14683. var selected = "rgba";
  14684. var _loop = function _loop(attributeName) {
  14685. var attribute = _this2.pcoGeometry.pointAttributes.attributes.find(a => a.name === attributeName);
  14686. if (!attribute) {
  14687. return 0; // continue
  14688. }
  14689. var min = attribute.range[0].constructor.name === "Array" ? attribute.range[0] : [attribute.range[0]];
  14690. var max = attribute.range[1].constructor.name === "Array" ? attribute.range[1] : [attribute.range[1]];
  14691. var range_min = new Vector3(...min);
  14692. var range_max = new Vector3(...max);
  14693. var range = range_min.distanceTo(range_max);
  14694. if (range === 0) {
  14695. return 0; // continue
  14696. }
  14697. selected = attributeName;
  14698. return 1; // break
  14699. },
  14700. _ret;
  14701. for (var attributeName of priorityQueue) {
  14702. _ret = _loop(attributeName);
  14703. if (_ret === 0) continue;
  14704. if (_ret === 1) break;
  14705. }
  14706. this.material.activeAttributeName = selected;
  14707. }
  14708. this.showBoundingBox = false;
  14709. this.boundingBoxNodes = [];
  14710. this.loadQueue = [];
  14711. this.visibleBounds = new Box3();
  14712. this.visibleNodes = [];
  14713. this.visibleGeometry = [];
  14714. this.generateDEM = false;
  14715. this.profileRequests = [];
  14716. this.name = '';
  14717. this._visible = true;
  14718. {
  14719. var box = [this.pcoGeometry.tightBoundingBox, this.getBoundingBoxWorld()].find(v => v !== undefined);
  14720. this.updateMatrixWorld(true);
  14721. box = Utils.computeTransformedBoundingBox(box, this.matrixWorld);
  14722. var bMin = box.min.z;
  14723. var bMax = box.max.z;
  14724. this.material.heightMin = bMin;
  14725. this.material.heightMax = bMax;
  14726. }
  14727. // TODO read projection from file instead
  14728. this.projection = geometry.projection;
  14729. this.fallbackProjection = geometry.fallbackProjection;
  14730. this.root = this.pcoGeometry.root;
  14731. }
  14732. setName(name) {
  14733. if (this.name !== name) {
  14734. this.name = name;
  14735. this.dispatchEvent({
  14736. type: 'name_changed',
  14737. name: name,
  14738. pointcloud: this
  14739. });
  14740. }
  14741. }
  14742. getName() {
  14743. return this.name;
  14744. }
  14745. getAttribute(name) {
  14746. var attribute = this.pcoGeometry.pointAttributes.attributes.find(a => a.name === name);
  14747. if (attribute) {
  14748. return attribute;
  14749. } else {
  14750. return null;
  14751. }
  14752. }
  14753. getAttributes() {
  14754. return this.pcoGeometry.pointAttributes;
  14755. }
  14756. toTreeNode(geometryNode, parent) {
  14757. var node = new PointCloudOctreeNode();
  14758. var sceneNode = new Points(geometryNode.geometry, this.material);
  14759. sceneNode.name = geometryNode.name;
  14760. sceneNode.position.copy(geometryNode.boundingBox.min);
  14761. sceneNode.frustumCulled = false;
  14762. sceneNode.onBeforeRender = (_this, scene, camera, geometry, material, group) => {
  14763. if (material.program) {
  14764. _this.getContext().useProgram(material.program.program);
  14765. if (material.program.getUniforms().map.level) {
  14766. var level = geometryNode.getLevel();
  14767. material.uniforms.level.value = level;
  14768. material.program.getUniforms().map.level.setValue(_this.getContext(), level);
  14769. }
  14770. if (this.visibleNodeTextureOffsets && material.program.getUniforms().map.vnStart) {
  14771. var vnStart = this.visibleNodeTextureOffsets.get(node);
  14772. material.uniforms.vnStart.value = vnStart;
  14773. material.program.getUniforms().map.vnStart.setValue(_this.getContext(), vnStart);
  14774. }
  14775. if (material.program.getUniforms().map.pcIndex) {
  14776. var i = node.pcIndex ? node.pcIndex : this.visibleNodes.indexOf(node);
  14777. material.uniforms.pcIndex.value = i;
  14778. material.program.getUniforms().map.pcIndex.setValue(_this.getContext(), i);
  14779. }
  14780. }
  14781. };
  14782. // { // DEBUG
  14783. // let sg = new THREE.SphereGeometry(1, 16, 16);
  14784. // let sm = new THREE.MeshNormalMaterial();
  14785. // let s = new THREE.Mesh(sg, sm);
  14786. // s.scale.set(5, 5, 5);
  14787. // s.position.copy(geometryNode.mean)
  14788. // .add(this.position)
  14789. // .add(geometryNode.boundingBox.min);
  14790. //
  14791. // viewer.scene.scene.add(s);
  14792. // }
  14793. node.geometryNode = geometryNode;
  14794. node.sceneNode = sceneNode;
  14795. node.pointcloud = this;
  14796. node.children = [];
  14797. //for (let key in geometryNode.children) {
  14798. // node.children[key] = geometryNode.children[key];
  14799. //}
  14800. for (var i = 0; i < 8; i++) {
  14801. node.children[i] = geometryNode.children[i];
  14802. }
  14803. if (!parent) {
  14804. this.root = node;
  14805. this.add(sceneNode);
  14806. } else {
  14807. var childIndex = parseInt(geometryNode.name[geometryNode.name.length - 1]);
  14808. parent.sceneNode.add(sceneNode);
  14809. parent.children[childIndex] = node;
  14810. }
  14811. var disposeListener = function disposeListener() {
  14812. var childIndex = parseInt(geometryNode.name[geometryNode.name.length - 1]);
  14813. parent.sceneNode.remove(node.sceneNode);
  14814. parent.children[childIndex] = geometryNode;
  14815. };
  14816. geometryNode.oneTimeDisposeHandlers.push(disposeListener);
  14817. return node;
  14818. }
  14819. updateVisibleBounds() {
  14820. var leafNodes = [];
  14821. for (var i = 0; i < this.visibleNodes.length; i++) {
  14822. var node = this.visibleNodes[i];
  14823. var isLeaf = true;
  14824. for (var j = 0; j < node.children.length; j++) {
  14825. var child = node.children[j];
  14826. if (child instanceof PointCloudOctreeNode) {
  14827. isLeaf = isLeaf && !child.sceneNode.visible;
  14828. } else if (child instanceof PointCloudOctreeGeometryNode) {
  14829. isLeaf = true;
  14830. }
  14831. }
  14832. if (isLeaf) {
  14833. leafNodes.push(node);
  14834. }
  14835. }
  14836. this.visibleBounds.min = new Vector3(Infinity, Infinity, Infinity);
  14837. this.visibleBounds.max = new Vector3(-Infinity, -Infinity, -Infinity);
  14838. for (var _i = 0; _i < leafNodes.length; _i++) {
  14839. var _node = leafNodes[_i];
  14840. this.visibleBounds.expandByPoint(_node.getBoundingBox().min);
  14841. this.visibleBounds.expandByPoint(_node.getBoundingBox().max);
  14842. }
  14843. }
  14844. updateMaterial(material, visibleNodes, camera, renderer) {
  14845. material.fov = camera.fov * (Math.PI / 180);
  14846. material.screenWidth = renderer.domElement.clientWidth;
  14847. material.screenHeight = renderer.domElement.clientHeight;
  14848. material.spacing = this.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  14849. material.near = camera.near;
  14850. material.far = camera.far;
  14851. material.uniforms.octreeSize.value = this.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  14852. }
  14853. computeVisibilityTextureData(nodes, camera) {
  14854. if (Potree.measureTimings) performance.mark("computeVisibilityTextureData-start");
  14855. var data = new Uint8Array(nodes.length * 4);
  14856. var visibleNodeTextureOffsets = new Map();
  14857. // copy array
  14858. nodes = nodes.slice();
  14859. // sort by level and index, e.g. r, r0, r3, r4, r01, r07, r30, ...
  14860. var sort = function sort(a, b) {
  14861. var na = a.geometryNode.name;
  14862. var nb = b.geometryNode.name;
  14863. if (na.length !== nb.length) return na.length - nb.length;
  14864. if (na < nb) return -1;
  14865. if (na > nb) return 1;
  14866. return 0;
  14867. };
  14868. nodes.sort(sort);
  14869. var worldDir = new Vector3();
  14870. var nodeMap = new Map();
  14871. var offsetsToChild = new Array(nodes.length).fill(Infinity);
  14872. for (var i = 0; i < nodes.length; i++) {
  14873. var node = nodes[i];
  14874. nodeMap.set(node.name, node);
  14875. visibleNodeTextureOffsets.set(node, i);
  14876. if (i > 0) {
  14877. var index = parseInt(node.name.slice(-1));
  14878. var parentName = node.name.slice(0, -1);
  14879. var parent = nodeMap.get(parentName);
  14880. var parentOffset = visibleNodeTextureOffsets.get(parent);
  14881. var parentOffsetToChild = i - parentOffset;
  14882. offsetsToChild[parentOffset] = Math.min(offsetsToChild[parentOffset], parentOffsetToChild);
  14883. data[parentOffset * 4 + 0] = data[parentOffset * 4 + 0] | 1 << index;
  14884. data[parentOffset * 4 + 1] = offsetsToChild[parentOffset] >> 8;
  14885. data[parentOffset * 4 + 2] = offsetsToChild[parentOffset] % 256;
  14886. }
  14887. var density = node.geometryNode.density;
  14888. if (typeof density === "number") {
  14889. var lodOffset = Math.log2(density) / 2 - 1.5;
  14890. var offsetUint8 = (lodOffset + 10) * 10;
  14891. data[i * 4 + 3] = offsetUint8;
  14892. } else {
  14893. data[i * 4 + 3] = 100;
  14894. }
  14895. }
  14896. if (Potree.measureTimings) {
  14897. performance.mark("computeVisibilityTextureData-end");
  14898. performance.measure("render.computeVisibilityTextureData", "computeVisibilityTextureData-start", "computeVisibilityTextureData-end");
  14899. }
  14900. return {
  14901. data: data,
  14902. offsets: visibleNodeTextureOffsets
  14903. };
  14904. }
  14905. nodeIntersectsProfile(node, profile) {
  14906. var bbWorld = node.boundingBox.clone().applyMatrix4(this.matrixWorld);
  14907. var bsWorld = bbWorld.getBoundingSphere(new Sphere());
  14908. var intersects = false;
  14909. for (var i = 0; i < profile.points.length - 1; i++) {
  14910. var start = new Vector3(profile.points[i + 0].x, profile.points[i + 0].y, bsWorld.center.z);
  14911. var end = new Vector3(profile.points[i + 1].x, profile.points[i + 1].y, bsWorld.center.z);
  14912. var closest = new Line3(start, end).closestPointToPoint(bsWorld.center, true, new Vector3());
  14913. var distance = closest.distanceTo(bsWorld.center);
  14914. intersects = intersects || distance < bsWorld.radius + profile.width;
  14915. }
  14916. //console.log(`${node.name}: ${intersects}`);
  14917. return intersects;
  14918. }
  14919. deepestNodeAt(position) {
  14920. var toObjectSpace = this.matrixWorld.clone().invert();
  14921. var objPos = position.clone().applyMatrix4(toObjectSpace);
  14922. var current = this.root;
  14923. while (true) {
  14924. var containingChild = null;
  14925. for (var child of current.children) {
  14926. if (child !== undefined) {
  14927. if (child.getBoundingBox().containsPoint(objPos)) {
  14928. containingChild = child;
  14929. }
  14930. }
  14931. }
  14932. if (containingChild !== null && containingChild instanceof PointCloudOctreeNode) {
  14933. current = containingChild;
  14934. } else {
  14935. break;
  14936. }
  14937. }
  14938. var deepest = current;
  14939. return deepest;
  14940. }
  14941. nodesOnRay(nodes, ray) {
  14942. var nodesOnRay = [];
  14943. var _ray = ray.clone();
  14944. for (var i = 0; i < nodes.length; i++) {
  14945. var node = nodes[i];
  14946. var sphere = node.getBoundingSphere().clone().applyMatrix4(this.matrixWorld);
  14947. if (_ray.intersectsSphere(sphere)) {
  14948. nodesOnRay.push(node);
  14949. }
  14950. }
  14951. return nodesOnRay;
  14952. }
  14953. updateMatrixWorld(force) {
  14954. if (this.matrixAutoUpdate === true) this.updateMatrix();
  14955. if (this.matrixWorldNeedsUpdate === true || force === true) {
  14956. if (!this.parent) {
  14957. this.matrixWorld.copy(this.matrix);
  14958. } else {
  14959. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
  14960. }
  14961. this.matrixWorldNeedsUpdate = false;
  14962. force = true;
  14963. }
  14964. }
  14965. hideDescendants(object) {
  14966. var stack = [];
  14967. for (var i = 0; i < object.children.length; i++) {
  14968. var child = object.children[i];
  14969. if (child.visible) {
  14970. stack.push(child);
  14971. }
  14972. }
  14973. while (stack.length > 0) {
  14974. var _object = stack.shift();
  14975. _object.visible = false;
  14976. for (var _i2 = 0; _i2 < _object.children.length; _i2++) {
  14977. var _child = _object.children[_i2];
  14978. if (_child.visible) {
  14979. stack.push(_child);
  14980. }
  14981. }
  14982. }
  14983. }
  14984. moveToOrigin() {
  14985. this.position.set(0, 0, 0);
  14986. this.updateMatrixWorld(true);
  14987. var box = this.boundingBox;
  14988. var transform = this.matrixWorld;
  14989. var tBox = Utils.computeTransformedBoundingBox(box, transform);
  14990. this.position.set(0, 0, 0).sub(tBox.getCenter(new Vector3()));
  14991. }
  14992. moveToGroundPlane() {
  14993. this.updateMatrixWorld(true);
  14994. var box = this.boundingBox;
  14995. var transform = this.matrixWorld;
  14996. var tBox = Utils.computeTransformedBoundingBox(box, transform);
  14997. this.position.y += -tBox.min.y;
  14998. }
  14999. getBoundingBoxWorld() {
  15000. this.updateMatrixWorld(true);
  15001. var box = this.boundingBox;
  15002. var transform = this.matrixWorld;
  15003. var tBox = Utils.computeTransformedBoundingBox(box, transform);
  15004. return tBox;
  15005. }
  15006. /**
  15007. * returns points inside the profile points
  15008. *
  15009. * maxDepth: search points up to the given octree depth
  15010. *
  15011. *
  15012. * The return value is an array with all segments of the profile path
  15013. * let segment = {
  15014. * start: THREE.Vector3,
  15015. * end: THREE.Vector3,
  15016. * points: {}
  15017. * project: function()
  15018. * };
  15019. *
  15020. * The project() function inside each segment can be used to transform
  15021. * that segments point coordinates to line up along the x-axis.
  15022. *
  15023. *
  15024. */
  15025. getPointsInProfile(profile, maxDepth, callback) {
  15026. if (callback) {
  15027. var request = new Potree.ProfileRequest(this, profile, maxDepth, callback);
  15028. this.profileRequests.push(request);
  15029. return request;
  15030. }
  15031. var points = {
  15032. segments: [],
  15033. boundingBox: new Box3(),
  15034. projectedBoundingBox: new Box2()
  15035. };
  15036. // evaluate segments
  15037. for (var i = 0; i < profile.points.length - 1; i++) {
  15038. var start = profile.points[i];
  15039. var end = profile.points[i + 1];
  15040. var ps = this.getProfile(start, end, profile.width, maxDepth);
  15041. var segment = {
  15042. start: start,
  15043. end: end,
  15044. points: ps,
  15045. project: null
  15046. };
  15047. points.segments.push(segment);
  15048. points.boundingBox.expandByPoint(ps.boundingBox.min);
  15049. points.boundingBox.expandByPoint(ps.boundingBox.max);
  15050. }
  15051. // add projection functions to the segments
  15052. var mileage = new Vector3();
  15053. for (var _i3 = 0; _i3 < points.segments.length; _i3++) {
  15054. var _segment = points.segments[_i3];
  15055. var _start2 = _segment.start;
  15056. var _end2 = _segment.end;
  15057. var project = function (_start, _end, _mileage, _boundingBox) {
  15058. var start = _start;
  15059. var end = _end;
  15060. var mileage = _mileage;
  15061. var boundingBox = _boundingBox;
  15062. var xAxis = new Vector3(1, 0, 0);
  15063. var dir = new Vector3().subVectors(end, start);
  15064. dir.y = 0;
  15065. dir.normalize();
  15066. var alpha = Math.acos(xAxis.dot(dir));
  15067. if (dir.z > 0) {
  15068. alpha = -alpha;
  15069. }
  15070. return function (position) {
  15071. var toOrigin = new Matrix4().makeTranslation(-start.x, -boundingBox.min.y, -start.z);
  15072. var alignWithX = new Matrix4().makeRotationY(-alpha);
  15073. var applyMileage = new Matrix4().makeTranslation(mileage.x, 0, 0);
  15074. var pos = position.clone();
  15075. pos.applyMatrix4(toOrigin);
  15076. pos.applyMatrix4(alignWithX);
  15077. pos.applyMatrix4(applyMileage);
  15078. return pos;
  15079. };
  15080. }(_start2, _end2, mileage.clone(), points.boundingBox.clone());
  15081. _segment.project = project;
  15082. mileage.x += new Vector3(_start2.x, 0, _start2.z).distanceTo(new Vector3(_end2.x, 0, _end2.z));
  15083. mileage.y += _end2.y - _start2.y;
  15084. }
  15085. points.projectedBoundingBox.min.x = 0;
  15086. points.projectedBoundingBox.min.y = points.boundingBox.min.y;
  15087. points.projectedBoundingBox.max.x = mileage.x;
  15088. points.projectedBoundingBox.max.y = points.boundingBox.max.y;
  15089. return points;
  15090. }
  15091. /**
  15092. * returns points inside the given profile bounds.
  15093. *
  15094. * start:
  15095. * end:
  15096. * width:
  15097. * depth: search points up to the given octree depth
  15098. * callback: if specified, points are loaded before searching
  15099. *
  15100. *
  15101. */
  15102. getProfile(start, end, width, depth, callback) {
  15103. var request = new Potree.ProfileRequest(start, end, width, depth, callback);
  15104. this.profileRequests.push(request);
  15105. }
  15106. getVisibleExtent() {
  15107. return this.visibleBounds.applyMatrix4(this.matrixWorld);
  15108. }
  15109. intersectsPoint(position) {
  15110. var rootAvailable = this.pcoGeometry.root && this.pcoGeometry.root.geometry;
  15111. if (!rootAvailable) {
  15112. return false;
  15113. }
  15114. if (typeof this.signedDistanceField === "undefined") {
  15115. var resolution = 32;
  15116. var field = new Float32Array(resolution ** 3).fill(Infinity);
  15117. var positions = this.pcoGeometry.root.geometry.attributes.position;
  15118. var boundingBox = this.boundingBox;
  15119. var n = positions.count;
  15120. for (var i = 0; i < n; i = i + 3) {
  15121. var x = positions.array[3 * i + 0];
  15122. var y = positions.array[3 * i + 1];
  15123. var z = positions.array[3 * i + 2];
  15124. var ix = parseInt(Math.min(resolution * (x / boundingBox.max.x), resolution - 1));
  15125. var iy = parseInt(Math.min(resolution * (y / boundingBox.max.y), resolution - 1));
  15126. var iz = parseInt(Math.min(resolution * (z / boundingBox.max.z), resolution - 1));
  15127. var index = ix + iy * resolution + iz * resolution * resolution;
  15128. field[index] = 0;
  15129. }
  15130. var sdf = {
  15131. resolution: resolution,
  15132. field: field
  15133. };
  15134. this.signedDistanceField = sdf;
  15135. }
  15136. {
  15137. var _sdf = this.signedDistanceField;
  15138. var _boundingBox2 = this.boundingBox;
  15139. var toObjectSpace = this.matrixWorld.clone().invert();
  15140. var objPos = position.clone().applyMatrix4(toObjectSpace);
  15141. var _resolution = _sdf.resolution;
  15142. var _ix = parseInt(_resolution * (objPos.x / _boundingBox2.max.x));
  15143. var _iy = parseInt(_resolution * (objPos.y / _boundingBox2.max.y));
  15144. var _iz = parseInt(_resolution * (objPos.z / _boundingBox2.max.z));
  15145. if (_ix < 0 || _iy < 0 || _iz < 0) {
  15146. return false;
  15147. }
  15148. if (_ix >= _resolution || _iy >= _resolution || _iz >= _resolution) {
  15149. return false;
  15150. }
  15151. var _index = _ix + _iy * _resolution + _iz * _resolution * _resolution;
  15152. var value = _sdf.field[_index];
  15153. if (value === 0) {
  15154. return true;
  15155. }
  15156. }
  15157. return false;
  15158. }
  15159. /**
  15160. *
  15161. *
  15162. *
  15163. * params.pickWindowSize: Look for points inside a pixel window of this size.
  15164. * Use odd values: 1, 3, 5, ...
  15165. *
  15166. *
  15167. * TODO: only draw pixels that are actually read with readPixels().
  15168. *
  15169. */
  15170. pick(viewer, camera, ray) {
  15171. var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  15172. var renderer = viewer.renderer;
  15173. var pRenderer = viewer.pRenderer;
  15174. performance.mark("pick-start");
  15175. var getVal = (a, b) => a !== undefined ? a : b;
  15176. var pickWindowSize = getVal(params.pickWindowSize, 65);
  15177. var pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  15178. var size = renderer.getSize(new Vector2());
  15179. var width = Math.ceil(getVal(params.width, size.width));
  15180. var height = Math.ceil(getVal(params.height, size.height));
  15181. var pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  15182. var pointSize = getVal(params.pointSize, this.material.size);
  15183. var nodes = this.nodesOnRay(this.visibleNodes, ray);
  15184. if (nodes.length === 0) {
  15185. return null;
  15186. }
  15187. if (!this.pickState) {
  15188. var scene = new Scene();
  15189. var material = new Potree.PointCloudMaterial();
  15190. material.activeAttributeName = "indices";
  15191. var renderTarget = new WebGLRenderTarget(1, 1, {
  15192. minFilter: LinearFilter,
  15193. magFilter: NearestFilter,
  15194. format: RGBAFormat
  15195. });
  15196. this.pickState = {
  15197. renderTarget: renderTarget,
  15198. material: material,
  15199. scene: scene
  15200. };
  15201. }
  15202. ;
  15203. var pickState = this.pickState;
  15204. var pickMaterial = pickState.material;
  15205. {
  15206. // update pick material
  15207. pickMaterial.pointSizeType = pointSizeType;
  15208. //pickMaterial.shape = this.material.shape;
  15209. pickMaterial.shape = Potree.PointShape.PARABOLOID;
  15210. pickMaterial.uniforms.uFilterReturnNumberRange.value = this.material.uniforms.uFilterReturnNumberRange.value;
  15211. pickMaterial.uniforms.uFilterNumberOfReturnsRange.value = this.material.uniforms.uFilterNumberOfReturnsRange.value;
  15212. pickMaterial.uniforms.uFilterGPSTimeClipRange.value = this.material.uniforms.uFilterGPSTimeClipRange.value;
  15213. pickMaterial.uniforms.uFilterPointSourceIDClipRange.value = this.material.uniforms.uFilterPointSourceIDClipRange.value;
  15214. pickMaterial.activeAttributeName = "indices";
  15215. pickMaterial.size = pointSize;
  15216. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  15217. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  15218. pickMaterial.classification = this.material.classification;
  15219. pickMaterial.recomputeClassification();
  15220. if (params.pickClipped) {
  15221. pickMaterial.clipBoxes = this.material.clipBoxes;
  15222. pickMaterial.uniforms.clipBoxes = this.material.uniforms.clipBoxes;
  15223. if (this.material.clipTask === Potree.ClipTask.HIGHLIGHT) {
  15224. pickMaterial.clipTask = Potree.ClipTask.NONE;
  15225. } else {
  15226. pickMaterial.clipTask = this.material.clipTask;
  15227. }
  15228. pickMaterial.clipMethod = this.material.clipMethod;
  15229. } else {
  15230. pickMaterial.clipBoxes = [];
  15231. }
  15232. this.updateMaterial(pickMaterial, nodes, camera, renderer);
  15233. }
  15234. pickState.renderTarget.setSize(width, height);
  15235. var pixelPos = new Vector2(params.x, params.y);
  15236. var gl = renderer.getContext();
  15237. gl.enable(gl.SCISSOR_TEST);
  15238. gl.scissor(parseInt(pixelPos.x - (pickWindowSize - 1) / 2), parseInt(pixelPos.y - (pickWindowSize - 1) / 2), parseInt(pickWindowSize), parseInt(pickWindowSize));
  15239. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  15240. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  15241. renderer.state.setBlending(NoBlending);
  15242. {
  15243. // RENDER
  15244. renderer.setRenderTarget(pickState.renderTarget);
  15245. gl.clearColor(0, 0, 0, 0);
  15246. renderer.clear(true, true, true);
  15247. var tmp = this.material;
  15248. this.material = pickMaterial;
  15249. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  15250. this.material = tmp;
  15251. }
  15252. var clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  15253. var x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  15254. var y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  15255. var w = parseInt(Math.min(x + pickWindowSize, width) - x);
  15256. var h = parseInt(Math.min(y + pickWindowSize, height) - y);
  15257. var pixelCount = w * h;
  15258. var buffer = new Uint8Array(4 * pixelCount);
  15259. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
  15260. renderer.setRenderTarget(null);
  15261. renderer.state.reset();
  15262. renderer.setScissorTest(false);
  15263. gl.disable(gl.SCISSOR_TEST);
  15264. var pixels = buffer;
  15265. var ibuffer = new Uint32Array(buffer.buffer);
  15266. // find closest hit inside pixelWindow boundaries
  15267. var min = Number.MAX_VALUE;
  15268. var hits = [];
  15269. for (var u = 0; u < pickWindowSize; u++) {
  15270. for (var v = 0; v < pickWindowSize; v++) {
  15271. var offset = u + v * pickWindowSize;
  15272. var distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  15273. var pcIndex = pixels[4 * offset + 3];
  15274. pixels[4 * offset + 3] = 0;
  15275. var pIndex = ibuffer[offset];
  15276. if (!(pcIndex === 0 && pIndex === 0) && pcIndex !== undefined && pIndex !== undefined) {
  15277. var hit = {
  15278. pIndex: pIndex,
  15279. pcIndex: pcIndex,
  15280. distanceToCenter: distance
  15281. };
  15282. if (params.all) {
  15283. hits.push(hit);
  15284. } else {
  15285. if (hits.length > 0) {
  15286. if (distance < hits[0].distanceToCenter) {
  15287. hits[0] = hit;
  15288. }
  15289. } else {
  15290. hits.push(hit);
  15291. }
  15292. }
  15293. }
  15294. }
  15295. }
  15296. // { // DEBUG: show panel with pick image
  15297. // let img = Utils.pixelsArrayToImage(buffer, w, h);
  15298. // let screenshot = img.src;
  15299. // if(!this.debugDIV){
  15300. // this.debugDIV = $(`
  15301. // <div id="pickDebug"
  15302. // style="position: absolute;
  15303. // right: 400px; width: 300px;
  15304. // bottom: 44px; width: 300px;
  15305. // z-index: 1000;
  15306. // "></div>`);
  15307. // $(document.body).append(this.debugDIV);
  15308. // }
  15309. // this.debugDIV.empty();
  15310. // this.debugDIV.append($(`<img src="${screenshot}"
  15311. // style="transform: scaleY(-1); width: 300px"/>`));
  15312. // //$(this.debugWindow.document).append($(`<img src="${screenshot}"/>`));
  15313. // //this.debugWindow.document.write('<img src="'+screenshot+'"/>');
  15314. // }
  15315. for (var _hit of hits) {
  15316. var point = {};
  15317. if (!nodes[_hit.pcIndex]) {
  15318. return null;
  15319. }
  15320. var node = nodes[_hit.pcIndex];
  15321. var pc = node.sceneNode;
  15322. var geometry = node.geometryNode.geometry;
  15323. var _loop2 = function _loop2() {
  15324. var attribute = geometry.attributes[attributeName];
  15325. if (attributeName === 'position') {
  15326. var _x = attribute.array[3 * _hit.pIndex + 0];
  15327. var _y = attribute.array[3 * _hit.pIndex + 1];
  15328. var z = attribute.array[3 * _hit.pIndex + 2];
  15329. var position = new Vector3(_x, _y, z);
  15330. position.applyMatrix4(pc.matrixWorld);
  15331. point[attributeName] = position;
  15332. } else if (attributeName === 'indices') {} else {
  15333. var values = attribute.array.slice(attribute.itemSize * _hit.pIndex, attribute.itemSize * (_hit.pIndex + 1));
  15334. if (attribute.potree) {
  15335. var {
  15336. scale,
  15337. offset: _offset
  15338. } = attribute.potree;
  15339. values = values.map(v => v / scale + _offset);
  15340. }
  15341. point[attributeName] = values;
  15342. //debugger;
  15343. //if (values.itemSize === 1) {
  15344. // point[attribute.name] = values.array[hit.pIndex];
  15345. //} else {
  15346. // let value = [];
  15347. // for (let j = 0; j < values.itemSize; j++) {
  15348. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  15349. // }
  15350. // point[attribute.name] = value;
  15351. //}
  15352. }
  15353. };
  15354. for (var attributeName in geometry.attributes) {
  15355. _loop2();
  15356. }
  15357. _hit.point = point;
  15358. }
  15359. performance.mark("pick-end");
  15360. performance.measure("pick", "pick-start", "pick-end");
  15361. if (params.all) {
  15362. return hits.map(hit => hit.point);
  15363. } else {
  15364. if (hits.length === 0) {
  15365. return null;
  15366. } else {
  15367. return hits[0].point;
  15368. //let sorted = hits.sort( (a, b) => a.distanceToCenter - b.distanceToCenter);
  15369. //return sorted[0].point;
  15370. }
  15371. }
  15372. }
  15373. *getFittedBoxGen(boxNode) {
  15374. var start = performance.now();
  15375. var shrinkedLocalBounds = new Box3();
  15376. var worldToBox = boxNode.matrixWorld.clone().invert();
  15377. for (var node of this.visibleNodes) {
  15378. if (!node.sceneNode) {
  15379. continue;
  15380. }
  15381. var buffer = node.geometryNode.buffer;
  15382. var posOffset = buffer.offset("position");
  15383. var stride = buffer.stride;
  15384. var view = new DataView(buffer.data);
  15385. var objectToBox = new Matrix4().multiplyMatrices(worldToBox, node.sceneNode.matrixWorld);
  15386. var pos = new Vector4();
  15387. for (var i = 0; i < buffer.numElements; i++) {
  15388. var x = view.getFloat32(i * stride + posOffset + 0, true);
  15389. var y = view.getFloat32(i * stride + posOffset + 4, true);
  15390. var z = view.getFloat32(i * stride + posOffset + 8, true);
  15391. pos.set(x, y, z, 1);
  15392. pos.applyMatrix4(objectToBox);
  15393. if (-0.5 < pos.x && pos.x < 0.5) {
  15394. if (-0.5 < pos.y && pos.y < 0.5) {
  15395. if (-0.5 < pos.z && pos.z < 0.5) {
  15396. shrinkedLocalBounds.expandByPoint(pos);
  15397. }
  15398. }
  15399. }
  15400. }
  15401. yield;
  15402. }
  15403. var fittedPosition = shrinkedLocalBounds.getCenter(new Vector3()).applyMatrix4(boxNode.matrixWorld);
  15404. var fitted = new Object3D();
  15405. fitted.position.copy(fittedPosition);
  15406. fitted.scale.copy(boxNode.scale);
  15407. fitted.rotation.copy(boxNode.rotation);
  15408. var ds = new Vector3().subVectors(shrinkedLocalBounds.max, shrinkedLocalBounds.min);
  15409. fitted.scale.multiply(ds);
  15410. var duration = performance.now() - start;
  15411. console.log("duration: ", duration);
  15412. yield fitted;
  15413. }
  15414. getFittedBox(boxNode) {
  15415. var maxLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Infinity;
  15416. maxLevel = Infinity;
  15417. var start = performance.now();
  15418. var shrinkedLocalBounds = new Box3();
  15419. var worldToBox = boxNode.matrixWorld.clone().invert();
  15420. for (var node of this.visibleNodes) {
  15421. if (!node.sceneNode || node.getLevel() > maxLevel) {
  15422. continue;
  15423. }
  15424. var buffer = node.geometryNode.buffer;
  15425. var posOffset = buffer.offset("position");
  15426. var stride = buffer.stride;
  15427. var view = new DataView(buffer.data);
  15428. var objectToBox = new Matrix4().multiplyMatrices(worldToBox, node.sceneNode.matrixWorld);
  15429. var pos = new Vector4();
  15430. for (var i = 0; i < buffer.numElements; i++) {
  15431. var x = view.getFloat32(i * stride + posOffset + 0, true);
  15432. var y = view.getFloat32(i * stride + posOffset + 4, true);
  15433. var z = view.getFloat32(i * stride + posOffset + 8, true);
  15434. pos.set(x, y, z, 1);
  15435. pos.applyMatrix4(objectToBox);
  15436. if (-0.5 < pos.x && pos.x < 0.5) {
  15437. if (-0.5 < pos.y && pos.y < 0.5) {
  15438. if (-0.5 < pos.z && pos.z < 0.5) {
  15439. shrinkedLocalBounds.expandByPoint(pos);
  15440. }
  15441. }
  15442. }
  15443. }
  15444. }
  15445. var fittedPosition = shrinkedLocalBounds.getCenter(new Vector3()).applyMatrix4(boxNode.matrixWorld);
  15446. var fitted = new Object3D();
  15447. fitted.position.copy(fittedPosition);
  15448. fitted.scale.copy(boxNode.scale);
  15449. fitted.rotation.copy(boxNode.rotation);
  15450. var ds = new Vector3().subVectors(shrinkedLocalBounds.max, shrinkedLocalBounds.min);
  15451. fitted.scale.multiply(ds);
  15452. var duration = performance.now() - start;
  15453. console.log("duration: ", duration);
  15454. return fitted;
  15455. }
  15456. get progress() {
  15457. return this.visibleNodes.length / this.visibleGeometry.length;
  15458. }
  15459. find(name) {
  15460. var node = null;
  15461. for (var char of name) {
  15462. if (char === "r") {
  15463. node = this.root;
  15464. } else {
  15465. node = node.children[char];
  15466. }
  15467. }
  15468. return node;
  15469. }
  15470. get visible() {
  15471. return this._visible;
  15472. }
  15473. set visible(value) {
  15474. if (value !== this._visible) {
  15475. this._visible = value;
  15476. this.dispatchEvent({
  15477. type: 'visibility_changed',
  15478. pointcloud: this
  15479. });
  15480. }
  15481. }
  15482. }
  15483. class PointCloudArena4DNode extends PointCloudTreeNode {
  15484. constructor() {
  15485. super();
  15486. this.left = null;
  15487. this.right = null;
  15488. this.sceneNode = null;
  15489. this.kdtree = null;
  15490. }
  15491. getNumPoints() {
  15492. return this.geometryNode.numPoints;
  15493. }
  15494. isLoaded() {
  15495. return true;
  15496. }
  15497. isTreeNode() {
  15498. return true;
  15499. }
  15500. isGeometryNode() {
  15501. return false;
  15502. }
  15503. getLevel() {
  15504. return this.geometryNode.level;
  15505. }
  15506. getBoundingSphere() {
  15507. return this.geometryNode.boundingSphere;
  15508. }
  15509. getBoundingBox() {
  15510. return this.geometryNode.boundingBox;
  15511. }
  15512. toTreeNode(child) {
  15513. var geometryNode = null;
  15514. if (this.left === child) {
  15515. geometryNode = this.left;
  15516. } else if (this.right === child) {
  15517. geometryNode = this.right;
  15518. }
  15519. if (!geometryNode.loaded) {
  15520. return;
  15521. }
  15522. var node = new PointCloudArena4DNode();
  15523. var sceneNode = PointCloud(geometryNode.geometry, this.kdtree.material);
  15524. sceneNode.visible = false;
  15525. node.kdtree = this.kdtree;
  15526. node.geometryNode = geometryNode;
  15527. node.sceneNode = sceneNode;
  15528. node.parent = this;
  15529. node.left = this.geometryNode.left;
  15530. node.right = this.geometryNode.right;
  15531. }
  15532. getChildren() {
  15533. var children = [];
  15534. if (this.left) {
  15535. children.push(this.left);
  15536. }
  15537. if (this.right) {
  15538. children.push(this.right);
  15539. }
  15540. return children;
  15541. }
  15542. }
  15543. ;
  15544. class PointCloudArena4D$1 extends PointCloudTree {
  15545. constructor(geometry) {
  15546. super();
  15547. this.root = null;
  15548. if (geometry.root) {
  15549. this.root = geometry.root;
  15550. } else {
  15551. geometry.addEventListener('hierarchy_loaded', () => {
  15552. this.root = geometry.root;
  15553. });
  15554. }
  15555. this.visiblePointsTarget = 2 * 1000 * 1000;
  15556. this.minimumNodePixelSize = 150;
  15557. this.position.sub(geometry.offset);
  15558. this.updateMatrix();
  15559. this.numVisibleNodes = 0;
  15560. this.numVisiblePoints = 0;
  15561. this.boundingBoxNodes = [];
  15562. this.loadQueue = [];
  15563. this.visibleNodes = [];
  15564. this.pcoGeometry = geometry;
  15565. this.boundingBox = this.pcoGeometry.boundingBox;
  15566. this.boundingSphere = this.pcoGeometry.boundingSphere;
  15567. this.material = new PointCloudMaterial$1({
  15568. vertexColors: VertexColors,
  15569. size: 0.05,
  15570. treeType: TreeType.KDTREE
  15571. });
  15572. this.material.sizeType = PointSizeType.ATTENUATED;
  15573. this.material.size = 0.05;
  15574. this.profileRequests = [];
  15575. this.name = '';
  15576. }
  15577. getBoundingBoxWorld() {
  15578. this.updateMatrixWorld(true);
  15579. var box = this.boundingBox;
  15580. var transform = this.matrixWorld;
  15581. var tBox = Utils.computeTransformedBoundingBox(box, transform);
  15582. return tBox;
  15583. }
  15584. setName(name) {
  15585. if (this.name !== name) {
  15586. this.name = name;
  15587. this.dispatchEvent({
  15588. type: 'name_changed',
  15589. name: name,
  15590. pointcloud: this
  15591. });
  15592. }
  15593. }
  15594. getName() {
  15595. return this.name;
  15596. }
  15597. getLevel() {
  15598. return this.level;
  15599. }
  15600. toTreeNode(geometryNode, parent) {
  15601. var node = new PointCloudArena4DNode();
  15602. var sceneNode = new Points(geometryNode.geometry, this.material);
  15603. sceneNode.frustumCulled = false;
  15604. sceneNode.onBeforeRender = (_this, scene, camera, geometry, material, group) => {
  15605. if (material.program) {
  15606. _this.getContext().useProgram(material.program.program);
  15607. if (material.program.getUniforms().map.level) {
  15608. var level = geometryNode.getLevel();
  15609. material.uniforms.level.value = level;
  15610. material.program.getUniforms().map.level.setValue(_this.getContext(), level);
  15611. }
  15612. if (this.visibleNodeTextureOffsets && material.program.getUniforms().map.vnStart) {
  15613. var vnStart = this.visibleNodeTextureOffsets.get(node);
  15614. material.uniforms.vnStart.value = vnStart;
  15615. material.program.getUniforms().map.vnStart.setValue(_this.getContext(), vnStart);
  15616. }
  15617. if (material.program.getUniforms().map.pcIndex) {
  15618. var i = node.pcIndex ? node.pcIndex : this.visibleNodes.indexOf(node);
  15619. material.uniforms.pcIndex.value = i;
  15620. material.program.getUniforms().map.pcIndex.setValue(_this.getContext(), i);
  15621. }
  15622. }
  15623. };
  15624. node.geometryNode = geometryNode;
  15625. node.sceneNode = sceneNode;
  15626. node.pointcloud = this;
  15627. node.left = geometryNode.left;
  15628. node.right = geometryNode.right;
  15629. if (!parent) {
  15630. this.root = node;
  15631. this.add(sceneNode);
  15632. } else {
  15633. parent.sceneNode.add(sceneNode);
  15634. if (parent.left === geometryNode) {
  15635. parent.left = node;
  15636. } else if (parent.right === geometryNode) {
  15637. parent.right = node;
  15638. }
  15639. }
  15640. var disposeListener = function disposeListener() {
  15641. parent.sceneNode.remove(node.sceneNode);
  15642. if (parent.left === node) {
  15643. parent.left = geometryNode;
  15644. } else if (parent.right === node) {
  15645. parent.right = geometryNode;
  15646. }
  15647. };
  15648. geometryNode.oneTimeDisposeHandlers.push(disposeListener);
  15649. return node;
  15650. }
  15651. updateMaterial(material, visibleNodes, camera, renderer) {
  15652. material.fov = camera.fov * (Math.PI / 180);
  15653. material.screenWidth = renderer.domElement.clientWidth;
  15654. material.screenHeight = renderer.domElement.clientHeight;
  15655. material.spacing = this.pcoGeometry.spacing;
  15656. material.near = camera.near;
  15657. material.far = camera.far;
  15658. // reduce shader source updates by setting maxLevel slightly higher than actually necessary
  15659. if (this.maxLevel > material.levels) {
  15660. material.levels = this.maxLevel + 2;
  15661. }
  15662. // material.uniforms.octreeSize.value = this.boundingBox.size().x;
  15663. var bbSize = this.boundingBox.getSize(new Vector3());
  15664. material.bbSize = [bbSize.x, bbSize.y, bbSize.z];
  15665. }
  15666. updateVisibleBounds() {}
  15667. hideDescendants(object) {
  15668. var stack = [];
  15669. for (var i = 0; i < object.children.length; i++) {
  15670. var child = object.children[i];
  15671. if (child.visible) {
  15672. stack.push(child);
  15673. }
  15674. }
  15675. while (stack.length > 0) {
  15676. var _child = stack.shift();
  15677. _child.visible = false;
  15678. if (_child.boundingBoxNode) {
  15679. _child.boundingBoxNode.visible = false;
  15680. }
  15681. for (var _i = 0; _i < _child.children.length; _i++) {
  15682. var childOfChild = _child.children[_i];
  15683. if (childOfChild.visible) {
  15684. stack.push(childOfChild);
  15685. }
  15686. }
  15687. }
  15688. }
  15689. updateMatrixWorld(force) {
  15690. // node.matrixWorld.multiplyMatrices( node.parent.matrixWorld, node.matrix );
  15691. if (this.matrixAutoUpdate === true) this.updateMatrix();
  15692. if (this.matrixWorldNeedsUpdate === true || force === true) {
  15693. if (this.parent === undefined) {
  15694. this.matrixWorld.copy(this.matrix);
  15695. } else {
  15696. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
  15697. }
  15698. this.matrixWorldNeedsUpdate = false;
  15699. force = true;
  15700. }
  15701. }
  15702. nodesOnRay(nodes, ray) {
  15703. var nodesOnRay = [];
  15704. var _ray = ray.clone();
  15705. for (var i = 0; i < nodes.length; i++) {
  15706. var node = nodes[i];
  15707. var sphere = node.getBoundingSphere().clone().applyMatrix4(node.sceneNode.matrixWorld);
  15708. // TODO Unused: let box = node.getBoundingBox().clone().applyMatrix4(node.sceneNode.matrixWorld);
  15709. if (_ray.intersectsSphere(sphere)) {
  15710. nodesOnRay.push(node);
  15711. }
  15712. // if(_ray.isIntersectionBox(box)){
  15713. // nodesOnRay.push(node);
  15714. // }
  15715. }
  15716. return nodesOnRay;
  15717. }
  15718. pick(viewer, camera, ray) {
  15719. var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  15720. var renderer = viewer.renderer;
  15721. var pRenderer = viewer.pRenderer;
  15722. performance.mark("pick-start");
  15723. var getVal = (a, b) => a !== undefined ? a : b;
  15724. var pickWindowSize = getVal(params.pickWindowSize, 17);
  15725. var pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  15726. var size = renderer.getSize(new Vector2());
  15727. var width = Math.ceil(getVal(params.width, size.width));
  15728. var height = Math.ceil(getVal(params.height, size.height));
  15729. var pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  15730. var pointSize = getVal(params.pointSize, this.material.size);
  15731. var nodes = this.nodesOnRay(this.visibleNodes, ray);
  15732. if (nodes.length === 0) {
  15733. return null;
  15734. }
  15735. if (!this.pickState) {
  15736. var scene = new Scene();
  15737. var material = new PointCloudMaterial$1();
  15738. material.activeAttributeName = "indices";
  15739. var renderTarget = new WebGLRenderTarget(1, 1, {
  15740. minFilter: LinearFilter,
  15741. magFilter: NearestFilter,
  15742. format: RGBAFormat
  15743. });
  15744. this.pickState = {
  15745. renderTarget: renderTarget,
  15746. material: material,
  15747. scene: scene
  15748. };
  15749. }
  15750. ;
  15751. var pickState = this.pickState;
  15752. var pickMaterial = pickState.material;
  15753. {
  15754. // update pick material
  15755. pickMaterial.pointSizeType = pointSizeType;
  15756. pickMaterial.shape = this.material.shape;
  15757. pickMaterial.size = pointSize;
  15758. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  15759. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  15760. pickMaterial.classification = this.material.classification;
  15761. if (params.pickClipped) {
  15762. pickMaterial.clipBoxes = this.material.clipBoxes;
  15763. if (this.material.clipTask === ClipTask.HIGHLIGHT) {
  15764. pickMaterial.clipTask = ClipTask.NONE;
  15765. } else {
  15766. pickMaterial.clipTask = this.material.clipTask;
  15767. }
  15768. } else {
  15769. pickMaterial.clipBoxes = [];
  15770. }
  15771. this.updateMaterial(pickMaterial, nodes, camera, renderer);
  15772. }
  15773. pickState.renderTarget.setSize(width, height);
  15774. var pixelPos = new Vector2(params.x, params.y);
  15775. var gl = renderer.getContext();
  15776. gl.enable(gl.SCISSOR_TEST);
  15777. gl.scissor(parseInt(pixelPos.x - (pickWindowSize - 1) / 2), parseInt(pixelPos.y - (pickWindowSize - 1) / 2), parseInt(pickWindowSize), parseInt(pickWindowSize));
  15778. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  15779. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  15780. renderer.state.setBlending(NoBlending);
  15781. renderer.clearTarget(pickState.renderTarget, true, true, true);
  15782. {
  15783. // RENDER
  15784. renderer.setRenderTarget(pickState.renderTarget);
  15785. gl.clearColor(0, 0, 0, 0);
  15786. renderer.clearTarget(pickState.renderTarget, true, true, true);
  15787. var tmp = this.material;
  15788. this.material = pickMaterial;
  15789. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  15790. this.material = tmp;
  15791. }
  15792. var clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  15793. var x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  15794. var y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  15795. var w = parseInt(Math.min(x + pickWindowSize, width) - x);
  15796. var h = parseInt(Math.min(y + pickWindowSize, height) - y);
  15797. var pixelCount = w * h;
  15798. var buffer = new Uint8Array(4 * pixelCount);
  15799. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
  15800. renderer.setRenderTarget(null);
  15801. renderer.state.reset();
  15802. renderer.setScissorTest(false);
  15803. gl.disable(gl.SCISSOR_TEST);
  15804. var pixels = buffer;
  15805. var ibuffer = new Uint32Array(buffer.buffer);
  15806. // find closest hit inside pixelWindow boundaries
  15807. var min = Number.MAX_VALUE;
  15808. var hits = [];
  15809. for (var u = 0; u < pickWindowSize; u++) {
  15810. for (var v = 0; v < pickWindowSize; v++) {
  15811. var offset = u + v * pickWindowSize;
  15812. var distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  15813. var pcIndex = pixels[4 * offset + 3];
  15814. pixels[4 * offset + 3] = 0;
  15815. var pIndex = ibuffer[offset];
  15816. if (!(pcIndex === 0 && pIndex === 0) && pcIndex !== undefined && pIndex !== undefined) {
  15817. var hit = {
  15818. pIndex: pIndex,
  15819. pcIndex: pcIndex,
  15820. distanceToCenter: distance
  15821. };
  15822. if (params.all) {
  15823. hits.push(hit);
  15824. } else {
  15825. if (hits.length > 0) {
  15826. if (distance < hits[0].distanceToCenter) {
  15827. hits[0] = hit;
  15828. }
  15829. } else {
  15830. hits.push(hit);
  15831. }
  15832. }
  15833. }
  15834. }
  15835. }
  15836. for (var _hit of hits) {
  15837. var point = {};
  15838. if (!nodes[_hit.pcIndex]) {
  15839. return null;
  15840. }
  15841. var node = nodes[_hit.pcIndex];
  15842. var pc = node.sceneNode;
  15843. var geometry = node.geometryNode.geometry;
  15844. for (var attributeName in geometry.attributes) {
  15845. var attribute = geometry.attributes[attributeName];
  15846. if (attributeName === 'position') {
  15847. var _x = attribute.array[3 * _hit.pIndex + 0];
  15848. var _y = attribute.array[3 * _hit.pIndex + 1];
  15849. var z = attribute.array[3 * _hit.pIndex + 2];
  15850. var position = new Vector3(_x, _y, z);
  15851. position.applyMatrix4(pc.matrixWorld);
  15852. point[attributeName] = position;
  15853. } else if (attributeName === 'indices') {} else {
  15854. //if (values.itemSize === 1) {
  15855. // point[attribute.name] = values.array[hit.pIndex];
  15856. //} else {
  15857. // let value = [];
  15858. // for (let j = 0; j < values.itemSize; j++) {
  15859. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  15860. // }
  15861. // point[attribute.name] = value;
  15862. //}
  15863. }
  15864. }
  15865. _hit.point = point;
  15866. }
  15867. performance.mark("pick-end");
  15868. performance.measure("pick", "pick-start", "pick-end");
  15869. if (params.all) {
  15870. return hits.map(hit => hit.point);
  15871. } else {
  15872. if (hits.length === 0) {
  15873. return null;
  15874. } else {
  15875. return hits[0].point;
  15876. }
  15877. }
  15878. }
  15879. computeVisibilityTextureData(nodes) {
  15880. if (exports.measureTimings) performance.mark("computeVisibilityTextureData-start");
  15881. var data = new Uint8Array(nodes.length * 3);
  15882. var visibleNodeTextureOffsets = new Map();
  15883. // copy array
  15884. nodes = nodes.slice();
  15885. // sort by level and number
  15886. var sort = function sort(a, b) {
  15887. var la = a.geometryNode.level;
  15888. var lb = b.geometryNode.level;
  15889. var na = a.geometryNode.number;
  15890. var nb = b.geometryNode.number;
  15891. if (la !== lb) return la - lb;
  15892. if (na < nb) return -1;
  15893. if (na > nb) return 1;
  15894. return 0;
  15895. };
  15896. nodes.sort(sort);
  15897. var visibleNodeNames = [];
  15898. for (var i = 0; i < nodes.length; i++) {
  15899. visibleNodeNames.push(nodes[i].geometryNode.number);
  15900. }
  15901. for (var _i2 = 0; _i2 < nodes.length; _i2++) {
  15902. var node = nodes[_i2];
  15903. visibleNodeTextureOffsets.set(node, _i2);
  15904. var b1 = 0; // children
  15905. var b2 = 0; // offset to first child
  15906. var b3 = 0; // split
  15907. if (node.geometryNode.left && visibleNodeNames.indexOf(node.geometryNode.left.number) > 0) {
  15908. b1 += 1;
  15909. b2 = visibleNodeNames.indexOf(node.geometryNode.left.number) - _i2;
  15910. }
  15911. if (node.geometryNode.right && visibleNodeNames.indexOf(node.geometryNode.right.number) > 0) {
  15912. b1 += 2;
  15913. b2 = b2 === 0 ? visibleNodeNames.indexOf(node.geometryNode.right.number) - _i2 : b2;
  15914. }
  15915. if (node.geometryNode.split === 'X') {
  15916. b3 = 1;
  15917. } else if (node.geometryNode.split === 'Y') {
  15918. b3 = 2;
  15919. } else if (node.geometryNode.split === 'Z') {
  15920. b3 = 4;
  15921. }
  15922. data[_i2 * 3 + 0] = b1;
  15923. data[_i2 * 3 + 1] = b2;
  15924. data[_i2 * 3 + 2] = b3;
  15925. }
  15926. if (exports.measureTimings) {
  15927. performance.mark("computeVisibilityTextureData-end");
  15928. performance.measure("render.computeVisibilityTextureData", "computeVisibilityTextureData-start", "computeVisibilityTextureData-end");
  15929. }
  15930. return {
  15931. data: data,
  15932. offsets: visibleNodeTextureOffsets
  15933. };
  15934. }
  15935. get progress() {
  15936. if (this.pcoGeometry.root) {
  15937. return exports.numNodesLoading > 0 ? 0 : 1;
  15938. } else {
  15939. return 0;
  15940. }
  15941. }
  15942. }
  15943. ;
  15944. // Copied from three.js: WebGLRenderer.js
  15945. function paramThreeToGL(_gl, p) {
  15946. var extension;
  15947. if (p === RepeatWrapping) return _gl.REPEAT;
  15948. if (p === ClampToEdgeWrapping) return _gl.CLAMP_TO_EDGE;
  15949. if (p === MirroredRepeatWrapping) return _gl.MIRRORED_REPEAT;
  15950. if (p === NearestFilter) return _gl.NEAREST;
  15951. if (p === NearestMipMapNearestFilter) return _gl.NEAREST_MIPMAP_NEAREST;
  15952. if (p === NearestMipMapLinearFilter) return _gl.NEAREST_MIPMAP_LINEAR;
  15953. if (p === LinearFilter) return _gl.LINEAR;
  15954. if (p === LinearMipMapNearestFilter) return _gl.LINEAR_MIPMAP_NEAREST;
  15955. if (p === LinearMipMapLinearFilter) return _gl.LINEAR_MIPMAP_LINEAR;
  15956. if (p === UnsignedByteType) return _gl.UNSIGNED_BYTE;
  15957. if (p === UnsignedShort4444Type) return _gl.UNSIGNED_SHORT_4_4_4_4;
  15958. if (p === UnsignedShort5551Type) return _gl.UNSIGNED_SHORT_5_5_5_1;
  15959. if (p === UnsignedShort565Type) return _gl.UNSIGNED_SHORT_5_6_5;
  15960. if (p === ByteType) return _gl.BYTE;
  15961. if (p === ShortType) return _gl.SHORT;
  15962. if (p === UnsignedShortType) return _gl.UNSIGNED_SHORT;
  15963. if (p === IntType) return _gl.INT;
  15964. if (p === UnsignedIntType) return _gl.UNSIGNED_INT;
  15965. if (p === FloatType) return _gl.FLOAT;
  15966. if (p === HalfFloatType) {
  15967. extension = extensions.get('OES_texture_half_float');
  15968. if (extension !== null) return extension.HALF_FLOAT_OES;
  15969. }
  15970. if (p === AlphaFormat) return _gl.ALPHA;
  15971. if (p === RGBFormat) return _gl.RGB;
  15972. if (p === RGBAFormat) return _gl.RGBA;
  15973. if (p === LuminanceFormat) return _gl.LUMINANCE;
  15974. if (p === LuminanceAlphaFormat) return _gl.LUMINANCE_ALPHA;
  15975. if (p === DepthFormat) return _gl.DEPTH_COMPONENT;
  15976. if (p === DepthStencilFormat) return _gl.DEPTH_STENCIL;
  15977. if (p === AddEquation) return _gl.FUNC_ADD;
  15978. if (p === SubtractEquation) return _gl.FUNC_SUBTRACT;
  15979. if (p === ReverseSubtractEquation) return _gl.FUNC_REVERSE_SUBTRACT;
  15980. if (p === ZeroFactor) return _gl.ZERO;
  15981. if (p === OneFactor) return _gl.ONE;
  15982. if (p === SrcColorFactor) return _gl.SRC_COLOR;
  15983. if (p === OneMinusSrcColorFactor) return _gl.ONE_MINUS_SRC_COLOR;
  15984. if (p === SrcAlphaFactor) return _gl.SRC_ALPHA;
  15985. if (p === OneMinusSrcAlphaFactor) return _gl.ONE_MINUS_SRC_ALPHA;
  15986. if (p === DstAlphaFactor) return _gl.DST_ALPHA;
  15987. if (p === OneMinusDstAlphaFactor) return _gl.ONE_MINUS_DST_ALPHA;
  15988. if (p === DstColorFactor) return _gl.DST_COLOR;
  15989. if (p === OneMinusDstColorFactor) return _gl.ONE_MINUS_DST_COLOR;
  15990. if (p === SrcAlphaSaturateFactor) return _gl.SRC_ALPHA_SATURATE;
  15991. if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
  15992. extension = extensions.get('WEBGL_compressed_texture_s3tc');
  15993. if (extension !== null) {
  15994. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
  15995. if (p === RGBA_S3TC_DXT1_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  15996. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  15997. if (p === RGBA_S3TC_DXT5_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  15998. }
  15999. }
  16000. if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
  16001. extension = extensions.get('WEBGL_compressed_texture_pvrtc');
  16002. if (extension !== null) {
  16003. if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  16004. if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  16005. if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  16006. if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  16007. }
  16008. }
  16009. if (p === RGB_ETC1_Format) {
  16010. extension = extensions.get('WEBGL_compressed_texture_etc1');
  16011. if (extension !== null) return extension.COMPRESSED_RGB_ETC1_WEBGL;
  16012. }
  16013. if (p === MinEquation || p === MaxEquation) {
  16014. extension = extensions.get('EXT_blend_minmax');
  16015. if (extension !== null) {
  16016. if (p === MinEquation) return extension.MIN_EXT;
  16017. if (p === MaxEquation) return extension.MAX_EXT;
  16018. }
  16019. }
  16020. if (p === UnsignedInt248Type) {
  16021. extension = extensions.get('WEBGL_depth_texture');
  16022. if (extension !== null) return extension.UNSIGNED_INT_24_8_WEBGL;
  16023. }
  16024. return 0;
  16025. }
  16026. ;
  16027. var attributeLocations = {
  16028. "position": {
  16029. name: "position",
  16030. location: 0
  16031. },
  16032. "color": {
  16033. name: "color",
  16034. location: 1
  16035. },
  16036. "rgba": {
  16037. name: "color",
  16038. location: 1
  16039. },
  16040. "intensity": {
  16041. name: "intensity",
  16042. location: 2
  16043. },
  16044. "classification": {
  16045. name: "classification",
  16046. location: 3
  16047. },
  16048. "returnNumber": {
  16049. name: "returnNumber",
  16050. location: 4
  16051. },
  16052. "return number": {
  16053. name: "returnNumber",
  16054. location: 4
  16055. },
  16056. "returns": {
  16057. name: "returnNumber",
  16058. location: 4
  16059. },
  16060. "numberOfReturns": {
  16061. name: "numberOfReturns",
  16062. location: 5
  16063. },
  16064. "number of returns": {
  16065. name: "numberOfReturns",
  16066. location: 5
  16067. },
  16068. "pointSourceID": {
  16069. name: "pointSourceID",
  16070. location: 6
  16071. },
  16072. "source id": {
  16073. name: "pointSourceID",
  16074. location: 6
  16075. },
  16076. "point source id": {
  16077. name: "pointSourceID",
  16078. location: 6
  16079. },
  16080. "indices": {
  16081. name: "indices",
  16082. location: 7
  16083. },
  16084. "normal": {
  16085. name: "normal",
  16086. location: 8
  16087. },
  16088. "spacing": {
  16089. name: "spacing",
  16090. location: 9
  16091. },
  16092. "gps-time": {
  16093. name: "gpsTime",
  16094. location: 10
  16095. },
  16096. "aExtra": {
  16097. name: "aExtra",
  16098. location: 11
  16099. }
  16100. };
  16101. class Shader {
  16102. constructor(gl, name, vsSource, fsSource) {
  16103. this.gl = gl;
  16104. this.name = name;
  16105. this.vsSource = vsSource;
  16106. this.fsSource = fsSource;
  16107. this.cache = new Map();
  16108. this.vs = null;
  16109. this.fs = null;
  16110. this.program = null;
  16111. this.uniformLocations = {};
  16112. this.attributeLocations = {};
  16113. this.uniformBlockIndices = {};
  16114. this.uniformBlocks = {};
  16115. this.uniforms = {};
  16116. this.update(vsSource, fsSource);
  16117. }
  16118. update(vsSource, fsSource) {
  16119. this.vsSource = vsSource;
  16120. this.fsSource = fsSource;
  16121. this.linkProgram();
  16122. }
  16123. compileShader(shader, source) {
  16124. var gl = this.gl;
  16125. gl.shaderSource(shader, source);
  16126. gl.compileShader(shader);
  16127. var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  16128. if (!success) {
  16129. var info = gl.getShaderInfoLog(shader);
  16130. var numberedSource = source.split("\n").map((a, i) => "".concat(i + 1).padEnd(5) + a).join("\n");
  16131. throw "could not compile shader ".concat(this.name, ": ").concat(info, ", \n").concat(numberedSource);
  16132. }
  16133. }
  16134. linkProgram() {
  16135. var tStart = performance.now();
  16136. var gl = this.gl;
  16137. this.uniformLocations = {};
  16138. this.attributeLocations = {};
  16139. this.uniforms = {};
  16140. gl.useProgram(null);
  16141. var cached = this.cache.get("".concat(this.vsSource, ", ").concat(this.fsSource));
  16142. if (cached) {
  16143. this.program = cached.program;
  16144. this.vs = cached.vs;
  16145. this.fs = cached.fs;
  16146. this.attributeLocations = cached.attributeLocations;
  16147. this.uniformLocations = cached.uniformLocations;
  16148. this.uniformBlocks = cached.uniformBlocks;
  16149. this.uniforms = cached.uniforms;
  16150. return;
  16151. } else {
  16152. this.vs = gl.createShader(gl.VERTEX_SHADER);
  16153. this.fs = gl.createShader(gl.FRAGMENT_SHADER);
  16154. this.program = gl.createProgram();
  16155. for (var name of Object.keys(attributeLocations)) {
  16156. var location = attributeLocations[name].location;
  16157. var glslName = attributeLocations[name].name;
  16158. gl.bindAttribLocation(this.program, location, glslName);
  16159. }
  16160. this.compileShader(this.vs, this.vsSource);
  16161. this.compileShader(this.fs, this.fsSource);
  16162. var program = this.program;
  16163. gl.attachShader(program, this.vs);
  16164. gl.attachShader(program, this.fs);
  16165. gl.linkProgram(program);
  16166. gl.detachShader(program, this.vs);
  16167. gl.detachShader(program, this.fs);
  16168. var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  16169. if (!success) {
  16170. var info = gl.getProgramInfoLog(program);
  16171. throw "could not link program ".concat(this.name, ": ").concat(info);
  16172. }
  16173. {
  16174. // attribute locations
  16175. var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
  16176. for (var i = 0; i < numAttributes; i++) {
  16177. var attribute = gl.getActiveAttrib(program, i);
  16178. var _location = gl.getAttribLocation(program, attribute.name);
  16179. this.attributeLocations[attribute.name] = _location;
  16180. }
  16181. }
  16182. {
  16183. // uniform locations
  16184. var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  16185. for (var _i = 0; _i < numUniforms; _i++) {
  16186. var uniform = gl.getActiveUniform(program, _i);
  16187. var _location2 = gl.getUniformLocation(program, uniform.name);
  16188. this.uniformLocations[uniform.name] = _location2;
  16189. this.uniforms[uniform.name] = {
  16190. location: _location2,
  16191. value: null
  16192. };
  16193. }
  16194. }
  16195. // uniform blocks
  16196. if (typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext) {
  16197. var numBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  16198. for (var _i2 = 0; _i2 < numBlocks; _i2++) {
  16199. var blockName = gl.getActiveUniformBlockName(program, _i2);
  16200. var blockIndex = gl.getUniformBlockIndex(program, blockName);
  16201. this.uniformBlockIndices[blockName] = blockIndex;
  16202. gl.uniformBlockBinding(program, blockIndex, blockIndex);
  16203. var dataSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
  16204. var uBuffer = gl.createBuffer();
  16205. gl.bindBuffer(gl.UNIFORM_BUFFER, uBuffer);
  16206. gl.bufferData(gl.UNIFORM_BUFFER, dataSize, gl.DYNAMIC_READ);
  16207. gl.bindBufferBase(gl.UNIFORM_BUFFER, blockIndex, uBuffer);
  16208. gl.bindBuffer(gl.UNIFORM_BUFFER, null);
  16209. this.uniformBlocks[blockName] = {
  16210. name: blockName,
  16211. index: blockIndex,
  16212. dataSize: dataSize,
  16213. buffer: uBuffer
  16214. };
  16215. }
  16216. }
  16217. var _cached = {
  16218. program: this.program,
  16219. vs: this.vs,
  16220. fs: this.fs,
  16221. attributeLocations: this.attributeLocations,
  16222. uniformLocations: this.uniformLocations,
  16223. uniforms: this.uniforms,
  16224. uniformBlocks: this.uniformBlocks
  16225. };
  16226. this.cache.set("".concat(this.vsSource, ", ").concat(this.fsSource), _cached);
  16227. }
  16228. var tEnd = performance.now();
  16229. var duration = tEnd - tStart;
  16230. console.log("shader compile duration: ".concat(duration.toFixed(3)));
  16231. }
  16232. setUniformMatrix4(name, value) {
  16233. var gl = this.gl;
  16234. var location = this.uniformLocations[name];
  16235. if (location == null) {
  16236. return;
  16237. }
  16238. var tmp = new Float32Array(value.elements);
  16239. gl.uniformMatrix4fv(location, false, tmp);
  16240. }
  16241. setUniform1f(name, value) {
  16242. var gl = this.gl;
  16243. var uniform = this.uniforms[name];
  16244. if (uniform === undefined) {
  16245. return;
  16246. }
  16247. if (uniform.value === value) {
  16248. return;
  16249. }
  16250. uniform.value = value;
  16251. gl.uniform1f(uniform.location, value);
  16252. }
  16253. setUniformBoolean(name, value) {
  16254. var gl = this.gl;
  16255. var uniform = this.uniforms[name];
  16256. if (uniform === undefined) {
  16257. return;
  16258. }
  16259. if (uniform.value === value) {
  16260. return;
  16261. }
  16262. uniform.value = value;
  16263. gl.uniform1i(uniform.location, value);
  16264. }
  16265. setUniformTexture(name, value) {
  16266. var gl = this.gl;
  16267. var location = this.uniformLocations[name];
  16268. if (location == null) {
  16269. return;
  16270. }
  16271. gl.uniform1i(location, value);
  16272. }
  16273. setUniform2f(name, value) {
  16274. var gl = this.gl;
  16275. var location = this.uniformLocations[name];
  16276. if (location == null) {
  16277. return;
  16278. }
  16279. gl.uniform2f(location, value[0], value[1]);
  16280. }
  16281. setUniform3f(name, value) {
  16282. var gl = this.gl;
  16283. var location = this.uniformLocations[name];
  16284. if (location == null) {
  16285. return;
  16286. }
  16287. gl.uniform3f(location, value[0], value[1], value[2]);
  16288. }
  16289. setUniform(name, value) {
  16290. if (value.constructor === Matrix4) {
  16291. this.setUniformMatrix4(name, value);
  16292. } else if (typeof value === "number") {
  16293. this.setUniform1f(name, value);
  16294. } else if (typeof value === "boolean") {
  16295. this.setUniformBoolean(name, value);
  16296. } else if (value instanceof WebGLTexture) {
  16297. this.setUniformTexture(name, value);
  16298. } else if (value instanceof Array) {
  16299. if (value.length === 2) {
  16300. this.setUniform2f(name, value);
  16301. } else if (value.length === 3) {
  16302. this.setUniform3f(name, value);
  16303. }
  16304. } else {
  16305. console.error("unhandled uniform type: ", name, value);
  16306. }
  16307. }
  16308. setUniform1i(name, value) {
  16309. var gl = this.gl;
  16310. var location = this.uniformLocations[name];
  16311. if (location == null) {
  16312. return;
  16313. }
  16314. gl.uniform1i(location, value);
  16315. }
  16316. }
  16317. ;
  16318. class WebGLTexture {
  16319. constructor(gl, texture) {
  16320. this.gl = gl;
  16321. this.texture = texture;
  16322. this.id = gl.createTexture();
  16323. this.target = gl.TEXTURE_2D;
  16324. this.version = -1;
  16325. this.update(texture);
  16326. }
  16327. update() {
  16328. if (!this.texture.image) {
  16329. this.version = this.texture.version;
  16330. return;
  16331. }
  16332. var gl = this.gl;
  16333. var texture = this.texture;
  16334. if (this.version === texture.version) {
  16335. return;
  16336. }
  16337. this.target = gl.TEXTURE_2D;
  16338. gl.bindTexture(this.target, this.id);
  16339. var level = 0;
  16340. var internalFormat = paramThreeToGL(gl, texture.format);
  16341. var width = texture.image.width;
  16342. var height = texture.image.height;
  16343. var border = 0;
  16344. var srcFormat = internalFormat;
  16345. var srcType = paramThreeToGL(gl, texture.type);
  16346. var data;
  16347. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
  16348. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
  16349. gl.pixelStorei(gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
  16350. if (texture instanceof DataTexture) {
  16351. data = texture.image.data;
  16352. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  16353. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  16354. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL(gl, texture.magFilter));
  16355. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL(gl, texture.minFilter));
  16356. gl.texImage2D(this.target, level, internalFormat, width, height, border, srcFormat, srcType, data);
  16357. } else if (texture instanceof CanvasTexture || texture instanceof Texture) {
  16358. data = texture.image;
  16359. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, paramThreeToGL(gl, texture.wrapS));
  16360. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, paramThreeToGL(gl, texture.wrapT));
  16361. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL(gl, texture.magFilter));
  16362. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL(gl, texture.minFilter));
  16363. gl.texImage2D(this.target, level, internalFormat, internalFormat, srcType, data);
  16364. if (texture instanceof Texture) {
  16365. gl.generateMipmap(gl.TEXTURE_2D);
  16366. }
  16367. }
  16368. gl.bindTexture(this.target, null);
  16369. this.version = texture.version;
  16370. }
  16371. }
  16372. ;
  16373. class WebGLBuffer {
  16374. constructor() {
  16375. this.numElements = 0;
  16376. this.vao = null;
  16377. this.vbos = new Map();
  16378. }
  16379. }
  16380. ;
  16381. class Renderer {
  16382. constructor(threeRenderer) {
  16383. this.threeRenderer = threeRenderer;
  16384. this.gl = this.threeRenderer.getContext();
  16385. this.buffers = new Map();
  16386. this.shaders = new Map();
  16387. this.textures = new Map();
  16388. this.glTypeMapping = new Map();
  16389. this.glTypeMapping.set(Float32Array, this.gl.FLOAT);
  16390. this.glTypeMapping.set(Uint8Array, this.gl.UNSIGNED_BYTE);
  16391. this.glTypeMapping.set(Uint16Array, this.gl.UNSIGNED_SHORT);
  16392. this.toggle = 0;
  16393. }
  16394. deleteBuffer(geometry) {
  16395. var gl = this.gl;
  16396. var webglBuffer = this.buffers.get(geometry);
  16397. if (webglBuffer != null) {
  16398. for (var attributeName in geometry.attributes) {
  16399. gl.deleteBuffer(webglBuffer.vbos.get(attributeName).handle);
  16400. }
  16401. this.buffers.delete(geometry);
  16402. }
  16403. }
  16404. createBuffer(geometry) {
  16405. var gl = this.gl;
  16406. var webglBuffer = new WebGLBuffer();
  16407. webglBuffer.vao = gl.createVertexArray();
  16408. webglBuffer.numElements = geometry.attributes.position.count;
  16409. gl.bindVertexArray(webglBuffer.vao);
  16410. for (var attributeName in geometry.attributes) {
  16411. var bufferAttribute = geometry.attributes[attributeName];
  16412. var vbo = gl.createBuffer();
  16413. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  16414. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  16415. var normalized = bufferAttribute.normalized;
  16416. var type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  16417. if (attributeLocations[attributeName] === undefined) {
  16418. //attributeLocation = attributeLocations["aExtra"];
  16419. } else {
  16420. var attributeLocation = attributeLocations[attributeName].location;
  16421. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  16422. gl.enableVertexAttribArray(attributeLocation);
  16423. }
  16424. webglBuffer.vbos.set(attributeName, {
  16425. handle: vbo,
  16426. name: attributeName,
  16427. count: bufferAttribute.count,
  16428. itemSize: bufferAttribute.itemSize,
  16429. type: geometry.attributes.position.array.constructor,
  16430. version: 0
  16431. });
  16432. }
  16433. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  16434. gl.bindVertexArray(null);
  16435. var disposeHandler = event => {
  16436. this.deleteBuffer(geometry);
  16437. geometry.removeEventListener("dispose", disposeHandler);
  16438. };
  16439. geometry.addEventListener("dispose", disposeHandler);
  16440. return webglBuffer;
  16441. }
  16442. updateBuffer(geometry) {
  16443. var gl = this.gl;
  16444. var webglBuffer = this.buffers.get(geometry);
  16445. gl.bindVertexArray(webglBuffer.vao);
  16446. for (var attributeName in geometry.attributes) {
  16447. var bufferAttribute = geometry.attributes[attributeName];
  16448. var normalized = bufferAttribute.normalized;
  16449. var type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  16450. var vbo = null;
  16451. if (!webglBuffer.vbos.has(attributeName)) {
  16452. vbo = gl.createBuffer();
  16453. webglBuffer.vbos.set(attributeName, {
  16454. handle: vbo,
  16455. name: attributeName,
  16456. count: bufferAttribute.count,
  16457. itemSize: bufferAttribute.itemSize,
  16458. type: geometry.attributes.position.array.constructor,
  16459. version: bufferAttribute.version
  16460. });
  16461. } else {
  16462. vbo = webglBuffer.vbos.get(attributeName).handle;
  16463. webglBuffer.vbos.get(attributeName).version = bufferAttribute.version;
  16464. }
  16465. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  16466. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  16467. if (attributeLocations[attributeName] === undefined) {
  16468. //attributeLocation = attributeLocations["aExtra"];
  16469. } else {
  16470. var attributeLocation = attributeLocations[attributeName].location;
  16471. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  16472. gl.enableVertexAttribArray(attributeLocation);
  16473. }
  16474. }
  16475. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  16476. gl.bindVertexArray(null);
  16477. }
  16478. traverse(scene) {
  16479. var octrees = [];
  16480. var stack = [scene];
  16481. while (stack.length > 0) {
  16482. var node = stack.pop();
  16483. if (node instanceof PointCloudTree) {
  16484. octrees.push(node);
  16485. continue;
  16486. }
  16487. var visibleChildren = node.children.filter(c => c.visible);
  16488. stack.push(...visibleChildren);
  16489. }
  16490. var result = {
  16491. octrees: octrees
  16492. };
  16493. return result;
  16494. }
  16495. renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params) {
  16496. var _this = this;
  16497. if (exports.measureTimings) performance.mark("renderNodes-start");
  16498. var gl = this.gl;
  16499. var material = params.material ? params.material : octree.material;
  16500. var shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  16501. var view = camera.matrixWorldInverse;
  16502. if (params.viewOverride) {
  16503. view = params.viewOverride;
  16504. }
  16505. var worldView = new Matrix4();
  16506. var mat4holder = new Float32Array(16);
  16507. var i = 0;
  16508. var _loop = function _loop() {
  16509. if (exports.debug.allowedNodes !== undefined) {
  16510. if (!exports.debug.allowedNodes.includes(node.name)) {
  16511. return 1; // continue
  16512. }
  16513. }
  16514. var world = node.sceneNode.matrixWorld;
  16515. worldView.multiplyMatrices(view, world);
  16516. if (visibilityTextureData) {
  16517. var vnStart = visibilityTextureData.offsets.get(node);
  16518. shader.setUniform1f("uVNStart", vnStart);
  16519. }
  16520. var level = node.getLevel();
  16521. if (node.debug) {
  16522. shader.setUniform("uDebug", true);
  16523. } else {
  16524. shader.setUniform("uDebug", false);
  16525. }
  16526. // let isLeaf = false;
  16527. // if(node instanceof PointCloudOctreeNode){
  16528. // isLeaf = Object.keys(node.children).length === 0;
  16529. // }else if(node instanceof PointCloudArena4DNode){
  16530. // isLeaf = node.geometryNode.isLeaf;
  16531. // }
  16532. // shader.setUniform("uIsLeafNode", isLeaf);
  16533. // let isLeaf = node.children.filter(n => n != null).length === 0;
  16534. // if(!isLeaf){
  16535. // continue;
  16536. // }
  16537. // TODO consider passing matrices in an array to avoid uniformMatrix4fv overhead
  16538. var lModel = shader.uniformLocations["modelMatrix"];
  16539. if (lModel) {
  16540. mat4holder.set(world.elements);
  16541. gl.uniformMatrix4fv(lModel, false, mat4holder);
  16542. }
  16543. var lModelView = shader.uniformLocations["modelViewMatrix"];
  16544. //mat4holder.set(worldView.elements);
  16545. // faster then set in chrome 63
  16546. for (var j = 0; j < 16; j++) {
  16547. mat4holder[j] = worldView.elements[j];
  16548. }
  16549. gl.uniformMatrix4fv(lModelView, false, mat4holder);
  16550. {
  16551. // Clip Polygons
  16552. if (material.clipPolygons && material.clipPolygons.length > 0) {
  16553. var clipPolygonVCount = [];
  16554. var worldViewProjMatrices = [];
  16555. for (var clipPolygon of material.clipPolygons) {
  16556. var _view = clipPolygon.viewMatrix;
  16557. var proj = clipPolygon.projMatrix;
  16558. var worldViewProj = proj.clone().multiply(_view).multiply(world);
  16559. clipPolygonVCount.push(clipPolygon.markers.length);
  16560. worldViewProjMatrices.push(worldViewProj);
  16561. }
  16562. var flattenedMatrices = [].concat(...worldViewProjMatrices.map(m => m.elements));
  16563. var flattenedVertices = new Array(8 * 3 * material.clipPolygons.length);
  16564. for (var _i3 = 0; _i3 < material.clipPolygons.length; _i3++) {
  16565. var _clipPolygon = material.clipPolygons[_i3];
  16566. for (var _j = 0; _j < _clipPolygon.markers.length; _j++) {
  16567. flattenedVertices[_i3 * 24 + (_j * 3 + 0)] = _clipPolygon.markers[_j].position.x;
  16568. flattenedVertices[_i3 * 24 + (_j * 3 + 1)] = _clipPolygon.markers[_j].position.y;
  16569. flattenedVertices[_i3 * 24 + (_j * 3 + 2)] = _clipPolygon.markers[_j].position.z;
  16570. }
  16571. }
  16572. var lClipPolygonVCount = shader.uniformLocations["uClipPolygonVCount[0]"];
  16573. gl.uniform1iv(lClipPolygonVCount, clipPolygonVCount);
  16574. var lClipPolygonVP = shader.uniformLocations["uClipPolygonWVP[0]"];
  16575. gl.uniformMatrix4fv(lClipPolygonVP, false, flattenedMatrices);
  16576. var lClipPolygons = shader.uniformLocations["uClipPolygonVertices[0]"];
  16577. gl.uniform3fv(lClipPolygons, flattenedVertices);
  16578. }
  16579. }
  16580. //shader.setUniformMatrix4("modelMatrix", world);
  16581. //shader.setUniformMatrix4("modelViewMatrix", worldView);
  16582. shader.setUniform1f("uLevel", level);
  16583. shader.setUniform1f("uNodeSpacing", node.geometryNode.estimatedSpacing);
  16584. shader.setUniform1f("uPCIndex", i);
  16585. // uBBSize
  16586. if (shadowMaps.length > 0) {
  16587. var lShadowMap = shader.uniformLocations["uShadowMap[0]"];
  16588. shader.setUniform3f("uShadowColor", material.uniforms.uShadowColor.value);
  16589. var bindingStart = 5;
  16590. var bindingPoints = new Array(shadowMaps.length).fill(bindingStart).map((a, i) => a + i);
  16591. gl.uniform1iv(lShadowMap, bindingPoints);
  16592. for (var _i4 = 0; _i4 < shadowMaps.length; _i4++) {
  16593. var shadowMap = shadowMaps[_i4];
  16594. var bindingPoint = bindingPoints[_i4];
  16595. var glTexture = _this.threeRenderer.properties.get(shadowMap.target.texture).__webglTexture;
  16596. gl.activeTexture(gl["TEXTURE".concat(bindingPoint)]);
  16597. gl.bindTexture(gl.TEXTURE_2D, glTexture);
  16598. }
  16599. {
  16600. var worldViewMatrices = shadowMaps.map(sm => sm.camera.matrixWorldInverse).map(view => new Matrix4().multiplyMatrices(view, world));
  16601. var _flattenedMatrices = [].concat(...worldViewMatrices.map(c => c.elements));
  16602. var lWorldView = shader.uniformLocations["uShadowWorldView[0]"];
  16603. gl.uniformMatrix4fv(lWorldView, false, _flattenedMatrices);
  16604. }
  16605. {
  16606. var _flattenedMatrices2 = [].concat(...shadowMaps.map(sm => sm.camera.projectionMatrix.elements));
  16607. var lProj = shader.uniformLocations["uShadowProj[0]"];
  16608. gl.uniformMatrix4fv(lProj, false, _flattenedMatrices2);
  16609. }
  16610. }
  16611. var geometry = node.geometryNode.geometry;
  16612. if (geometry.attributes["gps-time"]) {
  16613. var bufferAttribute = geometry.attributes["gps-time"];
  16614. var attGPS = octree.getAttribute("gps-time");
  16615. var initialRange = attGPS.initialRange;
  16616. var initialRangeSize = initialRange[1] - initialRange[0];
  16617. var globalRange = attGPS.range;
  16618. var globalRangeSize = globalRange[1] - globalRange[0];
  16619. var scale = initialRangeSize / globalRangeSize;
  16620. var offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  16621. scale = Number.isNaN(scale) ? 1 : scale;
  16622. offset = Number.isNaN(offset) ? 0 : offset;
  16623. shader.setUniform1f("uGpsScale", scale);
  16624. shader.setUniform1f("uGpsOffset", offset);
  16625. //shader.setUniform2f("uFilterGPSTimeClipRange", [-Infinity, Infinity]);
  16626. var uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  16627. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  16628. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  16629. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  16630. var normalizedClipRange = [(uFilterGPSTimeClipRange[0] - globalRange[0]) / globalRangeSize, (uFilterGPSTimeClipRange[1] - globalRange[0]) / globalRangeSize];
  16631. shader.setUniform2f("uFilterGPSTimeClipRange", normalizedClipRange);
  16632. // // ranges in full gps coordinate system
  16633. // const globalRange = attGPS.range;
  16634. // const bufferRange = bufferAttribute.potree.range;
  16635. // // ranges in [0, 1]
  16636. // // normalizedGlobalRange = [0, 1]
  16637. // // normalizedBufferRange: norm buffer within norm global range e.g. [0.2, 0.8]
  16638. // const globalWidth = globalRange[1] - globalRange[0];
  16639. // const normalizedBufferRange = [
  16640. // (bufferRange[0] - globalRange[0]) / globalWidth,
  16641. // (bufferRange[1] - globalRange[0]) / globalWidth,
  16642. // ];
  16643. // shader.setUniform2f("uNormalizedGpsBufferRange", normalizedBufferRange);
  16644. // let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  16645. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  16646. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  16647. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  16648. // shader.setUniform1f("uGpsScale", bufferAttribute.potree.scale);
  16649. // shader.setUniform1f("uGpsOffset", bufferAttribute.potree.offset);
  16650. }
  16651. {
  16652. var uFilterReturnNumberRange = material.uniforms.uFilterReturnNumberRange.value;
  16653. var uFilterNumberOfReturnsRange = material.uniforms.uFilterNumberOfReturnsRange.value;
  16654. var uFilterPointSourceIDClipRange = material.uniforms.uFilterPointSourceIDClipRange.value;
  16655. shader.setUniform2f("uFilterReturnNumberRange", uFilterReturnNumberRange);
  16656. shader.setUniform2f("uFilterNumberOfReturnsRange", uFilterNumberOfReturnsRange);
  16657. shader.setUniform2f("uFilterPointSourceIDClipRange", uFilterPointSourceIDClipRange);
  16658. }
  16659. var webglBuffer = null;
  16660. if (!_this.buffers.has(geometry)) {
  16661. webglBuffer = _this.createBuffer(geometry);
  16662. _this.buffers.set(geometry, webglBuffer);
  16663. } else {
  16664. webglBuffer = _this.buffers.get(geometry);
  16665. for (var attributeName in geometry.attributes) {
  16666. var attribute = geometry.attributes[attributeName];
  16667. if (attribute.version > webglBuffer.vbos.get(attributeName).version) {
  16668. _this.updateBuffer(geometry);
  16669. }
  16670. }
  16671. }
  16672. gl.bindVertexArray(webglBuffer.vao);
  16673. var isExtraAttribute = attributeLocations[material.activeAttributeName] === undefined && Object.keys(geometry.attributes).includes(material.activeAttributeName);
  16674. if (isExtraAttribute) {
  16675. var attributeLocation = attributeLocations["aExtra"].location;
  16676. for (var _attributeName in geometry.attributes) {
  16677. var _bufferAttribute = geometry.attributes[_attributeName];
  16678. var _vbo = webglBuffer.vbos.get(_attributeName);
  16679. gl.bindBuffer(gl.ARRAY_BUFFER, _vbo.handle);
  16680. gl.disableVertexAttribArray(attributeLocation);
  16681. }
  16682. var attName = material.activeAttributeName;
  16683. var _bufferAttribute2 = geometry.attributes[attName];
  16684. var vbo = webglBuffer.vbos.get(attName);
  16685. if (_bufferAttribute2 !== undefined && vbo !== undefined) {
  16686. var type = _this.glTypeMapping.get(_bufferAttribute2.array.constructor);
  16687. var normalized = _bufferAttribute2.normalized;
  16688. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  16689. gl.vertexAttribPointer(attributeLocation, _bufferAttribute2.itemSize, type, normalized, 0, 0);
  16690. gl.enableVertexAttribArray(attributeLocation);
  16691. }
  16692. {
  16693. var attExtra = octree.pcoGeometry.pointAttributes.attributes.find(a => a.name === attName);
  16694. var range = material.getRange(attName);
  16695. if (!range) {
  16696. range = attExtra.range;
  16697. }
  16698. if (!range) {
  16699. range = [0, 1];
  16700. }
  16701. var _initialRange = attExtra.initialRange;
  16702. var _initialRangeSize = _initialRange[1] - _initialRange[0];
  16703. var _globalRange = range;
  16704. var _globalRangeSize = _globalRange[1] - _globalRange[0];
  16705. var _scale = _initialRangeSize / _globalRangeSize;
  16706. var _offset = -(_globalRange[0] - _initialRange[0]) / _initialRangeSize;
  16707. _scale = Number.isNaN(_scale) ? 1 : _scale;
  16708. _offset = Number.isNaN(_offset) ? 0 : _offset;
  16709. shader.setUniform1f("uExtraScale", _scale);
  16710. shader.setUniform1f("uExtraOffset", _offset);
  16711. }
  16712. } else {
  16713. for (var _attributeName2 in geometry.attributes) {
  16714. var _bufferAttribute3 = geometry.attributes[_attributeName2];
  16715. var _vbo2 = webglBuffer.vbos.get(_attributeName2);
  16716. if (attributeLocations[_attributeName2] !== undefined) {
  16717. var _attributeLocation = attributeLocations[_attributeName2].location;
  16718. var _type = _this.glTypeMapping.get(_bufferAttribute3.array.constructor);
  16719. var _normalized = _bufferAttribute3.normalized;
  16720. gl.bindBuffer(gl.ARRAY_BUFFER, _vbo2.handle);
  16721. gl.vertexAttribPointer(_attributeLocation, _bufferAttribute3.itemSize, _type, _normalized, 0, 0);
  16722. gl.enableVertexAttribArray(_attributeLocation);
  16723. }
  16724. }
  16725. }
  16726. var numPoints = webglBuffer.numElements;
  16727. gl.drawArrays(gl.POINTS, 0, numPoints);
  16728. i++;
  16729. };
  16730. for (var node of nodes) {
  16731. if (_loop()) continue;
  16732. }
  16733. gl.bindVertexArray(null);
  16734. if (exports.measureTimings) {
  16735. performance.mark("renderNodes-end");
  16736. performance.measure("render.renderNodes", "renderNodes-start", "renderNodes-end");
  16737. }
  16738. }
  16739. renderOctree(octree, nodes, camera, target) {
  16740. var params = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  16741. var gl = this.gl;
  16742. var material = params.material ? params.material : octree.material;
  16743. var shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  16744. var view = camera.matrixWorldInverse;
  16745. var viewInv = camera.matrixWorld;
  16746. if (params.viewOverride) {
  16747. view = params.viewOverride;
  16748. viewInv = view.clone().invert();
  16749. }
  16750. var proj = camera.projectionMatrix;
  16751. var projInv = proj.clone().invert();
  16752. //let worldView = new THREE.Matrix4();
  16753. var shader = null;
  16754. var visibilityTextureData = null;
  16755. var currentTextureBindingPoint = 0;
  16756. if (material.pointSizeType >= 0) {
  16757. if (material.pointSizeType === PointSizeType.ADAPTIVE || material.activeAttributeName === "level of detail") {
  16758. var vnNodes = params.vnTextureNodes != null ? params.vnTextureNodes : nodes;
  16759. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  16760. var vnt = material.visibleNodesTexture;
  16761. var data = vnt.image.data;
  16762. data.set(visibilityTextureData.data);
  16763. vnt.needsUpdate = true;
  16764. }
  16765. }
  16766. {
  16767. // UPDATE SHADER AND TEXTURES
  16768. if (!this.shaders.has(material)) {
  16769. var [vs, fs] = [material.vertexShader, material.fragmentShader];
  16770. var _shader = new Shader(gl, "pointcloud", vs, fs);
  16771. this.shaders.set(material, _shader);
  16772. }
  16773. shader = this.shaders.get(material);
  16774. //if(material.needsUpdate){
  16775. {
  16776. var [_vs, _fs] = [material.vertexShader, material.fragmentShader];
  16777. var numSnapshots = material.snapEnabled ? material.numSnapshots : 0;
  16778. var numClipBoxes = material.clipBoxes && material.clipBoxes.length ? material.clipBoxes.length : 0;
  16779. var numClipSpheres = params.clipSpheres && params.clipSpheres.length ? params.clipSpheres.length : 0;
  16780. var numClipPolygons = material.clipPolygons && material.clipPolygons.length ? material.clipPolygons.length : 0;
  16781. var defines = ["#define num_shadowmaps ".concat(shadowMaps.length), "#define num_snapshots ".concat(numSnapshots), "#define num_clipboxes ".concat(numClipBoxes), "#define num_clipspheres ".concat(numClipSpheres), "#define num_clippolygons ".concat(numClipPolygons)];
  16782. if (octree.pcoGeometry.root.isLoaded()) {
  16783. var attributes = octree.pcoGeometry.root.geometry.attributes;
  16784. if (attributes["gps-time"]) {
  16785. defines.push("#define clip_gps_enabled");
  16786. }
  16787. if (attributes["return number"]) {
  16788. defines.push("#define clip_return_number_enabled");
  16789. }
  16790. if (attributes["number of returns"]) {
  16791. defines.push("#define clip_number_of_returns_enabled");
  16792. }
  16793. if (attributes["source id"] || attributes["point source id"]) {
  16794. defines.push("#define clip_point_source_id_enabled");
  16795. }
  16796. }
  16797. var definesString = defines.join("\n");
  16798. var vsVersionIndex = _vs.indexOf("#version ");
  16799. var fsVersionIndex = _fs.indexOf("#version ");
  16800. if (vsVersionIndex >= 0) {
  16801. _vs = _vs.replace(/(#version .*)/, "$1\n".concat(definesString));
  16802. } else {
  16803. _vs = "".concat(definesString, "\n").concat(_vs);
  16804. }
  16805. if (fsVersionIndex >= 0) {
  16806. _fs = _fs.replace(/(#version .*)/, "$1\n".concat(definesString));
  16807. } else {
  16808. _fs = "".concat(definesString, "\n").concat(_fs);
  16809. }
  16810. shader.update(_vs, _fs);
  16811. material.needsUpdate = false;
  16812. }
  16813. for (var uniformName of Object.keys(material.uniforms)) {
  16814. var uniform = material.uniforms[uniformName];
  16815. if (uniform.type == "t") {
  16816. var texture = uniform.value;
  16817. if (!texture) {
  16818. continue;
  16819. }
  16820. if (!this.textures.has(texture)) {
  16821. var webglTexture = new WebGLTexture(gl, texture);
  16822. this.textures.set(texture, webglTexture);
  16823. }
  16824. var webGLTexture = this.textures.get(texture);
  16825. webGLTexture.update();
  16826. }
  16827. }
  16828. }
  16829. gl.useProgram(shader.program);
  16830. var transparent = false;
  16831. if (params.transparent !== undefined) {
  16832. transparent = params.transparent && material.opacity < 1;
  16833. } else {
  16834. transparent = material.opacity < 1;
  16835. }
  16836. if (transparent) {
  16837. gl.enable(gl.BLEND);
  16838. gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
  16839. gl.depthMask(false);
  16840. gl.disable(gl.DEPTH_TEST);
  16841. } else {
  16842. gl.disable(gl.BLEND);
  16843. gl.depthMask(true);
  16844. gl.enable(gl.DEPTH_TEST);
  16845. }
  16846. if (params.blendFunc !== undefined) {
  16847. gl.enable(gl.BLEND);
  16848. gl.blendFunc(...params.blendFunc);
  16849. }
  16850. if (params.depthTest !== undefined) {
  16851. if (params.depthTest === true) {
  16852. gl.enable(gl.DEPTH_TEST);
  16853. } else {
  16854. gl.disable(gl.DEPTH_TEST);
  16855. }
  16856. }
  16857. if (params.depthWrite !== undefined) {
  16858. if (params.depthWrite === true) {
  16859. gl.depthMask(true);
  16860. } else {
  16861. gl.depthMask(false);
  16862. }
  16863. }
  16864. {
  16865. // UPDATE UNIFORMS
  16866. shader.setUniformMatrix4("projectionMatrix", proj);
  16867. shader.setUniformMatrix4("viewMatrix", view);
  16868. shader.setUniformMatrix4("uViewInv", viewInv);
  16869. shader.setUniformMatrix4("uProjInv", projInv);
  16870. var screenWidth = target ? target.width : material.screenWidth;
  16871. var screenHeight = target ? target.height : material.screenHeight;
  16872. shader.setUniform1f("uScreenWidth", screenWidth);
  16873. shader.setUniform1f("uScreenHeight", screenHeight);
  16874. shader.setUniform1f("fov", Math.PI * camera.fov / 180);
  16875. shader.setUniform1f("near", camera.near);
  16876. shader.setUniform1f("far", camera.far);
  16877. if (camera instanceof OrthographicCamera) {
  16878. shader.setUniform("uUseOrthographicCamera", true);
  16879. shader.setUniform("uOrthoWidth", camera.right - camera.left);
  16880. shader.setUniform("uOrthoHeight", camera.top - camera.bottom);
  16881. } else {
  16882. shader.setUniform("uUseOrthographicCamera", false);
  16883. }
  16884. if (material.clipBoxes.length + material.clipPolygons.length === 0) {
  16885. shader.setUniform1i("clipTask", ClipTask.NONE);
  16886. } else {
  16887. shader.setUniform1i("clipTask", material.clipTask);
  16888. }
  16889. shader.setUniform1i("clipMethod", material.clipMethod);
  16890. if (material.clipBoxes && material.clipBoxes.length > 0) {
  16891. //let flattenedMatrices = [].concat(...material.clipBoxes.map(c => c.inverse.elements));
  16892. //const lClipBoxes = shader.uniformLocations["clipBoxes[0]"];
  16893. //gl.uniformMatrix4fv(lClipBoxes, false, flattenedMatrices);
  16894. var lClipBoxes = shader.uniformLocations["clipBoxes[0]"];
  16895. gl.uniformMatrix4fv(lClipBoxes, false, material.uniforms.clipBoxes.value);
  16896. }
  16897. // TODO CLIPSPHERES
  16898. if (params.clipSpheres && params.clipSpheres.length > 0) {
  16899. var clipSpheres = params.clipSpheres;
  16900. var matrices = [];
  16901. for (var clipSphere of clipSpheres) {
  16902. //let mScale = new THREE.Matrix4().makeScale(...clipSphere.scale.toArray());
  16903. //let mTranslate = new THREE.Matrix4().makeTranslation(...clipSphere.position.toArray());
  16904. //let clipToWorld = new THREE.Matrix4().multiplyMatrices(mTranslate, mScale);
  16905. var clipToWorld = clipSphere.matrixWorld;
  16906. var viewToWorld = camera.matrixWorld;
  16907. var worldToClip = clipToWorld.clone().invert();
  16908. var viewToClip = new Matrix4().multiplyMatrices(worldToClip, viewToWorld);
  16909. matrices.push(viewToClip);
  16910. }
  16911. var flattenedMatrices = [].concat(...matrices.map(matrix => matrix.elements));
  16912. var lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  16913. gl.uniformMatrix4fv(lClipSpheres, false, flattenedMatrices);
  16914. //const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  16915. //gl.uniformMatrix4fv(lClipSpheres, false, material.uniforms.clipSpheres.value);
  16916. }
  16917. shader.setUniform1f("size", material.size);
  16918. shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
  16919. shader.setUniform1f("minSize", material.uniforms.minSize.value);
  16920. // uniform float uPCIndex
  16921. shader.setUniform1f("uOctreeSpacing", material.spacing);
  16922. shader.setUniform("uOctreeSize", material.uniforms.octreeSize.value);
  16923. //uniform vec3 uColor;
  16924. shader.setUniform3f("uColor", material.color.toArray());
  16925. //uniform float opacity;
  16926. shader.setUniform1f("uOpacity", material.opacity);
  16927. shader.setUniform2f("elevationRange", material.elevationRange);
  16928. shader.setUniform2f("intensityRange", material.intensityRange);
  16929. shader.setUniform3f("uIntensity_gbc", [material.intensityGamma, material.intensityBrightness, material.intensityContrast]);
  16930. shader.setUniform3f("uRGB_gbc", [material.rgbGamma, material.rgbBrightness, material.rgbContrast]);
  16931. shader.setUniform1f("uTransition", material.transition);
  16932. shader.setUniform1f("wRGB", material.weightRGB);
  16933. shader.setUniform1f("wIntensity", material.weightIntensity);
  16934. shader.setUniform1f("wElevation", material.weightElevation);
  16935. shader.setUniform1f("wClassification", material.weightClassification);
  16936. shader.setUniform1f("wReturnNumber", material.weightReturnNumber);
  16937. shader.setUniform1f("wSourceID", material.weightSourceID);
  16938. shader.setUniform("backfaceCulling", material.uniforms.backfaceCulling.value);
  16939. var vnWebGLTexture = this.textures.get(material.visibleNodesTexture);
  16940. if (vnWebGLTexture) {
  16941. shader.setUniform1i("visibleNodesTexture", currentTextureBindingPoint);
  16942. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  16943. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  16944. currentTextureBindingPoint++;
  16945. }
  16946. var gradientTexture = this.textures.get(material.gradientTexture);
  16947. shader.setUniform1i("gradient", currentTextureBindingPoint);
  16948. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  16949. gl.bindTexture(gradientTexture.target, gradientTexture.id);
  16950. var repeat = material.elevationGradientRepeat;
  16951. if (repeat === ElevationGradientRepeat.REPEAT) {
  16952. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.REPEAT);
  16953. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.REPEAT);
  16954. } else if (repeat === ElevationGradientRepeat.MIRRORED_REPEAT) {
  16955. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
  16956. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
  16957. } else {
  16958. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  16959. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  16960. }
  16961. currentTextureBindingPoint++;
  16962. var classificationTexture = this.textures.get(material.classificationTexture);
  16963. shader.setUniform1i("classificationLUT", currentTextureBindingPoint);
  16964. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  16965. gl.bindTexture(classificationTexture.target, classificationTexture.id);
  16966. currentTextureBindingPoint++;
  16967. var matcapTexture = this.textures.get(material.matcapTexture);
  16968. shader.setUniform1i("matcapTextureUniform", currentTextureBindingPoint);
  16969. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  16970. gl.bindTexture(matcapTexture.target, matcapTexture.id);
  16971. currentTextureBindingPoint++;
  16972. if (material.snapEnabled === true) {
  16973. {
  16974. var lSnapshot = shader.uniformLocations["uSnapshot[0]"];
  16975. var lSnapshotDepth = shader.uniformLocations["uSnapshotDepth[0]"];
  16976. var bindingStart = currentTextureBindingPoint;
  16977. var lSnapshotBindingPoints = new Array(5).fill(bindingStart).map((a, i) => a + i);
  16978. var lSnapshotDepthBindingPoints = new Array(5).fill(1 + Math.max(...lSnapshotBindingPoints)).map((a, i) => a + i);
  16979. currentTextureBindingPoint = 1 + Math.max(...lSnapshotDepthBindingPoints);
  16980. gl.uniform1iv(lSnapshot, lSnapshotBindingPoints);
  16981. gl.uniform1iv(lSnapshotDepth, lSnapshotDepthBindingPoints);
  16982. for (var i = 0; i < 5; i++) {
  16983. var _texture = material.uniforms["uSnapshot"].value[i];
  16984. var textureDepth = material.uniforms["uSnapshotDepth"].value[i];
  16985. if (!_texture) {
  16986. break;
  16987. }
  16988. var snapTexture = this.threeRenderer.properties.get(_texture).__webglTexture;
  16989. var snapTextureDepth = this.threeRenderer.properties.get(textureDepth).__webglTexture;
  16990. var bindingPoint = lSnapshotBindingPoints[i];
  16991. var depthBindingPoint = lSnapshotDepthBindingPoints[i];
  16992. gl.activeTexture(gl["TEXTURE".concat(bindingPoint)]);
  16993. gl.bindTexture(gl.TEXTURE_2D, snapTexture);
  16994. gl.activeTexture(gl["TEXTURE".concat(depthBindingPoint)]);
  16995. gl.bindTexture(gl.TEXTURE_2D, snapTextureDepth);
  16996. }
  16997. }
  16998. {
  16999. var _flattenedMatrices3 = [].concat(...material.uniforms.uSnapView.value.map(c => c.elements));
  17000. var lSnapView = shader.uniformLocations["uSnapView[0]"];
  17001. gl.uniformMatrix4fv(lSnapView, false, _flattenedMatrices3);
  17002. }
  17003. {
  17004. var _flattenedMatrices4 = [].concat(...material.uniforms.uSnapProj.value.map(c => c.elements));
  17005. var lSnapProj = shader.uniformLocations["uSnapProj[0]"];
  17006. gl.uniformMatrix4fv(lSnapProj, false, _flattenedMatrices4);
  17007. }
  17008. {
  17009. var _flattenedMatrices5 = [].concat(...material.uniforms.uSnapProjInv.value.map(c => c.elements));
  17010. var lSnapProjInv = shader.uniformLocations["uSnapProjInv[0]"];
  17011. gl.uniformMatrix4fv(lSnapProjInv, false, _flattenedMatrices5);
  17012. }
  17013. {
  17014. var _flattenedMatrices6 = [].concat(...material.uniforms.uSnapViewInv.value.map(c => c.elements));
  17015. var lSnapViewInv = shader.uniformLocations["uSnapViewInv[0]"];
  17016. gl.uniformMatrix4fv(lSnapViewInv, false, _flattenedMatrices6);
  17017. }
  17018. }
  17019. }
  17020. this.renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params);
  17021. gl.activeTexture(gl.TEXTURE2);
  17022. gl.bindTexture(gl.TEXTURE_2D, null);
  17023. gl.activeTexture(gl.TEXTURE0);
  17024. }
  17025. render(scene, camera) {
  17026. var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
  17027. var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  17028. var gl = this.gl;
  17029. // PREPARE
  17030. if (target != null) {
  17031. this.threeRenderer.setRenderTarget(target);
  17032. }
  17033. //camera.updateProjectionMatrix();
  17034. // camera.matrixWorldInverse.invert(camera.matrixWorld);
  17035. var traversalResult = this.traverse(scene);
  17036. // RENDER
  17037. for (var octree of traversalResult.octrees) {
  17038. var nodes = octree.visibleNodes;
  17039. this.renderOctree(octree, nodes, camera, target, params);
  17040. }
  17041. // CLEANUP
  17042. gl.activeTexture(gl.TEXTURE1);
  17043. gl.bindTexture(gl.TEXTURE_2D, null);
  17044. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  17045. gl.bindVertexArray(null);
  17046. this.threeRenderer.resetState();
  17047. }
  17048. }
  17049. ;
  17050. function copyMaterial(source, target) {
  17051. for (var name of Object.keys(target.uniforms)) {
  17052. target.uniforms[name].value = source.uniforms[name].value;
  17053. }
  17054. target.gradientTexture = source.gradientTexture;
  17055. target.visibleNodesTexture = source.visibleNodesTexture;
  17056. target.classificationTexture = source.classificationTexture;
  17057. target.matcapTexture = source.matcapTexture;
  17058. target.activeAttributeName = source.activeAttributeName;
  17059. target.ranges = source.ranges;
  17060. //target.updateShaderSource();
  17061. }
  17062. class Batch {
  17063. constructor(geometry, material) {
  17064. this.geometry = geometry;
  17065. this.material = material;
  17066. this.sceneNode = new Points(geometry, material);
  17067. this.geometryNode = {
  17068. estimatedSpacing: 1.0,
  17069. geometry: geometry
  17070. };
  17071. }
  17072. getLevel() {
  17073. return 0;
  17074. }
  17075. }
  17076. class ProfileFakeOctree extends PointCloudTree {
  17077. constructor(octree) {
  17078. super();
  17079. this.trueOctree = octree;
  17080. this.pcoGeometry = octree.pcoGeometry;
  17081. this.points = [];
  17082. this.visibleNodes = [];
  17083. //this.material = this.trueOctree.material;
  17084. this.material = new PointCloudMaterial$1();
  17085. //this.material.copy(this.trueOctree.material);
  17086. copyMaterial(this.trueOctree.material, this.material);
  17087. this.material.pointSizeType = PointSizeType.FIXED;
  17088. this.batchSize = 100 * 1000;
  17089. this.currentBatch = null;
  17090. }
  17091. getAttribute(name) {
  17092. return this.trueOctree.getAttribute(name);
  17093. }
  17094. dispose() {
  17095. for (var node of this.visibleNodes) {
  17096. node.geometry.dispose();
  17097. }
  17098. this.visibleNodes = [];
  17099. this.currentBatch = null;
  17100. this.points = [];
  17101. }
  17102. addPoints(data) {
  17103. // since each call to addPoints can deliver very very few points,
  17104. // we're going to batch them into larger buffers for efficiency.
  17105. if (this.currentBatch === null) {
  17106. this.currentBatch = this.createNewBatch(data);
  17107. }
  17108. this.points.push(data);
  17109. var updateRange = {
  17110. start: this.currentBatch.geometry.drawRange.count,
  17111. count: 0
  17112. };
  17113. var projectedBox = new Box3();
  17114. var truePos = new Vector3();
  17115. for (var i = 0; i < data.numPoints; i++) {
  17116. if (updateRange.start + updateRange.count >= this.batchSize) {
  17117. // current batch full, start new batch
  17118. for (var key of Object.keys(this.currentBatch.geometry.attributes)) {
  17119. var attribute = this.currentBatch.geometry.attributes[key];
  17120. attribute.updateRange.offset = updateRange.start;
  17121. attribute.updateRange.count = updateRange.count;
  17122. attribute.needsUpdate = true;
  17123. }
  17124. this.currentBatch.geometry.computeBoundingBox();
  17125. this.currentBatch.geometry.computeBoundingSphere();
  17126. this.currentBatch = this.createNewBatch(data);
  17127. updateRange = {
  17128. start: 0,
  17129. count: 0
  17130. };
  17131. }
  17132. truePos.set(data.data.position[3 * i + 0] + this.trueOctree.position.x, data.data.position[3 * i + 1] + this.trueOctree.position.y, data.data.position[3 * i + 2] + this.trueOctree.position.z);
  17133. var x = data.data.mileage[i];
  17134. var y = 0;
  17135. var z = truePos.z;
  17136. projectedBox.expandByPoint(new Vector3(x, y, z));
  17137. var index = updateRange.start + updateRange.count;
  17138. var geometry = this.currentBatch.geometry;
  17139. for (var attributeName of Object.keys(data.data)) {
  17140. var source = data.data[attributeName];
  17141. var target = geometry.attributes[attributeName];
  17142. var numElements = target.itemSize;
  17143. for (var item = 0; item < numElements; item++) {
  17144. target.array[numElements * index + item] = source[numElements * i + item];
  17145. }
  17146. }
  17147. {
  17148. var position = geometry.attributes.position;
  17149. position.array[3 * index + 0] = x;
  17150. position.array[3 * index + 1] = y;
  17151. position.array[3 * index + 2] = z;
  17152. }
  17153. updateRange.count++;
  17154. this.currentBatch.geometry.drawRange.count++;
  17155. }
  17156. for (var _key of Object.keys(this.currentBatch.geometry.attributes)) {
  17157. var _attribute = this.currentBatch.geometry.attributes[_key];
  17158. _attribute.updateRange.offset = updateRange.start;
  17159. _attribute.updateRange.count = updateRange.count;
  17160. _attribute.needsUpdate = true;
  17161. }
  17162. data.projectedBox = projectedBox;
  17163. this.projectedBox = this.points.reduce((a, i) => a.union(i.projectedBox), new Box3());
  17164. }
  17165. createNewBatch(data) {
  17166. var geometry = new BufferGeometry();
  17167. // create new batches with batch_size elements of the same type as the attribute
  17168. for (var attributeName of Object.keys(data.data)) {
  17169. var buffer = data.data[attributeName];
  17170. var numElements = buffer.length / data.numPoints; // 3 for pos, 4 for col, 1 for scalars
  17171. var _constructor = buffer.constructor;
  17172. var normalized = false;
  17173. if (this.trueOctree.root.sceneNode) {
  17174. if (this.trueOctree.root.sceneNode.geometry.attributes[attributeName]) {
  17175. normalized = this.trueOctree.root.sceneNode.geometry.attributes[attributeName].normalized;
  17176. }
  17177. }
  17178. var batchBuffer = new _constructor(numElements * this.batchSize);
  17179. var bufferAttribute = new BufferAttribute(batchBuffer, numElements, normalized);
  17180. bufferAttribute.potree = {
  17181. range: [0, 1]
  17182. };
  17183. geometry.setAttribute(attributeName, bufferAttribute);
  17184. }
  17185. geometry.drawRange.start = 0;
  17186. geometry.drawRange.count = 0;
  17187. var batch = new Batch(geometry, this.material);
  17188. this.visibleNodes.push(batch);
  17189. return batch;
  17190. }
  17191. computeVisibilityTextureData() {
  17192. var data = new Uint8Array(this.visibleNodes.length * 4);
  17193. var offsets = new Map();
  17194. for (var i = 0; i < this.visibleNodes.length; i++) {
  17195. var node = this.visibleNodes[i];
  17196. offsets[node] = i;
  17197. }
  17198. return {
  17199. data: data,
  17200. offsets: offsets
  17201. };
  17202. }
  17203. }
  17204. class ProfileWindow extends EventDispatcher$1 {
  17205. constructor(viewer) {
  17206. super();
  17207. this.viewer = viewer;
  17208. this.elRoot = $('#profile_window');
  17209. this.renderArea = this.elRoot.find('#profileCanvasContainer');
  17210. this.svg = d3.select('svg#profileSVG');
  17211. this.mouseIsDown = false;
  17212. this.projectedBox = new Box3();
  17213. this.pointclouds = new Map();
  17214. this.numPoints = 0;
  17215. this.lastAddPointsTimestamp = undefined;
  17216. this.mouse = new Vector2(0, 0);
  17217. this.scale = new Vector3(1, 1, 1);
  17218. this.autoFitEnabled = true; // completely disable/enable
  17219. this.autoFit = false; // internal
  17220. var cwIcon = "".concat(exports.resourcePath, "/icons/arrow_cw.svg");
  17221. $('#potree_profile_rotate_cw').attr('src', cwIcon);
  17222. var ccwIcon = "".concat(exports.resourcePath, "/icons/arrow_ccw.svg");
  17223. $('#potree_profile_rotate_ccw').attr('src', ccwIcon);
  17224. var forwardIcon = "".concat(exports.resourcePath, "/icons/arrow_up.svg");
  17225. $('#potree_profile_move_forward').attr('src', forwardIcon);
  17226. var backwardIcon = "".concat(exports.resourcePath, "/icons/arrow_down.svg");
  17227. $('#potree_profile_move_backward').attr('src', backwardIcon);
  17228. var csvIcon = "".concat(exports.resourcePath, "/icons/file_csv_2d.svg");
  17229. $('#potree_download_csv_icon').attr('src', csvIcon);
  17230. var lasIcon = "".concat(exports.resourcePath, "/icons/file_las_3d.svg");
  17231. $('#potree_download_las_icon').attr('src', lasIcon);
  17232. var closeIcon = "".concat(exports.resourcePath, "/icons/close.svg");
  17233. $('#closeProfileContainer').attr("src", closeIcon);
  17234. this.initTHREE();
  17235. this.initSVG();
  17236. this.initListeners();
  17237. this.pRenderer = new Renderer(this.renderer);
  17238. this.elRoot.i18n();
  17239. }
  17240. initListeners() {
  17241. $(window).resize(() => {
  17242. if (this.enabled) {
  17243. this.render();
  17244. }
  17245. });
  17246. this.renderArea.mousedown(e => {
  17247. this.mouseIsDown = true;
  17248. });
  17249. this.renderArea.mouseup(e => {
  17250. this.mouseIsDown = false;
  17251. });
  17252. var viewerPickSphereSizeHandler = () => {
  17253. var camera = this.viewer.scene.getActiveCamera();
  17254. var domElement = this.viewer.renderer.domElement;
  17255. var distance = this.viewerPickSphere.position.distanceTo(camera.position);
  17256. var pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
  17257. var scale = 10 / pr;
  17258. this.viewerPickSphere.scale.set(scale, scale, scale);
  17259. };
  17260. this.renderArea.mousemove(e => {
  17261. if (this.pointclouds.size === 0) {
  17262. return;
  17263. }
  17264. var rect = this.renderArea[0].getBoundingClientRect();
  17265. var x = e.clientX - rect.left;
  17266. var y = e.clientY - rect.top;
  17267. var newMouse = new Vector2(x, y);
  17268. if (this.mouseIsDown) {
  17269. // DRAG
  17270. this.autoFit = false;
  17271. this.lastDrag = new Date().getTime();
  17272. var cPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  17273. var ncPos = [this.scaleX.invert(newMouse.x), this.scaleY.invert(newMouse.y)];
  17274. this.camera.position.x -= ncPos[0] - cPos[0];
  17275. this.camera.position.z -= ncPos[1] - cPos[1];
  17276. this.render();
  17277. } else if (this.pointclouds.size > 0) {
  17278. // FIND HOVERED POINT
  17279. var radius = Math.abs(this.scaleX.invert(0) - this.scaleX.invert(40));
  17280. var mileage = this.scaleX.invert(newMouse.x);
  17281. var elevation = this.scaleY.invert(newMouse.y);
  17282. var closest = this.selectPoint(mileage, elevation, radius);
  17283. if (closest) {
  17284. var point = closest.point;
  17285. var position = new Float64Array([point.position[0] + closest.pointcloud.position.x, point.position[1] + closest.pointcloud.position.y, point.position[2] + closest.pointcloud.position.z]);
  17286. this.elRoot.find('#profileSelectionProperties').fadeIn(200);
  17287. this.pickSphere.visible = true;
  17288. this.pickSphere.scale.set(0.5 * radius, 0.5 * radius, 0.5 * radius);
  17289. this.pickSphere.position.set(point.mileage, 0, position[2]);
  17290. this.viewerPickSphere.position.set(...position);
  17291. if (!this.viewer.scene.scene.children.includes(this.viewerPickSphere)) {
  17292. this.viewer.scene.scene.add(this.viewerPickSphere);
  17293. if (!this.viewer.hasEventListener("update", viewerPickSphereSizeHandler)) {
  17294. this.viewer.addEventListener("update", viewerPickSphereSizeHandler);
  17295. }
  17296. }
  17297. var info = this.elRoot.find('#profileSelectionProperties');
  17298. var html = '<table>';
  17299. var _loop = function _loop() {
  17300. var value = point[attributeName];
  17301. var attribute = closest.pointcloud.getAttribute(attributeName);
  17302. var transform = value => value;
  17303. if (attribute && attribute.type.size > 4) {
  17304. var range = attribute.initialRange;
  17305. var scale = 1 / (range[1] - range[0]);
  17306. var offset = range[0];
  17307. transform = value => value / scale + offset;
  17308. }
  17309. if (attributeName === 'position') {
  17310. var values = [...position].map(v => Utils.addCommas(v.toFixed(3)));
  17311. html += "\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>x</td>\n\t\t\t\t\t\t\t\t\t<td>".concat(values[0], "</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>y</td>\n\t\t\t\t\t\t\t\t\t<td>").concat(values[1], "</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>z</td>\n\t\t\t\t\t\t\t\t\t<td>").concat(values[2], "</td>\n\t\t\t\t\t\t\t\t</tr>");
  17312. } else if (attributeName === 'rgba') {
  17313. html += "\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>".concat(attributeName, "</td>\n\t\t\t\t\t\t\t\t\t<td>").concat(value.join(', '), "</td>\n\t\t\t\t\t\t\t\t</tr>");
  17314. } else if (attributeName === 'normal') {
  17315. return 1; // continue
  17316. } else if (attributeName === 'mileage') {
  17317. html += "\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>".concat(attributeName, "</td>\n\t\t\t\t\t\t\t\t\t<td>").concat(value.toFixed(3), "</td>\n\t\t\t\t\t\t\t\t</tr>");
  17318. } else {
  17319. html += "\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>".concat(attributeName, "</td>\n\t\t\t\t\t\t\t\t\t<td>").concat(transform(value), "</td>\n\t\t\t\t\t\t\t\t</tr>");
  17320. }
  17321. };
  17322. for (var attributeName of Object.keys(point)) {
  17323. if (_loop()) continue;
  17324. }
  17325. html += '</table>';
  17326. info.html(html);
  17327. this.selectedPoint = point;
  17328. } else {
  17329. // this.pickSphere.visible = false;
  17330. // this.selectedPoint = null;
  17331. this.viewer.scene.scene.add(this.viewerPickSphere);
  17332. var index = this.viewer.scene.scene.children.indexOf(this.viewerPickSphere);
  17333. if (index >= 0) {
  17334. this.viewer.scene.scene.children.splice(index, 1);
  17335. }
  17336. this.viewer.removeEventListener("update", viewerPickSphereSizeHandler);
  17337. }
  17338. this.render();
  17339. }
  17340. this.mouse.copy(newMouse);
  17341. });
  17342. var onWheel = e => {
  17343. this.autoFit = false;
  17344. var delta = 0;
  17345. if (e.wheelDelta !== undefined) {
  17346. // WebKit / Opera / Explorer 9
  17347. delta = e.wheelDelta;
  17348. } else if (e.detail !== undefined) {
  17349. // Firefox
  17350. delta = -e.detail;
  17351. }
  17352. var ndelta = Math.sign(delta);
  17353. var cPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  17354. if (ndelta > 0) {
  17355. // + 10%
  17356. this.scale.multiplyScalar(1.1);
  17357. } else {
  17358. // - 10%
  17359. this.scale.multiplyScalar(100 / 110);
  17360. }
  17361. this.updateScales();
  17362. var ncPos = [this.scaleX.invert(this.mouse.x), this.scaleY.invert(this.mouse.y)];
  17363. this.camera.position.x -= ncPos[0] - cPos[0];
  17364. this.camera.position.z -= ncPos[1] - cPos[1];
  17365. this.render();
  17366. this.updateScales();
  17367. };
  17368. $(this.renderArea)[0].addEventListener('mousewheel', onWheel, false);
  17369. $(this.renderArea)[0].addEventListener('DOMMouseScroll', onWheel, false); // Firefox
  17370. $('#closeProfileContainer').click(() => {
  17371. this.hide();
  17372. });
  17373. var getProfilePoints = () => {
  17374. var points = new Points$1();
  17375. for (var [pointcloud, entry] of this.pointclouds) {
  17376. for (var pointSet of entry.points) {
  17377. var originPos = pointSet.data.position;
  17378. var trueElevationPosition = new Float32Array(originPos);
  17379. for (var i = 0; i < pointSet.numPoints; i++) {
  17380. trueElevationPosition[3 * i + 2] += pointcloud.position.z;
  17381. }
  17382. pointSet.data.position = trueElevationPosition;
  17383. points.add(pointSet);
  17384. pointSet.data.position = originPos;
  17385. }
  17386. }
  17387. return points;
  17388. };
  17389. $('#potree_download_csv_icon').click(() => {
  17390. var points = getProfilePoints();
  17391. var string = CSVExporter.toString(points);
  17392. var blob = new Blob([string], {
  17393. type: "text/string"
  17394. });
  17395. $('#potree_download_profile_ortho_link').attr('href', URL.createObjectURL(blob));
  17396. });
  17397. $('#potree_download_las_icon').click(() => {
  17398. var points = getProfilePoints();
  17399. var buffer = LASExporter.toLAS(points);
  17400. var blob = new Blob([buffer], {
  17401. type: "application/octet-binary"
  17402. });
  17403. $('#potree_download_profile_link').attr('href', URL.createObjectURL(blob));
  17404. });
  17405. }
  17406. selectPoint(mileage, elevation, radius) {
  17407. var closest = {
  17408. distance: Infinity,
  17409. pointcloud: null,
  17410. points: null,
  17411. index: null
  17412. };
  17413. var pointBox = new Box2(new Vector2(mileage - radius, elevation - radius), new Vector2(mileage + radius, elevation + radius));
  17414. var numTested = 0;
  17415. var numSkipped = 0;
  17416. var numTestedPoints = 0;
  17417. var numSkippedPoints = 0;
  17418. for (var [pointcloud, entry] of this.pointclouds) {
  17419. for (var points of entry.points) {
  17420. var collisionBox = new Box2(new Vector2(points.projectedBox.min.x, points.projectedBox.min.z), new Vector2(points.projectedBox.max.x, points.projectedBox.max.z));
  17421. var intersects = collisionBox.intersectsBox(pointBox);
  17422. if (!intersects) {
  17423. numSkipped++;
  17424. numSkippedPoints += points.numPoints;
  17425. continue;
  17426. }
  17427. numTested++;
  17428. numTestedPoints += points.numPoints;
  17429. for (var i = 0; i < points.numPoints; i++) {
  17430. var m = points.data.mileage[i] - mileage;
  17431. var e = points.data.position[3 * i + 2] - elevation + pointcloud.position.z;
  17432. var r = Math.sqrt(m * m + e * e);
  17433. var withinDistance = r < radius && r < closest.distance;
  17434. var unfilteredClass = true;
  17435. if (points.data.classification) {
  17436. var classification = pointcloud.material.classification;
  17437. var pointClassID = points.data.classification[i];
  17438. var pointClassValue = classification[pointClassID];
  17439. if (pointClassValue && (!pointClassValue.visible || pointClassValue.color.w === 0)) {
  17440. unfilteredClass = false;
  17441. }
  17442. }
  17443. if (withinDistance && unfilteredClass) {
  17444. closest = {
  17445. distance: r,
  17446. pointcloud: pointcloud,
  17447. points: points,
  17448. index: i
  17449. };
  17450. }
  17451. }
  17452. }
  17453. }
  17454. //console.log(`nodes: ${numTested}, ${numSkipped} || points: ${numTestedPoints}, ${numSkippedPoints}`);
  17455. if (closest.distance < Infinity) {
  17456. var _points = closest.points;
  17457. var point = {};
  17458. var attributes = Object.keys(_points.data);
  17459. for (var attribute of attributes) {
  17460. var attributeData = _points.data[attribute];
  17461. var itemSize = attributeData.length / _points.numPoints;
  17462. var value = attributeData.subarray(itemSize * closest.index, itemSize * closest.index + itemSize);
  17463. if (value.length === 1) {
  17464. point[attribute] = value[0];
  17465. } else {
  17466. point[attribute] = value;
  17467. }
  17468. }
  17469. closest.point = point;
  17470. return closest;
  17471. } else {
  17472. return null;
  17473. }
  17474. }
  17475. initTHREE() {
  17476. this.renderer = new WebGLRenderer({
  17477. alpha: true,
  17478. premultipliedAlpha: false
  17479. });
  17480. this.renderer.setClearColor(0x000000, 0);
  17481. this.renderer.setSize(10, 10);
  17482. this.renderer.autoClear = false;
  17483. this.renderArea.append($(this.renderer.domElement));
  17484. this.renderer.domElement.tabIndex = '2222';
  17485. $(this.renderer.domElement).css('width', '100%');
  17486. $(this.renderer.domElement).css('height', '100%');
  17487. {
  17488. var gl = this.renderer.getContext();
  17489. if (gl.createVertexArray == null) {
  17490. var extVAO = gl.getExtension('OES_vertex_array_object');
  17491. if (!extVAO) {
  17492. throw new Error("OES_vertex_array_object extension not supported");
  17493. }
  17494. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  17495. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  17496. }
  17497. }
  17498. this.camera = new OrthographicCamera(-1000, 1000, 1000, -1000, -1000, 1000);
  17499. this.camera.up.set(0, 0, 1);
  17500. this.camera.rotation.order = "ZXY";
  17501. this.camera.rotation.x = Math.PI / 2.0;
  17502. this.scene = new Scene();
  17503. this.profileScene = new Scene();
  17504. var sg = new SphereGeometry(1, 16, 16);
  17505. var sm = new MeshNormalMaterial();
  17506. this.pickSphere = new Mesh(sg, sm);
  17507. this.scene.add(this.pickSphere);
  17508. this.viewerPickSphere = new Mesh(sg, sm);
  17509. }
  17510. initSVG() {
  17511. var width = this.renderArea[0].clientWidth;
  17512. var height = this.renderArea[0].clientHeight;
  17513. var marginLeft = this.renderArea[0].offsetLeft;
  17514. this.svg.selectAll('*').remove();
  17515. this.scaleX = d3.scale.linear().domain([this.camera.left + this.camera.position.x, this.camera.right + this.camera.position.x]).range([0, width]);
  17516. this.scaleY = d3.scale.linear().domain([this.camera.bottom + this.camera.position.z, this.camera.top + this.camera.position.z]).range([height, 0]);
  17517. this.xAxis = d3.svg.axis().scale(this.scaleX).orient('bottom').innerTickSize(-height).outerTickSize(1).tickPadding(10).ticks(width / 50);
  17518. this.yAxis = d3.svg.axis().scale(this.scaleY).orient('left').innerTickSize(-width).outerTickSize(1).tickPadding(10).ticks(height / 20);
  17519. this.elXAxis = this.svg.append('g').attr('class', 'x axis').attr('transform', "translate(".concat(marginLeft, ", ").concat(height, ")")).call(this.xAxis);
  17520. this.elYAxis = this.svg.append('g').attr('class', 'y axis').attr('transform', "translate(".concat(marginLeft, ", 0)")).call(this.yAxis);
  17521. }
  17522. addPoints(pointcloud, points) {
  17523. if (points.numPoints === 0) {
  17524. return;
  17525. }
  17526. var entry = this.pointclouds.get(pointcloud);
  17527. if (!entry) {
  17528. entry = new ProfileFakeOctree(pointcloud);
  17529. this.pointclouds.set(pointcloud, entry);
  17530. this.profileScene.add(entry);
  17531. var materialChanged = () => {
  17532. this.render();
  17533. };
  17534. materialChanged();
  17535. pointcloud.material.addEventListener('material_property_changed', materialChanged);
  17536. this.addEventListener("on_reset_once", () => {
  17537. pointcloud.material.removeEventListener('material_property_changed', materialChanged);
  17538. });
  17539. }
  17540. entry.addPoints(points);
  17541. this.projectedBox.union(entry.projectedBox);
  17542. if (this.autoFit && this.autoFitEnabled) {
  17543. var width = this.renderArea[0].clientWidth;
  17544. var height = this.renderArea[0].clientHeight;
  17545. var size = this.projectedBox.getSize(new Vector3());
  17546. var sx = width / size.x;
  17547. var sy = height / size.z;
  17548. var scale = Math.min(sx, sy);
  17549. var center = this.projectedBox.getCenter(new Vector3());
  17550. this.scale.set(scale, scale, 1);
  17551. this.camera.position.copy(center);
  17552. //console.log("camera: ", this.camera.position.toArray().join(", "));
  17553. }
  17554. //console.log(entry);
  17555. this.render();
  17556. var numPoints = 0;
  17557. for (var [key, value] of this.pointclouds.entries()) {
  17558. numPoints += value.points.reduce((a, i) => a + i.numPoints, 0);
  17559. }
  17560. $("#profile_num_points").html(Utils.addCommas(numPoints));
  17561. }
  17562. reset() {
  17563. this.lastReset = new Date().getTime();
  17564. this.dispatchEvent({
  17565. type: "on_reset_once"
  17566. });
  17567. this.removeEventListeners("on_reset_once");
  17568. this.autoFit = true;
  17569. this.projectedBox = new Box3();
  17570. for (var [key, entry] of this.pointclouds) {
  17571. entry.dispose();
  17572. }
  17573. this.pointclouds.clear();
  17574. this.mouseIsDown = false;
  17575. this.mouse.set(0, 0);
  17576. if (this.autoFitEnabled) {
  17577. this.scale.set(1, 1, 1);
  17578. }
  17579. this.pickSphere.visible = false;
  17580. this.elRoot.find('#profileSelectionProperties').hide();
  17581. this.render();
  17582. }
  17583. show() {
  17584. this.elRoot.fadeIn();
  17585. this.enabled = true;
  17586. }
  17587. hide() {
  17588. this.elRoot.fadeOut();
  17589. this.enabled = false;
  17590. }
  17591. updateScales() {
  17592. var width = this.renderArea[0].clientWidth;
  17593. var height = this.renderArea[0].clientHeight;
  17594. var left = -width / 2 / this.scale.x;
  17595. var right = +width / 2 / this.scale.x;
  17596. var top = +height / 2 / this.scale.y;
  17597. var bottom = -height / 2 / this.scale.y;
  17598. this.camera.left = left;
  17599. this.camera.right = right;
  17600. this.camera.top = top;
  17601. this.camera.bottom = bottom;
  17602. this.camera.updateProjectionMatrix();
  17603. this.scaleX.domain([this.camera.left + this.camera.position.x, this.camera.right + this.camera.position.x]).range([0, width]);
  17604. this.scaleY.domain([this.camera.bottom + this.camera.position.z, this.camera.top + this.camera.position.z]).range([height, 0]);
  17605. var marginLeft = this.renderArea[0].offsetLeft;
  17606. this.xAxis.scale(this.scaleX).orient('bottom').innerTickSize(-height).outerTickSize(1).tickPadding(10).ticks(width / 50);
  17607. this.yAxis.scale(this.scaleY).orient('left').innerTickSize(-width).outerTickSize(1).tickPadding(10).ticks(height / 20);
  17608. this.elXAxis.attr('transform', "translate(".concat(marginLeft, ", ").concat(height, ")")).call(this.xAxis);
  17609. this.elYAxis.attr('transform', "translate(".concat(marginLeft, ", 0)")).call(this.yAxis);
  17610. }
  17611. requestScaleUpdate() {
  17612. var threshold = 100;
  17613. var allowUpdate = this.lastReset === undefined || this.lastScaleUpdate === undefined || new Date().getTime() - this.lastReset > threshold && new Date().getTime() - this.lastScaleUpdate > threshold;
  17614. if (allowUpdate) {
  17615. this.updateScales();
  17616. this.lastScaleUpdate = new Date().getTime();
  17617. this.scaleUpdatePending = false;
  17618. } else if (!this.scaleUpdatePending) {
  17619. setTimeout(this.requestScaleUpdate.bind(this), 100);
  17620. this.scaleUpdatePending = true;
  17621. }
  17622. }
  17623. render() {
  17624. var width = this.renderArea[0].clientWidth;
  17625. var height = this.renderArea[0].clientHeight;
  17626. var {
  17627. renderer,
  17628. pRenderer,
  17629. camera,
  17630. profileScene,
  17631. scene
  17632. } = this;
  17633. var {
  17634. scaleX,
  17635. pickSphere
  17636. } = this;
  17637. renderer.setSize(width, height);
  17638. renderer.setClearColor(0x000000, 0);
  17639. renderer.clear(true, true, false);
  17640. for (var pointcloud of this.pointclouds.keys()) {
  17641. var source = pointcloud.material;
  17642. var target = this.pointclouds.get(pointcloud).material;
  17643. copyMaterial(source, target);
  17644. target.size = 2;
  17645. }
  17646. pRenderer.render(profileScene, camera, null);
  17647. var radius = Math.abs(scaleX.invert(0) - scaleX.invert(5));
  17648. if (radius === 0) {
  17649. pickSphere.visible = false;
  17650. } else {
  17651. pickSphere.scale.set(radius, radius, radius);
  17652. pickSphere.visible = true;
  17653. }
  17654. renderer.render(scene, camera);
  17655. this.requestScaleUpdate();
  17656. }
  17657. }
  17658. ;
  17659. class ProfileWindowController {
  17660. constructor(viewer) {
  17661. this.viewer = viewer;
  17662. this.profileWindow = viewer.profileWindow;
  17663. this.profile = null;
  17664. this.numPoints = 0;
  17665. this.threshold = 60 * 1000;
  17666. this.rotateAmount = 10;
  17667. this.scheduledRecomputeTime = null;
  17668. this.enabled = true;
  17669. this.requests = [];
  17670. this._recompute = () => {
  17671. this.recompute();
  17672. };
  17673. this.viewer.addEventListener("scene_changed", e => {
  17674. e.oldScene.removeEventListener("pointcloud_added", this._recompute);
  17675. e.scene.addEventListener("pointcloud_added", this._recompute);
  17676. });
  17677. this.viewer.scene.addEventListener("pointcloud_added", this._recompute);
  17678. $("#potree_profile_rotate_amount").val(parseInt(this.rotateAmount));
  17679. $("#potree_profile_rotate_amount").on("input", e => {
  17680. var str = $("#potree_profile_rotate_amount").val();
  17681. if (!isNaN(str)) {
  17682. var value = parseFloat(str);
  17683. this.rotateAmount = value;
  17684. $("#potree_profile_rotate_amount").css("background-color", "");
  17685. } else {
  17686. $("#potree_profile_rotate_amount").css("background-color", "#ff9999");
  17687. }
  17688. });
  17689. var rotate = radians => {
  17690. var profile = this.profile;
  17691. var points = profile.points;
  17692. var start = points[0];
  17693. var end = points[points.length - 1];
  17694. var center = start.clone().add(end).multiplyScalar(0.5);
  17695. var mMoveOrigin = new Matrix4().makeTranslation(-center.x, -center.y, -center.z);
  17696. var mRotate = new Matrix4().makeRotationZ(radians);
  17697. var mMoveBack = new Matrix4().makeTranslation(center.x, center.y, center.z);
  17698. //const transform = mMoveOrigin.multiply(mRotate).multiply(mMoveBack);
  17699. var transform = mMoveBack.multiply(mRotate).multiply(mMoveOrigin);
  17700. var rotatedPoints = points.map(point => point.clone().applyMatrix4(transform));
  17701. this.profileWindow.autoFitEnabled = false;
  17702. for (var i = 0; i < points.length; i++) {
  17703. profile.setPosition(i, rotatedPoints[i]);
  17704. }
  17705. };
  17706. $("#potree_profile_rotate_cw").click(() => {
  17707. var radians = MathUtils.degToRad(this.rotateAmount);
  17708. rotate(-radians);
  17709. });
  17710. $("#potree_profile_rotate_ccw").click(() => {
  17711. var radians = MathUtils.degToRad(this.rotateAmount);
  17712. rotate(radians);
  17713. });
  17714. $("#potree_profile_move_forward").click(() => {
  17715. var profile = this.profile;
  17716. var points = profile.points;
  17717. var start = points[0];
  17718. var end = points[points.length - 1];
  17719. var dir = end.clone().sub(start).normalize();
  17720. var up = new Vector3(0, 0, 1);
  17721. var forward = up.cross(dir);
  17722. var move = forward.clone().multiplyScalar(profile.width / 2);
  17723. this.profileWindow.autoFitEnabled = false;
  17724. for (var i = 0; i < points.length; i++) {
  17725. profile.setPosition(i, points[i].clone().add(move));
  17726. }
  17727. });
  17728. $("#potree_profile_move_backward").click(() => {
  17729. var profile = this.profile;
  17730. var points = profile.points;
  17731. var start = points[0];
  17732. var end = points[points.length - 1];
  17733. var dir = end.clone().sub(start).normalize();
  17734. var up = new Vector3(0, 0, 1);
  17735. var forward = up.cross(dir);
  17736. var move = forward.clone().multiplyScalar(-profile.width / 2);
  17737. this.profileWindow.autoFitEnabled = false;
  17738. for (var i = 0; i < points.length; i++) {
  17739. profile.setPosition(i, points[i].clone().add(move));
  17740. }
  17741. });
  17742. }
  17743. setProfile(profile) {
  17744. if (this.profile !== null && this.profile !== profile) {
  17745. this.profile.removeEventListener('marker_moved', this._recompute);
  17746. this.profile.removeEventListener('marker_added', this._recompute);
  17747. this.profile.removeEventListener('marker_removed', this._recompute);
  17748. this.profile.removeEventListener('width_changed', this._recompute);
  17749. }
  17750. this.profile = profile;
  17751. {
  17752. this.profile.addEventListener('marker_moved', this._recompute);
  17753. this.profile.addEventListener('marker_added', this._recompute);
  17754. this.profile.addEventListener('marker_removed', this._recompute);
  17755. this.profile.addEventListener('width_changed', this._recompute);
  17756. }
  17757. this.recompute();
  17758. }
  17759. reset() {
  17760. this.profileWindow.reset();
  17761. this.numPoints = 0;
  17762. if (this.profile) {
  17763. for (var request of this.requests) {
  17764. request.cancel();
  17765. }
  17766. }
  17767. }
  17768. progressHandler(pointcloud, progress) {
  17769. for (var segment of progress.segments) {
  17770. this.profileWindow.addPoints(pointcloud, segment.points);
  17771. this.numPoints += segment.points.numPoints;
  17772. }
  17773. }
  17774. cancel() {
  17775. for (var request of this.requests) {
  17776. request.cancel();
  17777. // request.finishLevelThenCancel();
  17778. }
  17779. this.requests = [];
  17780. }
  17781. finishLevelThenCancel() {
  17782. for (var request of this.requests) {
  17783. request.finishLevelThenCancel();
  17784. }
  17785. this.requests = [];
  17786. }
  17787. recompute() {
  17788. var _this = this;
  17789. if (!this.profile) {
  17790. return;
  17791. }
  17792. if (this.scheduledRecomputeTime !== null && this.scheduledRecomputeTime > new Date().getTime()) {
  17793. return;
  17794. } else {
  17795. this.scheduledRecomputeTime = new Date().getTime() + 100;
  17796. }
  17797. this.scheduledRecomputeTime = null;
  17798. this.reset();
  17799. var _loop2 = function _loop2(pointcloud) {
  17800. var request = pointcloud.getPointsInProfile(_this.profile, null, {
  17801. 'onProgress': event => {
  17802. if (!_this.enabled) {
  17803. return;
  17804. }
  17805. _this.progressHandler(pointcloud, event.points);
  17806. if (_this.numPoints > _this.threshold) {
  17807. _this.finishLevelThenCancel();
  17808. }
  17809. },
  17810. 'onFinish': event => {
  17811. if (!_this.enabled) {}
  17812. },
  17813. 'onCancel': () => {
  17814. if (!_this.enabled) {}
  17815. }
  17816. });
  17817. _this.requests.push(request);
  17818. };
  17819. for (var pointcloud of this.viewer.scene.pointclouds.filter(p => p.visible)) {
  17820. _loop2(pointcloud);
  17821. }
  17822. }
  17823. }
  17824. ;
  17825. //import { EventDispatcher } from "../EventDispatcher.js";
  17826. class VolumeTool extends EventDispatcher {
  17827. constructor(viewer) {
  17828. super();
  17829. this.viewer = viewer;
  17830. this.renderer = viewer.renderer;
  17831. this.addEventListener('start_inserting_volume', e => {
  17832. this.viewer.dispatchEvent({
  17833. type: 'cancel_insertions'
  17834. });
  17835. });
  17836. this.scene = new Scene();
  17837. this.scene.name = 'scene_volume';
  17838. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  17839. this.onRemove = e => {
  17840. this.scene.remove(e.volume);
  17841. };
  17842. this.onAdd = e => {
  17843. this.scene.add(e.volume);
  17844. };
  17845. for (var volume of viewer.scene.volumes) {
  17846. this.onAdd({
  17847. volume: volume
  17848. });
  17849. }
  17850. this.viewer.inputHandler.addEventListener('delete', e => {
  17851. var volumes = e.selection.filter(e => e instanceof Volume);
  17852. volumes.forEach(e => this.viewer.scene.removeVolume(e));
  17853. });
  17854. viewer.addEventListener("update", this.update.bind(this));
  17855. viewer.addEventListener("render.pass.scene", e => this.render(e));
  17856. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  17857. viewer.scene.addEventListener('volume_added', this.onAdd);
  17858. viewer.scene.addEventListener('volume_removed', this.onRemove);
  17859. }
  17860. onSceneChange(e) {
  17861. if (e.oldScene) {
  17862. e.oldScene.removeEventListeners('volume_added', this.onAdd);
  17863. e.oldScene.removeEventListeners('volume_removed', this.onRemove);
  17864. }
  17865. e.scene.addEventListener('volume_added', this.onAdd);
  17866. e.scene.addEventListener('volume_removed', this.onRemove);
  17867. }
  17868. startInsertion() {
  17869. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  17870. var volume;
  17871. if (args.type) {
  17872. volume = new args.type();
  17873. } else {
  17874. volume = new BoxVolume();
  17875. }
  17876. volume.clip = args.clip || false;
  17877. volume.name = args.name || 'Volume';
  17878. this.dispatchEvent({
  17879. type: 'start_inserting_volume',
  17880. volume: volume
  17881. });
  17882. this.viewer.scene.addVolume(volume);
  17883. this.scene.add(volume);
  17884. var cancel = {
  17885. callback: null
  17886. };
  17887. var drag = e => {
  17888. var camera = this.viewer.scene.getActiveCamera();
  17889. var I = Utils.getMousePointCloudIntersection(e.drag.end, this.viewer.scene.getActiveCamera(), this.viewer, this.viewer.scene.pointclouds, {
  17890. pickClipped: false
  17891. });
  17892. if (I) {
  17893. volume.position.copy(I.location);
  17894. var wp = volume.getWorldPosition(new Vector3()).applyMatrix4(camera.matrixWorldInverse);
  17895. // let pp = new THREE.Vector4(wp.x, wp.y, wp.z).applyMatrix4(camera.projectionMatrix);
  17896. var w = Math.abs(wp.z / 5);
  17897. volume.scale.set(w, w, w);
  17898. }
  17899. };
  17900. var drop = e => {
  17901. volume.removeEventListener('drag', drag);
  17902. volume.removeEventListener('drop', drop);
  17903. cancel.callback();
  17904. };
  17905. cancel.callback = e => {
  17906. volume.removeEventListener('drag', drag);
  17907. volume.removeEventListener('drop', drop);
  17908. this.viewer.removeEventListener('cancel_insertions', cancel.callback);
  17909. };
  17910. volume.addEventListener('drag', drag);
  17911. volume.addEventListener('drop', drop);
  17912. this.viewer.addEventListener('cancel_insertions', cancel.callback);
  17913. this.viewer.inputHandler.startDragging(volume);
  17914. return volume;
  17915. }
  17916. update() {
  17917. if (!this.viewer.scene) {
  17918. return;
  17919. }
  17920. var camera = this.viewer.scene.getActiveCamera();
  17921. var renderAreaSize = this.viewer.renderer.getSize(new Vector2());
  17922. var clientWidth = renderAreaSize.width;
  17923. var clientHeight = renderAreaSize.height;
  17924. var volumes = this.viewer.scene.volumes;
  17925. for (var volume of volumes) {
  17926. var label = volume.label;
  17927. {
  17928. var distance = label.position.distanceTo(camera.position);
  17929. var pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  17930. var scale = 70 / pr;
  17931. label.scale.set(scale, scale, scale);
  17932. }
  17933. var calculatedVolume = volume.getVolume();
  17934. 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
  17935. var text = Utils.addCommas(calculatedVolume.toFixed(3)) + ' ' + this.viewer.lengthUnitDisplay.code + '\u00B3';
  17936. label.setText(text);
  17937. }
  17938. }
  17939. render(params) {
  17940. var renderer = this.viewer.renderer;
  17941. var oldTarget = renderer.getRenderTarget();
  17942. if (params.renderTarget) {
  17943. renderer.setRenderTarget(params.renderTarget);
  17944. }
  17945. renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  17946. renderer.setRenderTarget(oldTarget);
  17947. }
  17948. }
  17949. /**
  17950. *
  17951. * code adapted from three.js BoxHelper.js
  17952. * https://github.com/mrdoob/three.js/blob/dev/src/helpers/BoxHelper.js
  17953. *
  17954. * @author mrdoob / http://mrdoob.com/
  17955. * @author Mugen87 / http://github.com/Mugen87
  17956. * @author mschuetz / http://potree.org
  17957. */
  17958. class Box3Helper$1 extends LineSegments {
  17959. constructor(box, color) {
  17960. var depthTest = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  17961. if (color === undefined) color = 0xffff00;
  17962. var 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]);
  17963. var positions = new Float32Array([box.min.x, box.min.y, box.min.z, box.max.x, box.min.y, box.min.z, box.max.x, box.min.y, box.max.z, box.min.x, box.min.y, box.max.z, box.min.x, box.max.y, box.min.z, box.max.x, box.max.y, box.min.z, box.max.x, box.max.y, box.max.z, box.min.x, box.max.y, box.max.z]);
  17964. var geometry = new BufferGeometry();
  17965. geometry.setIndex(new BufferAttribute(indices, 1));
  17966. geometry.setAttribute('position', new BufferAttribute(positions, 3));
  17967. var material = new LineBasicMaterial({
  17968. color: color,
  17969. depthTest
  17970. });
  17971. super(geometry, material);
  17972. }
  17973. }
  17974. var KeyCodes = {
  17975. LEFT: 37,
  17976. UP: 38,
  17977. RIGHT: 39,
  17978. BOTTOM: 40,
  17979. DELETE: 46,
  17980. A: 'A'.charCodeAt(0),
  17981. S: 'S'.charCodeAt(0),
  17982. D: 'D'.charCodeAt(0),
  17983. W: 'W'.charCodeAt(0),
  17984. Q: 'Q'.charCodeAt(0),
  17985. E: 'E'.charCodeAt(0),
  17986. R: 'R'.charCodeAt(0),
  17987. F: 'F'.charCodeAt(0)
  17988. };
  17989. class NormalizationMaterial extends RawShaderMaterial {
  17990. constructor() {
  17991. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  17992. super();
  17993. var uniforms = {
  17994. uDepthMap: {
  17995. type: 't',
  17996. value: null
  17997. },
  17998. uWeightMap: {
  17999. type: 't',
  18000. value: null
  18001. }
  18002. };
  18003. this.setValues({
  18004. uniforms: uniforms,
  18005. vertexShader: this.getDefines() + Shaders['normalize.vs'],
  18006. fragmentShader: this.getDefines() + Shaders['normalize.fs']
  18007. });
  18008. }
  18009. getDefines() {
  18010. var defines = '';
  18011. return defines;
  18012. }
  18013. updateShaderSource() {
  18014. var vs = this.getDefines() + Shaders['normalize.vs'];
  18015. var fs = this.getDefines() + Shaders['normalize.fs'];
  18016. this.setValues({
  18017. vertexShader: vs,
  18018. fragmentShader: fs
  18019. });
  18020. this.needsUpdate = true;
  18021. }
  18022. }
  18023. class NormalizationEDLMaterial extends RawShaderMaterial {
  18024. constructor() {
  18025. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  18026. super();
  18027. var uniforms = {
  18028. screenWidth: {
  18029. type: 'f',
  18030. value: 0
  18031. },
  18032. screenHeight: {
  18033. type: 'f',
  18034. value: 0
  18035. },
  18036. edlStrength: {
  18037. type: 'f',
  18038. value: 1.0
  18039. },
  18040. radius: {
  18041. type: 'f',
  18042. value: 1.0
  18043. },
  18044. neighbours: {
  18045. type: '2fv',
  18046. value: []
  18047. },
  18048. uEDLMap: {
  18049. type: 't',
  18050. value: null
  18051. },
  18052. uDepthMap: {
  18053. type: 't',
  18054. value: null
  18055. },
  18056. uWeightMap: {
  18057. type: 't',
  18058. value: null
  18059. }
  18060. };
  18061. this.setValues({
  18062. uniforms: uniforms,
  18063. vertexShader: this.getDefines() + Shaders['normalize.vs'],
  18064. fragmentShader: this.getDefines() + Shaders['normalize_and_edl.fs']
  18065. });
  18066. this.neighbourCount = 8;
  18067. }
  18068. getDefines() {
  18069. var defines = '';
  18070. defines += '#define NEIGHBOUR_COUNT ' + this.neighbourCount + '\n';
  18071. return defines;
  18072. }
  18073. updateShaderSource() {
  18074. var vs = this.getDefines() + Shaders['normalize.vs'];
  18075. var fs = this.getDefines() + Shaders['normalize_and_edl.fs'];
  18076. this.setValues({
  18077. vertexShader: vs,
  18078. fragmentShader: fs
  18079. });
  18080. this.uniforms.neighbours.value = this.neighbours;
  18081. this.needsUpdate = true;
  18082. }
  18083. get neighbourCount() {
  18084. return this._neighbourCount;
  18085. }
  18086. set neighbourCount(value) {
  18087. if (this._neighbourCount !== value) {
  18088. this._neighbourCount = value;
  18089. this.neighbours = new Float32Array(this._neighbourCount * 2);
  18090. for (var c = 0; c < this._neighbourCount; c++) {
  18091. this.neighbours[2 * c + 0] = Math.cos(2 * c * Math.PI / this._neighbourCount);
  18092. this.neighbours[2 * c + 1] = Math.sin(2 * c * Math.PI / this._neighbourCount);
  18093. }
  18094. this.updateShaderSource();
  18095. }
  18096. }
  18097. }
  18098. //在potree.shim中修改。 。official中用不到且有bug
  18099. class HQSplatRenderer {
  18100. constructor(viewer) {
  18101. this.viewer = viewer;
  18102. this.depthMaterials = new Map();
  18103. this.attributeMaterials = new Map();
  18104. this.normalizationMaterial = null;
  18105. this.rtDepth = null;
  18106. this.rtAttribute = null;
  18107. this.gl = viewer.renderer.getContext();
  18108. this.initialized = false;
  18109. }
  18110. init() {
  18111. if (this.initialized) {
  18112. return;
  18113. }
  18114. this.normalizationMaterial = new NormalizationMaterial();
  18115. this.normalizationMaterial.depthTest = true;
  18116. this.normalizationMaterial.depthWrite = true;
  18117. this.normalizationMaterial.transparent = true;
  18118. this.normalizationEDLMaterial = new NormalizationEDLMaterial();
  18119. this.normalizationEDLMaterial.depthTest = true;
  18120. this.normalizationEDLMaterial.depthWrite = true;
  18121. this.normalizationEDLMaterial.transparent = true;
  18122. this.rtDepth = new WebGLRenderTarget(1024, 1024, {
  18123. minFilter: NearestFilter,
  18124. magFilter: NearestFilter,
  18125. format: RGBAFormat,
  18126. type: FloatType,
  18127. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  18128. });
  18129. this.rtAttribute = new WebGLRenderTarget(1024, 1024, {
  18130. minFilter: NearestFilter,
  18131. magFilter: NearestFilter,
  18132. format: RGBAFormat,
  18133. type: FloatType,
  18134. depthTexture: this.rtDepth.depthTexture
  18135. });
  18136. this.initialized = true;
  18137. }
  18138. resize(width, height) {
  18139. this.rtDepth.setSize(width, height);
  18140. this.rtAttribute.setSize(width, height);
  18141. }
  18142. clearTargets() {
  18143. var viewer = this.viewer;
  18144. var {
  18145. renderer
  18146. } = viewer;
  18147. var oldTarget = renderer.getRenderTarget();
  18148. renderer.setClearColor(0x000000, 0);
  18149. renderer.setRenderTarget(this.rtDepth);
  18150. renderer.clear(true, true, true);
  18151. renderer.setRenderTarget(this.rtAttribute);
  18152. renderer.clear(true, true, true);
  18153. renderer.setRenderTarget(oldTarget);
  18154. }
  18155. clear() {
  18156. this.init();
  18157. var {
  18158. renderer,
  18159. background
  18160. } = this.viewer;
  18161. if (background === "skybox") {
  18162. renderer.setClearColor(0x000000, 0);
  18163. } else if (background === 'gradient') {
  18164. renderer.setClearColor(0x000000, 0);
  18165. } else if (background === 'black') {
  18166. renderer.setClearColor(0x000000, 1);
  18167. } else if (background === 'white') {
  18168. renderer.setClearColor(0xFFFFFF, 1);
  18169. } else {
  18170. renderer.setClearColor(0x000000, 0);
  18171. }
  18172. renderer.clear();
  18173. this.clearTargets();
  18174. }
  18175. render(params) {
  18176. this.init();
  18177. var viewer = this.viewer;
  18178. var camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  18179. var {
  18180. width,
  18181. height
  18182. } = this.viewer.renderer.getSize(new Vector2());
  18183. viewer.dispatchEvent({
  18184. type: "render.pass.begin",
  18185. viewer: viewer
  18186. });
  18187. this.resize(width, height);
  18188. var visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
  18189. var originalMaterials = new Map();
  18190. for (var pointcloud of visiblePointClouds) {
  18191. originalMaterials.set(pointcloud, pointcloud.material);
  18192. if (!this.attributeMaterials.has(pointcloud)) {
  18193. var attributeMaterial = new PointCloudMaterial$1();
  18194. this.attributeMaterials.set(pointcloud, attributeMaterial);
  18195. }
  18196. if (!this.depthMaterials.has(pointcloud)) {
  18197. var depthMaterial = new PointCloudMaterial$1();
  18198. depthMaterial.setDefine("depth_pass", "#define hq_depth_pass");
  18199. depthMaterial.setDefine("use_edl", "#define use_edl");
  18200. this.depthMaterials.set(pointcloud, depthMaterial);
  18201. }
  18202. }
  18203. {
  18204. // DEPTH PASS
  18205. for (var _pointcloud of visiblePointClouds) {
  18206. var octreeSize = _pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  18207. var material = originalMaterials.get(_pointcloud);
  18208. var _depthMaterial = this.depthMaterials.get(_pointcloud);
  18209. _depthMaterial.size = material.size;
  18210. _depthMaterial.minSize = material.minSize;
  18211. _depthMaterial.maxSize = material.maxSize;
  18212. _depthMaterial.pointSizeType = material.pointSizeType;
  18213. _depthMaterial.visibleNodesTexture = material.visibleNodesTexture;
  18214. _depthMaterial.weighted = false;
  18215. _depthMaterial.screenWidth = width;
  18216. _depthMaterial.shape = PointShape$1.CIRCLE;
  18217. _depthMaterial.screenHeight = height;
  18218. _depthMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  18219. _depthMaterial.uniforms.octreeSize.value = octreeSize;
  18220. _depthMaterial.spacing = _pointcloud.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  18221. _depthMaterial.classification = material.classification;
  18222. _depthMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  18223. _depthMaterial.classificationTexture.needsUpdate = true;
  18224. _depthMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  18225. _depthMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  18226. _depthMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  18227. _depthMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  18228. _depthMaterial.clipTask = material.clipTask;
  18229. _depthMaterial.clipMethod = material.clipMethod;
  18230. _depthMaterial.setClipBoxes(material.clipBoxes);
  18231. _depthMaterial.setClipPolygons(material.clipPolygons);
  18232. _pointcloud.material = _depthMaterial;
  18233. }
  18234. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtDepth, {
  18235. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume$1)
  18236. });
  18237. }
  18238. {
  18239. // ATTRIBUTE PASS
  18240. for (var _pointcloud2 of visiblePointClouds) {
  18241. var _octreeSize = _pointcloud2.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  18242. var _material = originalMaterials.get(_pointcloud2);
  18243. var _attributeMaterial = this.attributeMaterials.get(_pointcloud2);
  18244. _attributeMaterial.size = _material.size;
  18245. _attributeMaterial.minSize = _material.minSize;
  18246. _attributeMaterial.maxSize = _material.maxSize;
  18247. _attributeMaterial.pointSizeType = _material.pointSizeType;
  18248. _attributeMaterial.activeAttributeName = _material.activeAttributeName;
  18249. _attributeMaterial.visibleNodesTexture = _material.visibleNodesTexture;
  18250. _attributeMaterial.weighted = true;
  18251. _attributeMaterial.screenWidth = width;
  18252. _attributeMaterial.screenHeight = height;
  18253. _attributeMaterial.shape = PointShape$1.CIRCLE;
  18254. _attributeMaterial.uniforms.visibleNodes.value = _material.visibleNodesTexture;
  18255. _attributeMaterial.uniforms.octreeSize.value = _octreeSize;
  18256. _attributeMaterial.spacing = _pointcloud2.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  18257. _attributeMaterial.classification = _material.classification;
  18258. _attributeMaterial.uniforms.classificationLUT.value.image.data = _material.uniforms.classificationLUT.value.image.data;
  18259. _attributeMaterial.classificationTexture.needsUpdate = true;
  18260. _attributeMaterial.uniforms.uFilterReturnNumberRange.value = _material.uniforms.uFilterReturnNumberRange.value;
  18261. _attributeMaterial.uniforms.uFilterNumberOfReturnsRange.value = _material.uniforms.uFilterNumberOfReturnsRange.value;
  18262. _attributeMaterial.uniforms.uFilterGPSTimeClipRange.value = _material.uniforms.uFilterGPSTimeClipRange.value;
  18263. _attributeMaterial.uniforms.uFilterPointSourceIDClipRange.value = _material.uniforms.uFilterPointSourceIDClipRange.value;
  18264. _attributeMaterial.elevationGradientRepeat = _material.elevationGradientRepeat;
  18265. _attributeMaterial.elevationRange = _material.elevationRange;
  18266. _attributeMaterial.gradient = _material.gradient;
  18267. _attributeMaterial.matcap = _material.matcap;
  18268. _attributeMaterial.intensityRange = _material.intensityRange;
  18269. _attributeMaterial.intensityGamma = _material.intensityGamma;
  18270. _attributeMaterial.intensityContrast = _material.intensityContrast;
  18271. _attributeMaterial.intensityBrightness = _material.intensityBrightness;
  18272. _attributeMaterial.rgbGamma = _material.rgbGamma;
  18273. _attributeMaterial.rgbContrast = _material.rgbContrast;
  18274. _attributeMaterial.rgbBrightness = _material.rgbBrightness;
  18275. _attributeMaterial.weightRGB = _material.weightRGB;
  18276. _attributeMaterial.weightIntensity = _material.weightIntensity;
  18277. _attributeMaterial.weightElevation = _material.weightElevation;
  18278. _attributeMaterial.weightRGB = _material.weightRGB;
  18279. _attributeMaterial.weightClassification = _material.weightClassification;
  18280. _attributeMaterial.weightReturnNumber = _material.weightReturnNumber;
  18281. _attributeMaterial.weightSourceID = _material.weightSourceID;
  18282. _attributeMaterial.color = _material.color;
  18283. _attributeMaterial.clipTask = _material.clipTask;
  18284. _attributeMaterial.clipMethod = _material.clipMethod;
  18285. _attributeMaterial.setClipBoxes(_material.clipBoxes);
  18286. _attributeMaterial.setClipPolygons(_material.clipPolygons);
  18287. _pointcloud2.material = _attributeMaterial;
  18288. }
  18289. var gl = this.gl;
  18290. viewer.renderer.setRenderTarget(null);
  18291. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtAttribute, {
  18292. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume$1),
  18293. //material: this.attributeMaterial,
  18294. blendFunc: [gl.SRC_ALPHA, gl.ONE],
  18295. //depthTest: false,
  18296. depthWrite: false
  18297. });
  18298. }
  18299. for (var [_pointcloud3, _material2] of originalMaterials) {
  18300. _pointcloud3.material = _material2;
  18301. }
  18302. viewer.renderer.setRenderTarget(null);
  18303. if (viewer.background === "skybox") {
  18304. viewer.renderer.setClearColor(0x000000, 0);
  18305. viewer.renderer.clear();
  18306. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  18307. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  18308. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  18309. viewer.skybox.parent.rotation.x = 0;
  18310. viewer.skybox.parent.updateMatrixWorld();
  18311. viewer.skybox.camera.updateProjectionMatrix();
  18312. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  18313. } else if (viewer.background === 'gradient') {
  18314. viewer.renderer.setClearColor(0x000000, 0);
  18315. viewer.renderer.clear();
  18316. viewer.renderer.render(viewer.scene.sceneBG, viewer.scene.cameraBG);
  18317. } else if (viewer.background === 'black') {
  18318. viewer.renderer.setClearColor(0x000000, 1);
  18319. viewer.renderer.clear();
  18320. } else if (viewer.background === 'white') {
  18321. viewer.renderer.setClearColor(0xFFFFFF, 1);
  18322. viewer.renderer.clear();
  18323. } else {
  18324. viewer.renderer.setClearColor(0x000000, 0);
  18325. viewer.renderer.clear();
  18326. }
  18327. {
  18328. // NORMALIZATION PASS
  18329. var normalizationMaterial = this.useEDL ? this.normalizationEDLMaterial : this.normalizationMaterial;
  18330. if (this.useEDL) {
  18331. normalizationMaterial.uniforms.edlStrength.value = viewer.edlStrength;
  18332. normalizationMaterial.uniforms.radius.value = viewer.edlRadius;
  18333. normalizationMaterial.uniforms.screenWidth.value = width;
  18334. normalizationMaterial.uniforms.screenHeight.value = height;
  18335. normalizationMaterial.uniforms.uEDLMap.value = this.rtDepth.texture;
  18336. }
  18337. normalizationMaterial.uniforms.uWeightMap.value = this.rtAttribute.texture;
  18338. normalizationMaterial.uniforms.uDepthMap.value = this.rtAttribute.depthTexture;
  18339. Utils.screenPass.render(viewer.renderer, normalizationMaterial);
  18340. }
  18341. viewer.renderer.render(viewer.scene.scene, camera);
  18342. viewer.dispatchEvent({
  18343. type: "render.pass.scene",
  18344. viewer: viewer
  18345. });
  18346. viewer.renderer.clearDepth();
  18347. viewer.transformationTool.update();
  18348. viewer.dispatchEvent({
  18349. type: "render.pass.perspective_overlay",
  18350. viewer: viewer
  18351. });
  18352. viewer.renderer.render(viewer.controls.sceneControls, camera);
  18353. viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
  18354. viewer.renderer.render(viewer.transformationTool.scene, camera);
  18355. viewer.renderer.setViewport(width - viewer.navigationCube.width, height - viewer.navigationCube.width, viewer.navigationCube.width, viewer.navigationCube.width);
  18356. viewer.renderer.render(viewer.navigationCube, viewer.navigationCube.camera);
  18357. viewer.renderer.setViewport(0, 0, width, height);
  18358. viewer.dispatchEvent({
  18359. type: "render.pass.end",
  18360. viewer: viewer
  18361. });
  18362. }
  18363. }
  18364. class LRUItem {
  18365. constructor(node) {
  18366. this.previous = null;
  18367. this.next = null;
  18368. this.node = node;
  18369. }
  18370. }
  18371. /**
  18372. *
  18373. * @class A doubly-linked-list of the least recently used elements.
  18374. */
  18375. class LRU {
  18376. constructor() {
  18377. //类似链表存储
  18378. // the least recently used item
  18379. this.first = null;
  18380. // the most recently used item
  18381. this.last = null;
  18382. // a list of all items in the lru list
  18383. this.items = {}; //按node的id存储。(id为0的就是root,name='r')
  18384. this.elements = 0;
  18385. this.numPoints = 0;
  18386. }
  18387. size() {
  18388. return this.elements;
  18389. }
  18390. contains(node) {
  18391. return this.items[node.id] == null;
  18392. }
  18393. touch(node) {
  18394. //链接node,并且永远放在最后. (每次updatePointClouds都要刷新一次链表)
  18395. if (!node.loaded) {
  18396. return;
  18397. }
  18398. var item;
  18399. if (this.items[node.id] == null) {
  18400. // add to list
  18401. item = new LRUItem(node);
  18402. item.previous = this.last;
  18403. this.last = item;
  18404. if (item.previous !== null) {
  18405. item.previous.next = item;
  18406. }
  18407. this.items[node.id] = item;
  18408. this.elements++;
  18409. if (this.first === null) {
  18410. this.first = item;
  18411. }
  18412. this.numPoints += node.numPoints;
  18413. } else {
  18414. // update in list
  18415. item = this.items[node.id];
  18416. if (item.previous === null) {
  18417. // handle touch on first element
  18418. if (item.next !== null) {
  18419. this.first = item.next;
  18420. this.first.previous = null;
  18421. item.previous = this.last;
  18422. item.next = null;
  18423. this.last = item;
  18424. item.previous.next = item;
  18425. }
  18426. } else if (item.next === null) {
  18427. // handle touch on last element
  18428. } else {
  18429. //从原来的位置挑出放最后
  18430. // handle touch on any other element
  18431. item.previous.next = item.next;
  18432. item.next.previous = item.previous;
  18433. item.previous = this.last;
  18434. item.next = null;
  18435. this.last = item;
  18436. item.previous.next = item;
  18437. }
  18438. }
  18439. }
  18440. //因为需要显示的都放末尾,所以不显示的部分都在前面,删除时从头删除。(但并不代表开头的一定是不显示的,所以如果第一个仍是显示的,它很可能是root,也就是name='r'的nodeGeo,删除它也就会删除全部)
  18441. remove(node) {
  18442. var lruItem = this.items[node.id];
  18443. if (lruItem) {
  18444. if (this.elements === 1) {
  18445. this.first = null;
  18446. this.last = null;
  18447. } else {
  18448. if (!lruItem.previous) {
  18449. this.first = lruItem.next;
  18450. this.first.previous = null;
  18451. }
  18452. if (!lruItem.next) {
  18453. this.last = lruItem.previous;
  18454. this.last.next = null;
  18455. }
  18456. if (lruItem.previous && lruItem.next) {
  18457. lruItem.previous.next = lruItem.next;
  18458. lruItem.next.previous = lruItem.previous;
  18459. }
  18460. }
  18461. delete this.items[node.id];
  18462. this.elements--;
  18463. this.numPoints -= node.numPoints;
  18464. }
  18465. }
  18466. getLRUItem() {
  18467. if (this.first === null) {
  18468. return null;
  18469. }
  18470. var lru = this.first;
  18471. return lru.node;
  18472. }
  18473. toString() {
  18474. var string = '{ ';
  18475. var curr = this.first;
  18476. while (curr !== null) {
  18477. string += curr.node.id;
  18478. if (curr.next !== null) {
  18479. string += ', ';
  18480. }
  18481. curr = curr.next;
  18482. }
  18483. string += '}';
  18484. string += '(' + this.size() + ')';
  18485. return string;
  18486. }
  18487. freeMemory() {
  18488. if (this.elements <= 1) {
  18489. return;
  18490. }
  18491. while (this.numPoints > Potree.pointLoadLimit) {
  18492. var element = this.first;
  18493. var node = element.node;
  18494. this.disposeDescendants(node);
  18495. }
  18496. }
  18497. disposeDescendants(node) {
  18498. var stack = [];
  18499. stack.push(node);
  18500. while (stack.length > 0) {
  18501. var current = stack.pop();
  18502. // console.log(current);
  18503. current.dispose(); //真正删除geometry等
  18504. this.remove(current);
  18505. for (var key in current.children) {
  18506. if (current.children.hasOwnProperty(key)) {
  18507. var child = current.children[key];
  18508. if (child.loaded) {
  18509. stack.push(current.children[key]);
  18510. }
  18511. }
  18512. }
  18513. }
  18514. }
  18515. }
  18516. //
  18517. // how to calculate the radius of a projected sphere in screen space
  18518. // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
  18519. // http://stackoverflow.com/questions/3717226/radius-of-projected-sphere
  18520. //
  18521. class ExtendPointCloudMaterial extends PointCloudMaterial$1 {
  18522. constructor() {
  18523. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  18524. super(parameters);
  18525. var getValid = (a, b) => {
  18526. if (a !== undefined) {
  18527. return a;
  18528. } else {
  18529. return b;
  18530. }
  18531. };
  18532. var maxSize = getValid(parameters.maxSize, 200.0);
  18533. var orthoMaxSize = getValid(parameters.orthoMaxSize, 3.0);
  18534. this._gradient = Gradients.ir; //Gradients.SPECTRAL;//海拔贴图种类,火灾也是这个
  18535. this.gradientTexture = ExtendPointCloudMaterial.generateGradientTexture(this._gradient);
  18536. this.classificationName = null;
  18537. delete this.uniforms.screenWidth;
  18538. delete this.uniforms.screenHeight;
  18539. delete this.uniforms.clipBoxes;
  18540. delete this.uniforms.clipPolygons;
  18541. delete this.uniforms.clipPolygonVCount;
  18542. delete this.uniforms.clipPolygonVP;
  18543. delete this.uniforms.clipBoxCount;
  18544. //注意:这里修改了uniforms后,还需要在PotreeRender中手动传递到shader, like: gl.uniformMatrix4fv(....
  18545. Object.assign(this.uniforms, {
  18546. resolution: {
  18547. type: 'v2',
  18548. value: new Vector2()
  18549. },
  18550. maxSize: {
  18551. type: "f",
  18552. value: maxSize
  18553. },
  18554. orthoMaxSize: {
  18555. type: "f",
  18556. value: orthoMaxSize
  18557. },
  18558. gradient: {
  18559. type: "t",
  18560. value: this.gradientTexture
  18561. },
  18562. clipBoxes_in: {
  18563. type: "Matrix4fv",
  18564. value: []
  18565. },
  18566. clipBoxes_out: {
  18567. type: "Matrix4fv",
  18568. value: []
  18569. },
  18570. clipBoxBig_in: {
  18571. type: "Matrix4fv",
  18572. value: []
  18573. },
  18574. boxes_highlight: {
  18575. type: "Matrix4fv",
  18576. value: []
  18577. },
  18578. progress: {
  18579. type: "f",
  18580. value: 0
  18581. },
  18582. easeInOutRatio: {
  18583. type: "f",
  18584. value: 0.3
  18585. },
  18586. pano0Map: {
  18587. type: "t",
  18588. value: null
  18589. },
  18590. pano0Position: {
  18591. type: "v3",
  18592. value: new Vector3()
  18593. },
  18594. pano0Matrix: {
  18595. type: "m4",
  18596. value: new Matrix4()
  18597. },
  18598. pano1Map: {
  18599. type: "t",
  18600. value: null
  18601. },
  18602. pano1Position: {
  18603. type: "v3",
  18604. value: new Vector3()
  18605. },
  18606. pano1Matrix: {
  18607. type: "m4",
  18608. value: new Matrix4()
  18609. },
  18610. prismList: {
  18611. type: "Matrix3fv",
  18612. value: null
  18613. },
  18614. prismPoints: {
  18615. type: "vec2fv",
  18616. value: null
  18617. },
  18618. baseHeightAreaMap: {
  18619. type: 't',
  18620. value: null
  18621. },
  18622. baseHeightBoundZ: {
  18623. type: 'vec2',
  18624. value: new Vector2()
  18625. },
  18626. baseHeightBoundXY: {
  18627. type: 'vec4',
  18628. value: new Vector4()
  18629. },
  18630. temperRange: {
  18631. //温度范围
  18632. type: 'vec2',
  18633. value: new Vector2(math.getKelvinFromCelsius(99), math.getKelvinFromCelsius(1500)) //火场温度
  18634. }
  18635. });
  18636. delete this.clipBoxes;
  18637. this.clipBoxes_in = [];
  18638. this.clipBoxes_out = [];
  18639. this.highlightBoxes = [];
  18640. this.prisms = [];
  18641. var {
  18642. vs,
  18643. fs
  18644. } = Common$1.changeShaderToWebgl2(Shaders['pointcloud_new.vs'], Shaders['pointcloud_new.fs'], 'selfBuild');
  18645. Shaders['pointcloud_new.vs'] = vs;
  18646. Shaders['pointcloud_new.fs'] = fs;
  18647. {
  18648. var setClass = () => {
  18649. this.classification = viewer.classifications;
  18650. this.recomputeClassification();
  18651. };
  18652. viewer.addEventListener('classifications_changed', setClass);
  18653. viewer.addEventListener('classification_visibility_changed', setClass);
  18654. setClass();
  18655. }
  18656. this.updateShaderSource();
  18657. }
  18658. /* get classificationName(){
  18659. return this.classificationName_
  18660. }
  18661. set classificationName(name){//add
  18662. if(this.classificationName_ != name){
  18663. this.classificationName_ = name
  18664. this.classification = ClassificationScheme[name]
  18665. this.recomputeClassification();
  18666. }
  18667. } */
  18668. updateShaderSource() {
  18669. var vs = Shaders['pointcloud_new.vs']; //改
  18670. var fs = Shaders['pointcloud_new.fs']; //改
  18671. var definesString = this.getDefines();
  18672. var vsVersionIndex = vs.indexOf("#version ");
  18673. var fsVersionIndex = fs.indexOf("#version ");
  18674. if (vsVersionIndex >= 0) {
  18675. vs = vs.replace(/(#version .*)/, "$1\n".concat(definesString));
  18676. } else {
  18677. vs = "".concat(definesString, "\n").concat(vs);
  18678. }
  18679. if (fsVersionIndex >= 0) {
  18680. fs = fs.replace(/(#version .*)/, "$1\n".concat(definesString));
  18681. } else {
  18682. fs = "".concat(definesString, "\n").concat(fs);
  18683. }
  18684. this.vertexShader = vs;
  18685. this.fragmentShader = fs;
  18686. if (this.opacity === 1.0 && !this.useFilterByNormal) {
  18687. //add useFilterByNormal
  18688. this.blending = NoBlending;
  18689. this.transparent = false;
  18690. this.depthTest = true;
  18691. this.depthWrite = true;
  18692. this.depthFunc = LessEqualDepth;
  18693. } else if ((this.opacity < 1.0 || this.useFilterByNormal) && !this.useEDL) {
  18694. //add useFilterByNormal
  18695. this.blending = AdditiveBlending;
  18696. this.transparent = true;
  18697. this.depthTest = false;
  18698. this.depthWrite = true;
  18699. this.depthFunc = AlwaysDepth;
  18700. }
  18701. if (this.weighted) {
  18702. this.blending = AdditiveBlending;
  18703. this.transparent = true;
  18704. this.depthTest = true;
  18705. this.depthWrite = false;
  18706. }
  18707. this.shaderNeedsUpdate = true;
  18708. }
  18709. getDefines() {
  18710. var defines = [];
  18711. if (this.pointSizeType === PointSizeType.FIXED) {
  18712. defines.push('#define fixed_point_size');
  18713. } else if (this.pointSizeType === PointSizeType.ATTENUATED) {
  18714. defines.push('#define attenuated_point_size');
  18715. } else if (this.pointSizeType === PointSizeType.ADAPTIVE) {
  18716. defines.push('#define adaptive_point_size');
  18717. }
  18718. if (!Features.EXT_DEPTH.isSupported(viewer.renderer.getContext()) && this.shape === PointShape$1.PARABOLOID) {
  18719. this.shape = PointShape$1.SQUARE; //强行替换
  18720. }
  18721. if (this.shape === PointShape$1.SQUARE) {
  18722. defines.push('#define square_point_shape');
  18723. } else if (this.shape === PointShape$1.CIRCLE) {
  18724. defines.push('#define circle_point_shape');
  18725. } else if (this.shape === PointShape$1.PARABOLOID) {
  18726. defines.push('#define paraboloid_point_shape');
  18727. }
  18728. //console.log('this.shape PARABOLOID', this.shape, this.shape === PointShape.PARABOLOID)
  18729. if (this._useEDL || this.fakeEDL) {
  18730. defines.push('#define use_edl');
  18731. }
  18732. if (this.activeAttributeName) {
  18733. var attributeName = this.activeAttributeName.replace(/[^a-zA-Z0-9]/g, '_');
  18734. defines.push("#define color_type_".concat(attributeName));
  18735. }
  18736. if (this._treeType === TreeType.OCTREE) {
  18737. defines.push('#define tree_type_octree');
  18738. } else if (this._treeType === TreeType.KDTREE) {
  18739. defines.push('#define tree_type_kdtree');
  18740. }
  18741. if (this.weighted) {
  18742. defines.push('#define weighted_splats');
  18743. }
  18744. for (var [key, value] of this.defines) {
  18745. defines.push(value);
  18746. }
  18747. return defines.join("\n");
  18748. }
  18749. get pointSizeType() {
  18750. return this._pointSizeType;
  18751. }
  18752. set pointSizeType(value) {
  18753. if (typeof value == 'string') value = PointSizeType[value];
  18754. super.pointSizeType = value;
  18755. /* if (this._pointSizeType !== value) {
  18756. this._pointSizeType = value;
  18757. this.updateShaderSource(); //这句表明这个属性频繁更改会卡顿
  18758. this.dispatchEvent({
  18759. type: 'point_size_type_changed',
  18760. target: this
  18761. });
  18762. this.dispatchEvent({
  18763. type: 'material_property_changed',
  18764. target: this
  18765. });
  18766. } */
  18767. }
  18768. get color() {
  18769. return this.uniforms.uColor.value;
  18770. }
  18771. set color(value) {
  18772. //改
  18773. if (value == this.color_) return;
  18774. var color = value;
  18775. //if (!this.uniforms.uColor.value.equals(value)) {
  18776. if (typeof value == 'string') {
  18777. var colorArr = Potree.config.colors[value];
  18778. if (!colorArr) {
  18779. //console.warn('没找到该颜色值'+ value)
  18780. } else {
  18781. color = new Color().fromArray(colorArr).multiplyScalar(1 / 255);
  18782. }
  18783. }
  18784. this.uniforms.uColor.value.set(color);
  18785. //this.uniforms.uColor.value.copy(value);
  18786. this.dispatchEvent({
  18787. type: 'color_changed',
  18788. target: this
  18789. });
  18790. this.dispatchEvent({
  18791. type: 'material_property_changed',
  18792. target: this
  18793. });
  18794. //}
  18795. this.color_ = value; //记录下str
  18796. }
  18797. ////////////////////////add
  18798. setProjectedPanos(pano0, pano1, progressValue, easeInOutRatio) {
  18799. //this.uniforms.usePanoMap.value = 1
  18800. this.usePanoMap = true;
  18801. progressValue != void 0 && (this.uniforms.progress.value = progressValue);
  18802. //pano0.ensureSkyboxReadyForRender();
  18803. this.uniforms.pano0Map.value = pano0.getSkyboxTexture();
  18804. this.uniforms.pano0Position.value.copy(pano0.position);
  18805. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix);
  18806. //pano1.ensureSkyboxReadyForRender();
  18807. this.uniforms.easeInOutRatio.value = easeInOutRatio || 0; //之前做点云和全景混合时加的,为了让点云颜色柔和切换到全景颜色。如不混合就0
  18808. this.uniforms.pano1Map.value = pano1.getSkyboxTexture();
  18809. this.uniforms.pano1Position.value.copy(pano1.position);
  18810. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix);
  18811. //this.updateShaderSource()
  18812. //this.needsUpdate = true;
  18813. }
  18814. stopProjectedPanos() {
  18815. //this.uniforms.usePanoMap.value = 0
  18816. this.usePanoMap = false;
  18817. }
  18818. setClipBoxes(bigClipInBox, clipBoxes_in, clipBoxes_out, highlightBoxes) {
  18819. var prismPolygons = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
  18820. if (!clipBoxes_in || !clipBoxes_out) {
  18821. return;
  18822. }
  18823. this.uniforms.clipBoxBig_in.value = bigClipInBox && bigClipInBox.inverse;
  18824. this.uniforms.clipBoxes_in.value = new Float32Array(clipBoxes_in.length * 16);
  18825. this.uniforms.clipBoxes_out.value = new Float32Array(clipBoxes_out.length * 16);
  18826. this.uniforms.boxes_highlight.value = new Float32Array(highlightBoxes.length * 16);
  18827. for (var i = 0; i < clipBoxes_in.length; i++) {
  18828. var box = clipBoxes_in[i];
  18829. this.uniforms.clipBoxes_in.value.set(box.inverse.elements, 16 * i);
  18830. }
  18831. for (var _i = 0; _i < clipBoxes_out.length; _i++) {
  18832. var _box = clipBoxes_out[_i];
  18833. this.uniforms.clipBoxes_out.value.set(_box.inverse.elements, 16 * _i);
  18834. }
  18835. for (var _i2 = 0; _i2 < highlightBoxes.length; _i2++) {
  18836. var _box2 = highlightBoxes[_i2];
  18837. this.uniforms.boxes_highlight.value.set(_box2.inverse.elements, 16 * _i2);
  18838. }
  18839. /* for (let i = 0; i < this.uniforms.clipBoxes.value.length; i++) {??
  18840. if (Number.isNaN(this.uniforms.clipBoxes.value[i])) {
  18841. this.uniforms.clipBoxes.value[i] = Infinity;
  18842. }
  18843. } */
  18844. if (prismPolygons.length) {
  18845. var pointsCount = prismPolygons.pointsCount = prismPolygons.reduce((w, c) => {
  18846. return w + c.points.length;
  18847. }, 0);
  18848. this.uniforms.prismList.value = new Float32Array(9 * prismPolygons.length);
  18849. this.uniforms.prismPoints.value = new Float32Array(2 * pointsCount);
  18850. prismPolygons.maxPointsCount = 0; //单个prism最大点个数
  18851. var pointIndex = 0;
  18852. for (var _i3 = 0; _i3 < prismPolygons.length; _i3++) {
  18853. var bound = prismPolygons[_i3].prismBound;
  18854. var z = prismPolygons[_i3].horizonZ;
  18855. //z = Potree.browser.urlHasValue('zmin',true) || zs[0]
  18856. this.uniforms.prismList.value.set([bound.min.z, z, bound.max.z, bound.min.x, bound.max.x, bound.min.y, bound.max.y, prismPolygons[_i3].points.length], 9 * _i3);
  18857. for (var j = 0; j < prismPolygons[_i3].points.length; j++) {
  18858. this.uniforms.prismPoints.value.set([prismPolygons[_i3].points[j].x, prismPolygons[_i3].points[j].y], 2 * j + pointIndex);
  18859. }
  18860. pointIndex += 2 * prismPolygons[_i3].points.length;
  18861. prismPolygons.maxPointsCount = Math.max(prismPolygons.maxPointsCount, prismPolygons[_i3].points.length);
  18862. }
  18863. }
  18864. var doUpdate = this.clipBoxes_in.length !== clipBoxes_in.length || this.clipBoxes_out.length != clipBoxes_out.length || this.highlightBoxes.length !== highlightBoxes.length || !this.bigClipInBox != !bigClipInBox || this.prisms.length != prismPolygons.length || this.prisms.maxPointsCount != prismPolygons.maxPointsCount;
  18865. //this.clipBoxes = clipBoxes;
  18866. if (doUpdate) {
  18867. this.shaderNeedsUpdate = true;
  18868. viewer.dispatchEvent('content_changed');
  18869. }
  18870. this.bigClipInBox = bigClipInBox;
  18871. this.clipBoxes_in = clipBoxes_in;
  18872. this.clipBoxes_out = clipBoxes_out;
  18873. this.highlightBoxes = highlightBoxes;
  18874. this.prisms = prismPolygons;
  18875. }
  18876. setTempRange(min, max) {
  18877. //温度范围
  18878. this.uniforms.temperRange.value.set(math.getKelvinFromCelsius(min), math.getKelvinFromCelsius(max));
  18879. }
  18880. }
  18881. var defaultColor = new Color(1, 1, 1); //config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
  18882. function dealPosArr(points) {
  18883. //识别是否每个点都不一样,把连续点变为不连续的片段连接
  18884. var add = points => {
  18885. var points2 = [],
  18886. len = points.length;
  18887. for (var i = 0; i < len - 1; i++) {
  18888. points2.push(points[i], points[i + 1]);
  18889. }
  18890. return points2;
  18891. };
  18892. if (points[0] && points[0] instanceof Array) {
  18893. //多组,每组间连续,但组之间不连续
  18894. var points2 = [];
  18895. points.forEach(ps => points2.push(...add(ps)));
  18896. return points2;
  18897. } else if (points.length > 2 && !points[2].equals(points[1])) {
  18898. return add(points);
  18899. } else return points;
  18900. }
  18901. var LineDraw = {
  18902. createLine: function createLine(posArr) {
  18903. var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  18904. //多段普通线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  18905. var mat;
  18906. if (o.mat) {
  18907. mat = o.mat;
  18908. } else {
  18909. var prop = Object.assign({
  18910. lineWidth: o.lineWidth || 1,
  18911. //windows无效。 似乎mac/ios上粗细有效 ?
  18912. color: o.color || defaultColor
  18913. }, o);
  18914. if (o.deshed) {
  18915. prop.dashSize = o.dashSize || 0.1, prop.gapSize = o.gapSize || 0.1;
  18916. }
  18917. mat = new THREE$1[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"](prop);
  18918. }
  18919. var line = new LineSegments(new BufferGeometry(), mat);
  18920. line.renderOrder = o.renderOrder || Potree.config.renderOrders.line;
  18921. this.moveLine(line, posArr);
  18922. return line;
  18923. },
  18924. moveLine: function moveLine(line, posArr) {
  18925. //if(posArr.length == 0)return
  18926. if (!line.uncontinuous || posArr[0] && posArr[0] instanceof Array) posArr = dealPosArr(posArr);
  18927. var position = [];
  18928. posArr.forEach(e => position.push(e.x, e.y, e.z));
  18929. line.geometry.setAttribute('position', new Float32BufferAttribute( /* new Float32Array( */position /* ) */, 3));
  18930. line.geometry.attributes.position.needsUpdate = true;
  18931. line.geometry.computeBoundingSphere();
  18932. if (line.material instanceof LineDashedMaterial) {
  18933. line.computeLineDistances();
  18934. //line.geometry.attributes.lineDistance.needsUpdate = true;
  18935. line.geometry.verticesNeedUpdate = true; //没用
  18936. }
  18937. },
  18938. createFatLineMat: function createFatLineMat(o) {
  18939. var supportExtDepth = !!Features.EXT_DEPTH.isSupported();
  18940. var params = $.extend({}, {
  18941. //默认
  18942. lineWidth: 5,
  18943. color: 0xffffff,
  18944. transparent: true,
  18945. depthWrite: false,
  18946. depthTest: false,
  18947. dashSize: 0.1,
  18948. gapSize: 0.1
  18949. }, o, {
  18950. //修正覆盖:
  18951. dashed: o.dashWithDepth ? supportExtDepth && !!o.dashed : !!o.dashed,
  18952. dashWithDepth: !!o.dashWithDepth,
  18953. //只在被遮住的部分显示虚线
  18954. useDepth: !!o.useDepth,
  18955. supportExtDepth
  18956. });
  18957. var mat = new LineMaterial(params);
  18958. //if(o.dashed)(mat.defines.USE_DASH = "")
  18959. return mat;
  18960. },
  18961. /*
  18962. 创建可以改变粗细的线。
  18963. */
  18964. createFatLine: function createFatLine(posArr, o) {
  18965. var geometry = new LineGeometry();
  18966. geometry.setColors(o.color || [1, 1, 1]);
  18967. var matLine = o.mat || this.createFatLineMat(o);
  18968. var line = new Line2(geometry, matLine);
  18969. //line.computeLineDistances();
  18970. line.uncontinuous = o.uncontinuous; //线不连续,由线段组成
  18971. line.scale.set(1, 1, 1);
  18972. line.renderOrder = Potree.config.renderOrders.line;
  18973. this.moveFatLine(line, posArr);
  18974. return line;
  18975. },
  18976. moveFatLine: function moveFatLine(line, posArr) {
  18977. var geometry = line.geometry;
  18978. var positions = [];
  18979. if (!line.uncontinuous || posArr[0] && posArr[0] instanceof Array) posArr = dealPosArr(posArr);
  18980. posArr.forEach(e => {
  18981. positions.push(...e.toArray());
  18982. });
  18983. if (!geometry) {
  18984. geometry = line.geometry = new LineGeometry();
  18985. }
  18986. if (geometry.attributes.instanceEnd && geometry.attributes.instanceEnd.data.array.length != positions.length) {
  18987. //positions个数改变会有部分显示不出来,所以重建
  18988. geometry.dispose();
  18989. geometry = new LineGeometry();
  18990. line.geometry = geometry;
  18991. }
  18992. geometry.setPositions(positions);
  18993. if (line.material.defines.USE_DASH != void 0) {
  18994. //line.geometry.verticesNeedUpdate = true; //没用
  18995. line.geometry.computeBoundingSphere(); //for raycaster
  18996. line.computeLineDistances();
  18997. }
  18998. },
  18999. updateLine: function updateLine(line, posArr) {
  19000. if (line instanceof Line2) {
  19001. LineDraw.moveFatLine(line, posArr);
  19002. } else {
  19003. LineDraw.moveLine(line, posArr);
  19004. }
  19005. },
  19006. /*
  19007. 为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
  19008. 由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
  19009. */
  19010. createBoldLine: function createBoldLine(points, o) {
  19011. o = o || {};
  19012. var cylinder = o && o.cylinder;
  19013. var CD = points[1].clone().sub(points[0]);
  19014. var rotate = function rotate() {
  19015. //根据端点旋转好模型
  19016. cylinder.lastVector = CD; //记录本次的端点向量
  19017. var AB = new Vector3(0, -1, 0);
  19018. var axisVec = AB.clone().cross(CD).normalize(); //得到垂直于它们的向量,也就是旋转轴
  19019. var rotationAngle = AB.angleTo(CD);
  19020. cylinder.quaternion.setFromAxisAngle(axisVec, rotationAngle);
  19021. };
  19022. if (o && o.type == "init") {
  19023. cylinder = new Mesh();
  19024. cylinder.material = o.mat;
  19025. if (CD.length() == 0) return cylinder;
  19026. rotate();
  19027. }
  19028. if (CD.length() == 0) return cylinder;
  19029. if (o.type != "update") {
  19030. var CDcenter = points[0].clone().add(points[1]).multiplyScalar(.5);
  19031. cylinder.position.copy(CDcenter);
  19032. if (!cylinder.lastVector || o.type == "moveAndRotate") rotate();else if (cylinder.lastVector && CD.angleTo(cylinder.lastVector) > 0) rotate(); //线方向改了or线反向了 重新旋转一下模型
  19033. if (config.isEdit && !objects.mainDesign.editing) return cylinder; //节省初始加载时间?
  19034. }
  19035. //为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
  19036. var height = points[0].distanceTo(points[1]);
  19037. var standPos = o && o.standPos || objects.player.position;
  19038. var k = config.isMobile ? 20 : 40;
  19039. var dis1 = points[0].distanceTo(standPos);
  19040. var dis2 = points[1].distanceTo(standPos);
  19041. var foot = math.getFootPoint(standPos, points[0], points[1]); //垂足
  19042. if (o.constantBold || objects.player.mode != "panorama") {
  19043. var width = 0.1; //0.08;
  19044. var pts = [new Vector2(width, height / 2), new Vector2(width, -height / 2)];
  19045. } else if (foot.clone().sub(points[0]).dot(foot.clone().sub(points[1])) > 0) {
  19046. //foot不在线段上
  19047. var pts = [new Vector2(dis1 / k, height / 2), new Vector2(dis2 / k, -height / 2)];
  19048. } else {
  19049. //在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
  19050. var dis3 = foot.distanceTo(standPos);
  19051. var len = foot.distanceTo(points[0]);
  19052. var pts = [new Vector2(dis1 / k, height / 2), new Vector2(dis3 / k, height / 2 - len), new Vector2(dis2 / k, -height / 2)];
  19053. }
  19054. cylinder.geometry && cylinder.geometry.dispose(); //若不删除会占用内存
  19055. cylinder.geometry = new LatheBufferGeometry(pts, 4 /* Math.min(dis1,dis2)<10?4:3 */);
  19056. cylinder.renderOrder = 2;
  19057. return cylinder;
  19058. },
  19059. updateBoldLine: function updateBoldLine(cylinder, points, type, standPos, constantBold) {
  19060. this.createBoldLine(points, {
  19061. type: type,
  19062. cylinder: cylinder,
  19063. standPos: standPos,
  19064. constantBold
  19065. }); //type:move:平移 会改长短 , type:update根据距离和角度更新 不改长短
  19066. }
  19067. };
  19068. var MeshDraw = {
  19069. getShape: function getShape(shapes, holes) {
  19070. //不一定闭合 暂时所有shapes共享holes。如果要单独的话, shapes改为[{shape:[],holes:[]},{}]的形式
  19071. if (shapes[0] && !(shapes[0] instanceof Array)) {
  19072. //仅是一个shape的点
  19073. shapes = [shapes];
  19074. }
  19075. var holesArr = [];
  19076. if (holes) {
  19077. //挖空
  19078. holes.forEach(points => {
  19079. var holePath = new Path();
  19080. holePath.moveTo(points[0].x, points[0].y);
  19081. for (var i = 1, len = points.length; i < len; i++) {
  19082. holePath.lineTo(points[i].x, points[i].y);
  19083. }
  19084. holesArr.push(holePath);
  19085. });
  19086. }
  19087. var shapesArr = shapes.map(points => {
  19088. var shape = new Shape();
  19089. shape.moveTo(points[0].x, points[0].y);
  19090. for (var i = 1, len = points.length; i < len; i++) {
  19091. shape.lineTo(points[i].x, points[i].y);
  19092. }
  19093. shape.holes.push(...holesArr);
  19094. shape.dontClose = points.dontClose; //add 有的shape不需要闭合
  19095. return shape;
  19096. });
  19097. return shapesArr;
  19098. },
  19099. /* getShape:function(shapes, holes){
  19100. var shape = new THREE.Shape();
  19101. if(shapes[0] && !(shapes[0] instanceof Array) ){//仅是一个shape的点
  19102. shapes = [shapes]
  19103. }
  19104. shapes.forEach((points)=>{
  19105. shape.moveTo( points[0].x, points[0].y );
  19106. for(var i=1,len=points.length; i<len; i++){
  19107. shape.lineTo(points[i].x, points[i].y )
  19108. }
  19109. })
  19110. //多个points的数组绘制在一个shape中,缺点是这些数组之间可能绘制出来会连在一起。
  19111. if(holes){//挖空
  19112. holes.forEach((points)=>{
  19113. var holePath = new THREE.Path()
  19114. holePath.moveTo( points[0].x, points[0].y )
  19115. for(var i=1,len=points.length; i<len; i++){
  19116. holePath.lineTo(points[i].x, points[i].y )
  19117. }
  19118. shape.holes.push( holePath );
  19119. })
  19120. }
  19121. return shape
  19122. }, */
  19123. getShapeGeo: function getShapeGeo(shapes, holes) {
  19124. //获取任意形状(多边形或弧形)的形状面 //quadraticCurveTo() 这是弧形的含函数
  19125. var geometry = new ShapeBufferGeometry(this.getShape(shapes, holes)); //ShapeGeometry
  19126. /* var matrix = new THREE.Matrix4();//将竖直的面变为水平
  19127. matrix.set(//z = y
  19128. 1, 0, 0, 0,
  19129. 0, 0, 0, 0,
  19130. 0, 1, 0, 0,
  19131. 0, 0, 0, 1
  19132. )
  19133. geometry.applyMatrix(matrix) */
  19134. //geometry.computeVertexNormals();//对于光照需要的是点法线
  19135. return geometry;
  19136. },
  19137. lessCurvePoints: function lessCurvePoints(points, oldCount) {
  19138. var minRad = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.03;
  19139. var UtoTMapArr = arguments.length > 3 ? arguments[3] : undefined;
  19140. //减少点数(拐弯的部分紧凑些,直线部分宽松些):
  19141. var count = points.length;
  19142. var newUtoTMapArr = [];
  19143. var newPoints = [];
  19144. var pointIndexs = [];
  19145. var lastVec;
  19146. var startTime = performance.now();
  19147. /* if(UtoTMapArr){
  19148. for(let n=1;n<oldCount-1;n++){
  19149. pointIndexs.push( UtoTMapArr.findIndex(e=>e>= n / (oldCount-1) ) )
  19150. }
  19151. } */
  19152. //console.log('cost dur:', performance.now() - startTime )
  19153. var nextUtoTIndex = 1;
  19154. for (var i = 0; i < count; i++) {
  19155. var point = points[i];
  19156. var last = points[i - 1];
  19157. var next = points[i + 1];
  19158. if (i == 0 || i == count - 1) {
  19159. newPoints.push(point); //直接加入
  19160. UtoTMapArr && newUtoTMapArr.push(i == 0 ? 0 : 1);
  19161. } else {
  19162. var curVec = new Vector3().subVectors(next, point);
  19163. if (!lastVec) lastVec = curVec;
  19164. if (i > 1) {
  19165. // 和上一个加入点的vec之间的夹角如果过大就加入
  19166. var reachNextUToT = void 0; //找出新点中对应原先控制点的index,这些点必须加入拐点,否则会出现控制点偏移path(当它所在部分接近直线时)
  19167. while (UtoTMapArr[i] > nextUtoTIndex / (oldCount - 1)) {
  19168. //可能多个控制点对应一个点,当控制点很近时
  19169. reachNextUToT = true;
  19170. nextUtoTIndex++;
  19171. }
  19172. if ( /* pointIndexs.includes(i) || */reachNextUToT || curVec.angleTo(lastVec) > minRad) {
  19173. //最小角度 (注意原始点不能太稀疏)
  19174. newPoints.push(point);
  19175. UtoTMapArr && newUtoTMapArr.push(UtoTMapArr[i]);
  19176. lastVec = curVec;
  19177. }
  19178. }
  19179. }
  19180. }
  19181. return {
  19182. newUtoTMapArr,
  19183. newPoints
  19184. };
  19185. },
  19186. getExtrudeGeo: function getExtrudeGeo(shapes, holes) {
  19187. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
  19188. openEnded: false,
  19189. shapeDontClose: false
  19190. };
  19191. //获得挤出棱柱,可以选择传递height,或者extrudePath
  19192. var shape = this.getShape(shapes, holes); //points是横截面 [vector2,...]
  19193. if (options.extrudePath) {
  19194. // 路径 :[vector3,...]
  19195. var length = options.extrudePath.reduce((total, currentValue, currentIndex, arr) => {
  19196. if (currentIndex == 0) return 0;
  19197. return total + currentValue.distanceTo(arr[currentIndex - 1]);
  19198. }, 0);
  19199. //options.extrudePath = new THREE.CatmullRomCurve3(options.extrudePath)
  19200. if (options.extrudePath.length == 2) {
  19201. options.tension = 0; //否则一端扭曲
  19202. options.steps = 1;
  19203. }
  19204. {
  19205. //去掉重复的点
  19206. var path = [];
  19207. var minDis = options.dontSmooth ? 0 : 0.2; //CatmullRomCurve3 经常扭曲,如果两个点靠得很近可能会扭曲,这里去除靠的太近的点。但去除后依旧会出现一定扭曲.
  19208. options.extrudePath.forEach((p, i) => {
  19209. if (i == 0 || i == options.extrudePath.length - 1) return path.push(p); //首尾直接加入
  19210. var last = path[path.length - 1]; //和上一个比
  19211. var dis = last.distanceTo(p);
  19212. if (dis <= minDis) {
  19213. console.log("\u7B2C".concat(i, "\u4E2A\u70B9(").concat(p.toArray(), ")\u56E0\u4E3A\u548C\u4E0A\u4E00\u4E2A\u6570\u636E(").concat(last.toArray(), ")\u592A\u63A5\u8FD1(dis:").concat(dis, ")\u6240\u4EE5\u5220\u9664"));
  19214. } else if (i == options.extrudePath.length - 2) {
  19215. //因为最后一个必定加入,所以倒数第二个还也不能太靠近最后一个
  19216. last = options.extrudePath[options.extrudePath.length - 1]; //和下一个(最后一个比)
  19217. if (dis <= minDis) {
  19218. console.log("\u7B2C".concat(i, "\u4E2A\u70B9(").concat(p.toArray(), ")\u56E0\u4E3A\u548C\u4E0B\u4E00\u4E2A\u6570\u636E(").concat(last.toArray(), ")\u592A\u63A5\u8FD1(dis:").concat(dis, ")\u6240\u4EE5\u5220\u9664"));
  19219. } else {
  19220. path.push(p);
  19221. }
  19222. } else {
  19223. path.push(p);
  19224. }
  19225. });
  19226. options.extrudePath = path;
  19227. }
  19228. if (!options.dontSmooth) {
  19229. //平滑连续的曲线(但经常会有扭曲的问题,tension:0能缓解, 另外shape和path都最好在原点附近,也就是点需减去bound.min )
  19230. options.extrudePath = new CatmullRomCurve3(options.extrudePath, options.closed, 'catmullrom' /* 'centripetal' */, options.tension); //tension:张力, 越大弯曲越大。 随着长度增长,该值需要减小,否则会扭曲
  19231. if (options.lessPoints !== false) {
  19232. //曲线但压缩直线部分点数量
  19233. options.extrudePath.UtoTMapArr = []; //用于存储 getSpacedPoints得到的点对应points的百分比对应
  19234. var count = Math.max(2, Math.round(length * (options.lessSpace || 200))); //为了防止有大拐弯才设置这么高
  19235. var points = options.extrudePath.getSpacedPoints(count - 1); //拆分为更密集的点
  19236. var result = this.lessCurvePoints(points, options.extrudePath.points.length, options.minRad, options.extrudePath.UtoTMapArr); //传UtoTMapArr的话点太多了卡住了
  19237. //options.extrudePath = points
  19238. options.extrudePath = result.newPoints;
  19239. options.dontSmooth = true;
  19240. }
  19241. }
  19242. if (options.dontSmooth) {
  19243. var curvePath = new CurvePath(); //通用的曲线路径对象,它可以包含直线段和曲线段。在这里只做折线
  19244. curvePath.points = options.extrudePath; //add
  19245. for (var i = 0; i < options.extrudePath.length - 1; i++) {
  19246. var curve3 = new LineCurve3(options.extrudePath[i], options.extrudePath[i + 1]); //添加线段
  19247. curvePath.add(curve3);
  19248. }
  19249. options.steps = options.extrudePath.length - 1;
  19250. options.extrudePath = curvePath;
  19251. options.tension = 0;
  19252. //已修改过three,原本会平分细分,现在dontSmooth时会直接按照控制点来分段
  19253. }
  19254. }
  19255. var extrudeSettings = $.extend(options, {
  19256. steps: options.steps != void 0 ? options.steps : options.extrudePath ? Math.round(length / (options.spaceDis || 0.2)) : 1,
  19257. //分成几段 spaceDis每段长度
  19258. bevelEnabled: false //不加的话,height为0时会有圆弧高度
  19259. //openEnded默认false
  19260. });
  19261. var geometry = new ExtrudeBufferGeometry(shape, extrudeSettings); //修改了three.js文件, buildLidFaces处,创建顶底面加了选项,可以选择开口。
  19262. return geometry;
  19263. /* tension = 0:曲线会变成一条直线,没有弯曲。
  19264. tension = 0.5:曲线会经过所有控制点,并保持自然的弯曲。
  19265. tension > 0.5:曲线会更平滑,远离控制点之间的路径。
  19266. tension < 0.5:曲线会更贴近控制点之间的路径,弯曲更明显。 */
  19267. },
  19268. getUnPosPlaneGeo: function () {
  19269. //获取还没有赋值位置的plane geometry
  19270. var e = new Uint16Array([0, 1, 2, 0, 2, 3])
  19271. // , t = new Float32Array([-.5, -.5, 0, .5, -.5, 0, .5, .5, 0, -.5, .5, 0])
  19272. ,
  19273. i = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
  19274. g = new BufferGeometry();
  19275. g.setIndex(new BufferAttribute(e, 1)),
  19276. //g.addAttribute("position", new n.BufferAttribute(t, 3)),
  19277. g.setAttribute("uv", new BufferAttribute(i, 2));
  19278. return function () {
  19279. return g;
  19280. };
  19281. }(),
  19282. getPlaneGeo: function getPlaneGeo(A, B, C, D) {
  19283. var geo = this.getUnPosPlaneGeo().clone();
  19284. var pos = [A.x, A.y, A.z, B.x, B.y, B.z, C.x, C.y, C.z, D.x, D.y, D.z];
  19285. //geo.addAttribute("position", new THREE.BufferAttribute(pos, 3))
  19286. geo.setAttribute('position', new Float32BufferAttribute(pos, 3));
  19287. geo.computeVertexNormals();
  19288. geo.computeBoundingSphere(); //for raycaster
  19289. return geo;
  19290. },
  19291. drawPlane: function drawPlane(A, B, C, D, material) {
  19292. var wall = new Mesh(this.getPlaneGeo(A, B, C, D), material);
  19293. return wall;
  19294. },
  19295. movePlane: function movePlane(mesh, A, B, C, D) {
  19296. var pos = new Float32Array([A.x, A.y, A.z, B.x, B.y, B.z, C.x, C.y, C.z, D.x, D.y, D.z]);
  19297. mesh.geometry.addAttribute("position", new BufferAttribute(pos, 3));
  19298. mesh.geometry.computeBoundingSphere(); //for checkIntersect
  19299. },
  19300. createGeometry: function createGeometry(posArr, faceArr, uvArr, normalArr) {
  19301. //创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  19302. var geo = new BufferGeometry();
  19303. var positions = [];
  19304. posArr.forEach(p => positions.push(p.x, p.y, p.z));
  19305. geo.setAttribute('position', new Float32BufferAttribute(positions, 3));
  19306. if (faceArr) {
  19307. var indice = [];
  19308. faceArr.forEach(f => indice.push(...f));
  19309. geo.setIndex(indice); // auto set Uint16BufferAttribute or Uint32BufferAttribute
  19310. }
  19311. if (uvArr) {
  19312. var uvs = [];
  19313. uvArr.forEach(uv => uvs.push(uv.x, uv.y));
  19314. geo.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
  19315. }
  19316. if (normalArr) {
  19317. var normals = [];
  19318. normalArr.forEach(n => normals.push(n.x, n.y, n.z));
  19319. geo.setAttribute("normal", new Float32BufferAttribute(normals, 3));
  19320. }
  19321. /*
  19322. geo.computeVertexNormals()
  19323. geo.computeBoundingSphere() //for raycaster
  19324. */
  19325. return geo;
  19326. },
  19327. updateGeometry: function updateGeometry(geo, posArr, faceArr, uvArr, normalArr) {
  19328. //创建复杂mesh. faceArr:[[0,1,2],[0,2,3]]
  19329. var positions = [];
  19330. posArr.forEach(p => positions.push(p.x, p.y, p.z));
  19331. geo.setAttribute('position', new Float32BufferAttribute(positions, 3));
  19332. geo.attributes.position.needsUpdate = true;
  19333. if (faceArr) {
  19334. var indice = [];
  19335. faceArr.forEach(f => indice.push(...f));
  19336. geo.setIndex(indice); // auto set Uint16BufferAttribute or Uint32BufferAttribute
  19337. }
  19338. if (uvArr) {
  19339. var uvs = [];
  19340. uvArr.forEach(uv => uvs.push(uv.x, uv.y));
  19341. geo.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
  19342. }
  19343. if (normalArr) {
  19344. var normals = [];
  19345. normalArr.forEach(n => normals.push(n.x, n.y, n.z));
  19346. geo.setAttribute("normal", new Float32BufferAttribute(normals, 3));
  19347. }
  19348. /*
  19349. geo.computeVertexNormals()
  19350. */
  19351. geo.computeBoundingSphere(); //for raycaster and visi
  19352. return geo;
  19353. }
  19354. };
  19355. class DepthBasicMaterial extends ShaderMaterial {
  19356. constructor() {
  19357. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19358. var {
  19359. width,
  19360. height
  19361. } = viewer.renderer.getSize(new Vector2());
  19362. var uniforms = {
  19363. resolution: {
  19364. type: 'v2',
  19365. value: new Vector2(width, height)
  19366. },
  19367. viewportOffset: {
  19368. type: 'v2',
  19369. value: new Vector2(0, 0)
  19370. },
  19371. //left, top
  19372. //uUseOrthographicCamera:{ type: "b", value: false },
  19373. nearPlane: {
  19374. type: 'f',
  19375. value: 0.1
  19376. },
  19377. farPlane: {
  19378. type: 'f',
  19379. value: 10000
  19380. },
  19381. depthTexture: {
  19382. type: 't',
  19383. value: null
  19384. },
  19385. opacity: {
  19386. type: 'f',
  19387. value: 1
  19388. },
  19389. map: {
  19390. type: 't',
  19391. value: o.map
  19392. },
  19393. mapColor: {
  19394. type: 'v3',
  19395. value: o.mapColor ? new Color(o.mapColor) : new Color("#ffffff")
  19396. },
  19397. baseColor: {
  19398. type: 'v3',
  19399. value: o.color ? new Color(o.color) : new Color("#ffffff")
  19400. },
  19401. backColor: {
  19402. type: 'v3',
  19403. value: o.backColor ? new Color(o.backColor) : new Color("#ddd")
  19404. },
  19405. clipDistance: {
  19406. type: 'f',
  19407. value: o.clipDistance || 4
  19408. },
  19409. //消失距离
  19410. occlusionDistance: {
  19411. type: 'f',
  19412. value: o.occlusionDistance || 1
  19413. },
  19414. //变为backColor距离
  19415. maxClipFactor: {
  19416. type: 'f',
  19417. value: o.maxClipFactor || 1
  19418. },
  19419. //0-1
  19420. maxOcclusionFactor: {
  19421. type: 'f',
  19422. value: o.maxOcclusionFactor || 1
  19423. },
  19424. //0-1
  19425. //mapScale: { type: 'f', value: o.mapScale || 1 }, //0-1
  19426. startClipDis: {
  19427. type: 'f',
  19428. value: o.startClipDis || 0
  19429. },
  19430. //开始逐渐消失的距离
  19431. startOcclusDis: {
  19432. type: 'f',
  19433. value: o.startOcclusDis || 0
  19434. },
  19435. //开始逐渐褪色的距离
  19436. fadeFar: {
  19437. value: 10
  19438. } //渐变消失
  19439. };
  19440. var {
  19441. vs,
  19442. fs
  19443. } = Common$1.changeShaderToWebgl2(Shaders['depthBasic.vs'], Shaders['depthBasic.fs'], 'ShaderMaterial');
  19444. super({
  19445. uniforms,
  19446. vertexShader: vs,
  19447. fragmentShader: fs,
  19448. depthWrite: false,
  19449. depthTest: false,
  19450. transparent: o.transparent == void 0 ? true : o.transparent
  19451. });
  19452. this.events = {
  19453. setSize: e => {
  19454. //如果出现横条状的异常,往往是viewportOffset出错 //地图不需要
  19455. if (!this.realUseDepth || !e.viewport) return;
  19456. var viewport = e.viewport;
  19457. var viewportOffset = viewport.offset || new Vector2();
  19458. this.uniforms.resolution.value.copy(viewport.resolution2); //2023.6.12突然发现ratio>1的用resolution不对,得用2才对。但是之前明明记得不是这样
  19459. this.uniforms.viewportOffset.value.copy(viewportOffset);
  19460. },
  19461. render: e => {
  19462. //before render 如果有大于两个viewport的话,不同viewport用不同的depthTex
  19463. this.updateDepthParams(e);
  19464. }
  19465. /* cameraChange:(e)=>{
  19466. if(e.changeInfo.projectionChanged){//resize时也会触发。虽然保守起见的话加上resize比较好//所以当时为何不用resize
  19467. //console.log('projectionChanged')
  19468. this.events.setSize(e)
  19469. }
  19470. } */
  19471. };
  19472. //-----其他----
  19473. /*this.autoDepthTest = o.autoDepthTest
  19474. if(o.opacity != void 0){
  19475. this.opacity = o.opacity
  19476. }
  19477. this.useDepth = o.useDepth
  19478. this.fadeFar = o.fadeFar
  19479. this.map = o.map */
  19480. this.setValues(o);
  19481. }
  19482. get useDepth() {
  19483. return this.useDepth_;
  19484. }
  19485. set useDepth(value) {
  19486. value = value && Features.EXT_DEPTH.isSupported(); //如果不支持 EXT_DEPTH 的话会失效
  19487. if (this.useDepth_ != value) {
  19488. this.setRealDepth(value);
  19489. this.useDepth_ = value;
  19490. if (value) {
  19491. viewer.addEventListener("render.begin", this.events.render);
  19492. //viewer.addEventListener('camera_changed', this.events.cameraChange)
  19493. viewer.addEventListener('resize', this.events.setSize);
  19494. this.updateDepthParams();
  19495. } else {
  19496. viewer.removeEventListener("render.begin", this.events.render);
  19497. viewer.removeEventListener('resize', this.events.setSize);
  19498. }
  19499. }
  19500. }
  19501. setRealDepth(useDepth, viewport) {
  19502. //确实使用到depthTex
  19503. if (this.realUseDepth != useDepth) {
  19504. if (useDepth) {
  19505. this.defines.useDepth = '';
  19506. } else {
  19507. delete this.defines.useDepth;
  19508. }
  19509. this.realUseDepth = useDepth;
  19510. if (this.autoDepthTest) this.depthWrite = this.depthTest = !useDepth; //如果useDepth = false,使用原始的depthTest
  19511. this.needsUpdate = true;
  19512. if (!viewport) viewport = viewer.mainViewport; //暂时这么设置
  19513. useDepth && this.events.setSize({
  19514. viewport
  19515. });
  19516. }
  19517. }
  19518. get map() {
  19519. return this.uniforms.map.value;
  19520. }
  19521. set map(map) {
  19522. var oldDefines = Common$1.CloneObject(this.defines);
  19523. this.uniforms.map.value = map;
  19524. if (map) {
  19525. this.defines.use_map = '';
  19526. if (map.repeat.x != 1 || map.repeat.y != 1) {
  19527. this.setUV();
  19528. }
  19529. } else {
  19530. delete this.defines.use_map;
  19531. delete this.defines.UV_Transform;
  19532. }
  19533. Common$1.ifSame(oldDefines, this.defines) || (this.needsUpdate = true);
  19534. }
  19535. get opacity() {
  19536. return this.uniforms.opacity.value;
  19537. }
  19538. set opacity(o) {
  19539. this.uniforms && o != void 0 && (this.uniforms.opacity.value = o);
  19540. }
  19541. get color() {
  19542. return this.uniforms.baseColor.value;
  19543. }
  19544. set color(c) {
  19545. this.uniforms && this.uniforms.baseColor.value.set(c);
  19546. }
  19547. set fadeFar(far) {
  19548. var needsUpdate = !this.fadeFar != !far; //null为全部范围可见
  19549. //console.log('fadeFar needsUpdate', needsUpdate)
  19550. if (far) {
  19551. this.defines.FadeFar = true;
  19552. this.uniforms.fadeFar.value = far;
  19553. } else {
  19554. delete this.defines.FadeFar;
  19555. }
  19556. needsUpdate && (this.needsUpdate = true);
  19557. }
  19558. get fadeFar() {
  19559. return 'FadeFar' in this.defines && this.uniforms.fadeFar.value;
  19560. }
  19561. copy(source) {
  19562. super.copy(source);
  19563. this.useDepth = source.useDepth;
  19564. this.map = source.map;
  19565. this.fadeFar = source.fadeFar;
  19566. return this;
  19567. }
  19568. updateDepthParams() {
  19569. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19570. //主要用于点云遮住mesh
  19571. var viewport = e.viewport || viewer.mainViewport;
  19572. var camera = viewport.camera;
  19573. var hasDepth = this.useDepth && camera.isPerspectiveCamera && (Potree.settings.pointEnableRT || Potree.settings.displayMode == 'showPanos' || viewer.useEDL);
  19574. this.setRealDepth(hasDepth, viewport);
  19575. if (hasDepth) {
  19576. this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture; //其实只赋值一次就行
  19577. }
  19578. //hasDepth or FadeFar:
  19579. this.uniforms.nearPlane.value = camera.near;
  19580. this.uniforms.farPlane.value = camera.far;
  19581. //this.uniforms.uUseOrthographicCamera.value = !camera.isPerspectiveCamera
  19582. }
  19583. setUV() {
  19584. if (!this.map) return;
  19585. this.map.updateMatrix();
  19586. this.uniforms.uvTransform = {
  19587. value: this.map.matrix.clone()
  19588. };
  19589. this.defines.UV_Transform = true;
  19590. }
  19591. }
  19592. var geo = new PlaneBufferGeometry(1, 1);
  19593. class Sprite$2 extends Mesh {
  19594. constructor() {
  19595. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19596. super(geo, options.mat || new DepthBasicMaterial(options)); /* ({map:options.map, useDepth:options.useDepth})) */
  19597. this.root = options.root || this;
  19598. this.renderOrder = options.renderOrder != void 0 ? options.renderOrder : 4;
  19599. this.pickOrder = options.pickOrder || 0;
  19600. this.sizeInfo = options.sizeInfo;
  19601. this.dontFixOrient = options.dontFixOrient;
  19602. this.options = options;
  19603. //this.position.y = options.disToLine || 0 //离线距离
  19604. options.transform2D && (this.position.x = options.transform2D.x, this.position.y = options.transform2D.y); //偏移
  19605. this.matrixAutoUpdate = false;
  19606. this.matrixMap = new Map();
  19607. if (this.root != this) {
  19608. this.matrixMapRoot = new Map();
  19609. this.root.matrixAutoUpdate = false;
  19610. }
  19611. this.visiMap = new Map();
  19612. this.name = options.name || 'sprite';
  19613. this.useViewport = null;
  19614. this.viewports = options.viewports; //指定更新的viewports
  19615. this.visible_ = true;
  19616. var clear = e => {
  19617. this.matrixMap.clear(); //清空后在所有viewport上都必须更新才能渲染 //this.needsUpdate = true
  19618. };
  19619. viewer.mapViewer && viewer.mapViewer.addEventListener("camera_changed", clear);
  19620. viewer.addEventListener("camera_changed", clear);
  19621. /* if(viewer.viewports.length == 1){//直接更新。如果有多个不在这更新,在"render.begin"
  19622. this.update(e)
  19623. } */
  19624. var applyMatrix = e => {
  19625. this.applyMatrix(e);
  19626. };
  19627. viewer.addEventListener("raycaster", applyMatrix); //before render
  19628. viewer.addEventListener("render.begin", applyMatrix); //before render
  19629. viewer.addEventListener("render.begin2", applyMatrix);
  19630. viewer.addEventListener("cameraSetLayers", applyMatrix);
  19631. this.addEventListener('dispose', () => {
  19632. viewer.mapViewer && viewer.mapViewer.removeEventListener("camera_changed", clear);
  19633. viewer.removeEventListener("camera_changed", clear);
  19634. viewer.removeEventListener("raycaster", applyMatrix); //before render
  19635. viewer.removeEventListener("render.begin", applyMatrix);
  19636. viewer.removeEventListener("render.begin2", applyMatrix);
  19637. });
  19638. }
  19639. /* set visible(v){//注释原因renderoverlay时会反复隐藏显示。没必要加,显示后因matrixmap是空的会自动update
  19640. let oldV = this.visible_
  19641. this.visible_ = v
  19642. if(v && !oldV){
  19643. this.matrixMap && this.matrixMap.clear() //this.update() //update内有unableCompute会无限回调
  19644. }
  19645. }
  19646. get visible(){
  19647. return this.visible_
  19648. } */
  19649. realVisible(viewport, interactables /* , raycaster */) {
  19650. if (interactables) {
  19651. if (!interactables.some(object => {
  19652. //interactables中是否能找到this
  19653. var finded;
  19654. object.traverse(object => {
  19655. if (object == this.root) {
  19656. finded = true;
  19657. return {
  19658. stopContinue: true
  19659. };
  19660. }
  19661. });
  19662. return finded;
  19663. })) return;
  19664. }
  19665. /* if(interactables && viewport.name == 'mapViewport'){
  19666. console.log(this)
  19667. } */
  19668. if (!( /* raycaster || */viewport.camera).layers.test(this.layers)) {
  19669. //如地图上一般不可见测量线
  19670. return false;
  19671. }
  19672. if (!this.visible && this.unvisibleReasons && this.unvisibleReasons.some(e => e.reason != 'unableCompute')) {
  19673. return false;
  19674. }
  19675. var v = true;
  19676. var parent = this.root;
  19677. var lastParent = this;
  19678. while (parent) {
  19679. if (parent.visible === false) {
  19680. v = false;
  19681. break;
  19682. }
  19683. lastParent = parent;
  19684. parent = parent.parent;
  19685. }
  19686. if (v && !(lastParent instanceof Scene)) {
  19687. //已被删除
  19688. v = false;
  19689. }
  19690. /* if(!this.latestRealVisi && v){//变为可见后先update
  19691. this.latestRealVisi = true
  19692. setTimeout(()=>{
  19693. this.update()
  19694. },1)//延迟 防止无限调用
  19695. return false
  19696. }
  19697. this.latestRealVisi = v */
  19698. return v;
  19699. }
  19700. waitUpdate() {
  19701. this.matrixMap.clear(); //清空后在所有viewport上都必须更新才能渲染
  19702. //viewer.dispatchEvent('content_changed')
  19703. }
  19704. update() {
  19705. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19706. if (!e.viewport) {
  19707. var viewports = this.viewports || viewer.viewports;
  19708. if (!viewports) return;
  19709. viewports.forEach(view => {
  19710. this.update({
  19711. viewport: view
  19712. });
  19713. });
  19714. return;
  19715. }
  19716. if (!this.root || !this.realVisible(e.viewport, e.interactables) /* this.visible */) return;
  19717. if (this.viewports && !this.viewports.includes(e.viewport)) return;
  19718. if (e.viewport.name == 'magnifier') return;
  19719. var camera = e.viewport.camera;
  19720. //rotation
  19721. if (!this.dontFixOrient) {
  19722. //orthoCamera一般要加dontFixOrient
  19723. var orient2dAngle;
  19724. if (this.root.lineDir) {
  19725. this.root.updateMatrix(); //先更新,getWorldPosition才能得到正确的
  19726. this.root.updateMatrixWorld(true);
  19727. var center = this.root.getWorldPosition(new Vector3());
  19728. //由于两个端点容易在屏幕外,所以使用center和center加dir
  19729. var setVisi = state => {
  19730. this.visiMap.set(e.viewport, state);
  19731. Potree.Utils.updateVisible(this, 'unableCompute', !!state);
  19732. //赋值原先的,否则之后每次render都触发update:
  19733. this.matrixMap.set(e.viewport, this.matrix.clone());
  19734. this.matrixMapRoot.set(e.viewport, this.root.matrix.clone());
  19735. };
  19736. var renderer = e.viewer ? e.viewer.renderer : e.renderer;
  19737. var r1 = Potree.Utils.getPos2d(center, e.viewport, renderer.domElement.parentElement, renderer);
  19738. //let r1 = Potree.Utils.getPos2d(center, e.viewport, viewer.renderArea, viewer.renderer);
  19739. if (!r1.trueSide) return setVisi(false); // 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  19740. var r2, point2;
  19741. var p2State = '',
  19742. len = 1,
  19743. p2StateHistory = [];
  19744. while (p2State != 'got' && p2StateHistory.length < 10) {
  19745. point2 = center.clone().add(this.root.lineDir.clone().multiplyScalar(len));
  19746. r2 = Potree.Utils.getPos2d(point2, e.viewport, renderer.domElement.parentElement, renderer);
  19747. if (!r2.trueSide) {
  19748. //很少遇到点2在背面的
  19749. if (!p2StateHistory.includes('tooLong-reverse')) {
  19750. p2State = 'tooLong-reverse'; //先尝试反向
  19751. len = -len;
  19752. } else {
  19753. p2State = 'tooLong';
  19754. len = len / 2;
  19755. }
  19756. } else {
  19757. var _dis = r2.pos.distanceTo(r1.pos);
  19758. if (math.closeTo(_dis, 0)) {
  19759. //console.log('dis == 0')
  19760. return setVisi(false);
  19761. break;
  19762. }
  19763. if (_dis < 10 && !p2StateHistory.includes('tooLong')) {
  19764. //和r1的屏幕距离太近,要加长,否则精度过低
  19765. p2State = 'tooShort';
  19766. len = 100 / _dis * len;
  19767. } else {
  19768. p2State = 'got';
  19769. break;
  19770. }
  19771. }
  19772. p2StateHistory.push(p2State);
  19773. }
  19774. //console.log(p2StateHistory,len)
  19775. if (!r2.trueSide) {
  19776. return setVisi(false); //, console.log(' !r2.trueSide', )
  19777. }
  19778. var p1 = r1.pos,
  19779. p2 = r2.pos;
  19780. if (p2StateHistory.filter(e => e == 'tooLong-reverse').length % 2 == 1) {
  19781. //反,for marker
  19782. p2 = r1.pos, p1 = r2.pos;
  19783. }
  19784. var vec = new Vector2().subVectors(p1, p2);
  19785. orient2dAngle = -vec.angle(); //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  19786. var y = Math.abs(this.position.y);
  19787. var facePlane = this.root.measure && this.root.measure.facePlane;
  19788. var eyeDir = new Vector3().subVectors(center, camera.position);
  19789. var clockWise = facePlane && facePlane.normal.dot(eyeDir /* e.viewport.view.direction */) < 0;
  19790. if (p1.x < p2.x) {
  19791. orient2dAngle += Math.PI; //避免字是倒着的情况。(使字一直在线的下方)
  19792. clockWise != void 0 && (this.position.y = clockWise ? y : -y);
  19793. } else {
  19794. clockWise != void 0 && (this.position.y = clockWise ? -y : y); //使area类型的edgeLabel都在外侧
  19795. }
  19796. //this.parent.text && console.log(this.parent.text, clockWise, this.position.y, e.viewport.name /* THREE.Math.radToDeg(angle), p1.x < p2.x */ )
  19797. setVisi(true);
  19798. }
  19799. var parentQua = this.root.parent.getWorldQuaternion(new Quaternion());
  19800. this.root.quaternion.multiplyQuaternions(parentQua.invert(), camera.quaternion); //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  19801. if (orient2dAngle) {
  19802. var qua = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), orient2dAngle);
  19803. this.root.quaternion.multiply(qua);
  19804. }
  19805. }
  19806. //scale
  19807. var info = this.sizeInfo;
  19808. if (info) {
  19809. this.root.updateMatrix(); //先更新,getWorldPosition才能得到正确的
  19810. this.root.updateMatrixWorld(true);
  19811. var scale;
  19812. if (info.nearBound == void 0 && info.farBound != void 0 || info.nearBound != void 0 && info.farBound == void 0) {
  19813. //仅限制最大或最小的话,不判断像素大小,直接限制mesh的scale
  19814. //这个判断也可以写到getScaleForConstantSize里,可以更严谨控制像素宽度,这里只简单计算大小
  19815. var dis = camera.position.distanceTo(this.root.getWorldPosition(new Vector3()));
  19816. if (info.farBound == void 0 && dis < info.nearBound) {
  19817. scale = info.scale * dis / info.nearBound;
  19818. } else if (info.nearBound == void 0 && dis > info.farBound) {
  19819. scale = info.scale * dis / info.farBound;
  19820. } else {
  19821. scale = info.scale;
  19822. }
  19823. } else {
  19824. scale = math.getScaleForConstantSize($.extend(info, {
  19825. //规定下最小最大像素
  19826. camera,
  19827. position: this.root.getWorldPosition(new Vector3()),
  19828. resolution: e.viewport.resolution //2
  19829. }));
  19830. if (this.root.parent) {
  19831. var scale_ = this.root.parent.getWorldScale(new Vector3());
  19832. scale = new Vector3(scale / scale_.x, scale / scale_.y, scale / scale_.z);
  19833. }
  19834. }
  19835. if (typeof scale == 'number') {
  19836. if (!isNaN(scale)) {
  19837. this.root.scale.set(scale, scale, scale);
  19838. }
  19839. } else {
  19840. this.root.scale.copy(scale);
  19841. }
  19842. }
  19843. this.updateMatrix();
  19844. //this.root.updateMatrixWorld(true)
  19845. //console.log(this.root.text, this.root.matrix.elements)
  19846. this.matrixMap.set(e.viewport, this.matrix.clone());
  19847. if (this.root != this) {
  19848. this.root.updateMatrix(); //因this.position可能在两个viewport不同
  19849. this.matrixMapRoot.set(e.viewport, this.root.matrix.clone());
  19850. }
  19851. //this.parent.text && console.log('update',this.parent.text, this.matrix.elements, this.root.matrix.elements)
  19852. this.needsUpdate = false;
  19853. this.useViewport = e.viewport;
  19854. this.dispatchEvent('spriteUpdated');
  19855. }
  19856. applyMatrix(e) {
  19857. if (!e) e = {
  19858. viewport: viewer.mainViewport
  19859. }; //随便写一个viewport
  19860. var visi = this.visiMap.get(e.viewport); //还原可见性
  19861. Potree.Utils.updateVisible(this, 'unableCompute', visi == false ? false : true);
  19862. /* if(e.viewport.name == 'mapViewport' && visi && this.visiMap.get(viewer.mainViewport) == false){
  19863. console.log(1)
  19864. } */
  19865. if (e.viewport.name == 'magnifier') return;
  19866. if (this.viewports && !this.viewports.includes(e.viewport)) return;
  19867. if (!this.root || !this.realVisible(e.viewport, e.interactables)) return;
  19868. var matrix = this.matrixMap.get(e.viewport);
  19869. if (!matrix) {
  19870. this.update(e);
  19871. matrix = this.matrixMap.get(e.viewport);
  19872. if (!matrix) return; //maybe unvisible
  19873. }
  19874. if (e.viewport == this.useViewport) {
  19875. return;
  19876. }
  19877. this.useViewport = e.viewport;
  19878. this.matrix.copy(matrix);
  19879. if (this.root != this) {
  19880. var matrix2 = this.matrixMapRoot.get(e.viewport);
  19881. this.root.matrix.copy(matrix2);
  19882. }
  19883. e.raycaster && this.root.updateMatrixWorld(true); //渲染前会自动updateMatrixWorld,但raycaster不会
  19884. //console.log(this.root.name + e.viewport.name + " : "+this.root.matrixWorld.elements)
  19885. }
  19886. setUniforms(name, value) {
  19887. this.material.setUniforms(name, value);
  19888. }
  19889. dispose() {
  19890. this.removeAllListeners();
  19891. this.parent && this.parent.remove(this);
  19892. this.dispatchEvent('dispose');
  19893. }
  19894. }
  19895. /*
  19896. let orient2d
  19897. if(this.lineDir){
  19898. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  19899. this.root.updateMatrixWorld(true)
  19900. let center = this.root.getWorldPosition(new THREE.Vector3())
  19901. //由于两个端点容易在屏幕外,所以使用center和center加dir
  19902. let lineDir = this.lineDir.clone();
  19903. let r1 = Potree.Utils.getPos2d(center, camera, viewer.renderArea, e.viewport);
  19904. if(!r1.trueSide)return Potree.Utils.updateVisible(this, 'unableCompute', false);// 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  19905. let r2, point2
  19906. let p2State = '', len=1, p2StateHistory = []
  19907. while(p2State != 'got' && p2StateHistory.length<10){
  19908. point2 = center.clone().add(lineDir.multiplyScalar(len));
  19909. r2 = Potree.Utils.getPos2d(point2, camera, viewer.renderArea, e.viewport);
  19910. if(!r2.trueSide){ //很少遇到点2在背面的
  19911. if(!p2StateHistory.includes('tooLong-reverse')){
  19912. p2State = 'tooLong-reverse' //先尝试反向
  19913. len = -len
  19914. }else{
  19915. p2State = 'tooLong'
  19916. len = len / 2
  19917. }
  19918. }else{
  19919. let dis = r2.pos.distanceTo(r1.pos)
  19920. if(dis == 0){
  19921. //console.log('dis == 0')
  19922. Potree.Utils.updateVisible(this, 'unableCompute', false)
  19923. return
  19924. break
  19925. }
  19926. if(dis<10 && !p2StateHistory.includes('tooLong')){//和r1的屏幕距离太近,要加长,否则精度过低
  19927. p2State = 'tooShort'
  19928. len = 100/dis * len
  19929. }else{
  19930. p2State = 'got'; break;
  19931. }
  19932. }
  19933. p2StateHistory.push(p2State)
  19934. }
  19935. //console.log(p2StateHistory,len)
  19936. if(!r2.trueSide){
  19937. return Potree.Utils.updateVisible(this, 'unableCompute', false)//, console.log(' !r2.trueSide', )
  19938. }
  19939. Potree.Utils.updateVisible(this, 'unableCompute', true)
  19940. let p1 = r1.pos, p2 = r2.pos
  19941. let vec = new THREE.Vector2().subVectors(p1,p2);
  19942. let angle = -vec.angle() //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  19943. if(p1.x < p2.x) angle += Math.PI //避免字是倒着的情况
  19944. orient2d = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), angle)
  19945. //console.log(this.parent.text, THREE.Math.radToDeg(angle), p1.x < p2.x )
  19946. }
  19947. let parentQua = this.root.parent.getWorldQuaternion(new THREE.Quaternion)
  19948. this.root.quaternion.multiplyQuaternions(parentQua.invert(),camera.quaternion) //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  19949. if(this.lineDir){
  19950. this.root.quaternion.multiply(orient2d)
  19951. }
  19952. */
  19953. // /**
  19954. class TextSprite$2 extends Object3D {
  19955. //注:为了分两层控制scale,不直接extend Sprite
  19956. constructor() {
  19957. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  19958. super();
  19959. var map = new Texture();
  19960. /* map.generateMipmaps = true
  19961. map.minFilter = THREE.LinearMipmapLinearFilter */ //这个比LinearFilter平滑所以模糊点
  19962. map.minFilter = LinearFilter; //缩小效果都不好,sizeInfo尽量放大些(但要跟看到的差不多宽),用框选工具测出像素宽度大于map.image.width即可
  19963. map.magFilter = NearestFilter; //试过 当可见宽度稍大于和贴图宽度时,放大后可以很清晰。可见宽度太大有锯齿。
  19964. //width2d一般设置为200
  19965. this.sprite = new Sprite$2(Object.assign({
  19966. root: this
  19967. }, options, {
  19968. map
  19969. }));
  19970. this.add(this.sprite);
  19971. this.sprite.material.map = map;
  19972. this.fontWeight = options.fontWeight == void 0 ? 'Bold' : options.fontWeight;
  19973. this.rectBorderThick = options.rectBorderThick || 0;
  19974. this.textBorderThick = options.textBorderThick || 0;
  19975. this.fontface = 'Arial';
  19976. this.fontsize = options.fontsize || 16;
  19977. this.lineSpace = options.lineSpace;
  19978. this.textBorderColor = options.textBorderColor ? Common$1.CloneObject(options.textBorderColor) : {
  19979. r: 0,
  19980. g: 0,
  19981. b: 0,
  19982. a: 1.0
  19983. };
  19984. this.backgroundColor = options.backgroundColor ? Common$1.CloneObject(options.backgroundColor) : {
  19985. r: 255,
  19986. g: 255,
  19987. b: 255,
  19988. a: 0.7
  19989. };
  19990. this.textColor = options.textColor ? Common$1.CloneObject(options.textColor) : {
  19991. r: 0,
  19992. g: 0,
  19993. b: 0,
  19994. a: 1.0
  19995. };
  19996. this.textshadowColor = options.textshadowColor;
  19997. this.borderColor = options.borderColor ? Common$1.CloneObject(options.borderColor) : {
  19998. r: 0,
  19999. g: 0,
  20000. b: 0,
  20001. a: 0.0
  20002. };
  20003. this.borderRadius = options.borderRadius || 6;
  20004. this.margin = options.margin;
  20005. this.textAlign = options.textAlign || 'center';
  20006. this.name = options.name;
  20007. this.transform2Dpercent = options.transform2Dpercent;
  20008. this.maxLineWidth = options.maxLineWidth;
  20009. this.setText(options.text);
  20010. }
  20011. setText(text) {
  20012. if (text == void 0) text = '';
  20013. if (this.text !== text) {
  20014. if (!(text instanceof Array)) {
  20015. this.text = text.split('\n'); //如果是input手动输入的\n这里会是\\n且不会被拆分, 绘制的依然是\n。
  20016. //this.text = [text + '']
  20017. } else this.text = text;
  20018. this.updateTexture();
  20019. }
  20020. }
  20021. /* setText(text){
  20022. if(text == void 0)text = ''
  20023. if (this.text !== text) {
  20024. if (!(text instanceof Array)) {
  20025. this.text = text.split('\n') //如果是input手动输入的\n这里会是\\n且不会被拆分, 绘制的依然是\n。
  20026. if(this.maxRowWordsCount){//每行显示最大字数
  20027. this.text.forEach(str=>{
  20028. if(str.length > this.maxRowWordsCount){
  20029. }
  20030. })
  20031. }
  20032. //this.text = [text + '']
  20033. } else this.text = text
  20034. this.updateTexture()
  20035. }
  20036. } */
  20037. setTextColor(color) {
  20038. this.textColor = Common$1.CloneObject(color);
  20039. this.updateTexture();
  20040. }
  20041. setBorderColor(color) {
  20042. this.borderColor = Common$1.CloneObject(color);
  20043. this.updateTexture();
  20044. }
  20045. setBackgroundColor(color) {
  20046. this.backgroundColor = Common$1.CloneObject(color);
  20047. this.updateTexture();
  20048. }
  20049. setPos(pos) {
  20050. this.position.copy(pos);
  20051. this.sprite.waitUpdate();
  20052. }
  20053. updatePose() {
  20054. this.sprite.waitUpdate();
  20055. }
  20056. setUniforms(name, value) {
  20057. this.sprite.setUniforms(name, value);
  20058. }
  20059. updateTexture() {
  20060. //canvas原点在左上角
  20061. var canvas = document.createElement('canvas');
  20062. var context = canvas.getContext('2d');
  20063. var r = window.devicePixelRatio; //不乘会模糊
  20064. context.font = this.fontWeight + ' ' + this.fontsize * r + 'px ' + this.fontface; //context["font-weight"] = 100; //语法与 CSS font 属性相同。
  20065. var textMaxWidth = 0,
  20066. infos = [];
  20067. context.textBaseline = 'alphabetic'; // "middle" //设置文字基线。当起点y设置为0时,只有该线以下的部分被绘制出来。middle时文字显示一半(但是对该字体所有字的一半,有的字是不一定显示一半的,尤其汉字),alphabetic时是英文字母的那条基线。
  20068. var textHeightAll = 0;
  20069. var texts = [];
  20070. if (this.maxLineWidth) {
  20071. this.text.forEach(words => {
  20072. if (!words) {
  20073. texts.push("");
  20074. return;
  20075. }
  20076. texts = texts.concat(breakLinesForCanvas(words, context, this.maxLineWidth));
  20077. });
  20078. } else {
  20079. texts = this.text;
  20080. }
  20081. for (var text of texts) {
  20082. var metrics = context.measureText(text);
  20083. var textWidth = metrics.width;
  20084. infos.push(metrics);
  20085. textMaxWidth = Math.max(textMaxWidth, textWidth);
  20086. textHeightAll += metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; //文字真实高度
  20087. }
  20088. var margin = (this.margin ? new Vector2().copy(this.margin) : new Vector2(this.fontsize, this.fontsize * 0.8)).multiplyScalar(r);
  20089. var lineSpace = (this.lineSpace || this.fontsize * 0.5) * r;
  20090. var rectBorderThick = this.rectBorderThick * r,
  20091. textBorderThick = this.textBorderThick * r;
  20092. var spriteWidth = 2 * (margin.x + rectBorderThick + textBorderThick) + textMaxWidth; //还要考虑this.textshadowColor,太麻烦了不写了
  20093. var spriteHeight = 2 * (margin.y + rectBorderThick + textBorderThick * texts.length) + lineSpace * (texts.length - 1) + textHeightAll;
  20094. //canvas宽高只会向下取整数,所以为了防止拉伸模糊这里必须先取整
  20095. spriteWidth = Math.floor(spriteWidth);
  20096. spriteHeight = Math.floor(spriteHeight);
  20097. context.canvas.width = spriteWidth;
  20098. context.canvas.height = spriteHeight;
  20099. context.font = this.fontWeight + ' ' + this.fontsize * r + 'px ' + this.fontface; //为何要再写一遍??
  20100. if (spriteWidth > 4000) {
  20101. console.error('spriteWidth', spriteWidth, 'spriteHeight', spriteHeight, this.fontsize, r, texts, margin);
  20102. }
  20103. var expand = 0; //Math.max(1, Math.pow(this.fontsize / 16, 1.1)) * r // 针对英文大部分在baseLine之上所以降低一点,或者可以识别当不包含jgqp时才加这个值 . 但即使都是汉字也会不同,如"哈哈"和"粉色",前者居中后者不
  20104. context.strokeStyle = 'rgba(' + this.borderColor.r + ',' + this.borderColor.g + ',' + this.borderColor.b + ',' + this.borderColor.a + ')';
  20105. context.lineWidth = rectBorderThick;
  20106. context.fillStyle = 'rgba(' + this.backgroundColor.r + ',' + this.backgroundColor.g + ',' + this.backgroundColor.b + ',' + this.backgroundColor.a + ')';
  20107. this.roundRect(context, rectBorderThick / 2, rectBorderThick / 2, spriteWidth - rectBorderThick, spriteHeight - rectBorderThick, this.borderRadius * r);
  20108. context.fillStyle = 'rgba(' + this.textColor.r + ',' + this.textColor.g + ',' + this.textColor.b + ',' + this.textColor.a + ')';
  20109. var y = margin.y + rectBorderThick;
  20110. for (var i = 0; i < texts.length; i++) {
  20111. //文字y向距离从textBaseline向上算
  20112. var actualBoundingBoxAscent = infos[i].fontBoundingBoxAscent == void 0 ? this.fontsize * r * 0.8 : infos[i].fontBoundingBoxAscent; //有的流览器没有。只能大概给一个
  20113. y += actualBoundingBoxAscent + textBorderThick;
  20114. var textLeftSpace = this.textAlign == 'center' ? (textMaxWidth - infos[i].width) / 2 : this.textAlign == 'left' ? 0 : textMaxWidth - infos[i].width;
  20115. var x = rectBorderThick + textBorderThick + margin.x + textLeftSpace;
  20116. // text color
  20117. if (this.textBorderThick) {
  20118. context.strokeStyle = 'rgba(' + this.textBorderColor.r + ',' + this.textBorderColor.g + ',' + this.textBorderColor.b + ',' + this.textBorderColor.a + ')';
  20119. context.lineWidth = this.textBorderThick * r;
  20120. context.strokeText(texts[i], x, y);
  20121. }
  20122. if (this.textshadowColor) {
  20123. context.shadowOffsetX = 0;
  20124. context.shadowOffsetY = 0;
  20125. context.shadowColor = this.textshadowColor; //'red'
  20126. context.shadowBlur = (this.textShadowBlur || this.fontsize / 6) * r;
  20127. }
  20128. context.fillText(texts[i], x, y);
  20129. var actualBoundingBoxDescent = infos[i].fontBoundingBoxDescent == void 0 ? this.fontsize * r * 0.2 : infos[i].fontBoundingBoxDescent;
  20130. y += actualBoundingBoxDescent + textBorderThick + lineSpace;
  20131. }
  20132. /* let texture = new THREE.Texture(canvas);
  20133. texture.needsUpdate = true; */
  20134. this.sprite.material.map.image = canvas;
  20135. this.sprite.material.map.needsUpdate = true;
  20136. /* if(this.sprite.material.map){
  20137. this.sprite.material.map.dispose()
  20138. }
  20139. this.sprite.material.map = texture; */
  20140. var oldScale = this.sprite.scale.clone();
  20141. this.sprite.scale.set(spriteWidth * 0.01 / r, spriteHeight * 0.01 / r, 1.0);
  20142. if (!oldScale.equals(this.sprite.scale)) {
  20143. this.updateTransform2D();
  20144. this.sprite.waitUpdate(); //重新计算各个viewport的matrix
  20145. }
  20146. }
  20147. roundRect(ctx, x, y, w, h, r) {
  20148. ctx.beginPath();
  20149. ctx.moveTo(x + r, y);
  20150. ctx.lineTo(x + w - r, y);
  20151. ctx.arcTo(x + w, y, x + w, y + r, r); //圆弧。前四个参数同quadraticCurveTo
  20152. //ctx.quadraticCurveTo(x + w, y, x + w, y + r); //二次贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。
  20153. ctx.lineTo(x + w, y + h - r);
  20154. ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
  20155. ctx.lineTo(x + r, y + h);
  20156. ctx.arcTo(x, y + h, x, y + h - r, r);
  20157. ctx.lineTo(x, y + r);
  20158. ctx.arcTo(x, y, x + r, y, r);
  20159. ctx.closePath();
  20160. ctx.fill();
  20161. ctx.stroke();
  20162. }
  20163. updateTransform2D() {
  20164. if (this.transform2Dpercent) {
  20165. ['x', 'y'].forEach(axis => {
  20166. var percent = this.transform2Dpercent[axis];
  20167. this.sprite.position.y = this.sprite.scale.y * percent;
  20168. });
  20169. }
  20170. }
  20171. dispose() {
  20172. this.sprite.material.uniforms.map.value.dispose();
  20173. this.parent && this.parent.remove(this);
  20174. this.sprite.dispose();
  20175. this.removeAllListeners();
  20176. this.dispatchEvent('dispose');
  20177. }
  20178. }
  20179. function findBreakPoint(text, width, context) {
  20180. var min = 0;
  20181. var max = text.length - 1;
  20182. while (min <= max) {
  20183. var middle = Math.floor((min + max) / 2);
  20184. var middleWidth = context.measureText(text.substr(0, middle)).width;
  20185. var oneCharWiderThanMiddleWidth = context.measureText(text.substr(0, middle + 1)).width;
  20186. if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
  20187. return middle;
  20188. }
  20189. if (middleWidth < width) {
  20190. min = middle + 1;
  20191. } else {
  20192. max = middle - 1;
  20193. }
  20194. }
  20195. return -1;
  20196. }
  20197. function breakLinesForCanvas(text, context, width, font) {
  20198. var result = [];
  20199. var breakPoint = 0;
  20200. if (font) {
  20201. context.font = font;
  20202. }
  20203. while ((breakPoint = findBreakPoint(text, width, context)) !== -1) {
  20204. result.push(text.substr(0, breakPoint));
  20205. text = text.substr(breakPoint);
  20206. }
  20207. if (text) {
  20208. result.push(text);
  20209. }
  20210. return result;
  20211. } //'使用很寻常的二分查找,如果某一个位置之前的文字宽度小于等于设定的宽度,并且它之后一个字之前的文字宽度大于设定的宽度,那么这个位置就是文本的换行点。上面只是找到一个换行点,对于输入的一段文本,需要循环查找,直到不存在这样的换行点为止, 完整的代码如下',
  20212. //待改进:breakLinesForCanvas后的lineSpace稍小于预设的[]换行的lineSpace, 用于测量标签
  20213. /*
  20214. function wrapText(text, maxWidth) {
  20215. // 创建一个 canvas 元素来测量文本宽度
  20216. const canvas = document.createElement('canvas');
  20217. const ctx = canvas.getContext('2d');
  20218. // 设置字体样式
  20219. ctx.font = '16px Arial';
  20220. let currentLine = '';
  20221. const lines = [];
  20222. // 拆分文本为单词数组
  20223. const words = text.split(' ');
  20224. for (let i = 0; i < words.length; i++) {
  20225. const word = words[i];
  20226. const wordWidth = ctx.measureText(word).width;
  20227. const currentLineWidth = ctx.measureText(currentLine).width;
  20228. if (currentLineWidth + wordWidth < maxWidth) {
  20229. // 如果当前行加上这个单词不会超出最大宽度,就将它添加到当前行
  20230. currentLine += (currentLine ? ' ' : '') + word;
  20231. } else {
  20232. // 如果当前行加上这个单词会超出最大宽度,就将当前行添加到结果数组,并开始新的一行
  20233. lines.push(currentLine.trim());
  20234. currentLine = word;
  20235. }
  20236. }
  20237. // 添加最后一行
  20238. if (currentLine) {
  20239. lines.push(currentLine.trim());
  20240. }
  20241. return lines;
  20242. }
  20243. */
  20244. /*
  20245. z
  20246. |
  20247. |
  20248. |
  20249. |
  20250. x <-------| 中心为点云position加boudingbox中心
  20251. /
  20252. /
  20253. y
  20254. */
  20255. var lineLen$1 = 2,
  20256. stemLen = 4,
  20257. arrowLen = 2,
  20258. lineDisToStem = 5;
  20259. var opacity = 0.5;
  20260. class Axis extends Object3D {
  20261. // 坐标轴
  20262. constructor() {
  20263. super();
  20264. this.getArrow();
  20265. this.createArrows();
  20266. //this.position.copy(position) 点云的中心点就是在(0,0,0)
  20267. //this.scale.set(2,2,2)
  20268. /* viewer.addEventListener('camera_changed', e => {
  20269. if(e.viewport.name != 'MainView')return //只调整mainView,否则需要每次渲染前调整。缺点:地图上的大小变来变去
  20270. let s = Potree.math.getScaleForConstantSize( {//规定下最小最大像素
  20271. width2d:50, camera:e.camera , position:this.position,
  20272. resolution: e.viewport.resolution//2
  20273. })
  20274. this.scale.set(s,s,s)
  20275. }) */
  20276. }
  20277. getArrow() {
  20278. var arrowGroup = new Object3D();
  20279. var line = LineDraw.createLine([new Vector3(), new Vector3(0, 0, lineLen$1)]);
  20280. var stem = new Mesh(new BoxGeometry(0.3, 0.3, stemLen));
  20281. stem.position.set(0, 0, lineLen$1 + lineDisToStem + stemLen / 2);
  20282. 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
  20283. arrow.position.set(0, 0, lineLen$1 + lineDisToStem + stemLen + arrowLen / 2);
  20284. arrow.rotation.set(Math.PI / 2, 0, 0);
  20285. arrowGroup.add(stem);
  20286. arrowGroup.add(line);
  20287. arrowGroup.add(arrow);
  20288. this.arrowGroup = arrowGroup;
  20289. }
  20290. createArrows() {
  20291. var material = new MeshBasicMaterial({
  20292. color: "#00d7df",
  20293. side: 2,
  20294. transparent: true,
  20295. opacity: 0.8,
  20296. depthWrite: false
  20297. });
  20298. ['x', 'y', 'z'].forEach(axisText => {
  20299. var color = new Color().set(Potree.config.axis[axisText].color);
  20300. var group = this.arrowGroup.clone();
  20301. group.children.forEach(e => {
  20302. e.material = e.material.clone();
  20303. /* e.material.opacity = opacity
  20304. e.material.transparent = true */
  20305. e.material.color.copy(color);
  20306. });
  20307. var label = this.createLabel(axisText, color);
  20308. label.position.set(0, 0, lineLen$1 + stemLen + arrowLen + lineDisToStem + 3);
  20309. group.add(label);
  20310. if (axisText == 'y') {
  20311. group.rotation.x = -Math.PI / 2;
  20312. } else if (axisText == 'x') {
  20313. group.rotation.y = Math.PI / 2;
  20314. }
  20315. this.add(group);
  20316. });
  20317. }
  20318. createLabel(text, color) {
  20319. var label = new TextSprite$2({
  20320. //无法解决 因其祖先有设定quaternion, 无法对着镜头
  20321. backgroundColor: {
  20322. r: 0,
  20323. g: 0,
  20324. b: 0,
  20325. a: 0
  20326. },
  20327. textColor: {
  20328. r: color.r * 255,
  20329. g: color.g * 255,
  20330. b: color.b * 255,
  20331. a: 1
  20332. },
  20333. fontsize: 120,
  20334. //useDepth : true ,
  20335. renderOrder: 5,
  20336. // pickOrder:5,
  20337. text,
  20338. name: 'axis'
  20339. });
  20340. label.scale.set(3, 3, 3);
  20341. return label;
  20342. }
  20343. /* createLabel(text,color){
  20344. var canvas = document.createElement("canvas")
  20345. var context = canvas.getContext("2d");
  20346. canvas.width = 256,
  20347. canvas.height = 256;
  20348. var fontSize = 120
  20349. context.fillStyle = color //"#00ffee";
  20350. context.font = "normal " + fontSize + "px 微软雅黑"
  20351. var textWidth = context.measureText(text).width;
  20352. context.clearRect(0,0,canvas.width,canvas.height);
  20353. context.fillText(text, (canvas.width - textWidth) / 2 , (canvas.height + fontSize) / 2);
  20354. var tex = new THREE.Texture(canvas);
  20355. tex.needsUpdate = true
  20356. tex.minFilter = THREE.NearestFilter//防止边缘发黑
  20357. tex.magFilter = THREE.NearestFilter//防止边缘发黑
  20358. var sprite = new THREE.Sprite(new THREE.SpriteMaterial({
  20359. map: tex , // depthWrite:false,
  20360. }))
  20361. sprite.renderOrder = 1//防止在透明后还是出现白矩形挡住其他mesh
  20362. sprite.scale.set(3,3,3)
  20363. return sprite
  20364. } */
  20365. }
  20366. class Action extends EventDispatcher$1 {
  20367. constructor() {
  20368. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  20369. super();
  20370. this.icon = args.icon || '';
  20371. this.tooltip = args.tooltip;
  20372. if (args.onclick !== undefined) {
  20373. this.onclick = args.onclick;
  20374. }
  20375. }
  20376. onclick(event) {}
  20377. pairWith(object) {}
  20378. setIcon(newIcon) {
  20379. var oldIcon = this.icon;
  20380. if (newIcon === oldIcon) {
  20381. return;
  20382. }
  20383. this.icon = newIcon;
  20384. this.dispatchEvent({
  20385. type: 'icon_changed',
  20386. action: this,
  20387. icon: newIcon,
  20388. oldIcon: oldIcon
  20389. });
  20390. }
  20391. }
  20392. ;
  20393. //Potree.Actions = {};
  20394. //
  20395. //Potree.Actions.ToggleAnnotationVisibility = class ToggleAnnotationVisibility extends Potree.Action {
  20396. // constructor (args = {}) {
  20397. // super(args);
  20398. //
  20399. // this.icon = Potree.resourcePath + '/icons/eye.svg';
  20400. // this.showIn = 'sidebar';
  20401. // this.tooltip = 'toggle visibility';
  20402. // }
  20403. //
  20404. // pairWith (annotation) {
  20405. // if (annotation.visible) {
  20406. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  20407. // } else {
  20408. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  20409. // }
  20410. //
  20411. // annotation.addEventListener('visibility_changed', e => {
  20412. // let annotation = e.annotation;
  20413. //
  20414. // if (annotation.visible) {
  20415. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  20416. // } else {
  20417. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  20418. // }
  20419. // });
  20420. // }
  20421. //
  20422. // onclick (event) {
  20423. // let annotation = event.annotation;
  20424. //
  20425. // annotation.visible = !annotation.visible;
  20426. //
  20427. // if (annotation.visible) {
  20428. // this.setIcon(Potree.resourcePath + '/icons/eye.svg');
  20429. // } else {
  20430. // this.setIcon(Potree.resourcePath + '/icons/eye_crossed.svg');
  20431. // }
  20432. // }
  20433. //};
  20434. class Annotation extends EventDispatcher$1 {
  20435. constructor() {
  20436. var _this;
  20437. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  20438. super();
  20439. _this = this;
  20440. this.scene = null;
  20441. this._title = args.title || 'No Title';
  20442. this._description = args.description || '';
  20443. this.offset = new Vector3();
  20444. this.uuid = MathUtils.generateUUID();
  20445. if (!args.position) {
  20446. this.position = null;
  20447. } else if (args.position.x != null) {
  20448. this.position = args.position;
  20449. } else {
  20450. this.position = new Vector3(...args.position);
  20451. }
  20452. this.cameraPosition = args.cameraPosition instanceof Array ? new Vector3().fromArray(args.cameraPosition) : args.cameraPosition;
  20453. this.cameraTarget = args.cameraTarget instanceof Array ? new Vector3().fromArray(args.cameraTarget) : args.cameraTarget;
  20454. this.radius = args.radius;
  20455. this.view = args.view || null;
  20456. this.keepOpen = false;
  20457. this.descriptionVisible = false;
  20458. this.showDescription = true;
  20459. this.actions = args.actions || [];
  20460. this.isHighlighted = false;
  20461. this._visible = true;
  20462. this.__visible = true;
  20463. this._display = true;
  20464. this._expand = false;
  20465. this.collapseThreshold = [args.collapseThreshold, 100].find(e => e !== undefined);
  20466. this.children = [];
  20467. this.parent = null;
  20468. this.boundingBox = new Box3();
  20469. var iconClose = exports.resourcePath + '/icons/close.svg';
  20470. this.domElement = $("\n\t\t\t<div class=\"annotation\" oncontextmenu=\"return false;\">\n\t\t\t\t<div class=\"annotation-titlebar\">\n\t\t\t\t\t<span class=\"annotation-label\"></span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"annotation-description\">\n\t\t\t\t\t<span class=\"annotation-description-close\">\n\t\t\t\t\t\t<img src=\"".concat(iconClose, "\" width=\"16px\">\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"annotation-description-content\">").concat(this._description, "</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  20471. this.elTitlebar = this.domElement.find('.annotation-titlebar');
  20472. this.elTitle = this.elTitlebar.find('.annotation-label');
  20473. this.elTitle.append(this._title);
  20474. this.elDescription = this.domElement.find('.annotation-description');
  20475. this.elDescriptionClose = this.elDescription.find('.annotation-description-close');
  20476. // this.elDescriptionContent = this.elDescription.find(".annotation-description-content");
  20477. this.clickTitle = () => {
  20478. if (this.hasView()) {
  20479. this.moveHere(this.scene.getActiveCamera());
  20480. }
  20481. this.dispatchEvent({
  20482. type: 'click',
  20483. target: this
  20484. });
  20485. };
  20486. this.elTitle.click(this.clickTitle);
  20487. this.actions = this.actions.map(a => {
  20488. if (a instanceof Action) {
  20489. return a;
  20490. } else {
  20491. return new Action(a);
  20492. }
  20493. });
  20494. for (var action of this.actions) {
  20495. action.pairWith(this);
  20496. }
  20497. var actions = this.actions.filter(a => a.showIn === undefined || a.showIn.includes('scene'));
  20498. var _loop = function _loop(_action) {
  20499. var elButton = $("<img src=\"".concat(_action.icon, "\" class=\"annotation-action-icon\">"));
  20500. _this.elTitlebar.append(elButton);
  20501. elButton.click(() => _action.onclick({
  20502. annotation: _this
  20503. }));
  20504. };
  20505. for (var _action of actions) {
  20506. _loop(_action);
  20507. }
  20508. this.elDescriptionClose.hover(e => this.elDescriptionClose.css('opacity', '1'), e => this.elDescriptionClose.css('opacity', '0.5'));
  20509. this.elDescriptionClose.click(e => this.setHighlighted(false));
  20510. // this.elDescriptionContent.html(this._description);
  20511. this.domElement.mouseenter(e => this.setHighlighted(true));
  20512. this.domElement.mouseleave(e => this.setHighlighted(false));
  20513. this.domElement.on('touchstart', e => {
  20514. this.setHighlighted(!this.isHighlighted);
  20515. });
  20516. this.display = false;
  20517. //this.display = true;
  20518. }
  20519. installHandles(viewer) {
  20520. if (this.handles !== undefined) {
  20521. return;
  20522. }
  20523. var domElement = $("\n\t\t\t<div style=\"position: absolute; left: 300; top: 200; pointer-events: none\">\n\t\t\t\t<svg width=\"300\" height=\"600\">\n\t\t\t\t\t<line x1=\"0\" y1=\"0\" x2=\"1200\" y2=\"200\" style=\"stroke: black; stroke-width:2\" />\n\t\t\t\t\t<circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"black\" stroke-width=\"2\" fill=\"gray\" />\n\t\t\t\t\t<circle cx=\"150\" cy=\"50\" r=\"4\" stroke=\"black\" stroke-width=\"2\" fill=\"gray\" />\n\t\t\t\t</svg>\n\t\t\t</div>\n\t\t");
  20524. var svg = domElement.find("svg")[0];
  20525. var elLine = domElement.find("line")[0];
  20526. var elStart = domElement.find("circle")[0];
  20527. var elEnd = domElement.find("circle")[1];
  20528. var setCoordinates = (start, end) => {
  20529. elStart.setAttribute("cx", "".concat(start.x));
  20530. elStart.setAttribute("cy", "".concat(start.y));
  20531. elEnd.setAttribute("cx", "".concat(end.x));
  20532. elEnd.setAttribute("cy", "".concat(end.y));
  20533. elLine.setAttribute("x1", start.x);
  20534. elLine.setAttribute("y1", start.y);
  20535. elLine.setAttribute("x2", end.x);
  20536. elLine.setAttribute("y2", end.y);
  20537. var box = svg.getBBox();
  20538. svg.setAttribute("width", "".concat(box.width));
  20539. svg.setAttribute("height", "".concat(box.height));
  20540. svg.setAttribute("viewBox", "".concat(box.x, " ").concat(box.y, " ").concat(box.width, " ").concat(box.height));
  20541. var ya = start.y - end.y;
  20542. var xa = start.x - end.x;
  20543. if (ya > 0) {
  20544. start.y = start.y - ya;
  20545. }
  20546. if (xa > 0) {
  20547. start.x = start.x - xa;
  20548. }
  20549. domElement.css("left", "".concat(start.x, "px"));
  20550. domElement.css("top", "".concat(start.y, "px"));
  20551. };
  20552. $(viewer.renderArea).append(domElement);
  20553. var annotationStartPos = this.position.clone();
  20554. var annotationStartOffset = this.offset.clone();
  20555. $(this.domElement).draggable({
  20556. start: (event, ui) => {
  20557. annotationStartPos = this.position.clone();
  20558. annotationStartOffset = this.offset.clone();
  20559. $(this.domElement).find(".annotation-titlebar").css("pointer-events", "none");
  20560. console.log($(this.domElement).find(".annotation-titlebar"));
  20561. },
  20562. stop: () => {
  20563. $(this.domElement).find(".annotation-titlebar").css("pointer-events", "");
  20564. },
  20565. drag: (event, ui) => {
  20566. var renderAreaWidth = viewer.renderer.getSize(new Vector2()).width;
  20567. //let renderAreaHeight = viewer.renderer.getSize().height;
  20568. var diff = {
  20569. x: ui.originalPosition.left - ui.position.left,
  20570. y: ui.originalPosition.top - ui.position.top
  20571. };
  20572. var nDiff = {
  20573. x: -(diff.x / renderAreaWidth) * 2,
  20574. y: diff.y / renderAreaWidth * 2
  20575. };
  20576. var camera = viewer.scene.getActiveCamera();
  20577. var oldScreenPos = new Vector3().addVectors(annotationStartPos, annotationStartOffset).project(camera);
  20578. var newScreenPos = oldScreenPos.clone();
  20579. newScreenPos.x += nDiff.x;
  20580. newScreenPos.y += nDiff.y;
  20581. var newPos = newScreenPos.clone();
  20582. newPos.unproject(camera);
  20583. var newOffset = new Vector3().subVectors(newPos, this.position);
  20584. this.offset.copy(newOffset);
  20585. }
  20586. });
  20587. var updateCallback = () => {
  20588. var position = this.position;
  20589. var scene = viewer.scene;
  20590. var renderAreaSize = viewer.renderer.getSize(new Vector2());
  20591. var renderAreaWidth = renderAreaSize.width;
  20592. var renderAreaHeight = renderAreaSize.height;
  20593. var start = this.position.clone();
  20594. var end = new Vector3().addVectors(this.position, this.offset);
  20595. var toScreen = position => {
  20596. var camera = scene.getActiveCamera();
  20597. var screenPos = new Vector3();
  20598. var worldView = new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
  20599. var ndc = new Vector4(position.x, position.y, position.z, 1.0).applyMatrix4(worldView);
  20600. // limit w to small positive value, in case position is behind the camera
  20601. ndc.w = Math.max(ndc.w, 0.1);
  20602. ndc.divideScalar(ndc.w);
  20603. screenPos.copy(ndc);
  20604. screenPos.x = renderAreaWidth * (screenPos.x + 1) / 2;
  20605. screenPos.y = renderAreaHeight * (1 - (screenPos.y + 1) / 2);
  20606. return screenPos;
  20607. };
  20608. start = toScreen(start);
  20609. end = toScreen(end);
  20610. setCoordinates(start, end);
  20611. };
  20612. viewer.addEventListener("update", updateCallback);
  20613. this.handles = {
  20614. domElement: domElement,
  20615. setCoordinates: setCoordinates,
  20616. updateCallback: updateCallback
  20617. };
  20618. }
  20619. removeHandles(viewer) {
  20620. if (this.handles === undefined) {
  20621. return;
  20622. }
  20623. //$(viewer.renderArea).remove(this.handles.domElement);
  20624. this.handles.domElement.remove();
  20625. viewer.removeEventListener("update", this.handles.updateCallback);
  20626. delete this.handles;
  20627. }
  20628. get visible() {
  20629. return this._visible;
  20630. }
  20631. set visible(value) {
  20632. if (this._visible === value) {
  20633. return;
  20634. }
  20635. this._visible = value;
  20636. //this.traverse(node => {
  20637. // node.display = value;
  20638. //});
  20639. this.dispatchEvent({
  20640. type: 'visibility_changed',
  20641. annotation: this
  20642. });
  20643. }
  20644. get display() {
  20645. return this._display;
  20646. }
  20647. set display(display) {
  20648. if (this._display === display) {
  20649. return;
  20650. }
  20651. this._display = display;
  20652. if (display) {
  20653. // this.domElement.fadeIn(200);
  20654. this.domElement.show();
  20655. } else {
  20656. // this.domElement.fadeOut(200);
  20657. this.domElement.hide();
  20658. }
  20659. }
  20660. get expand() {
  20661. return this._expand;
  20662. }
  20663. set expand(expand) {
  20664. if (this._expand === expand) {
  20665. return;
  20666. }
  20667. if (expand) {
  20668. this.display = false;
  20669. } else {
  20670. this.display = true;
  20671. this.traverseDescendants(node => {
  20672. node.display = false;
  20673. });
  20674. }
  20675. this._expand = expand;
  20676. }
  20677. get title() {
  20678. return this._title;
  20679. }
  20680. set title(title) {
  20681. if (this._title === title) {
  20682. return;
  20683. }
  20684. this._title = title;
  20685. this.elTitle.empty();
  20686. this.elTitle.append(this._title);
  20687. this.dispatchEvent({
  20688. type: "annotation_changed",
  20689. annotation: this
  20690. });
  20691. }
  20692. get description() {
  20693. return this._description;
  20694. }
  20695. set description(description) {
  20696. if (this._description === description) {
  20697. return;
  20698. }
  20699. this._description = description;
  20700. var elDescriptionContent = this.elDescription.find(".annotation-description-content");
  20701. elDescriptionContent.empty();
  20702. elDescriptionContent.append(this._description);
  20703. this.dispatchEvent({
  20704. type: "annotation_changed",
  20705. annotation: this
  20706. });
  20707. }
  20708. add(annotation) {
  20709. if (!this.children.includes(annotation)) {
  20710. this.children.push(annotation);
  20711. annotation.parent = this;
  20712. var descendants = [];
  20713. annotation.traverse(a => {
  20714. descendants.push(a);
  20715. });
  20716. for (var descendant of descendants) {
  20717. var c = this;
  20718. while (c !== null) {
  20719. c.dispatchEvent({
  20720. 'type': 'annotation_added',
  20721. 'annotation': descendant
  20722. });
  20723. c = c.parent;
  20724. }
  20725. }
  20726. }
  20727. }
  20728. level() {
  20729. if (this.parent === null) {
  20730. return 0;
  20731. } else {
  20732. return this.parent.level() + 1;
  20733. }
  20734. }
  20735. hasChild(annotation) {
  20736. return this.children.includes(annotation);
  20737. }
  20738. remove(annotation) {
  20739. if (this.hasChild(annotation)) {
  20740. annotation.removeAllChildren();
  20741. annotation.dispose();
  20742. this.children = this.children.filter(e => e !== annotation);
  20743. annotation.parent = null;
  20744. }
  20745. }
  20746. removeAllChildren() {
  20747. this.children.forEach(child => {
  20748. if (child.children.length > 0) {
  20749. child.removeAllChildren();
  20750. }
  20751. this.remove(child);
  20752. });
  20753. }
  20754. updateBounds() {
  20755. var box = new Box3();
  20756. if (this.position) {
  20757. box.expandByPoint(this.position);
  20758. }
  20759. for (var child of this.children) {
  20760. child.updateBounds();
  20761. box.union(child.boundingBox);
  20762. }
  20763. this.boundingBox.copy(box);
  20764. }
  20765. traverse(handler) {
  20766. var expand = handler(this);
  20767. if (expand === undefined || expand === true) {
  20768. for (var child of this.children) {
  20769. child.traverse(handler);
  20770. }
  20771. }
  20772. }
  20773. traverseDescendants(handler) {
  20774. for (var child of this.children) {
  20775. child.traverse(handler);
  20776. }
  20777. }
  20778. flatten() {
  20779. var annotations = [];
  20780. this.traverse(annotation => {
  20781. annotations.push(annotation);
  20782. });
  20783. return annotations;
  20784. }
  20785. descendants() {
  20786. var annotations = [];
  20787. this.traverse(annotation => {
  20788. if (annotation !== this) {
  20789. annotations.push(annotation);
  20790. }
  20791. });
  20792. return annotations;
  20793. }
  20794. setHighlighted(highlighted) {
  20795. if (highlighted) {
  20796. this.domElement.css('opacity', '0.8');
  20797. this.elTitlebar.css('box-shadow', '0 0 5px #fff');
  20798. this.domElement.css('z-index', '1000');
  20799. if (this._description) {
  20800. this.descriptionVisible = true;
  20801. this.elDescription.fadeIn(200);
  20802. this.elDescription.css('position', 'relative');
  20803. }
  20804. } else {
  20805. this.domElement.css('opacity', '0.5');
  20806. this.elTitlebar.css('box-shadow', '');
  20807. this.domElement.css('z-index', '100');
  20808. this.descriptionVisible = false;
  20809. this.elDescription.css('display', 'none');
  20810. }
  20811. this.isHighlighted = highlighted;
  20812. }
  20813. hasView() {
  20814. var hasPosTargetView = this.cameraTarget.x != null;
  20815. hasPosTargetView = hasPosTargetView && this.cameraPosition.x != null;
  20816. var hasRadiusView = this.radius !== undefined;
  20817. var hasView = hasPosTargetView || hasRadiusView;
  20818. return hasView;
  20819. }
  20820. moveHere(camera) {
  20821. if (!this.hasView()) {
  20822. return;
  20823. }
  20824. var view = this.scene.view;
  20825. var animationDuration = 500;
  20826. var easing = TWEEN.Easing.Quartic.Out;
  20827. var endTarget;
  20828. if (this.cameraTarget) {
  20829. endTarget = this.cameraTarget;
  20830. } else if (this.position) {
  20831. endTarget = this.position;
  20832. } else {
  20833. endTarget = this.boundingBox.getCenter(new Vector3());
  20834. }
  20835. if (this.cameraPosition) {
  20836. var endPosition = this.cameraPosition;
  20837. Utils.moveTo(this.scene, endPosition, endTarget);
  20838. } else if (this.radius) {
  20839. var direction = view.direction;
  20840. var _endPosition = endTarget.clone().add(direction.multiplyScalar(-this.radius));
  20841. var startRadius = view.radius;
  20842. var endRadius = this.radius;
  20843. {
  20844. // animate camera position
  20845. var tween = new TWEEN.Tween(view.position).to(_endPosition, animationDuration);
  20846. tween.easing(easing);
  20847. tween.start();
  20848. }
  20849. {
  20850. // animate radius
  20851. var t = {
  20852. x: 0
  20853. };
  20854. var _tween = new TWEEN.Tween(t).to({
  20855. x: 1
  20856. }, animationDuration).onUpdate(function () {
  20857. view.radius = this.x * endRadius + (1 - this.x) * startRadius;
  20858. });
  20859. _tween.easing(easing);
  20860. _tween.start();
  20861. }
  20862. }
  20863. }
  20864. dispose() {
  20865. if (this.domElement.parentElement) {
  20866. this.domElement.parentElement.removeChild(this.domElement);
  20867. }
  20868. }
  20869. toString() {
  20870. return 'Annotation: ' + this._title;
  20871. }
  20872. }
  20873. ;
  20874. class Scene$1 extends EventDispatcher$1 {
  20875. //base
  20876. constructor() {
  20877. super();
  20878. this.annotations = new Annotation();
  20879. this.scene = new Scene();
  20880. this.sceneBG = new Scene();
  20881. this.scenePointCloud = new Scene();
  20882. this.cameraP = new PerspectiveCamera(this.fov, 1, 0.1, 1000 * 1000);
  20883. this.cameraO = new OrthographicCamera(-1, 1, 1, -1, 0.1, 1000 * 1000);
  20884. this.cameraVR = new PerspectiveCamera();
  20885. this.cameraBG = new Camera();
  20886. this.cameraScreenSpace = new OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
  20887. this.cameraMode = CameraMode.PERSPECTIVE;
  20888. this.overrideCamera = null;
  20889. this.pointclouds = [];
  20890. this.measurements = [];
  20891. this.profiles = [];
  20892. this.volumes = [];
  20893. this.polygonClipVolumes = [];
  20894. this.cameraAnimations = [];
  20895. this.orientedImages = [];
  20896. this.images360 = [];
  20897. this.geopackages = [];
  20898. this.fpControls = null;
  20899. this.orbitControls = null;
  20900. this.earthControls = null;
  20901. this.geoControls = null;
  20902. this.deviceControls = null;
  20903. this.inputHandler = null;
  20904. this.view = new ExtendView();
  20905. this.directionalLight = null;
  20906. this.initialize();
  20907. }
  20908. estimateHeightAt(position) {
  20909. var height = null;
  20910. var fromSpacing = Infinity;
  20911. for (var pointcloud of this.pointclouds) {
  20912. if (pointcloud.root.geometryNode === undefined) {
  20913. continue;
  20914. }
  20915. var pHeight = null;
  20916. var pFromSpacing = Infinity;
  20917. var lpos = position.clone().sub(pointcloud.position);
  20918. lpos.z = 0;
  20919. var ray = new Ray(lpos, new Vector3(0, 0, 1));
  20920. var stack = [pointcloud.root];
  20921. while (stack.length > 0) {
  20922. var node = stack.pop();
  20923. var box = node.getBoundingBox();
  20924. var inside = ray.intersectBox(box);
  20925. if (!inside) {
  20926. continue;
  20927. }
  20928. var h = node.geometryNode.mean.z + pointcloud.position.z + node.geometryNode.boundingBox.min.z;
  20929. if (node.geometryNode.spacing <= pFromSpacing) {
  20930. pHeight = h;
  20931. pFromSpacing = node.geometryNode.spacing;
  20932. }
  20933. for (var index of Object.keys(node.children)) {
  20934. var child = node.children[index];
  20935. if (child.geometryNode) {
  20936. stack.push(node.children[index]);
  20937. }
  20938. }
  20939. }
  20940. if (height === null || pFromSpacing < fromSpacing) {
  20941. height = pHeight;
  20942. fromSpacing = pFromSpacing;
  20943. }
  20944. }
  20945. return height;
  20946. }
  20947. getBoundingBox() {
  20948. var pointclouds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.pointclouds;
  20949. var box = new Box3();
  20950. this.scenePointCloud.updateMatrixWorld(true);
  20951. this.referenceFrame.updateMatrixWorld(true);
  20952. for (var pointcloud of pointclouds) {
  20953. pointcloud.updateMatrixWorld(true);
  20954. var pointcloudBox = pointcloud.pcoGeometry.tightBoundingBox ? pointcloud.pcoGeometry.tightBoundingBox : pointcloud.boundingBox;
  20955. var boxWorld = Utils.computeTransformedBoundingBox(pointcloudBox, pointcloud.matrixWorld);
  20956. box.union(boxWorld);
  20957. }
  20958. return box;
  20959. }
  20960. addPointCloud(pointcloud) {
  20961. this.pointclouds.push(pointcloud);
  20962. this.scenePointCloud.add(pointcloud);
  20963. this.dispatchEvent({
  20964. type: 'pointcloud_added',
  20965. pointcloud: pointcloud
  20966. });
  20967. }
  20968. addVolume(volume) {
  20969. this.volumes.push(volume);
  20970. this.dispatchEvent({
  20971. 'type': 'volume_added',
  20972. 'scene': this,
  20973. 'volume': volume
  20974. });
  20975. viewer.dispatchEvent('content_changed');
  20976. }
  20977. addOrientedImages(images) {
  20978. this.orientedImages.push(images);
  20979. this.scene.add(images.node);
  20980. this.dispatchEvent({
  20981. 'type': 'oriented_images_added',
  20982. 'scene': this,
  20983. 'images': images
  20984. });
  20985. }
  20986. removeOrientedImages(images) {
  20987. var index = this.orientedImages.indexOf(images);
  20988. if (index > -1) {
  20989. this.orientedImages.splice(index, 1);
  20990. this.dispatchEvent({
  20991. 'type': 'oriented_images_removed',
  20992. 'scene': this,
  20993. 'images': images
  20994. });
  20995. }
  20996. }
  20997. add360Images(images) {
  20998. this.images360.push(images);
  20999. this.scene.add(images.node);
  21000. this.dispatchEvent({
  21001. 'type': '360_images_added',
  21002. 'scene': this,
  21003. 'images': images
  21004. });
  21005. }
  21006. remove360Images(images) {
  21007. var index = this.images360.indexOf(images);
  21008. if (index > -1) {
  21009. this.images360.splice(index, 1);
  21010. this.dispatchEvent({
  21011. 'type': '360_images_removed',
  21012. 'scene': this,
  21013. 'images': images
  21014. });
  21015. }
  21016. }
  21017. addGeopackage(geopackage) {
  21018. this.geopackages.push(geopackage);
  21019. this.scene.add(geopackage.node);
  21020. this.dispatchEvent({
  21021. 'type': 'geopackage_added',
  21022. 'scene': this,
  21023. 'geopackage': geopackage
  21024. });
  21025. }
  21026. removeGeopackage(geopackage) {
  21027. var index = this.geopackages.indexOf(geopackage);
  21028. if (index > -1) {
  21029. this.geopackages.splice(index, 1);
  21030. this.dispatchEvent({
  21031. 'type': 'geopackage_removed',
  21032. 'scene': this,
  21033. 'geopackage': geopackage
  21034. });
  21035. }
  21036. }
  21037. removeVolume(volume) {
  21038. var index = this.volumes.indexOf(volume);
  21039. if (index > -1) {
  21040. this.volumes.splice(index, 1);
  21041. this.dispatchEvent({
  21042. 'type': 'volume_removed',
  21043. 'scene': this,
  21044. 'volume': volume
  21045. });
  21046. }
  21047. viewer.dispatchEvent('content_changed');
  21048. }
  21049. addCameraAnimation(animation) {
  21050. this.cameraAnimations.push(animation);
  21051. this.dispatchEvent({
  21052. 'type': 'camera_animation_added',
  21053. 'scene': this,
  21054. 'animation': animation
  21055. });
  21056. }
  21057. removeCameraAnimation(animation) {
  21058. var index = this.cameraAnimations.indexOf(volume);
  21059. if (index > -1) {
  21060. this.cameraAnimations.splice(index, 1);
  21061. this.dispatchEvent({
  21062. 'type': 'camera_animation_removed',
  21063. 'scene': this,
  21064. 'animation': animation
  21065. });
  21066. }
  21067. }
  21068. addPolygonClipVolume(volume) {
  21069. this.polygonClipVolumes.push(volume);
  21070. this.dispatchEvent({
  21071. "type": "polygon_clip_volume_added",
  21072. "scene": this,
  21073. "volume": volume
  21074. });
  21075. }
  21076. removePolygonClipVolume(volume) {
  21077. var index = this.polygonClipVolumes.indexOf(volume);
  21078. if (index > -1) {
  21079. this.polygonClipVolumes.splice(index, 1);
  21080. this.dispatchEvent({
  21081. "type": "polygon_clip_volume_removed",
  21082. "scene": this,
  21083. "volume": volume
  21084. });
  21085. }
  21086. }
  21087. addMeasurement(measurement) {
  21088. measurement.lengthUnit = this.lengthUnit;
  21089. measurement.lengthUnitDisplay = this.lengthUnitDisplay;
  21090. this.measurements.push(measurement);
  21091. this.dispatchEvent({
  21092. 'type': 'measurement_added',
  21093. 'scene': this,
  21094. 'measurement': measurement
  21095. });
  21096. viewer.dispatchEvent('content_changed');
  21097. }
  21098. removeMeasurement(measurement) {
  21099. var index = this.measurements.indexOf(measurement);
  21100. if (index > -1) {
  21101. this.measurements.splice(index, 1);
  21102. this.dispatchEvent({
  21103. 'type': 'measurement_removed',
  21104. 'scene': this,
  21105. 'measurement': measurement
  21106. });
  21107. viewer.dispatchEvent('content_changed');
  21108. }
  21109. }
  21110. addProfile(profile) {
  21111. this.profiles.push(profile);
  21112. this.dispatchEvent({
  21113. 'type': 'profile_added',
  21114. 'scene': this,
  21115. 'profile': profile
  21116. });
  21117. }
  21118. removeProfile(profile) {
  21119. var index = this.profiles.indexOf(profile);
  21120. if (index > -1) {
  21121. this.profiles.splice(index, 1);
  21122. this.dispatchEvent({
  21123. 'type': 'profile_removed',
  21124. 'scene': this,
  21125. 'profile': profile
  21126. });
  21127. }
  21128. }
  21129. removeAllMeasurements() {
  21130. while (this.measurements.length > 0) {
  21131. this.removeMeasurement(this.measurements[0]);
  21132. }
  21133. while (this.profiles.length > 0) {
  21134. this.removeProfile(this.profiles[0]);
  21135. }
  21136. while (this.volumes.length > 0) {
  21137. this.removeVolume(this.volumes[0]);
  21138. }
  21139. }
  21140. removeAllClipVolumes() {
  21141. var clipVolumes = this.volumes.filter(volume => volume.clip === true);
  21142. for (var clipVolume of clipVolumes) {
  21143. this.removeVolume(clipVolume);
  21144. }
  21145. while (this.polygonClipVolumes.length > 0) {
  21146. this.removePolygonClipVolume(this.polygonClipVolumes[0]);
  21147. }
  21148. }
  21149. getActiveCamera() {
  21150. if (this.overrideCamera) {
  21151. return this.overrideCamera;
  21152. }
  21153. if (this.cameraMode === CameraMode.PERSPECTIVE) {
  21154. return this.cameraP;
  21155. } else if (this.cameraMode === CameraMode.ORTHOGRAPHIC) {
  21156. return this.cameraO;
  21157. } else if (this.cameraMode === CameraMode.VR) {
  21158. return this.cameraVR;
  21159. }
  21160. return null;
  21161. }
  21162. initialize() {
  21163. this.referenceFrame = new Object3D();
  21164. this.referenceFrame.matrixAutoUpdate = false;
  21165. this.scenePointCloud.add(this.referenceFrame);
  21166. this.cameraP.up.set(0, 0, 1);
  21167. this.cameraP.position.set(1000, 1000, 1000);
  21168. this.cameraO.up.set(0, 0, 1);
  21169. this.cameraO.position.set(1000, 1000, 1000);
  21170. //this.camera.rotation.y = -Math.PI / 4;
  21171. //this.camera.rotation.x = -Math.PI / 6;
  21172. this.cameraScreenSpace.lookAt(new Vector3(0, 0, 0), new Vector3(0, 0, -1), new Vector3(0, 1, 0));
  21173. this.directionalLight = new DirectionalLight(0xffffff, 0.5);
  21174. this.directionalLight.position.set(10, 10, 10);
  21175. this.directionalLight.lookAt(new Vector3(0, 0, 0));
  21176. this.scenePointCloud.add(this.directionalLight);
  21177. var light = new AmbientLight(0x555555); // soft white light
  21178. this.scenePointCloud.add(light);
  21179. {
  21180. // background
  21181. var texture = Utils.createBackgroundTexture(512, 512);
  21182. texture.minFilter = texture.magFilter = NearestFilter;
  21183. texture.minFilter = texture.magFilter = LinearFilter;
  21184. var bg = new Mesh(new PlaneBufferGeometry(2, 2, 1), new MeshBasicMaterial({
  21185. map: texture
  21186. }));
  21187. bg.material.depthTest = false;
  21188. bg.material.depthWrite = false;
  21189. this.sceneBG.add(bg);
  21190. }
  21191. // { // lights
  21192. // {
  21193. // let light = new THREE.DirectionalLight(0xffffff);
  21194. // light.position.set(10, 10, 1);
  21195. // light.target.position.set(0, 0, 0);
  21196. // this.scene.add(light);
  21197. // }
  21198. // {
  21199. // let light = new THREE.DirectionalLight(0xffffff);
  21200. // light.position.set(-10, 10, 1);
  21201. // light.target.position.set(0, 0, 0);
  21202. // this.scene.add(light);
  21203. // }
  21204. // {
  21205. // let light = new THREE.DirectionalLight(0xffffff);
  21206. // light.position.set(0, -10, 20);
  21207. // light.target.position.set(0, 0, 0);
  21208. // this.scene.add(light);
  21209. // }
  21210. // }
  21211. }
  21212. addAnnotation(position) {
  21213. var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  21214. if (position instanceof Array) {
  21215. args.position = new Vector3().fromArray(position);
  21216. } else if (position.x != null) {
  21217. args.position = position;
  21218. }
  21219. var annotation = new Annotation(args);
  21220. this.annotations.add(annotation);
  21221. return annotation;
  21222. }
  21223. getAnnotations() {
  21224. return this.annotations;
  21225. }
  21226. removeAnnotation(annotationToRemove) {
  21227. this.annotations.remove(annotationToRemove);
  21228. }
  21229. }
  21230. ;
  21231. class ExtendScene extends Scene$1 {
  21232. constructor() {
  21233. super();
  21234. delete this.sceneBG;
  21235. this.overlayScene = new Scene();
  21236. this.overlayScene.name = 'overlay';
  21237. viewer.addEventListener("render.pass.perspective_overlay", this.renderOverlay.bind(this));
  21238. this.cameraP = new PerspectiveCamera(this.fov, 1, Potree.config.view.near, Potree.config.view.cameraFar);
  21239. this.cameraO = new OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
  21240. this.cameraP.limitFar = true; //add
  21241. this.initializeExtend();
  21242. //-------------
  21243. this.axisArrow = new Axis();
  21244. this.scene.add(this.axisArrow);
  21245. if (!Potree.settings.isDebug && !Potree.settings.showAxis) this.axisArrow.visible = false;
  21246. Potree.Utils.setObjectLayers(this.axisArrow, 'bothMapAndScene');
  21247. this.monitors = [];
  21248. this.overlays = [];
  21249. }
  21250. estimateHeightAt(position) {
  21251. var height = null;
  21252. var fromSpacing = Infinity;
  21253. for (var pointcloud of this.pointclouds) {
  21254. if (pointcloud.root.geometryNode === undefined) {
  21255. continue;
  21256. }
  21257. var pHeight = null;
  21258. var pFromSpacing = Infinity;
  21259. var lpos = position.clone().sub(pointcloud.position);
  21260. lpos.z = 0;
  21261. var ray = new Ray(lpos, new Vector3(0, 0, 1));
  21262. var stack = [pointcloud.root];
  21263. while (stack.length > 0) {
  21264. var node = stack.pop();
  21265. var box = node.getBoundingBox();
  21266. var inside = ray.intersectBox(box);
  21267. if (!inside) {
  21268. continue;
  21269. }
  21270. var h = node.geometryNode.mean.z + pointcloud.position.z + node.geometryNode.boundingBox.min.z;
  21271. if (node.geometryNode.spacing <= pFromSpacing) {
  21272. pHeight = h;
  21273. pFromSpacing = node.geometryNode.spacing;
  21274. }
  21275. for (var index of Object.keys(node.children)) {
  21276. var child = node.children[index];
  21277. if (child.geometryNode) {
  21278. stack.push(node.children[index]);
  21279. }
  21280. }
  21281. }
  21282. if (height === null || pFromSpacing < fromSpacing) {
  21283. height = pHeight;
  21284. fromSpacing = pFromSpacing;
  21285. }
  21286. }
  21287. return height;
  21288. }
  21289. //add:
  21290. removePointCloud(pointcloud) {
  21291. var index = this.pointclouds.indexOf(pointcloud);
  21292. if (index == -1) return;
  21293. this.pointclouds.splice(index, 1);
  21294. this.scenePointCloud.remove(pointcloud);
  21295. pointcloud.panos.forEach(pano => {
  21296. pano.dispose();
  21297. });
  21298. }
  21299. removeCameraAnimation(animation) {
  21300. var index = this.cameraAnimations.indexOf(animation);
  21301. if (index > -1) {
  21302. this.cameraAnimations.splice(index, 1);
  21303. this.dispatchEvent({
  21304. 'type': 'camera_animation_removed',
  21305. 'scene': this,
  21306. 'animation': animation
  21307. });
  21308. }
  21309. }
  21310. getActiveCamera() {
  21311. return viewer.mainViewport.camera;
  21312. }
  21313. initialize() {//不用旧的 因为还没创建完变量
  21314. }
  21315. initializeExtend() {
  21316. //add 新的initialize
  21317. this.referenceFrame = new Object3D();
  21318. this.referenceFrame.matrixAutoUpdate = false;
  21319. this.scenePointCloud.add(this.referenceFrame);
  21320. if (window.axisYup) {} else {
  21321. this.cameraP.up.set(0, 0, 1);
  21322. this.cameraO.up.set(0, 0, 1);
  21323. }
  21324. this.cameraP.position.set(1000, 1000, 1000);
  21325. this.cameraO.position.set(1000, 1000, 1000);
  21326. //this.camera.rotation.y = -Math.PI / 4;
  21327. //this.camera.rotation.x = -Math.PI / 6;
  21328. this.cameraScreenSpace.lookAt(new Vector3(0, 0, 0), new Vector3(0, 0, -1), new Vector3(0, 1, 0));
  21329. this.directionalLight = new DirectionalLight(0xffffff, 0.5);
  21330. this.directionalLight.position.set(10, 10, 10);
  21331. this.directionalLight.lookAt(new Vector3(0, 0, 0));
  21332. this.scenePointCloud.add(this.directionalLight);
  21333. var light = new AmbientLight(0x555555); // soft white light
  21334. this.scenePointCloud.add(light);
  21335. //add:------给空间模型的box 或其他obj------
  21336. var light2 = new AmbientLight(16777215, 0.5);
  21337. Potree.Utils.setObjectLayers(light2, 'light' /* 'bothMapAndScene' */);
  21338. this.scene.add(light2);
  21339. var light3 = new DirectionalLight(16777215, 0.7);
  21340. light3.position.set(10, 10, 10);
  21341. light3.lookAt(new Vector3(0, 0, 0));
  21342. Potree.Utils.setObjectLayers(light3, 'light');
  21343. this.scene.add(light3);
  21344. var light4 = new DirectionalLight(16777215, 0.3); //补光
  21345. light4.position.set(-10, -5, -7);
  21346. light4.lookAt(new Vector3(0, 0, 0));
  21347. Potree.Utils.setObjectLayers(light4, 'light');
  21348. this.scene.add(light4);
  21349. //--------------------------------------------
  21350. {
  21351. // background
  21352. var texture = Utils.createBackgroundTexture(512, 512);
  21353. texture.minFilter = texture.magFilter = NearestFilter;
  21354. texture.minFilter = texture.magFilter = LinearFilter;
  21355. var bg = new Mesh(new PlaneBufferGeometry(2, 2, 1), new MeshBasicMaterial({
  21356. map: texture
  21357. }));
  21358. bg.material.depthTest = false;
  21359. bg.material.depthWrite = false;
  21360. bg.name = 'bg';
  21361. //this.sceneBG.add(bg);
  21362. this.scene.add(bg);
  21363. bg.layers.set(Potree.config.renderLayers.bg);
  21364. }
  21365. {
  21366. // background color
  21367. var bg2 = new Mesh(new PlaneBufferGeometry(2, 2, 1), new MeshBasicMaterial({
  21368. transparent: true
  21369. }));
  21370. bg2.material.depthTest = false;
  21371. bg2.material.depthWrite = false;
  21372. bg2.name = 'bg2';
  21373. this.scene.add(bg2);
  21374. bg2.layers.set(Potree.config.renderLayers.bg2);
  21375. this.bg2 = bg2;
  21376. }
  21377. }
  21378. renderOverlay() {
  21379. var _o$viewport;
  21380. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  21381. // measure tag
  21382. if (this.overlayScene.children.filter(e => e.visible).length == 0 || (_o$viewport = o.viewport) !== null && _o$viewport !== void 0 && (_o$viewport = _o$viewport.cameraLayers) !== null && _o$viewport !== void 0 && _o$viewport.length && !o.viewport.cameraLayers.includes('sceneObjects')) return;
  21383. var renderer = o.renderer || this.viewer.renderer;
  21384. Potree.Utils.setCameraLayers(o.camera, ['sceneObjects']);
  21385. viewer.dispatchEvent({
  21386. type: "render.begin2",
  21387. name: 'overlays',
  21388. viewport: o.viewport,
  21389. renderer: o.renderer
  21390. });
  21391. renderer.render(this.overlayScene, o.camera);
  21392. }
  21393. }
  21394. ;
  21395. KeyCodes.BACKSPACE = 8;
  21396. //注意,这时候Potree.js中export的内容还不在Potree变量中
  21397. var texLoader$1 = new TextureLoader();
  21398. texLoader$1.crossOrigin = "anonymous";
  21399. {
  21400. //defines:
  21401. Potree.defines = {};
  21402. Potree.defines.Buttons = {
  21403. // MouseEvent.buttons
  21404. //buttons,设置按下了鼠标哪些键,是一个3个比特位的二进制值,默认为0。1表示按下主键(通常是左键),2表示按下次要键(通常是右键),4表示按下辅助键(通常是中间的键)。
  21405. NONE: 0,
  21406. //add
  21407. LEFT: 0b0001,
  21408. RIGHT: 0b0010,
  21409. MIDDLE: 0b0100
  21410. };
  21411. /* 如果访问的是button, 用THREE.MOUSE来判断:
  21412. button,设置按下了哪一个鼠标按键,默认为0。-1表示没有按键,0表示按下主键(通常是左键),1表示按下辅助键(通常是中间的键),2表示按下次要键(通常是右键)
  21413. */
  21414. Potree.browser = browser;
  21415. /////////// add //////////////////////////////////
  21416. Potree.defines.GLCubeFaces = {
  21417. GL_TEXTURE_CUBE_MAP_POSITIVE_X: 0,
  21418. GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1,
  21419. GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2,
  21420. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 3,
  21421. GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 4,
  21422. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 5
  21423. };
  21424. Potree.defines.PanoSizeClass = {
  21425. BASE: 1,
  21426. STANDARD: 2,
  21427. HIGH: 3,
  21428. ULTRAHIGH: 4
  21429. };
  21430. Potree.defines.PanoRendererEvents = {
  21431. PanoRenderComplete: "panorama.render.complete",
  21432. TileRenderFailure: "panorama.tile.render.failed",
  21433. TileRenderSuccess: "panorama.tile.render.success",
  21434. TileUploadAttempted: "panorama.tile.upload.attempted",
  21435. UploadAttemptedForAllTiles: "panorama.upload.attempted.all.tiles",
  21436. ZoomLevelRenderStarted: "panorama.zoom.render.started"
  21437. };
  21438. Potree.defines.SceneRendererEvents = {
  21439. ContextCreated: "scene-renderer-context-created",
  21440. AfterRender: "after-render",
  21441. MemoryUsageUpdated: "scene-renderer-memory-usage-updated"
  21442. };
  21443. Potree.defines.TileDownloaderEvents = {
  21444. TileDownloadSuccess: "tiledownloader.download.success",
  21445. TileDownloadFailure: "tiledownloader.download.failure",
  21446. PanoDownloadComplete: "tiledownloader.pano.download.complete"
  21447. };
  21448. Potree.defines.Vectors = {
  21449. UP: new Vector3(0, 1, 0),
  21450. DOWN: new Vector3(0, -1, 0),
  21451. LEFT: new Vector3(-1, 0, 0),
  21452. RIGHT: new Vector3(1, 0, 0),
  21453. FORWARD: new Vector3(0, 0, -1),
  21454. BACK: new Vector3(0, 0, 1)
  21455. };
  21456. Potree.defines.gs3d = {
  21457. DepthMapRange: 1 << 16,
  21458. MemoryPageSize: 65536,
  21459. BytesPerFloat: 4,
  21460. BytesPerInt: 4,
  21461. MaxScenes: 32,
  21462. ProgressiveLoadSectionSize: 262144,
  21463. ProgressiveLoadSectionDelayDuration: 15,
  21464. SphericalHarmonics8BitCompressionRange: 3
  21465. };
  21466. Potree.defines.DownloadStatus = Object.freeze({
  21467. None: 0,
  21468. Queued: 1,
  21469. ForceQueued: 2,
  21470. Downloading: 3,
  21471. Downloaded: 4,
  21472. DownloadFailed: 5
  21473. });
  21474. Potree.defines.ModelManagerEvents = {
  21475. ModelAdded: "model-added",
  21476. ActiveModelChanged: "active-model-changed"
  21477. };
  21478. Potree.defines.PanoramaEvents = {
  21479. Enter: 'panorama.enter',
  21480. Exit: 'panorama.exit',
  21481. LoadComplete: "panorama.load.complete",
  21482. LoadFailed: "panorama.load.failed",
  21483. TileLoaded: "panorama.tile.loaded",
  21484. VideoRendered: "panorama.video.rendered"
  21485. };
  21486. ClipTask.SHOW_INSIDE_Big = 4;
  21487. }
  21488. {
  21489. //Features
  21490. var gl_, webgl2Support;
  21491. Features.EXT_DEPTH = {
  21492. isSupported: function isSupported(gl) {
  21493. gl = gl || gl_;
  21494. gl_ = gl;
  21495. if (browser.detectIOS()) {
  21496. var {
  21497. major,
  21498. minor,
  21499. patch
  21500. } = browser.iosVersion();
  21501. //console.warn('iosVersion',major,minor,patch)
  21502. if (major == 15 && minor == 4 && patch == 1) {
  21503. console.warn('检测到是ios15.4.1, 关闭EXT_frag_depth'); //该版本ext_depth有问题,导致clear错乱。没有解决办法先关闭。
  21504. return false;
  21505. }
  21506. }
  21507. return typeof WebGL2RenderingContext != 'undefined' && gl instanceof WebGL2RenderingContext || gl.getExtension('EXT_frag_depth'); //shader中的GL_EXT_frag_depth需要判断一下detectIOS吗。。
  21508. }
  21509. };
  21510. /* Features.getMaxMapSize = (gl)=>{
  21511. // 查询最大立方体贴图纹理尺寸
  21512. gl = gl || gl_
  21513. gl_ = gl
  21514. let info = {
  21515. cubeMap: gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE),
  21516. tex: gl.getParameter( gl.MAX_TEXTURE_SIZE )
  21517. }
  21518. if(info.cubeMap < 4096){
  21519. console.warn('cubeMap最大仅支持', info.cubeMap)
  21520. }
  21521. return info
  21522. } */
  21523. Features.webgl2RealSupport = () => {
  21524. if (webgl2Support != void 0) {
  21525. return webgl2Support;
  21526. }
  21527. var gl;
  21528. try {
  21529. var canvas = document.createElement('canvas');
  21530. if (window.WebGL2RenderingContext) {
  21531. //遇到有设备(iphone8 plus ios14.1 型号MQ8F2CH/A)直接获取webgl2后会点云和全景图闪烁,WebGL2RenderingContext和得到的context是undefined。但是为何4dkk不会闪烁
  21532. gl = canvas.getContext('webgl2'); //麒麟系统chromium 128 到这一步才获取失败 如果直接对最终的canvas获取webgl2,会造成多viewport无法单独渲染以及clearAlpha透明失败
  21533. }
  21534. } catch (e) {
  21535. console.log(e);
  21536. }
  21537. webgl2Support = !!gl;
  21538. return webgl2Support;
  21539. };
  21540. }
  21541. Utils.loadSkybox = function (path, oldSky, callback) {
  21542. var camera, scene, parent, cameraOrtho;
  21543. if (!oldSky) {
  21544. parent = new Object3D("skybox_root");
  21545. camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
  21546. cameraOrtho = new OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
  21547. if (!window.axisYup) camera.up.set(0, 0, 1); //add
  21548. scene = new Scene();
  21549. var skyboxBgWidth = Potree.config.skyboxBgWidth;
  21550. var skyGeometry = new BoxBufferGeometry(skyboxBgWidth, skyboxBgWidth, skyboxBgWidth);
  21551. var skybox = new Mesh(skyGeometry, new ShaderMaterial({
  21552. vertexShader: Shaders['skybox.vs'],
  21553. fragmentShader: Shaders['skybox.fs'],
  21554. side: BackSide,
  21555. uniforms: {
  21556. tDiffuse: {
  21557. type: "t",
  21558. value: null
  21559. },
  21560. matrix: {
  21561. type: "m4",
  21562. value: new Matrix4()
  21563. }
  21564. },
  21565. depthTest: false,
  21566. depthWrite: false
  21567. }));
  21568. scene.add(skybox);
  21569. scene.traverse(n => n.frustumCulled = false);
  21570. // z up
  21571. //scene.rotation.x = Math.PI / 2;
  21572. parent.children.push(camera);
  21573. camera.parent = parent;
  21574. } else {
  21575. camera = oldSky.camera, scene = oldSky.scene;
  21576. parent = oldSky.parent;
  21577. cameraOrtho = oldSky.cameraOrtho;
  21578. }
  21579. var texture = texLoader$1.load(path, () => {
  21580. console.log('loadSkybox成功', path);
  21581. texture.wrapS = RepeatWrapping;
  21582. texture.flipY = false;
  21583. texture.magFilter = LinearFilter;
  21584. texture.minFilter = LinearFilter;
  21585. scene.children[0].material.uniforms.tDiffuse.value = texture;
  21586. callback && callback();
  21587. viewer.dispatchEvent('content_changed');
  21588. }, null, e => {
  21589. //error
  21590. console.error('loadSkybox失败', path);
  21591. });
  21592. return {
  21593. camera,
  21594. scene,
  21595. parent,
  21596. cameraOrtho
  21597. };
  21598. };
  21599. Utils.getMousePointCloudIntersection = function (viewport, mouse, pointer, camera, viewer, pointclouds) {
  21600. var pickParams = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
  21601. //let startTime = performance.now()
  21602. if (!pointclouds || pointclouds.filter(e => Potree.Utils.getObjVisiByReason(e, 'datasetSelection')).length == 0) return;
  21603. //console.log('getMousePointCloudIntersection')
  21604. var renderer = viewer.renderer;
  21605. var resolution = pickParams.resolution || (viewport === null || viewport === void 0 ? void 0 : viewport.resolution) || renderer.getSize(new Vector2());
  21606. if (pickParams.ifCenter) {
  21607. pickParams.x = Math.round(resolution.x / 2);
  21608. pickParams.y = Math.round(resolution.y / 2);
  21609. } else {
  21610. pickParams.x = mouse.x;
  21611. pickParams.y = resolution.y - mouse.y;
  21612. }
  21613. var raycaster = new Raycaster();
  21614. raycaster.setFromCamera(pointer, camera);
  21615. var ray = raycaster.ray;
  21616. var selectedPointcloud = null;
  21617. var closestDistance = Infinity;
  21618. var closestIntersection = null;
  21619. var closestPoint = null;
  21620. //-----------add--------------------
  21621. var old_clipBoxes_in = new Map();
  21622. var old_clipBoxes_out = new Map();
  21623. var old_bigClipInBox = new Map();
  21624. var old_highlightBoxes = new Map();
  21625. var old_visibleNodes = new Map();
  21626. //bigClipInBox 最好也写下
  21627. var density;
  21628. var sizeType;
  21629. var size = new Map();
  21630. var visiMap = new Map();
  21631. var needsUpdate = false;
  21632. if (pickParams.measuring || Potree.settings.displayMode == 'showPanos') {
  21633. //测量或无深度图时的全景模式提高精准度. (全景模式有深度图时不会执行到这)
  21634. density = Potree.settings.pointDensity;
  21635. Potree.settings.pointDensity = 'magnifier'; //加载最高level
  21636. pointclouds.forEach(e => {
  21637. //因为全景模式的pointSizeType是fixed所以要还原下
  21638. visiMap.set(e, e.visible);
  21639. e.visible = Potree.Utils.getObjVisiByReason(e, 'datasetSelection'); //先将隐藏的点云显示
  21640. if (!e.visible) return;
  21641. size.set(e, e.temp.pointSize);
  21642. sizeType = e.material.pointSizeType;
  21643. e.material.pointSizeType = Potree.config.material.pointSizeType;
  21644. //e.changePointSize(Potree.config.material.realPointSize*2, true)//更改点云大小到能铺满为止,否则容易识别不到
  21645. });
  21646. needsUpdate = true;
  21647. } else {
  21648. if (viewer.viewports.filter(e => !e.noPointcloud && e.active).length > 1 || pickParams.cameraChanged) {
  21649. //在pick时相机和渲染时不一样的话
  21650. viewport.beforeRender && viewport.beforeRender();
  21651. needsUpdate = true; //不updatePointClouds的话hover久了会不准 因node是错的
  21652. //但依旧需要camera真的移动到那个位置才能加载出点云
  21653. }
  21654. }
  21655. if (!pickParams.pickClipped) {
  21656. // 无视clipBoxes
  21657. for (var pointcloud of pointclouds) {
  21658. old_clipBoxes_in.set(pointcloud, pointcloud.clipBoxes_in);
  21659. old_clipBoxes_out.set(pointcloud, pointcloud.clipBoxes_out);
  21660. old_bigClipInBox.set(pointcloud, pointcloud.bigClipInBox);
  21661. old_highlightBoxes.set(pointcloud, pointcloud.highlightBoxes);
  21662. pointcloud.material.setClipBoxes(null, [], [], []);
  21663. }
  21664. needsUpdate = true;
  21665. }
  21666. if (needsUpdate) {
  21667. for (var _pointcloud of pointclouds) {
  21668. old_visibleNodes.set(_pointcloud, _pointcloud.visibleNodes);
  21669. }
  21670. if (window.notViewOffset) {
  21671. Potree.updatePointClouds(pointclouds, camera, viewport.resolution);
  21672. } else {
  21673. //尽量减少点云加载的范围,集中在pick的空间(这部分以外还是会加载一些散点的)
  21674. var viewWidth = Math.max(pickParams.pickWindowSize || 80, 80); //viewer.magnifier ? viewer.magnifier.viewport.resolution.x : 200
  21675. var camera_ = camera.clone();
  21676. camera_.setViewOffset(resolution.x, resolution.y, pickParams.x - viewWidth / 2, resolution.y - pickParams.y - viewWidth / 2, viewWidth, viewWidth); //注意offsetY是从上到下,和一般的不同
  21677. Potree.updatePointClouds(pointclouds, camera_, resolution);
  21678. }
  21679. }
  21680. //------------------------------------------------
  21681. var allPointclouds = [];
  21682. for (var _pointcloud2 of pointclouds) {
  21683. var point = _pointcloud2.pick(viewer, viewport, camera, ray, pickParams);
  21684. if (!point) {
  21685. continue;
  21686. }
  21687. allPointclouds.push(_pointcloud2);
  21688. var distance = camera.position.distanceTo(point.position);
  21689. if (distance < closestDistance) {
  21690. closestDistance = distance;
  21691. selectedPointcloud = _pointcloud2;
  21692. closestIntersection = point.position;
  21693. closestPoint = point;
  21694. }
  21695. }
  21696. //恢复
  21697. if (pickParams.measuring || Potree.settings.displayMode == 'showPanos') {
  21698. Potree.settings.pointDensity = density;
  21699. pointclouds.forEach(e => {
  21700. if (e.visible) {
  21701. e.material.pointSizeType = sizeType;
  21702. //e.changePointSize(size.get(e))
  21703. }
  21704. e.visible = visiMap.get(e);
  21705. });
  21706. } else {
  21707. /* if(viewer.viewports.filter(e=>!e.noPointcloud).length>1){
  21708. viewport.afterRender && viewport.afterRender()
  21709. } */
  21710. }
  21711. if (!pickParams.pickClipped) {
  21712. //add
  21713. for (var _pointcloud3 of pointclouds) {
  21714. _pointcloud3.material.setClipBoxes(old_bigClipInBox.get(_pointcloud3), old_clipBoxes_in.get(_pointcloud3), old_clipBoxes_out.get(_pointcloud3), old_highlightBoxes.get(_pointcloud3));
  21715. }
  21716. }
  21717. if (needsUpdate) {
  21718. for (var _pointcloud4 of pointclouds) {
  21719. //不恢复的话(尤其cameraChanged时),在下次render前,再次pick可能是错的。表现为多数据集刚开始reticule消失了,直到ifPointBlockedByIntersect停止
  21720. _pointcloud4.visibleNodes = old_visibleNodes.get(_pointcloud4);
  21721. }
  21722. }
  21723. //console.log('pick', performance.now() - startTime )
  21724. if (selectedPointcloud) {
  21725. var localNormal = closestPoint.normal && new Vector3().fromArray(closestPoint.normal);
  21726. return {
  21727. location: closestIntersection,
  21728. distance: closestDistance,
  21729. pointcloud: selectedPointcloud,
  21730. point: closestPoint,
  21731. pointclouds: allPointclouds,
  21732. //add
  21733. localNormal: localNormal,
  21734. normal: localNormal === null || localNormal === void 0 ? void 0 : localNormal.clone().applyMatrix4(selectedPointcloud.rotateMatrix) //add
  21735. };
  21736. } else {
  21737. return null;
  21738. }
  21739. };
  21740. Utils.pixelsArrayToDataUrl = function (pixels, width, height) {
  21741. var compressRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.7;
  21742. var canvas = document.createElement('canvas');
  21743. canvas.width = width;
  21744. canvas.height = height;
  21745. var context = canvas.getContext('2d');
  21746. pixels = new pixels.constructor(pixels);
  21747. /* for (let i = 0; i < pixels.length; i++) {
  21748. pixels[i * 4 + 3] = 255;
  21749. } */
  21750. // flip vertically
  21751. var bytesPerLine = width * 4;
  21752. for (var i = 0; i < parseInt(height / 2); i++) {
  21753. var j = height - i - 1;
  21754. var lineI = pixels.slice(i * bytesPerLine, i * bytesPerLine + bytesPerLine);
  21755. var lineJ = pixels.slice(j * bytesPerLine, j * bytesPerLine + bytesPerLine);
  21756. pixels.set(lineJ, i * bytesPerLine);
  21757. pixels.set(lineI, j * bytesPerLine);
  21758. }
  21759. var imageData = context.createImageData(width, height);
  21760. imageData.data.set(pixels);
  21761. context.putImageData(imageData, 0, 0);
  21762. var dataURL = canvas.toDataURL(compressRatio < 1 ? 'image/jpeg' : 'image/png', compressRatio);
  21763. return dataURL;
  21764. };
  21765. Utils.renderTargetToDataUrl = function (renderTarget, width, height, renderer) {
  21766. var compressRatio = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0.7;
  21767. var pixelCount = width * height;
  21768. var buffer = new Uint8Array(4 * pixelCount);
  21769. renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, buffer);
  21770. var dataUrl = Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio);
  21771. return dataUrl;
  21772. };
  21773. Utils.mouseToRay = function (pointer, camera) {
  21774. var vector = new Vector3(pointer.x, pointer.y, 1);
  21775. var origin = new Vector3(pointer.x, pointer.y, -1); //不能用camera.position,在orbitCamera时不准
  21776. vector.unproject(camera);
  21777. origin.unproject(camera);
  21778. var direction = new Vector3().subVectors(vector, origin).normalize();
  21779. var ray = new Ray(origin, direction);
  21780. return ray;
  21781. };
  21782. Utils.getPos2d = function (point, viewport, dom, renderer) {
  21783. //获取一个三维坐标对应屏幕中的二维坐标
  21784. var pos;
  21785. if (math.closeTo(viewport.camera.position, point, 1e-5)) {
  21786. //和相机位置重合时显示会四处飘,看是要改成一直显示中间还是隐藏?
  21787. pos = new Vector3(0, 0, 1.5); //1.5是为了不可见
  21788. } else {
  21789. pos = point.clone().project(viewport.camera); //比之前hotspot的计算方式写得简单 project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
  21790. }
  21791. var size = renderer && renderer.getSize(new Vector2()); //如果是渲染到renderTarget上,resolution和dom的大小不一致。如果输出的结果给前端2d用,就使用clinetWidth,如果自己场景用,用renderer.size
  21792. var w = renderer ? size.x : dom.clientWidth;
  21793. var h = renderer ? size.y : dom.clientHeight;
  21794. var x, y, left, top;
  21795. x = (pos.x + 1) / 2 * w * viewport.width;
  21796. y = (1 - (pos.y + 1) / 2) * h * viewport.height;
  21797. left = viewport.left * w;
  21798. top = (1 - viewport.bottom - viewport.height) * h;
  21799. var inSight = pos.x <= 1 && pos.x >= -1 //是否在屏幕中
  21800. && pos.x <= 1 && pos.y >= -1;
  21801. return {
  21802. pos: new Vector2(left + x, top + y),
  21803. // 屏幕像素坐标
  21804. vector: pos,
  21805. //(范围 -1 ~ 1)
  21806. trueSide: pos.z < 1 && pos.z > -1,
  21807. //z > 1 在远裁剪面之外, z < -1在近裁剪面之内。通常在相机背面时z也>1,反过来说z>1未必一定在背面
  21808. inSight: inSight,
  21809. //在屏幕范围内可见,
  21810. posInViewport: new Vector2(x, y)
  21811. };
  21812. /* 要判断一个点是否在相机背面,应该检查 相机空间(视图空间)的 z 值,而不是投影后的 z 值:
  21813. const viewPosition = vertex.clone().applyMatrix4(camera.matrixWorldInverse); //project的前半部分
  21814. const isBehindCamera = viewPosition.z > 0; // 相机看向 -Z 方向
  21815. */
  21816. };
  21817. Utils.getPointerPosAtHeight = function () {
  21818. var planeZ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  21819. var pointer = arguments.length > 1 ? arguments[1] : undefined;
  21820. var camera = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : viewer.mainViewport.camera;
  21821. var origin = new Vector3(pointer.x, pointer.y, -1).unproject(camera),
  21822. end = new Vector3(pointer.x, pointer.y, 1).unproject(camera);
  21823. var dir = end.sub(origin);
  21824. var r = (planeZ - origin.z) / dir.z;
  21825. var x = r * dir.x + origin.x;
  21826. var y = r * dir.y + origin.y;
  21827. return {
  21828. x,
  21829. y
  21830. };
  21831. };
  21832. Utils.screenPass = new function () {
  21833. this.screenScene = new Scene();
  21834. this.screenQuad = new Mesh(new PlaneBufferGeometry(2, 2, 1));
  21835. this.screenQuad.material.depthTest = true;
  21836. this.screenQuad.material.depthWrite = true;
  21837. this.screenQuad.material.transparent = true;
  21838. this.screenScene.add(this.screenQuad);
  21839. this.camera = new Camera();
  21840. this.render = function (renderer, material, target, composer) {
  21841. this.screenQuad.material = material;
  21842. if (typeof target === 'undefined') {
  21843. (composer || renderer).render(this.screenScene, this.camera);
  21844. } else {
  21845. var oldTarget = renderer.getRenderTarget();
  21846. renderer.setRenderTarget(target);
  21847. //renderer.clear(); //有时候不能clear,如renderBG后再
  21848. (composer || renderer).render(this.screenScene, this.camera);
  21849. renderer.setRenderTarget(oldTarget);
  21850. }
  21851. };
  21852. }();
  21853. //add
  21854. Utils.computePointcloudsBound = function (pointclouds) {
  21855. var boundingBox = new Box3();
  21856. pointclouds.forEach(pointcloud => {
  21857. pointcloud.updateBound();
  21858. boundingBox.union(pointcloud.bound2);
  21859. });
  21860. var boundSize = boundingBox.getSize(new Vector3());
  21861. var center = boundingBox.getCenter(new Vector3());
  21862. return {
  21863. boundSize,
  21864. center,
  21865. boundingBox
  21866. };
  21867. };
  21868. Utils.convertScreenPositionToNDC = function (pointer, mouse, width, height) {
  21869. return pointer = pointer || new Vector2(), pointer.x = mouse.x / width * 2 - 1, pointer.y = 2 * -(mouse.y / height) + 1, pointer;
  21870. };
  21871. Utils.convertNDCToScreenPosition = function (pointer, mouse, width, height) {
  21872. return mouse = mouse || new Vector2(), mouse.x = Math.round((pointer.x + 1) / 2 * width), mouse.y = Math.round(-(pointer.y - 1) / 2 * height), mouse;
  21873. };
  21874. Utils.getOrthoCameraMoveVec = function (pointerDelta, camera) {
  21875. //获取当camera为Ortho型时 屏幕点1 到 屏幕点2 的三维距离
  21876. var cameraViewWidth = camera.right / camera.zoom;
  21877. var cameraViewHeight = camera.top / camera.zoom;
  21878. var moveVec = new Vector3();
  21879. moveVec.set(pointerDelta.x * cameraViewWidth, pointerDelta.y * cameraViewHeight, 0).applyQuaternion(camera.quaternion);
  21880. return moveVec;
  21881. };
  21882. Utils.VectorFactory = {
  21883. fromArray: function fromArray(t) {
  21884. if (t) {
  21885. if (t.length < 2 || t.length > 3) console.error("Wrong number of ordinates for a point!");
  21886. return 3 === t.length ? new Vector3().fromArray(t) : new Vector2().fromArray(t);
  21887. }
  21888. },
  21889. fromArray3: function fromArray3(t) {
  21890. if (t) {
  21891. if (3 !== t.length) console.error("Wrong number of ordinates for a point!");
  21892. return new Vector3().fromArray(t);
  21893. }
  21894. },
  21895. fromArray2: function fromArray2(t) {
  21896. if (t) {
  21897. if (2 !== t.length) console.error("Wrong number of ordinates for a point!");
  21898. return new Vector2().fromArray(t);
  21899. }
  21900. },
  21901. toString: function toString(t) {
  21902. return t.x.toFixed(8) + "," + t.y.toFixed(8) + "," + t.z.toFixed(3);
  21903. }
  21904. };
  21905. Utils.QuaternionFactory = {
  21906. rot90: new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), MathUtils.degToRad(-90)),
  21907. fromArray: function fromArray(t) {
  21908. if (t) {
  21909. if (4 !== t.length) console.error("Wrong number of ordinates for a quaternion!");
  21910. return new Quaternion(t[1], t[2], t[3], t[0]).multiply(this.rot90);
  21911. }
  21912. },
  21913. toArray: function toArray(t) {
  21914. if (t) {
  21915. var e = t.clone().multiply(a).toArray();
  21916. return [e[3], e[0], e[1], e[2]];
  21917. }
  21918. },
  21919. fromLonLat: function fromLonLat(t) {
  21920. if (t) return new Quaternion().setFromEuler(new Euler(t.lon, t.lat, 0));
  21921. },
  21922. toLonLat: function toLonLat(t) {
  21923. if (t) {
  21924. var e = new Euler().setFromQuaternion(t);
  21925. return {
  21926. lon: e.x,
  21927. lat: e.y
  21928. };
  21929. }
  21930. }
  21931. };
  21932. Utils.datasetPosTransform = function () {
  21933. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  21934. var pointcloud = o.pointcloud || viewer.scene.pointclouds.find(e => e.dataset_id == o.datasetId);
  21935. var tranMatrix;
  21936. if (pointcloud) {
  21937. if (Potree.settings.editType == 'merge') {
  21938. tranMatrix = o.fromDataset ? pointcloud.matrixWorld : new Matrix4().copy(pointcloud.matrixWorld).invert();
  21939. } else {
  21940. tranMatrix = o.fromDataset ? pointcloud.transformMatrix : pointcloud.transformInvMatrix;
  21941. }
  21942. } else {
  21943. if (Potree.settings.intersectOnObjs) {
  21944. var object = o.object || viewer.objs.children.find(e => e.dataset_id == o.datasetId);
  21945. if (object) {
  21946. tranMatrix = o.fromDataset ? object.matrixWorld : new Matrix4().copy(object.matrixWorld).invert();
  21947. }
  21948. }
  21949. }
  21950. if (tranMatrix) {
  21951. return new Vector3().copy(o.position).applyMatrix4(tranMatrix);
  21952. } else {
  21953. if (o.datasetId != void 0) {
  21954. console.error("datasetPosTransform\u627E\u4E0D\u5230datasetId\u4E3A".concat(o.datasetId, "\u7684\u6570\u636E\u96C6\u6216\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6570\u636E\uFF0C \u6A21\u578B\u672A\u521B\u5EFA\u6216\u5220\u9664"));
  21955. //很可能是旧的热点,需要删除
  21956. }
  21957. }
  21958. };
  21959. Utils.datasetRotTransform = function () {
  21960. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  21961. var object = o.pointcloud || viewer.scene.pointclouds.find(e => e.dataset_id == o.datasetId) || o.object || viewer.objs.children.find(e => e.dataset_id == o.datasetId);
  21962. if (object) {
  21963. var matrix, newMatrix, result;
  21964. if (o.rotation) {
  21965. matrix = new Matrix4().makeRotationFromEuler(o.rotation);
  21966. } else if (o.quaternion) {
  21967. matrix = new Matrix4().makeRotationFromQuaternion(o.quaternion);
  21968. } else if (o.matrix) {
  21969. matrix = o.matrix.clone();
  21970. } else {
  21971. return;
  21972. }
  21973. var rotateMatrix = o.fromDataset ? object.rotateMatrix : object.rotateInvMatrix;
  21974. if (!rotateMatrix) {
  21975. rotateMatrix = new Matrix4().makeRotationFromEuler(object.rotation); //如果是没有漫游点的模型,在此临时获取一个,但和有漫游点的比会有所不同,因为没有初始旋转(如转90度)
  21976. if (o.toDataset) {
  21977. rotateMatrix.invert();
  21978. }
  21979. }
  21980. newMatrix = new Matrix4().multiplyMatrices(rotateMatrix, matrix);
  21981. if (o.getRotation) {
  21982. result = new Euler().setFromRotationMatrix(newMatrix);
  21983. } else if (o.getQuaternion) {
  21984. result = new Quaternion().setFromRotationMatrix(newMatrix);
  21985. } else if (o.getMatrix) {
  21986. result = newMatrix;
  21987. }
  21988. return result;
  21989. }
  21990. };
  21991. Utils.isInsideFrustum = function (bounding, camera) {
  21992. // bounding是否在视野范围内有可见部分(视野就是一个锥状box)
  21993. var frustumMatrix = new Matrix4();
  21994. frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
  21995. var frustum = new Frustum();
  21996. frustum.setFromProjectionMatrix(frustumMatrix);
  21997. if (bounding instanceof Sphere) {
  21998. return frustum.intersectsSphere(bounding);
  21999. } else {
  22000. return frustum.intersectsBox(bounding);
  22001. }
  22002. };
  22003. Utils.isIntersectBox = function (object, boxMatrix) {
  22004. //object是否有在box中的部分。 object可以是点或者bounding, box原为1*1*1,但可能形变
  22005. //let frustum = new THREE.Frustum();
  22006. //frustum.setFromProjectionMatrix(boxMatrixInverse) --错
  22007. var px = new Vector3(+0.5, 0, 0).applyMatrix4(boxMatrix);
  22008. var nx = new Vector3(-0.5, 0, 0).applyMatrix4(boxMatrix);
  22009. var py = new Vector3(0, +0.5, 0).applyMatrix4(boxMatrix);
  22010. var ny = new Vector3(0, -0.5, 0).applyMatrix4(boxMatrix);
  22011. var pz = new Vector3(0, 0, +0.5).applyMatrix4(boxMatrix);
  22012. var nz = new Vector3(0, 0, -0.5).applyMatrix4(boxMatrix);
  22013. var pxN = new Vector3().subVectors(nx, px).normalize();
  22014. var nxN = pxN.clone().multiplyScalar(-1);
  22015. var pyN = new Vector3().subVectors(ny, py).normalize();
  22016. var nyN = pyN.clone().multiplyScalar(-1);
  22017. var pzN = new Vector3().subVectors(nz, pz).normalize();
  22018. var nzN = pzN.clone().multiplyScalar(-1);
  22019. var pxPlane = new Plane().setFromNormalAndCoplanarPoint(pxN, px);
  22020. var nxPlane = new Plane().setFromNormalAndCoplanarPoint(nxN, nx);
  22021. var pyPlane = new Plane().setFromNormalAndCoplanarPoint(pyN, py);
  22022. var nyPlane = new Plane().setFromNormalAndCoplanarPoint(nyN, ny);
  22023. var pzPlane = new Plane().setFromNormalAndCoplanarPoint(pzN, pz);
  22024. var nzPlane = new Plane().setFromNormalAndCoplanarPoint(nzN, nz);
  22025. var frustum = new Frustum(pxPlane, nxPlane, pyPlane, nyPlane, pzPlane, nzPlane);
  22026. if (object instanceof Box3) {
  22027. var boxBound = new Box3(new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, 0.5, 0.5)).applyMatrix4(boxMatrix); //large boundingbox
  22028. if (!object.intersectsBox(boxBound)) return;
  22029. return frustum.intersectsBox(object); //根据该函数, 若存在某个plane在box上的对应点都在plane背面,则不相交. 可得知在box构成的frustum倾斜时不准确,不相交也判断为相交,甚至不如bound相交准确。所以前面加步骤排除下,但仍不完全准确。(可在裁剪中将box放置到数据集上方旋转下校验)
  22030. } else if (object instanceof Array) {
  22031. //点合集, 只能粗略计算下
  22032. var sphere = new Sphere();
  22033. sphere.setFromPoints(object);
  22034. return this.isIntersectBox(sphere, boxMatrix);
  22035. } else if (object instanceof Sphere) {
  22036. return frustum.intersectsSphere(object);
  22037. } else if (object instanceof Vector3) {
  22038. return frustum.containsPoint(object);
  22039. } else if (object instanceof Matrix4) {//第一个参数如果和第二个参数一样都是box的worldMatrix
  22040. }
  22041. /* containsPoint: ƒ containsPoint( point )
  22042. intersectsBox: ƒ intersectsBox( box )
  22043. intersectsObject: ƒ intersectsObject( object )//geo
  22044. intersectsSphere: ƒ intersectsSphere( sphere )
  22045. intersectsSprite: ƒ intersectsSprite( sprite )
  22046. */
  22047. };
  22048. Utils.getIntersect = function (camera, meshes, pointer, raycaster) {
  22049. //获取鼠标和meshes交点
  22050. if (!raycaster) {
  22051. //getMouseIntersect
  22052. camera.updateMatrixWorld();
  22053. raycaster = new Raycaster();
  22054. var origin = new Vector3(pointer.x, pointer.y, -1).unproject(camera),
  22055. end = new Vector3(pointer.x, pointer.y, 1).unproject(camera);
  22056. var dir = end.sub(origin).normalize();
  22057. raycaster.set(origin, dir);
  22058. }
  22059. meshes.forEach(e => {
  22060. raycaster.layers.enable(math.getBaseLog(2, e.layers.mask));
  22061. });
  22062. var n = raycaster.intersectObjects(meshes);
  22063. if (0 === n.length) return null;
  22064. return n[0];
  22065. };
  22066. Utils.addOrRemoveDefine = function (material, defineName, type) {
  22067. var value = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
  22068. var defines = material.defines;
  22069. if (type == 'add') {
  22070. if (defines[defineName] != void 0 && defines[defineName] == value) return;
  22071. defines[defineName] = value;
  22072. } else {
  22073. if (defines[defineName] == void 0) return;
  22074. delete defines[defineName];
  22075. }
  22076. material.needsUpdate = true;
  22077. };
  22078. Utils.makeTexDontResize = function (map) {
  22079. //避免贴图因非2的次方而缩小。小心使用
  22080. if (!map || !map.image) {
  22081. return console.log('!map || !map.image', map, map && map.image);
  22082. }
  22083. if (MathUtils.isPowerOfTwo(map.image.width) && MathUtils.isPowerOfTwo(map.image.height)) return;
  22084. map.wrapS = map.wrapT = ClampToEdgeWrapping; //原默认 RepeatWrapping
  22085. map.minFilter = LinearFilter; // or THREE.NearestFilter 原默认 LinearMipmapLinearFilter
  22086. map.generateMipmaps = false;
  22087. map.needsUpdate = true;
  22088. };
  22089. Utils.updateVisible = function (object, reason, ifShow) {
  22090. var level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  22091. var type = arguments.length > 4 ? arguments[4] : undefined;
  22092. var needRender = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
  22093. //当所有加入的条件都不为false时才显示. reason='force'一般是强制、临时的
  22094. if (!object.unvisibleReasons) object.unvisibleReasons = []; //如果length>0代表不可见
  22095. if (!object.visibleReasons) object.visibleReasons = []; //在同级时,优先可见
  22096. var update = function update() {
  22097. //先按从高到低的level排列
  22098. object.unvisibleReasons = object.unvisibleReasons.sort((a, b) => b.level - a.level);
  22099. object.visibleReasons = object.visibleReasons.sort((a, b) => b.level - a.level);
  22100. var maxVisiLevel = object.visibleReasons[0] ? object.visibleReasons[0].level : -1;
  22101. var maxunVisiLevel = object.unvisibleReasons[0] ? object.unvisibleReasons[0].level : -1;
  22102. var shouldVisi = maxVisiLevel >= maxunVisiLevel;
  22103. var visiBefore = object.visible;
  22104. if (visiBefore != shouldVisi) {
  22105. object.visible = shouldVisi;
  22106. object.dispatchEvent({
  22107. type: 'isVisible',
  22108. visible: shouldVisi,
  22109. reason
  22110. });
  22111. needRender && viewer.dispatchEvent('content_changed');
  22112. }
  22113. };
  22114. if (ifShow) {
  22115. var index = object.unvisibleReasons.findIndex(e => e.reason == reason);
  22116. if (index > -1) {
  22117. type = 'cancel';
  22118. object.unvisibleReasons.splice(index, 1);
  22119. }
  22120. if (type == 'add') {
  22121. if (!object.visibleReasons.some(e => e.reason == reason)) {
  22122. object.visibleReasons.push({
  22123. reason,
  22124. level
  22125. });
  22126. }
  22127. }
  22128. } else {
  22129. var index = object.visibleReasons.findIndex(e => e.reason == reason);
  22130. if (index > -1) {
  22131. type = 'cancel';
  22132. object.visibleReasons.splice(index, 1);
  22133. }
  22134. if (type != 'cancel') {
  22135. if (!object.unvisibleReasons.some(e => e.reason == reason)) {
  22136. object.unvisibleReasons.push({
  22137. reason,
  22138. level
  22139. });
  22140. }
  22141. }
  22142. }
  22143. update();
  22144. };
  22145. /*
  22146. 复杂案例: 如果物体默认隐藏, 当符合任何一个其他条件时可见,则可:
  22147. Potree.Utils.updateVisible(this, "default", false, 0 ) //默认隐藏
  22148. Potree.Utils.updateVisible(this, 条件名, ifShow, 1, ifShow?'add':'cancel' ) //其他的条件
  22149. */
  22150. Utils.getObjVisiByReason = function (object, reason) {
  22151. //获取在某条件下是否可见. 注: 用户在数据集选择可不可见为"datasetSelection"
  22152. if (object.visible) return true;else {
  22153. return !object.unvisibleReasons || !object.unvisibleReasons.some(e => e.reason == reason);
  22154. }
  22155. };
  22156. Utils.setCameraLayers = function (camera, enableLayers) {
  22157. var extraEnableLayers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  22158. //add
  22159. camera.layers.disableAll();
  22160. enableLayers.concat(extraEnableLayers).forEach(e => {
  22161. var layer = Potree.config.renderLayers[e];
  22162. if (layer == void 0) {
  22163. console.error('setCameraLayer没找到layer!', e);
  22164. return;
  22165. }
  22166. camera.layers.enable(layer);
  22167. });
  22168. };
  22169. Utils.setObjectLayers = function (object, layerName) {
  22170. //add
  22171. var layer = Potree.config.renderLayers[layerName];
  22172. if (layer == void 0) {
  22173. console.error('setObjectLayers没找到layer!', layerName);
  22174. return;
  22175. }
  22176. object.traverse(e => {
  22177. e.layers.set(layer);
  22178. });
  22179. };
  22180. Utils.imgAddText = async (img, text, labelInfo) => {
  22181. var label = new Potree.TextSprite(Object.assign({
  22182. //如果直接在canvas里写字,要另外写很多和canvas.drawText有关的,所以还是借助textSprite吧
  22183. backgroundColor: {
  22184. r: 0,
  22185. g: 0,
  22186. b: 0,
  22187. a: 0
  22188. },
  22189. textColor: {
  22190. r: 255,
  22191. g: 255,
  22192. b: 255,
  22193. a: 1
  22194. },
  22195. margin: {
  22196. x: 3,
  22197. y: 3
  22198. },
  22199. renderOrder: 50,
  22200. fontsize: 20,
  22201. text
  22202. }, labelInfo));
  22203. var labelImg = new Image();
  22204. labelImg.src = label.sprite.material.map.image.toDataURL('image/png');
  22205. return new Promise((resolve, reject) => {
  22206. labelImg.onload = () => {
  22207. if (labelInfo.horizonCenter) {
  22208. //水平居中(对img来说)
  22209. labelInfo.leftRatioToImg = 0.5 - labelImg.width / img.width / 2;
  22210. }
  22211. var result = Common$1.imgAddLabel(img, labelImg, labelInfo);
  22212. label.dispose();
  22213. resolve(result);
  22214. };
  22215. });
  22216. };
  22217. Utils.combineImgs = async (imgs, compressRatio, width, height) => {
  22218. //拼合图片,顺序从上到下从左到右, 每张图大小不一定一致,但同列的宽一致,同行宽一致
  22219. return new Promise((resolve, reject) => {
  22220. var item = imgs[0][0];
  22221. var wc = imgs.length,
  22222. hc = imgs[0].length,
  22223. loadCount = 0,
  22224. amount = wc * hc;
  22225. width = width || imgs.reduce((w, c) => w + c[0].width, 0),
  22226. //相加得到的可能比想要得到的大几个像素,之后会重叠
  22227. height = height || imgs[0].reduce((w, c) => w + c.height, 0);
  22228. var canvas = document.createElement('canvas');
  22229. canvas.width = width;
  22230. canvas.height = height;
  22231. var context = canvas.getContext('2d');
  22232. var _loop = function _loop(i) {
  22233. var _loop2 = function _loop2(j) {
  22234. var img = new Image();
  22235. img.src = imgs[i][j].dataUrl;
  22236. img.index = {
  22237. i,
  22238. j
  22239. };
  22240. img.onload = () => {
  22241. loadCount++;
  22242. var startX = img.index.i * img.width,
  22243. startY = img.index.j * img.height;
  22244. if (imgs[i][j].rot180) {
  22245. //旋转180度
  22246. context.save(); // 保存当前画布状态
  22247. context.translate(startX + img.width / 2, startY + img.height / 2),
  22248. // 移动到旋转中心点(图像中心)旋转
  22249. context.rotate(Math.PI);
  22250. startX = -img.width / 2, startY = -img.height / 2;
  22251. }
  22252. context.drawImage(img, startX, startY, img.width, img.height);
  22253. imgs[i][j].rot180 && context.restore(); // 恢复画布状态
  22254. if (loadCount == amount) {
  22255. var dataUrl = canvas.toDataURL(compressRatio < 1 ? 'image/jpeg' : 'image/png', compressRatio);
  22256. context.clearRect(0, 0, width, height);
  22257. resolve(dataUrl);
  22258. }
  22259. };
  22260. };
  22261. for (var j = 0; j < hc; j++) {
  22262. _loop2(j);
  22263. }
  22264. };
  22265. for (var i = 0; i < wc; i++) {
  22266. _loop(i);
  22267. }
  22268. });
  22269. };
  22270. Utils.tran4dkkVecInModel = (vec, model) => {
  22271. //将四维看看里的坐标转换成在此平台模型上的坐标(主要是3dtiles需要平移) 见load4dkkpanos
  22272. //if(model.fileType != '3dTiles') return Potree.math.convertVector.YupToZup(vec)
  22273. return Potree.math.convertVector.YupToZup(vec).applyMatrix4(model.posRot1MatrixInvert); //若要全局坐标,可以直接像pano那样转换,多乘个matrix
  22274. };
  22275. BinaryLoader.prototype.load = function (node, callback) {
  22276. //解析点云
  22277. if (node.loaded) {
  22278. return;
  22279. }
  22280. var url = node.getURL();
  22281. if (this.version.equalOrHigher('1.4')) {
  22282. url += '.bin';
  22283. }
  22284. url += '?m=' + node.pcoGeometry.timeStamp; //add
  22285. var xhr = XHRFactory.createXMLHttpRequest();
  22286. xhr.open('GET', url, true);
  22287. xhr.responseType = 'arraybuffer';
  22288. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  22289. xhr.onreadystatechange = () => {
  22290. if (xhr.readyState === 4) {
  22291. if ((xhr.status === 200 || xhr.status === 0) && xhr.response !== null) {
  22292. var buffer = xhr.response;
  22293. this.parse(node, buffer, callback);
  22294. } else {
  22295. node.loadFailed = 'status:' + xhr.status + ",url:" + url;
  22296. Potree.numNodesLoading--;
  22297. //console.error(`Failed to load file! HTTP status: ${xhr.status}, file: ${url}`);
  22298. throw new Error("Failed to load file! HTTP status: ".concat(xhr.status, ", file: ").concat(url));
  22299. }
  22300. }
  22301. };
  22302. try {
  22303. xhr.send(null);
  22304. } catch (e) {
  22305. node.loadFailed = 'catchError';
  22306. Potree.numNodesLoading--;
  22307. console.error('加载点云node出错 ', url, e);
  22308. }
  22309. };
  22310. PointAttribute.RGBA_PACKED = new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_INT8, 4);
  22311. PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;
  22312. PointAttribute.INTENSITY = new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1);
  22313. PointAttribute.CLASSIFICATION = new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1);
  22314. PointAttribute.GPS_TIME = new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);
  22315. ProfileWindow.prototype.initTHREE = function () {
  22316. this.renderer = new WebGLRenderer({
  22317. alpha: true,
  22318. premultipliedAlpha: false
  22319. });
  22320. this.renderer.setClearColor(0x000000, 0);
  22321. this.renderer.setSize(10, 10);
  22322. this.renderer.autoClear = false;
  22323. this.renderArea.append($(this.renderer.domElement));
  22324. this.renderer.domElement.tabIndex = '2222';
  22325. $(this.renderer.domElement).css('width', '100%');
  22326. $(this.renderer.domElement).css('height', '100%');
  22327. {
  22328. var gl = this.renderer.getContext();
  22329. if (gl.createVertexArray == null) {
  22330. var extVAO = gl.getExtension('OES_vertex_array_object');
  22331. if (!extVAO) {
  22332. throw new Error("OES_vertex_array_object extension not supported");
  22333. }
  22334. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  22335. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  22336. }
  22337. }
  22338. this.camera = new OrthographicCamera(-1000, 1000, 1000, -1000, -1000, 1000);
  22339. this.camera.up.set(0, 0, 1);
  22340. this.camera.rotation.order = "ZXY";
  22341. this.camera.rotation.x = Math.PI / 2.0;
  22342. this.scene = new Scene();
  22343. this.profileScene = new Scene();
  22344. var sg = new SphereGeometry(1, 16, 16);
  22345. var sm = new MeshNormalMaterial();
  22346. this.pickSphere = new Mesh(sg, sm);
  22347. this.scene.add(this.pickSphere);
  22348. this.viewerPickSphere = new Mesh(sg, sm);
  22349. };
  22350. //Potree_update_visibility
  22351. Potree.updatePointClouds = function (pointclouds, camera, areaSize) {
  22352. viewer.addTimeMark('updateClouds', 'start');
  22353. for (var pointcloud of pointclouds) {
  22354. var start = performance.now();
  22355. for (var profileRequest of pointcloud.profileRequests) {
  22356. profileRequest.update();
  22357. var _duration = performance.now() - start;
  22358. if (_duration > 5) {
  22359. break;
  22360. }
  22361. }
  22362. var duration = performance.now() - start;
  22363. }
  22364. var result = Potree.updateVisibility(pointclouds, camera, areaSize);
  22365. for (var _pointcloud5 of pointclouds) {
  22366. //pointcloud.updateMaterial(pointcloud.material, pointcloud.visibleNodes, camera, renderer);//转移到渲染时
  22367. _pointcloud5.updateVisibleBounds();
  22368. }
  22369. Potree.lru.freeMemory(); //即Potree.lru 能看到所有在加载的node
  22370. viewer.addTimeMark('updateClouds', 'end');
  22371. return result;
  22372. };
  22373. Potree.updateVisibilityStructures = function (pointclouds, camera, areaSize) {
  22374. var frustums = {};
  22375. var camObjPositions = {};
  22376. var camObjDirs = {}; //add
  22377. var priorityQueue = new BinaryHeap(function (x) {
  22378. return -x.weight; /* 1 / x.weight; */
  22379. }); //二叉堆。 改,之前的weight不支持负数
  22380. viewer.addTimeMark('visiStructure', 'start');
  22381. //camera.updateMatrixWorld();
  22382. var viewI = camera.matrixWorldInverse;
  22383. var proj = camera.projectionMatrix;
  22384. var view = camera.matrixWorld;
  22385. var projViewI = new Matrix4().multiply(proj).multiply(viewI);
  22386. /* let list = pointclouds // stopWhenAllUsed = !viewer.lastFrameChanged
  22387. let min = 5, max = Math.max(20 , Math.round(list.length / 10 ))
  22388. let result = Common.batchHandling.getSlice('pcGetFrustum', list, { min,max, durBound1: 3, durBound2: 10} ) //iphonex稳定后大概在7-10。
  22389. */
  22390. for (var i = 0; i < pointclouds.length; i++) {
  22391. var pointcloud = pointclouds[i];
  22392. if (!pointcloud.initialized()) {
  22393. continue;
  22394. }
  22395. /* let info = history.get(pointcloud)
  22396. if() */
  22397. pointcloud.numVisibleNodes = 0;
  22398. pointcloud.numVisiblePoints = 0;
  22399. pointcloud.deepestVisibleLevel = 0;
  22400. pointcloud.visibleNodes = [];
  22401. pointcloud.visibleGeometry = [];
  22402. // 因漫游模式而隐藏的话 依旧需要加入visibleNodes,因为pick需要
  22403. /* if (pointcloud.visible && pointcloud.root !== null) {
  22404. priorityQueue.push({pointcloud: i, node: pointcloud.root, weight: Number.MAX_VALUE});
  22405. } */
  22406. if (pointcloud.visible || !pointcloud.hasDepthTex && pointcloud.unvisibleReasons && pointcloud.unvisibleReasons.length == 1 && pointcloud.unvisibleReasons[0].reason == 'displayMode' && pointcloud.root !== null) {
  22407. //改 visible ->
  22408. priorityQueue.push({
  22409. pointcloud: i,
  22410. node: pointcloud.root,
  22411. weight: Number.MAX_VALUE
  22412. });
  22413. } else {
  22414. continue;
  22415. }
  22416. // frustum in object space
  22417. var frustum = new Frustum();
  22418. var world = pointcloud.matrixWorld;
  22419. // use close near plane for frustum intersection
  22420. /* let frustumCam = camera.clone();
  22421. frustumCam.zoom = camera.zoom //add
  22422. frustumCam.near = Math.min(camera.near, 0.1);
  22423. frustumCam.updateProjectionMatrix(); */ //----没用到frustumCam,删了
  22424. var fm = new Matrix4().multiply(projViewI).multiply(world);
  22425. frustum.setFromProjectionMatrix(fm);
  22426. frustums[i] = frustum; //frustums.push(frustum);
  22427. // camera position in object space
  22428. var worldI = pointcloud.matrixWorldInverse;
  22429. var camMatrixObject = new Matrix4().multiply(worldI).multiply(view); //假设点云无变换的话,相机相对于点云的变换矩阵
  22430. var camObjPos = new Vector3().setFromMatrixPosition(camMatrixObject);
  22431. camObjPositions[i] = camObjPos; //camObjPositions.push(camObjPos);
  22432. var quaternion = new Quaternion().setFromRotationMatrix(camMatrixObject);
  22433. var camDir = new Vector3(0, 0, -1).applyQuaternion(quaternion);
  22434. camObjDirs[i] = camDir;
  22435. // hide all previously visible nodes
  22436. // if(pointcloud.root instanceof PointCloudOctreeNode){
  22437. // pointcloud.hideDescendants(pointcloud.root.sceneNode);
  22438. // }
  22439. if (pointcloud.root.isTreeNode()) {
  22440. pointcloud.hideDescendants(pointcloud.root.sceneNode);
  22441. }
  22442. for (var j = 0; j < pointcloud.boundingBoxNodes.length; j++) {
  22443. pointcloud.boundingBoxNodes[j].visible = false;
  22444. }
  22445. }
  22446. viewer.addTimeMark('visiStructure', 'end');
  22447. return {
  22448. 'frustums': frustums,
  22449. 'camObjPositions': camObjPositions,
  22450. 'priorityQueue': priorityQueue,
  22451. camObjDirs
  22452. };
  22453. };
  22454. Potree.updateVisibility = function (pointclouds, camera, areaSize) {
  22455. var numVisibleNodes = 0;
  22456. var numVisiblePoints = 0;
  22457. var numVisiblePointsInPointclouds = new Map(pointclouds.map(pc => [pc, 0]));
  22458. var visibleNodes = [];
  22459. var visibleGeometry = [];
  22460. var unloadedGeometry = [];
  22461. var lowestSpacing = Infinity;
  22462. // calculate object space frustum and cam pos and setup priority queue
  22463. var s = Potree.updateVisibilityStructures(pointclouds, camera, areaSize); //得到相机可见范围
  22464. var frustums = s.frustums;
  22465. var camObjPositions = s.camObjPositions;
  22466. var priorityQueue = s.priorityQueue;
  22467. var camObjDirs = s.camObjDirs;
  22468. var loadedToGPUThisFrame = 0;
  22469. var domWidth = areaSize.x; //renderer.domElement.clientWidth;
  22470. var domHeight = areaSize.y; //renderer.domElement.clientHeight;
  22471. var fov = camera.fov * Math.PI / 180;
  22472. var slope = Math.tan(fov / 2);
  22473. var projFactor0 = 0.5 * domHeight / slope;
  22474. // check if pointcloud has been transformed
  22475. // some code will only be executed if changes have been detected
  22476. if (!Potree._pointcloudTransformVersion) {
  22477. Potree._pointcloudTransformVersion = new Map();
  22478. }
  22479. var pointcloudTransformVersion = Potree._pointcloudTransformVersion;
  22480. for (var pointcloud of pointclouds) {
  22481. if (pointcloud.hasDepthTex ? !pointcloud.visible : !Potree.Utils.getObjVisiByReason(pointcloud, 'datasetSelection')) {
  22482. //改 visible ->
  22483. continue;
  22484. }
  22485. //if(!pointcloud.visible) continue
  22486. pointcloud.updateMatrixWorld();
  22487. if (!pointcloudTransformVersion.has(pointcloud)) {
  22488. pointcloudTransformVersion.set(pointcloud, {
  22489. number: 0,
  22490. transform: pointcloud.matrixWorld.clone()
  22491. });
  22492. } else {
  22493. var version = pointcloudTransformVersion.get(pointcloud);
  22494. if (!version.transform.equals(pointcloud.matrixWorld)) {
  22495. version.number++;
  22496. version.transform.copy(pointcloud.matrixWorld);
  22497. pointcloud.dispatchEvent({
  22498. type: "transformation_changed",
  22499. target: pointcloud
  22500. });
  22501. }
  22502. }
  22503. }
  22504. var _loop3 = function _loop3() {
  22505. var element = priorityQueue.pop(); //取出权重最大的一个
  22506. var node = element.node;
  22507. var parent = element.parent;
  22508. var pointcloud = pointclouds[element.pointcloud];
  22509. // { // restrict to certain nodes for debugging
  22510. // let allowedNodes = ["r", "r0", "r4"];
  22511. // if(!allowedNodes.includes(node.name)){
  22512. // continue;
  22513. // }
  22514. // }
  22515. var box = node.getBoundingBox();
  22516. var frustum = frustums[element.pointcloud];
  22517. var camObjPos = camObjPositions[element.pointcloud];
  22518. if (!frustum) return 0; // continue
  22519. //add
  22520. var camObjDir = camObjDirs[element.pointcloud];
  22521. var insideFrustum = frustum.intersectsBox(box);
  22522. var maxLevel = pointcloud.maxLevel == void 0 ? Infinity : pointcloud.maxLevel;
  22523. var minLevel = pointcloud.minLevel == void 0 ? 0 : pointcloud.minLevel; //add
  22524. var level = node.getLevel();
  22525. var visible = insideFrustum;
  22526. visible = visible && !(numVisiblePoints + node.getNumPoints() > Potree.pointBudget);
  22527. visible = visible && !(numVisiblePointsInPointclouds.get(pointcloud) + node.getNumPoints() > pointcloud.pointBudget); // pointcloud.pointBudget一直是Infinity
  22528. visible = visible && level <= maxLevel; //< 改为 <=
  22529. //visible = visible || node.getLevel() <= 2;
  22530. var pcWorldInverse = pointcloud.matrixWorld.clone().invert();
  22531. /* let m = pcWorldInverse.elements
  22532. let pcWorldInvM3 = new THREE.Matrix3().set(m[0],m[4],m[12],m[1],m[5],m[13],m[3],m[7],m[15]) //去掉z的
  22533. */
  22534. //pointcloud.pcMatrix3 = new THREE.Matrix3().set(m[0],m[4],m[12],m[1],m[5],m[13],m[3],m[7],m[15]) //去掉z的
  22535. var intersectBox = clipBox => {
  22536. var toPCObject = pcWorldInverse.clone().multiply(clipBox.box.matrixWorld); //box乘上点云逆矩阵
  22537. return Potree.Utils.isIntersectBox(box, toPCObject);
  22538. };
  22539. //改 总共两种box : 可见和不可见(都是并集)
  22540. var clipBoxes_in = pointcloud.material.clipBoxes_in;
  22541. var clipBoxes_out = pointcloud.material.clipBoxes_out;
  22542. var bigClipInBox = pointcloud.material.bigClipInBox;
  22543. if (visible && bigClipInBox) {
  22544. //不在剪裁下载的框内
  22545. if (!intersectBox(bigClipInBox)) {
  22546. visible = false;
  22547. }
  22548. }
  22549. if (visible && clipBoxes_in.length > 0) {
  22550. //当有可见box时,需要在任一可见box内才可见
  22551. var visi = false;
  22552. for (var _i = 0, length = clipBoxes_in.length; _i < length; _i++) {
  22553. if (intersectBox(clipBoxes_in[_i])) {
  22554. visi = true;
  22555. break;
  22556. }
  22557. }
  22558. if (!visi) {
  22559. visible = false;
  22560. }
  22561. }
  22562. //outside不做处理。因为node必须完全在clipBox内才能完全隐藏,而这里的intersect只能识别出部分在clipBox内。因而只能说明不在任意一个box内绝对可见,没有意义,这里需要找出不可见的。
  22563. if (visible) {
  22564. var prism = pointcloud.material.activeAttributeName == 'prismHeight' && pointcloud.material.prisms && pointcloud.material.prisms.find(e => e.computing);
  22565. if (prism) {
  22566. var bound = box.clone().applyMatrix4(pointcloud.matrixWorld);
  22567. if (bound.intersectsBox(prism.prismBound)) {
  22568. /* //node box是否包含points中的一个点
  22569. let box2 = new THREE.Box2().copy(box)
  22570. let points2d = prisms.points.map(e=>new THREE.Vector2().copy(e).applyMatrix3(pcWorldInvM3))
  22571. let intersect = points2d.some(e=>{
  22572. return box2.containsPoint(e)
  22573. })
  22574. if(!intersect){
  22575. //或者多边形中是否包含node box中的一个点
  22576. intersect = [
  22577. new THREE.Vector2(box.min.x, box.min.y),
  22578. new THREE.Vector2(box.max.x, box.max.y),
  22579. new THREE.Vector2(box.min.x, box.max.y),
  22580. new THREE.Vector2(box.max.x, box.min.y),
  22581. ].some(e=>{
  22582. if(math.isPointInArea(points2d, null, e) ){
  22583. return true
  22584. }
  22585. })
  22586. //z是不是在外层已经判断好了?
  22587. if(!intersect){
  22588. visible = false
  22589. }
  22590. } */
  22591. //会有两个互不包含点但是交叉了的情况,所以就不仔细判断了(如横竖两个矩形构成十字架)
  22592. } else visible = false;
  22593. }
  22594. }
  22595. if (node.spacing) {
  22596. lowestSpacing = Math.min(lowestSpacing, node.spacing);
  22597. } else if (node.geometryNode && node.geometryNode.spacing) {
  22598. lowestSpacing = Math.min(lowestSpacing, node.geometryNode.spacing);
  22599. }
  22600. if (numVisiblePoints + node.getNumPoints() > Potree.pointBudget) {
  22601. viewer.dispatchEvent({
  22602. type: 'overPointBudget',
  22603. restQueueSize: priorityQueue.size(),
  22604. numVisiblePoints
  22605. });
  22606. return 1; // break
  22607. }
  22608. if (!visible) {
  22609. return 0; // continue
  22610. }
  22611. // TODO: not used, same as the declaration?
  22612. // numVisibleNodes++;
  22613. numVisiblePoints += node.getNumPoints();
  22614. var numVisiblePointsInPointcloud = numVisiblePointsInPointclouds.get(pointcloud);
  22615. numVisiblePointsInPointclouds.set(pointcloud, numVisiblePointsInPointcloud + node.getNumPoints());
  22616. pointcloud.numVisibleNodes++;
  22617. pointcloud.numVisiblePoints += node.getNumPoints();
  22618. if (node.isGeometryNode() && (!parent || parent.isTreeNode())) {
  22619. if (node.isLoaded() && loadedToGPUThisFrame < 2) {
  22620. node = pointcloud.toTreeNode(node, parent);
  22621. loadedToGPUThisFrame++;
  22622. } else {
  22623. //console.log('unloadedGeometry',node)
  22624. unloadedGeometry.push({
  22625. pointcloud,
  22626. node
  22627. }); //加载点云。虽然还没加载,但也计入了visibleNodes,只是无children,numPoints=0
  22628. visibleGeometry.push(node);
  22629. }
  22630. }
  22631. if (node.isTreeNode()) {
  22632. Potree.lru.touch(node.geometryNode); //在缓存中计入点云
  22633. node.sceneNode.visible = true;
  22634. node.sceneNode.material = pointcloud.material;
  22635. var show = level >= minLevel && (!Potree.hideParentNode || node.children.some(e => !e || !e.isTreeNode())); //满子集且都加载好的不显示
  22636. show && visibleNodes.push(node);
  22637. show && pointcloud.visibleNodes.push(node);
  22638. //if(Potree.settings.sortNodesDis){//add
  22639. if (pointcloud.material.opacity < 1 && Potree.settings.notAdditiveBlending) {
  22640. var nodePos = node.getBoundingSphere().center;
  22641. var toCam = new Vector3().subVectors(nodePos, camObjPos);
  22642. toCam.projectOnVector(camObjDir);
  22643. node.disSqToCamZ_ = toCam.lengthSq();
  22644. }
  22645. if (node._transformVersion === undefined) {
  22646. node._transformVersion = -1;
  22647. }
  22648. var transformVersion = pointcloudTransformVersion.get(pointcloud);
  22649. if (node._transformVersion !== transformVersion.number) {
  22650. node.sceneNode.updateMatrix();
  22651. //node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);
  22652. node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);
  22653. node._transformVersion = transformVersion.number;
  22654. }
  22655. if (pointcloud.showBoundingBox && !node.boundingBoxNode && node.getBoundingBox) {
  22656. var colorHue = level / (maxLevel + 1);
  22657. var _s = 0.1 + level / (maxLevel + 1);
  22658. var color = new Color().setHSL(colorHue, _s, _s);
  22659. var boxHelper = new Box3Helper$1(node.getBoundingBox(), color);
  22660. boxHelper.matrixAutoUpdate = false;
  22661. pointcloud.boundingBoxNodes.push(boxHelper);
  22662. node.boundingBoxNode = boxHelper;
  22663. node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
  22664. } else if (pointcloud.showBoundingBox) {
  22665. node.boundingBoxNode.visible = true;
  22666. node.boundingBoxNode.matrix.copy(pointcloud.matrixWorld);
  22667. } else if (!pointcloud.showBoundingBox && node.boundingBoxNode) {
  22668. node.boundingBoxNode.visible = false;
  22669. }
  22670. // if(node.boundingBoxNode !== undefined && exports.debug.allowedNodes !== undefined){
  22671. // if(!exports.debug.allowedNodes.includes(node.name)){
  22672. // node.boundingBoxNode.visible = false;
  22673. // }
  22674. // }
  22675. }
  22676. // add child nodes to priorityQueue 由近及远、由大及小逐渐加载
  22677. var children = node.getChildren();
  22678. for (var _i2 = 0; _i2 < children.length; _i2++) {
  22679. var child = children[_i2];
  22680. var weight = 0;
  22681. if (camera.isPerspectiveCamera) {
  22682. var sphere = child.getBoundingSphere();
  22683. var center = sphere.center;
  22684. var dd = sphere.center.distanceToSquared(camObjPos);
  22685. var addPow = 0.2; //viewer.mainViewport.view.isFlying() ? 0 : 0.5 //0-0.5,正常原本是0. 数字越大近处加载越快。但会造成远处加载慢甚至因pointBudge限制不加载。 isFlying:漫游时需要尽量加载一下远处的点云
  22686. //addPow *= window.devicePixelRatio //devicePixelRatio高的手机需要优先加载最近的高级点云,减少远处的中高级点云。
  22687. var distance = Math.pow(dd, 0.5 + addPow); //Math.sqrt(dd); //提高距离权重,为了提高近处加载速度。 某些场景近处加载慢优化明显,如SS-t-cqCAL6rJ5i
  22688. //let attenuateDis = 10;//add
  22689. var radius = sphere.radius;
  22690. var projFactor = projFactor0 / distance;
  22691. var screenPixelRadius = radius * projFactor;
  22692. /* if(distance > attenuateDis){
  22693. screenPixelRadius -= (distance - attenuateDis) * Math.sqrt(radius) * projFactor0 * 0.002
  22694. } */
  22695. //screenPixelRadius 和 domHeight 成正比,所以手机横屏后screenPixelRadius会变小。这是正常的,因为vhov不变,相同物体高度在横屏后高度变小,所需要的密度不需要那么高了。但hfov横屏后扩大,所以可见的node范围变大,又增加了一些可见node;只是总体的可见node还是减少了。
  22696. //使用hfov和domWidth计算结果相同。
  22697. if (screenPixelRadius < pointcloud.minimumNodePixelSize / Math.pow(dd, addPow)) {
  22698. //理论上因手机像素小,更不容易堆叠铺满,minimumNodePixelSize应该除以window.deviceRatio 但会造成加载过多,而内存小
  22699. continue;
  22700. }
  22701. weight = screenPixelRadius;
  22702. if (!sphere.containsPoint(camObjPos)) {
  22703. //add 优先加载屏幕中央的点云(手机端缩小离远效果明显,不会那么稀疏)
  22704. var dir = new Vector3().subVectors(center, camObjPos).normalize();
  22705. var cos = 1 + dir.dot(camObjDir); //0-2
  22706. weight *= cos / 2; //Math.pow(cos,0.5) //幂越高,旁边的容易加载不到,出现缺块 如SS-t-7DUfWAUZ3V
  22707. }
  22708. if (distance - radius < 0) {
  22709. weight = Number.MAX_VALUE;
  22710. }
  22711. //如果能得到每个方向上的密度,也就是node数量,密度大的远处少加载,因为被遮挡了显示也没有意义,就好了。
  22712. } else {
  22713. // TODO ortho visibility
  22714. //let bb = child.getBoundingBox();
  22715. var _sphere = child.getBoundingSphere();
  22716. //let diagonal = bb.max.clone().sub(bb.min).length();
  22717. var reduce = 0; //0-0.5,正常原本是0.
  22718. if (_sphere.radius * /* Math.pow( */camera.zoom /* ,1-reduce) */ < pointcloud.minimumNodePixelSize) {
  22719. continue;
  22720. }
  22721. var _distance = _sphere.center.distanceToSquared(camObjPos); //先加载中间然后四周
  22722. weight = _sphere.radius / _distance;
  22723. /* let vec = new THREE.Vector3().subVectors(sphere.center, camObjPos)
  22724. let disOnCamDir = vec.dot(camObjDir)
  22725. let vecOnCamDir = camObjDir.clone().multiplyScalar(disOnCamDir)
  22726. let vecSide = new THREE.Vector3().subVectors(vec, vecOnCamDir) //在屏幕上从中心到该node的向量
  22727. let disSide = vecSide.length()
  22728. //weight = sphere.radius / disSide * camera.zoom - disOnCamDir * 2; //如果用除的,ortho的camera离远了的话dis的影响就小了
  22729. weight = sphere.radius / ( disSide * 0.1 + disOnCamDir * 14 )
  22730. */
  22731. //weight = diagonal;
  22732. }
  22733. priorityQueue.push({
  22734. pointcloud: element.pointcloud,
  22735. node: child,
  22736. parent: node,
  22737. weight: weight
  22738. }); //貌似好像二叉堆中子节点和父节点没什么关系,就只是为了方便排序层层遍历
  22739. }
  22740. //手机上像素点更小,所以远处感觉会更稀疏
  22741. },
  22742. _ret;
  22743. while (priorityQueue.size() > 0) {
  22744. _ret = _loop3();
  22745. if (_ret === 0) continue;
  22746. if (_ret === 1) break;
  22747. } // end priority queue loop
  22748. {
  22749. // update DEM 这是什么
  22750. var maxDEMLevel = 4;
  22751. var candidates = pointclouds.filter(p => p.generateDEM && p.dem instanceof Potree.DEM);
  22752. for (var _pointcloud6 of candidates) {
  22753. var updatingNodes = _pointcloud6.visibleNodes.filter(n => n.getLevel() <= maxDEMLevel);
  22754. _pointcloud6.dem.update(updatingNodes);
  22755. }
  22756. }
  22757. unloadedGeometry = unloadedGeometry.filter(e => !e.loadFailed); //过滤加载失败的,否则有失败的就无法发送加载完成
  22758. if (unloadedGeometry.length) {
  22759. //加载点云
  22760. var idleCount = Common$1.getBestCountFPS('unloadedGeometry', false, 1, 3); //即使静止,因为加载不仅影响这一帧,所以低fps还是加载少一些
  22761. var maxNodesLoading = Common$1.getBestCount('unloadedGeometry', viewer.lastFrameChanged ? 1 : idleCount, idleCount + 4, 3, 14 /* , true */); //dur在iphoneX中静止有7,pc是2 //!lastFrameChanged静止时加速下载
  22762. //THREE.Math.clamp(Math.round(9 - dur), 1, 6 )
  22763. //console.log('unloadedGeometry', unloadedGeometry.length)
  22764. //主要在手机端有效果。不改之前在展示的点云较多时前进会卡。
  22765. for (var i = 0; i < Math.min(maxNodesLoading, unloadedGeometry.length); i++) {
  22766. unloadedGeometry[i].node.load(unloadedGeometry[i].pointcloud.pcoGeometry);
  22767. }
  22768. if (!Potree.pointsLoading) {
  22769. Potree.pointsLoading = true;
  22770. //console.log('startLoad')
  22771. viewer.dispatchEvent('startLoadPoints');
  22772. }
  22773. } else {
  22774. if (Potree.pointsLoading) {
  22775. Potree.pointsLoading = false;
  22776. //console.log('load done!')
  22777. setTimeout(() => {
  22778. Potree.pointsLoading || viewer.dispatchEvent('pointsLoaded');
  22779. }, document.hidden ? 3000 : 50); //hidden时可能好几秒才更新一次,所以这个并不准
  22780. }
  22781. }
  22782. Potree.unloadedGeometry = unloadedGeometry;
  22783. //add:
  22784. Potree.numVisiblePoints = numVisiblePoints;
  22785. Potree.visibleNodes = visibleNodes;
  22786. //if(Potree.settings.sortNodesDis){
  22787. //let s = performance.now()
  22788. for (var _pointcloud7 of pointclouds) {
  22789. if (_pointcloud7.material.opacity < 1 && Potree.settings.notAdditiveBlending) {
  22790. //排序。如果能所有点云一起排序更好,这样遮挡更正确
  22791. _pointcloud7.visibleNodes.sort((a, b) => {
  22792. return b.disSqToCamZ_ - a.disSqToCamZ_;
  22793. });
  22794. }
  22795. }
  22796. //console.log(performance.now() - s)
  22797. //}
  22798. return {
  22799. visibleNodes: visibleNodes,
  22800. numVisiblePoints: numVisiblePoints,
  22801. lowestSpacing: lowestSpacing
  22802. };
  22803. };
  22804. Potree.numVisiblePoints = 0;
  22805. /*
  22806. note:
  22807. 缓存中的点数 Potree.lru.numPoints 一般会 大于 每个点云显示点总数的numVisiblePoints
  22808. 当超出缓冲区最大点云数时,加载的点云节点会被dispose彻底消除;否则,隐藏的节点就会等待再次被使用显示
  22809. 由于加载按照由近及远、由大及小的顺序,要降低卡顿,就只需要降低Potree.pointBudget即可。但目前只设置了三个层次;另外提供maxLevel细节调节,能显示更均匀. 最好多一个调节pointBudge的滑动条
  22810. Potree.lru.numPoints
  22811. Potree.numVisiblePoints
  22812. viewer.scene.pointclouds[0].visibleNodes.length
  22813. */
  22814. {
  22815. //HQSplatRenderer
  22816. var oldInit = HQSplatRenderer.prototype.init;
  22817. HQSplatRenderer.prototype.init = function () {
  22818. oldInit();
  22819. viewer.addEventListener('resize', this.resize.bind(this));
  22820. };
  22821. HQSplatRenderer.prototype.resize = function (e) {
  22822. this.rtDepth.setSize(e.canvasWidth, e.canvasHeight);
  22823. this.rtAttribute.setSize(e.canvasWidth, e.canvasHeight);
  22824. };
  22825. HQSplatRenderer.prototype.clear = function () {
  22826. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  22827. this.init();
  22828. var {
  22829. renderer,
  22830. background
  22831. } = this.viewer;
  22832. if (background === "skybox") {
  22833. renderer.setClearColor(0x000000, 0);
  22834. } else if (background === 'gradient') {
  22835. renderer.setClearColor(0x000000, 0);
  22836. } else if (background === 'black') {
  22837. renderer.setClearColor(0x000000, 1);
  22838. } else if (background === 'white') {
  22839. renderer.setClearColor(0xFFFFFF, 1);
  22840. } else {
  22841. renderer.setClearColor(0x000000, 0);
  22842. }
  22843. params.target || renderer.clear();
  22844. this.clearTargets(params);
  22845. };
  22846. HQSplatRenderer.prototype.render = function () {
  22847. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  22848. this.init();
  22849. var viewer = this.viewer;
  22850. var camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  22851. var {
  22852. width,
  22853. height
  22854. } = params.width ? params : this.viewer.renderer.getSize(new Vector2());
  22855. viewer.renderer.setRenderTarget(params.target || null);
  22856. viewer.dispatchEvent({
  22857. type: "render.pass.begin",
  22858. viewer: viewer
  22859. });
  22860. //params.target || this.resize(width, height);
  22861. var visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
  22862. var originalMaterials = new Map();
  22863. for (var pointcloud of visiblePointClouds) {
  22864. originalMaterials.set(pointcloud, pointcloud.material);
  22865. if (!this.attributeMaterials.has(pointcloud)) {
  22866. var attributeMaterial = new ExtendPointCloudMaterial();
  22867. this.attributeMaterials.set(pointcloud, attributeMaterial);
  22868. }
  22869. if (!this.depthMaterials.has(pointcloud)) {
  22870. var depthMaterial = new ExtendPointCloudMaterial();
  22871. depthMaterial.setDefine("depth_pass", "#define hq_depth_pass");
  22872. depthMaterial.setDefine("use_edl", "#define use_edl");
  22873. this.depthMaterials.set(pointcloud, depthMaterial);
  22874. }
  22875. }
  22876. {
  22877. // DEPTH PASS
  22878. for (var _pointcloud8 of visiblePointClouds) {
  22879. var octreeSize = _pointcloud8.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  22880. var material = originalMaterials.get(_pointcloud8);
  22881. var _depthMaterial = this.depthMaterials.get(_pointcloud8);
  22882. _depthMaterial.size = material.size;
  22883. _depthMaterial.minSize = material.minSize;
  22884. _depthMaterial.maxSize = material.maxSize;
  22885. _depthMaterial.pointSizeType = material.pointSizeType;
  22886. _depthMaterial.visibleNodesTexture = material.visibleNodesTexture;
  22887. _depthMaterial.weighted = false;
  22888. _depthMaterial.screenWidth = width;
  22889. _depthMaterial.shape = PointShape.CIRCLE;
  22890. _depthMaterial.screenHeight = height;
  22891. _depthMaterial.uniforms.visibleNodes.value = material.visibleNodesTexture;
  22892. _depthMaterial.uniforms.octreeSize.value = octreeSize;
  22893. _depthMaterial.spacing = _pointcloud8.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  22894. _depthMaterial.classification = material.classification;
  22895. _depthMaterial.uniforms.classificationLUT.value.image.data = material.uniforms.classificationLUT.value.image.data;
  22896. _depthMaterial.classificationTexture.needsUpdate = true;
  22897. _depthMaterial.uniforms.uFilterReturnNumberRange.value = material.uniforms.uFilterReturnNumberRange.value;
  22898. _depthMaterial.uniforms.uFilterNumberOfReturnsRange.value = material.uniforms.uFilterNumberOfReturnsRange.value;
  22899. _depthMaterial.uniforms.uFilterGPSTimeClipRange.value = material.uniforms.uFilterGPSTimeClipRange.value;
  22900. _depthMaterial.uniforms.uFilterPointSourceIDClipRange.value = material.uniforms.uFilterPointSourceIDClipRange.value;
  22901. _depthMaterial.clipTask = material.clipTask;
  22902. _depthMaterial.clipMethod = material.clipMethod;
  22903. _depthMaterial.setClipBoxes(material.clipBoxes);
  22904. _depthMaterial.setClipPolygons(material.clipPolygons);
  22905. _pointcloud8.material = _depthMaterial;
  22906. }
  22907. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.rtDepth, {
  22908. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume)
  22909. });
  22910. }
  22911. {
  22912. // ATTRIBUTE PASS
  22913. for (var _pointcloud9 of visiblePointClouds) {
  22914. var _octreeSize = _pointcloud9.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  22915. var _material = originalMaterials.get(_pointcloud9);
  22916. var _attributeMaterial = this.attributeMaterials.get(_pointcloud9);
  22917. _attributeMaterial.size = _material.size;
  22918. _attributeMaterial.minSize = _material.minSize;
  22919. _attributeMaterial.maxSize = _material.maxSize;
  22920. _attributeMaterial.pointSizeType = _material.pointSizeType;
  22921. _attributeMaterial.activeAttributeName = _material.activeAttributeName;
  22922. _attributeMaterial.visibleNodesTexture = _material.visibleNodesTexture;
  22923. _attributeMaterial.weighted = true;
  22924. _attributeMaterial.screenWidth = width;
  22925. _attributeMaterial.screenHeight = height;
  22926. _attributeMaterial.shape = PointShape.CIRCLE;
  22927. _attributeMaterial.uniforms.visibleNodes.value = _material.visibleNodesTexture;
  22928. _attributeMaterial.uniforms.octreeSize.value = _octreeSize;
  22929. _attributeMaterial.spacing = _pointcloud9.pcoGeometry.spacing; // * Math.max(...pointcloud.scale.toArray());
  22930. _attributeMaterial.classification = _material.classification;
  22931. _attributeMaterial.uniforms.classificationLUT.value.image.data = _material.uniforms.classificationLUT.value.image.data;
  22932. _attributeMaterial.classificationTexture.needsUpdate = true;
  22933. _attributeMaterial.uniforms.uFilterReturnNumberRange.value = _material.uniforms.uFilterReturnNumberRange.value;
  22934. _attributeMaterial.uniforms.uFilterNumberOfReturnsRange.value = _material.uniforms.uFilterNumberOfReturnsRange.value;
  22935. _attributeMaterial.uniforms.uFilterGPSTimeClipRange.value = _material.uniforms.uFilterGPSTimeClipRange.value;
  22936. _attributeMaterial.uniforms.uFilterPointSourceIDClipRange.value = _material.uniforms.uFilterPointSourceIDClipRange.value;
  22937. _attributeMaterial.elevationGradientRepeat = _material.elevationGradientRepeat;
  22938. _attributeMaterial.elevationRange = _material.elevationRange;
  22939. _attributeMaterial.gradient = _material.gradient;
  22940. _attributeMaterial.matcap = _material.matcap;
  22941. _attributeMaterial.intensityRange = _material.intensityRange;
  22942. _attributeMaterial.intensityGamma = _material.intensityGamma;
  22943. _attributeMaterial.intensityContrast = _material.intensityContrast;
  22944. _attributeMaterial.intensityBrightness = _material.intensityBrightness;
  22945. _attributeMaterial.rgbGamma = _material.rgbGamma;
  22946. _attributeMaterial.rgbContrast = _material.rgbContrast;
  22947. _attributeMaterial.rgbBrightness = _material.rgbBrightness;
  22948. _attributeMaterial.weightRGB = _material.weightRGB;
  22949. _attributeMaterial.weightIntensity = _material.weightIntensity;
  22950. _attributeMaterial.weightElevation = _material.weightElevation;
  22951. _attributeMaterial.weightRGB = _material.weightRGB;
  22952. _attributeMaterial.weightClassification = _material.weightClassification;
  22953. _attributeMaterial.weightReturnNumber = _material.weightReturnNumber;
  22954. _attributeMaterial.weightSourceID = _material.weightSourceID;
  22955. _attributeMaterial.color = _material.color;
  22956. _attributeMaterial.clipTask = _material.clipTask;
  22957. _attributeMaterial.clipMethod = _material.clipMethod;
  22958. _attributeMaterial.setClipBoxes(_material.clipBoxes);
  22959. _attributeMaterial.setClipPolygons(_material.clipPolygons);
  22960. _pointcloud9.material = _attributeMaterial;
  22961. }
  22962. var gl = this.gl;
  22963. //viewer.renderer.setRenderTarget(null);
  22964. viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtAttribute, {
  22965. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume),
  22966. //material: this.attributeMaterial,
  22967. blendFunc: [gl.SRC_ALPHA, gl.ONE],
  22968. //depthTest: false,
  22969. depthWrite: false
  22970. });
  22971. }
  22972. for (var [_pointcloud10, _material2] of originalMaterials) {
  22973. _pointcloud10.material = _material2;
  22974. }
  22975. if (viewer.background === "skybox") {
  22976. viewer.renderer.setClearColor(0x000000, 0);
  22977. viewer.renderer.clear();
  22978. viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
  22979. viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
  22980. viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
  22981. viewer.skybox.parent.rotation.x = 0;
  22982. viewer.skybox.parent.updateMatrixWorld();
  22983. viewer.skybox.camera.updateProjectionMatrix();
  22984. viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
  22985. } else if (viewer.background === 'gradient') {
  22986. viewer.renderer.setClearColor(0x000000, 0);
  22987. viewer.renderer.clear();
  22988. viewer.renderer.render(viewer.scene.sceneBG, viewer.scene.cameraBG);
  22989. } else if (viewer.background === 'black') {
  22990. viewer.renderer.setClearColor(0x000000, 1);
  22991. viewer.renderer.clear();
  22992. } else if (viewer.background === 'white') {
  22993. viewer.renderer.setClearColor(0xFFFFFF, 1);
  22994. viewer.renderer.clear();
  22995. } else {
  22996. viewer.renderer.setClearColor(0x000000, 0);
  22997. viewer.renderer.clear();
  22998. }
  22999. {
  23000. // NORMALIZATION PASS
  23001. var normalizationMaterial = this.useEDL ? this.normalizationEDLMaterial : this.normalizationMaterial;
  23002. if (this.useEDL) {
  23003. normalizationMaterial.uniforms.edlStrength.value = viewer.edlStrength;
  23004. normalizationMaterial.uniforms.radius.value = viewer.edlRadius;
  23005. normalizationMaterial.uniforms.screenWidth.value = width;
  23006. normalizationMaterial.uniforms.screenHeight.value = height;
  23007. normalizationMaterial.uniforms.uEDLMap.value = (params.rtEDL || this.rtDepth).texture;
  23008. }
  23009. normalizationMaterial.uniforms.uWeightMap.value = this.rtAttribute.texture;
  23010. normalizationMaterial.uniforms.uDepthMap.value = this.rtAttribute.depthTexture;
  23011. Utils.screenPass.render(viewer.renderer, normalizationMaterial);
  23012. }
  23013. viewer.renderer.render(viewer.scene.scene, camera);
  23014. viewer.dispatchEvent({
  23015. type: "render.pass.scene",
  23016. viewer: viewer
  23017. });
  23018. viewer.renderer.render(viewer.scene.sceneOverlay, camera); // add 透明贴图层
  23019. viewer.renderer.clearDepth();
  23020. viewer.transformationTool.update();
  23021. if (!params.target) {
  23022. //测量线
  23023. viewer.dispatchEvent({
  23024. type: "render.pass.perspective_overlay",
  23025. viewer: viewer,
  23026. camera
  23027. });
  23028. viewer.renderer.render(viewer.overlay, camera); //从 viewer.renderDefault搬过来,为了reticule不遮住测量线
  23029. }
  23030. viewer.renderer.render(viewer.controls.sceneControls, camera);
  23031. viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
  23032. viewer.renderer.render(viewer.transformationTool.scene, camera);
  23033. viewer.renderer.setViewport(width - viewer.navigationCube.width, height - viewer.navigationCube.width, viewer.navigationCube.width, viewer.navigationCube.width);
  23034. viewer.renderer.render(viewer.navigationCube, viewer.navigationCube.camera);
  23035. viewer.renderer.setViewport(0, 0, width, height);
  23036. viewer.dispatchEvent({
  23037. type: "render.pass.end",
  23038. viewer: viewer
  23039. });
  23040. viewer.renderer.setRenderTarget(null);
  23041. };
  23042. }
  23043. //PointCloudOctreeGeometry.js
  23044. PointCloudOctreeGeometryNode.prototype.loadHierachyThenPoints = function (pointcloud) {
  23045. var node = this;
  23046. // load hierarchy
  23047. var callback = function callback(node, hbuffer) {
  23048. var tStart = performance.now();
  23049. var view = new DataView(hbuffer);
  23050. var stack = [];
  23051. var children = view.getUint8(0);
  23052. var numPoints = view.getUint32(1, true);
  23053. node.numPoints = numPoints;
  23054. stack.push({
  23055. children: children,
  23056. numPoints: numPoints,
  23057. name: node.name
  23058. });
  23059. var decoded = [];
  23060. var offset = 5;
  23061. while (stack.length > 0) {
  23062. var snode = stack.shift();
  23063. var mask = 1;
  23064. for (var i = 0; i < 8; i++) {
  23065. if ((snode.children & mask) !== 0) {
  23066. var childName = snode.name + i;
  23067. var childChildren = view.getUint8(offset);
  23068. var childNumPoints = view.getUint32(offset + 1, true);
  23069. stack.push({
  23070. children: childChildren,
  23071. numPoints: childNumPoints,
  23072. name: childName
  23073. });
  23074. decoded.push({
  23075. children: childChildren,
  23076. numPoints: childNumPoints,
  23077. name: childName
  23078. });
  23079. offset += 5;
  23080. }
  23081. mask = mask * 2;
  23082. }
  23083. if (offset === hbuffer.byteLength) {
  23084. break;
  23085. }
  23086. }
  23087. // console.log(decoded);
  23088. var nodes = {};
  23089. nodes[node.name] = node;
  23090. var pco = node.pcoGeometry;
  23091. var maxLevel_ = 0;
  23092. for (var _i3 = 0; _i3 < decoded.length; _i3++) {
  23093. var name = decoded[_i3].name;
  23094. var decodedNumPoints = decoded[_i3].numPoints;
  23095. var index = parseInt(name.charAt(name.length - 1));
  23096. var parentName = name.substring(0, name.length - 1);
  23097. var parentNode = nodes[parentName];
  23098. var level = name.length - 1;
  23099. maxLevel_ = Math.max(maxLevel_, level); //add
  23100. var boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  23101. var currentNode = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  23102. currentNode.level = level;
  23103. currentNode.numPoints = decodedNumPoints;
  23104. currentNode.hasChildren = decoded[_i3].children > 0;
  23105. currentNode.spacing = pco.spacing / Math.pow(2, level);
  23106. parentNode.addChild(currentNode);
  23107. nodes[name] = currentNode;
  23108. }
  23109. pco.dispatchEvent({
  23110. type: 'updateNodeMaxLevel',
  23111. level: maxLevel_
  23112. }); //add
  23113. var duration = performance.now() - tStart;
  23114. if (duration > 5) {
  23115. /* let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
  23116. console.log(msg); */
  23117. }
  23118. node.loadPoints();
  23119. };
  23120. if (node.level % node.pcoGeometry.hierarchyStepSize === 0) {
  23121. // let hurl = node.pcoGeometry.octreeDir + "/../hierarchy/" + node.name + ".hrc";
  23122. var hurl = node.pcoGeometry.octreeDir + '/' + node.getHierarchyPath() + '/' + node.name + '.hrc';
  23123. hurl += '?m=' + node.pcoGeometry.timeStamp; //add
  23124. var xhr = XHRFactory.createXMLHttpRequest();
  23125. xhr.open('GET', hurl, true);
  23126. xhr.responseType = 'arraybuffer';
  23127. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  23128. xhr.onreadystatechange = () => {
  23129. if (xhr.readyState === 4) {
  23130. if (xhr.status === 200 || xhr.status === 0) {
  23131. var hbuffer = xhr.response;
  23132. callback(node, hbuffer);
  23133. } else {
  23134. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + hurl);
  23135. Potree.numNodesLoading--;
  23136. }
  23137. }
  23138. };
  23139. try {
  23140. xhr.send(null);
  23141. } catch (e) {
  23142. console.log('fehler beim laden der punktwolke: ' + e);
  23143. }
  23144. }
  23145. };
  23146. PointCloudOctreeGeometryNode.prototype.loadPoints = function () {
  23147. var name = this.name;
  23148. this.pcoGeometry.loader.load(this, () => {
  23149. //callback
  23150. viewer.dispatchEvent('pointcloud_changed');
  23151. //console.log('loadPoints success ', name)
  23152. });
  23153. };
  23154. //加载点云成功->准备渲染画面->更新点云可见性updateVisibility->请求加载新的点云
  23155. PointCloudOctreeGeometryNode.prototype.traverse = function (t, e) {
  23156. //add from navvis 25.js
  23157. void 0 === e && (e = !0);
  23158. for (var n, i = e ? [this] : []; void 0 !== (n = i.pop());) {
  23159. t(n);
  23160. for (var o = 0, r = n.children; o < r.length; o++) {
  23161. var a = r[o];
  23162. null !== a && i.push(a);
  23163. }
  23164. }
  23165. };
  23166. Object.assign(PointCloudOctreeGeometry.prototype, EventDispatcher.prototype);
  23167. LRU.prototype.freeMemory = function () {
  23168. if (this.elements <= 1) {
  23169. return;
  23170. }
  23171. var memoryRatio = browser.isMobile() ? 2 : 5;
  23172. //改成navvis的,使用pointBudget,否则四屏点云闪烁。 (似乎要比updateVisiblede的node时限制要宽些,作为缓存继续存着。否则会闪烁)
  23173. var max = MathUtils.clamp(viewer.viewports.length * memoryRatio * Potree.pointBudget, 0, Potree.settings.maxLRUPoints);
  23174. for (; this.numPoints > max;) {
  23175. var node = this.getLRUItem();
  23176. node && this.disposeDescendants(node);
  23177. }
  23178. };
  23179. VolumeTool.prototype.update = function () {};
  23180. VolumeTool.prototype.startInsertion = function () {
  23181. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  23182. var volume;
  23183. if (args.type) {
  23184. volume = new args.type();
  23185. } else {
  23186. volume = new Potree.BoxVolume(Object.assign(args, {
  23187. clip: true
  23188. }));
  23189. }
  23190. volume.highlight = true;
  23191. volume.name = args.name || 'Volume-' + args.clipTask;
  23192. volume.isNew = true;
  23193. viewer.transformObject(null); //先清空
  23194. //console.log('startInsertion',volume.uuid)
  23195. var oldVisiBoxes;
  23196. if (args.clipTask == Potree.ClipTask.SHOW_INSIDE) {
  23197. //如果是显示类型,需要将所有同类型的解除效果,否则看不到效果。 (或者可以在添加非第一个时去除highlight效果,会更自然,但看不清全貌)
  23198. oldVisiBoxes = viewer.scene.volumes.filter(v => v.clipTask == Potree.ClipTask.SHOW_INSIDE && !v.highlight);
  23199. oldVisiBoxes.forEach(box => box.highlight = true);
  23200. }
  23201. var updatePose = () => {
  23202. //保证在视野中的大小一致:
  23203. var camera = this.viewer.scene.getActiveCamera();
  23204. var w = math.getScaleForConstantSize({
  23205. width2d: 300,
  23206. camera,
  23207. position: volume.getWorldPosition(new Vector3()),
  23208. resolution: viewer.mainViewport.resolution //2
  23209. });
  23210. /* let wp = volume.getWorldPosition(new THREE.Vector3()).applyMatrix4(camera.matrixWorldInverse);
  23211. // let pp = new THREE.Vector4(wp.x, wp.y, wp.z).applyMatrix4(camera.projectionMatrix);
  23212. let w = Math.abs((wp.z / 3));*/
  23213. if (!isNaN(w)) volume.scale.set(w, w, w);
  23214. {
  23215. //使水平朝向与camera一致
  23216. var direction = viewer.mainViewport.view.direction.setZ(0);
  23217. volume.quaternion.copy(math.getQuaByAim(direction));
  23218. }
  23219. };
  23220. this.dispatchEvent({
  23221. type: 'start_inserting_volume',
  23222. volume: volume
  23223. });
  23224. updatePose();
  23225. this.viewer.scene.addVolume(volume);
  23226. this.scene.add(volume);
  23227. var drag = e => {
  23228. if (e.hoverViewport.name == 'mapViewport') return;
  23229. var I = Utils.getMousePointCloudIntersection(viewer.mainViewport, viewer.inputHandler.mouse, viewer.inputHandler.pointer, this.viewer.scene.getActiveCamera(), this.viewer, this.viewer.scene.pointclouds, {
  23230. pickClipped: args.clipTask == Potree.ClipTask.SHOW_OUTSIDE
  23231. } //无视clip状态
  23232. );
  23233. var worldPos = I && I.location;
  23234. if (!worldPos) {
  23235. return;
  23236. }
  23237. volume.position.copy(worldPos);
  23238. updatePose();
  23239. };
  23240. var cancel = () => {
  23241. end('remove');
  23242. };
  23243. var end = e => {
  23244. if (e.button == MOUSE.RIGHT && e.pressDistance <= Potree.config.clickMaxDragDis) {
  23245. //remove
  23246. e = 'remove';
  23247. }
  23248. //console.log('end',volume.uuid, e)
  23249. if (e != 'remove' && (!e.isAtDomElement || e.pressDistance > Potree.config.clickMaxDragDis)) return continueDrag();
  23250. volume.removeEventListener('drag', drag);
  23251. volume.removeEventListener('drop', end);
  23252. this.viewer.removeEventListener('cancel_insertions', cancel);
  23253. volume.isNew = false;
  23254. viewer.removeEventListener('camera_changed', updatePose);
  23255. if (e == 'remove') {
  23256. viewer.scene.removeVolume(volume); //删除没完成的
  23257. } else {
  23258. viewer.transformObject(volume);
  23259. volume.highlight = false;
  23260. }
  23261. volume.dispatchEvent({
  23262. type: 'createFinish',
  23263. success: e != 'remove'
  23264. });
  23265. oldVisiBoxes && oldVisiBoxes.forEach(box => box.highlight = false);
  23266. };
  23267. var continueDrag = () => {
  23268. //console.log('continueDrag',volume.uuid )
  23269. var timer = setTimeout(() => {
  23270. //等 drag=null之后 //右键拖拽结束后需要重新得到drag
  23271. if (volume.parent && volume.isNew) {
  23272. viewer.inputHandler.startDragging(volume, {
  23273. notPressMouse: true
  23274. }
  23275. /* {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport} */);
  23276. }
  23277. }, 1);
  23278. return timer;
  23279. };
  23280. volume.addEventListener('drag', drag);
  23281. volume.addEventListener('drop', end);
  23282. this.viewer.addEventListener('cancel_insertions', cancel);
  23283. viewer.addEventListener('camera_changed', updatePose);
  23284. this.viewer.inputHandler.startDragging(volume, {
  23285. notPressMouse: true
  23286. });
  23287. return volume;
  23288. };
  23289. LineGeometry.prototype.setPositions = function (array) {
  23290. //xzw改成类似LineSegments的多段线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  23291. var points = new Float32Array(array);
  23292. LineSegmentsGeometry.prototype.setPositions.call(this, points);
  23293. return this;
  23294. };
  23295. Object.assign(ExtendView.prototype, EventDispatcher.prototype);
  23296. Object.assign(ExtendScene.prototype, EventDispatcher.prototype);
  23297. var _this = undefined;
  23298. window.THREE = THREE$1;
  23299. var baseZ = 0; //所以数据集高度都要减去这个值。在laser场景里该值为初始数据集的高程
  23300. var transformPointcloud = (pointcloud, dataset) => {
  23301. var _dataset$quaternion;
  23302. var locationLonLat = dataset.location.slice(0, 3); // [lon,lat,高程海拔]
  23303. //当只有一个dataset时,无论如何transform 点云和漫游点都能对应上。
  23304. var location = viewer.transform.lonlatToLocal.forward(locationLonLat); //transform.inverse()
  23305. //初始化位置
  23306. viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud);
  23307. //dataset.orientation = 0
  23308. var Alignment = viewer.modules.Alignment;
  23309. Alignment.rotate(pointcloud, null, ((_dataset$quaternion = dataset.quaternion) === null || _dataset$quaternion === void 0 ? void 0 : _dataset$quaternion.length) == 4 ? dataset.quaternion : dataset.orientation);
  23310. Alignment.translate(pointcloud, new Vector3(location[0], location[1], dataset.location[2] - baseZ)); //要使初始数据集的z为0,所以要减去初始数据集的z
  23311. pointcloud.updateMatrixWorld();
  23312. Potree.Log("\u70B9\u4E91".concat(pointcloud.dataset_id, "(").concat(pointcloud.name, ")\u65CB\u8F6C\u503C: qua ").concat(dataset.quaternion || '', "\u3001orient ").concat(math.toPrecision(dataset.orientation, 3), ", \n \u4F4D\u7F6E").concat(math.toPrecision(pointcloud.translateUser.toArray(), 3), ", \u7ECF\u7EAC\u5EA6 ").concat(dataset.location, ", spacing ").concat(pointcloud.material.spacing), {
  23313. font: {
  23314. color: "#f49",
  23315. fontSize: 13
  23316. }
  23317. });
  23318. };
  23319. function start(dom, mapDom, number) {
  23320. //t-Zvd3w0m
  23321. /* {
  23322. let obj = JSON.parse(localStorage.getItem('setting'))
  23323. for(let i in obj){
  23324. console.log(i + ': ' + obj[i])
  23325. }
  23326. }
  23327. */
  23328. console.log('2024.9');
  23329. Potree.settings.number = number || 't-o5YMR13'; // 't-iksBApb'// 写在viewer前
  23330. if (!Potree.settings.isOfficial) {
  23331. if ( /* Potree.settings.isTest && */browser.isMobile()) {
  23332. changeLog();
  23333. }
  23334. }
  23335. if (browser.urlHasValue('google')) Potree.settings.mapCompany = 'google';
  23336. if (browser.urlHasValue('timing')) Potree.measureTimings = 1;
  23337. var viewer = new Potree.Viewer(dom, mapDom);
  23338. var Alignment = viewer.modules.Alignment;
  23339. viewer.setEDLEnabled(false);
  23340. viewer.setFOV(Potree.config.view.fov);
  23341. //viewer.loadSettingsFromURL();
  23342. Potree.settings.cameraFar = Potree.config.view.far;
  23343. if (!Potree.settings.isOfficial) {
  23344. viewer.loadGUI(() => {
  23345. viewer.setLanguage('en');
  23346. //$("#menu_appearance").next().show();
  23347. $("#menu_tools").next().show();
  23348. $("#menu_scene").next().show();
  23349. $("#siteModel").show();
  23350. //$("#alignment").show();
  23351. viewer.toggleSidebar();
  23352. });
  23353. Potree.settings.sizeFitToLevel = true; //当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  23354. Potree.settings.rotAroundPoint = false;
  23355. }
  23356. Potree.loadDatasetsCallback = function (data, ifReload) {
  23357. if (!data || data.length == 0) return console.error('getDataSet加载的数据为空');
  23358. Potree.datasetData = data;
  23359. viewer.transform = null;
  23360. var datasetLength = data.length;
  23361. var pointcloudLoaded = 0;
  23362. var panosLoaded = 0;
  23363. var pointcloudLoadDone = function pointcloudLoadDone() {//点云cloud.js加载完毕后
  23364. };
  23365. var panosLoadDone = function panosLoadDone() {
  23366. viewer.images360.loadDone();
  23367. viewer.scene.add360Images(viewer.images360);
  23368. viewer.mapViewer.addListener(viewer.images360);
  23369. viewer.updateModelBound(); //需等pano加载完
  23370. var {
  23371. boundSize,
  23372. center
  23373. } = viewer.bound;
  23374. if (!Potree.settings.isOfficial) {
  23375. Potree.loadMapEntity('all'); //加载floorplan
  23376. }
  23377. Potree.loadNeighborFile();
  23378. Potree.setNeighborGui();
  23379. if (!ifReload) {
  23380. viewer.dispatchEvent({
  23381. type: 'loadPointCloudDone'
  23382. });
  23383. if (!Potree.settings.UserPointDensity) {
  23384. Potree.settings.UserPointDensity = 'high'; //'middle'
  23385. }
  23386. Potree.Log('loadPointCloudDone 点云加载完毕');
  23387. }
  23388. {
  23389. //初始位置
  23390. var panoId = browser.urlHasValue('pano', true);
  23391. if (panoId !== '') {
  23392. var pos;
  23393. var pano = viewer.images360.panos.find(e => e.id == panoId);
  23394. if (pano) {
  23395. viewer.images360.focusPano({
  23396. pano,
  23397. duration: 0,
  23398. callback: () => {/* Potree.settings.displayMode = 'showPanos' */}
  23399. });
  23400. }
  23401. } else {
  23402. //考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上
  23403. var {
  23404. boundSize: _boundSize,
  23405. center: _center
  23406. } = viewer.bound;
  23407. var _pano = viewer.images360.findNearestPano(_center);
  23408. if (_pano) {
  23409. viewer.images360.flyToPano({
  23410. pano: _pano,
  23411. duration: 0,
  23412. target: viewer.images360.bound.center.setZ(_pano.position.z) //平视中心区域(但也不能保证这个方向一定能看到点云密集区,如果在边缘的话)
  23413. });
  23414. } else {
  23415. // 无漫游点 避免加载时看不到点云 SG-t-DXmdymgZ2sX SG-t-rVB03a5GXr8
  23416. //SG-t-XPf1k9pv3Zg 总有极端的场景,如这是倾斜的桥 - -, 只能调整为看到全局了
  23417. viewer.mainViewport.view.pitch = -0.7; //相对俯视
  23418. var bound = viewer.bound.boundingBox.clone();
  23419. viewer.focusOnObject({
  23420. boundingBox: bound
  23421. }, 'boundingBox', 0, {
  23422. dontChangeCamDir: true
  23423. });
  23424. if (viewer.bound.boundSize.length() > 20) {
  23425. //否则有可能超出far范围
  23426. viewer.mainViewport.camera.far = 10000;
  23427. viewer.mainViewport.camera.updateProjectionMatrix();
  23428. viewer.fixCamFar = true; //不允许修改camera.far
  23429. //等有点云加载出来后,再去focus其中一个,使camera.far不超过最大值
  23430. var count_ = 0;
  23431. var done = () => {
  23432. viewer.fixCamFar = false;
  23433. viewer.mainViewport.camera.far = Potree.settings.cameraFar;
  23434. viewer.mainViewport.camera.updateProjectionMatrix();
  23435. viewer.removeEventListener('pageVisible', focusPoint);
  23436. clearTimeout(timer);
  23437. };
  23438. var timer;
  23439. var focusPoint = e => {
  23440. //拉近到某个点
  23441. if (e && e.v === false) return;
  23442. viewer.removeEventListener('pageVisible', focusPoint);
  23443. var pointcloud = viewer.scene.pointclouds.find(e => e.root.geometryNode);
  23444. console.log('初始加载focus点云', e, pointcloud);
  23445. if (!pointcloud) {
  23446. if (count_ < 10) {
  23447. //可能没加载到,可能被隐藏
  23448. if (document.hidden) {
  23449. //等回到页面再focus
  23450. console.log('focus hidden');
  23451. return viewer.addEventListener('pageVisible', focusPoint);
  23452. }
  23453. count_++; //如果在别的
  23454. timer = setTimeout(focusPoint, 200);
  23455. } else {
  23456. //放弃
  23457. console.log('初始加载focus点云 放弃');
  23458. done();
  23459. }
  23460. return console.warn('no!!!!!!!!!!!!!!');
  23461. }
  23462. viewer.flyToDataset({
  23463. focusOnPoint: true,
  23464. pointcloud,
  23465. duration: 0
  23466. });
  23467. console.warn('ok!!!!!!!!!!!!!!!!');
  23468. done();
  23469. };
  23470. var focus = () => {
  23471. timer = setTimeout(focusPoint, 300);
  23472. };
  23473. viewer.addEventListener('setPose', () => {
  23474. //设置了初始画面
  23475. viewer.removeEventListener('pointcloud_changed', focus);
  23476. done();
  23477. });
  23478. viewer.addEventListener('pointcloud_changed', focus, {
  23479. once: true
  23480. }); //加载了点之后
  23481. }
  23482. }
  23483. }
  23484. }
  23485. viewer.addVideo(); //addFire()
  23486. viewer.scene.pointclouds.some(e => !e.hasDepthTex) && (Potree.config.shelterMargin *= 3); //没有深度图的话在全景模式测量有偏差
  23487. console.log('allLoaded');
  23488. viewer.addTube({
  23489. 't-8KbK1JjubE': [{
  23490. //地上管子 黄色
  23491. path: [{
  23492. "x": -109.83,
  23493. "y": -68.33,
  23494. "z": -7.52
  23495. }, {
  23496. "x": -95.17,
  23497. "y": -59.3,
  23498. "z": -7.38
  23499. }, {
  23500. "x": -38.75,
  23501. "y": -24.01,
  23502. "z": -6.01
  23503. }, {
  23504. "x": 0.5,
  23505. "y": 0.19,
  23506. "z": -3.89
  23507. }, {
  23508. "x": 39.29,
  23509. "y": 24.41,
  23510. "z": -1.31
  23511. }, {
  23512. "x": 43.58,
  23513. "y": 27.7,
  23514. "z": -0.97
  23515. }, {
  23516. "x": 40.22,
  23517. "y": 35.37,
  23518. "z": -0.67
  23519. } // 拐弯向右
  23520. , {
  23521. "x": 39.18,
  23522. "y": 36.71,
  23523. "z": 0.35
  23524. }, {
  23525. "x": 38.69,
  23526. "y": 36.04,
  23527. "z": 18.04
  23528. } // 拐弯向上 }
  23529. ],
  23530. color: '#b86',
  23531. radius: 0.08,
  23532. height: 0.13,
  23533. tension: 0.3,
  23534. lessSpace: 60
  23535. }, {
  23536. //地下管子 藍色
  23537. path: [{
  23538. "x": -108.24,
  23539. "y": -70.61,
  23540. "z": -7.52
  23541. }, {
  23542. "x": -57.8,
  23543. "y": -39.31,
  23544. "z": -6.72
  23545. }, {
  23546. "x": -18.8,
  23547. "y": -15.35,
  23548. "z": -5.01
  23549. }, {
  23550. "x": 55.87,
  23551. "y": 31.67,
  23552. "z": -0.04
  23553. }, {
  23554. "x": 110.53,
  23555. "y": 66.48,
  23556. "z": 5.14
  23557. }],
  23558. color: '#48a',
  23559. radius: 0.08,
  23560. height: -0.5,
  23561. lessSpace: 60
  23562. }
  23563. /* {//cross n
  23564. path:[{
  23565. "x": 67.07955953921191,
  23566. "y": 42.43221326163323,
  23567. "z": 3
  23568. },
  23569. {
  23570. "x": 61.893225891856005,
  23571. "y": 51.21636591599333,
  23572. "z": 3
  23573. }],
  23574. color:'#faa', radius:0.1, height:0
  23575. },
  23576. {//cross n
  23577. path:[{
  23578. "x": 61.125217071633024,
  23579. "y": 45.61024394626761,
  23580. "z": 3
  23581. },
  23582. {
  23583. "x": 71.39519484782664,
  23584. "y": 47.81818954083545,
  23585. "z": 3
  23586. }],
  23587. color:'#faa', radius:0.1, height:0
  23588. },
  23589. {//cross n
  23590. path:[{
  23591. "x": 58.307941469658175,
  23592. "y": 38.00791434589657,
  23593. "z": 3
  23594. },
  23595. {
  23596. "x": 70.97012488078363,
  23597. "y": 54.49470440381565,
  23598. "z": 3
  23599. }],
  23600. color:'#faa', radius:0.1, height:0
  23601. },
  23602. {//cross n
  23603. path:[{
  23604. "x": 59.40792027206088,
  23605. "y": 49.62134527481198,
  23606. "z": 3
  23607. },
  23608. {
  23609. "x": 67.22182631922209,
  23610. "y": 44.893214711761544,
  23611. "z": 3
  23612. }],
  23613. color:'#faa', radius:0.1, height:0
  23614. },
  23615. {//cross
  23616. path:[
  23617. {
  23618. "x": 22.264080508219305,
  23619. "y": 12.15228853990859,
  23620. "z": 1
  23621. },
  23622. {
  23623. "x": 19.005656779941955,
  23624. "y": 16.23551039605065,
  23625. "z": 1
  23626. },
  23627. {
  23628. "x": 20.979741345561404,
  23629. "y": 17.51464704500214,
  23630. "z": 1
  23631. },
  23632. {
  23633. "x": 21.5934746129188,
  23634. "y": 17.195035517333054,
  23635. "z": 1
  23636. },
  23637. {
  23638. "x": 22.63170813625128,
  23639. "y": 15.760646363029101,
  23640. "z": 1
  23641. },
  23642. {
  23643. "x": 16.694896649835762,
  23644. "y": 11.78057010590217,
  23645. "z": 1
  23646. },
  23647. {
  23648. "x": 21.936713867547073,
  23649. "y": 10.835961521749118,
  23650. "z": 1
  23651. },
  23652. {
  23653. "x": 22.97841434844728,
  23654. "y": 13.551361417531485,
  23655. "z": 1
  23656. }
  23657. ],
  23658. color:'#eee', radius:0.1, height:0
  23659. },
  23660. */],
  23661. 'SS-t-HE28Q2wHFS': [
  23662. //食堂 test
  23663. {
  23664. //地上管子 黄色
  23665. path: [{
  23666. "x": -0.5091109247689113,
  23667. "y": 1.508718032877598,
  23668. "z": 2.6578301191329956
  23669. }, {
  23670. "x": 1.6691028191759722,
  23671. "y": 2.1808285943848674,
  23672. "z": 2.642110586166382
  23673. }, {
  23674. "x": 2.164859460492007,
  23675. "y": 3.1794038455034364,
  23676. "z": 2.6188302040100098
  23677. }],
  23678. color: '#fff',
  23679. radius: 0.05,
  23680. height: 0.13,
  23681. spaceDis: 0.02,
  23682. minRad: 0.005,
  23683. lessSpace: 100
  23684. }]
  23685. /* 'SG-t-h0I7LnfGFwj':[ //港华M层
  23686. {
  23687. path:[[20.295,-10.269,-1.152],[19.996,-10.252,-1.153],[19.98,-10.253,-1.156],[19.967,-10.252,-1.165],[19.957,-10.251,-1.179],[19.953,-10.251,-1.225],[19.961,-10.242,-1.267],[19.968,-10.223,-1.296],[19.967,-10.193,-1.304],[20.007,-10.092,-1.321],[19.997,-10.063,-1.309],[19.979,-10.039,-1.284],[19.989,-10.028,-1.256],[19.993,-10.024,-1.23],[19.972,-10.026,-1.181],[20.009,-10.045,-1.026],[20.025,-10.048,-1.013],[20.045,-10.05,-1.006],[20.056,-10.052,-1.001],[20.413,-10.073,-1.016],[20.461,-10.075,-1.02],[20.498,-10.053,-1.018],[20.525,-10.022,-1.025],[20.538,-9.983,-1.029],[20.554,-9.536,-1.111],[20.554,-9.487,-1.118],[20.545,-9.445,-1.129],[20.521,-9.418,-1.14],[20.478,-9.396,-1.156],[20.427,-9.379,-1.182],[20.367,-9.369,-1.198],[19.971,-9.304,-1.221],[19.749,-9.197,-1.345]]
  23688. ,color:'#8c99aa', radius:0.025, height:-0, fromDataset:true, tension:0.01, spaceDis:0.02,visiEntity:'厨房'
  23689. },
  23690. {
  23691. path:[[19.708,-2.921,-1.145],[19.721,-2.924,-1.119],[20.704,-2.881,-1.134],[20.736,-2.87,-1.138],[20.76,-2.852,-1.147],[20.773,-2.828,-1.148],[20.777,-2.809,-1.148],[20.794,-2.493,-1.167],[20.793,-2.461,-1.169],[20.776,-2.436,-1.174],[20.742,-2.425,-1.198],[20.14,-2.459,-1.309],[20.123,-2.457,-1.309],[20.108,-2.451,-1.31],[20.101,-2.439,-1.311],[20.095,-2.42,-1.313],[20.094,-2.399,-1.311],[20.092,-1.966,-1.295],[20.093,-1.945,-1.286],[20.094,-1.931,-1.269],[20.093,-1.929,-1.251],[20.09,-1.921,-1.197],[20.096,-1.914,-1.181],[20.107,-1.909,-1.174],[20.176,-1.893,-1.141],[20.699,-1.848,-1.076],[20.759,-1.824,-1.068],[20.81,-1.754,-1.076],[20.837,-1.71,-1.086],[20.85,-1.634,-1.1],[20.815,-1.01,-1.104],[20.824,-0.979,-1.115],[20.83,-0.957,-1.124],[20.843,-0.936,-1.132],[20.871,-0.925,-1.139],[21.065,-0.936,-1.166],[21.096,-0.935,-1.167],[21.115,-0.919,-1.167],[21.129,-0.887,-1.165],[21.136,-0.783,-1.167],[21.136,0.555,-1.201],[21.128,0.599,-1.201],[21.1,0.627,-1.199],[21.058,0.639,-1.198],[20.832,0.616,-1.179],[20.782,0.62,-1.186],[20.748,0.637,-1.19],[20.728,0.698,-1.21],[20.731,1.311,-1.233],[20.68,2.081,-1.292],[20.654,2.157,-1.307],[20.576,2.215,-1.314],[20.484,2.274,-1.321],[20.035,2.354,-1.353],[20.013,2.367,-1.363],[20.008,2.39,-1.371],[19.989,3.124,-1.384],[19.993,3.175,-1.39],[19.995,3.208,-1.393],[19.995,3.233,-1.374],[20.002,3.246,-1.324],[20.006,3.248,-1.266],[20.027,3.243,-1.245],[20.063,3.241,-1.239],[20.62,3.229,-1.226],[20.645,3.235,-1.204],[20.658,3.251,-1.191],[20.667,3.278,-1.184],[20.675,3.312,-1.193],[20.716,3.71,-1.24],[20.722,3.767,-1.251],[20.704,3.823,-1.268],[20.652,3.864,-1.279],[20.026,3.901,-1.368],[19.999,3.919,-1.37],[19.982,3.95,-1.361],[19.933,4.69,-1.285],[19.972,4.812,-1.332],[19.978,4.817,-1.233],[19.992,4.814,-1.203],[20.047,4.81,-1.196],[20.738,4.794,-1.196]]
  23692. ,color:'#8c99aa', radius:0.025, height:-0, fromDataset:true, tension:0.01, spaceDis:0.02,visiEntity:'厨房'
  23693. },
  23694. {
  23695. path:[[19.685,-2.896,-1.115],[19.699,-2.93,-1.274],[19.701,-2.936,-1.295],[19.707,-2.94,-1.316],[19.712,-2.951,-1.34],[19.714,-2.965,-1.353],[19.716,-2.986,-1.359],[19.7,-3.595,-1.309],[19.703,-3.619,-1.303],[19.704,-3.628,-1.274],[19.719,-3.632,-1.256],[20.063,-3.633,-1.275],[20.089,-3.637,-1.254],[20.103,-3.64,-1.227],[20.11,-3.642,-1.191],[20.083,-3.669,-1.027],[20.075,-3.68,-0.999],[20.053,-3.694,-0.978],[20.053,-3.805,-0.957],[20.063,-3.827,-0.963],[20.045,-3.836,-0.962],[20.01,-3.841,-0.957],[19.737,-3.818,-0.964],[19.712,-3.814,-0.985],[19.699,-3.819,-1.059],[19.724,-3.817,-1.247],[19.725,-3.827,-1.28],[19.719,-3.842,-1.309],[19.719,-3.858,-1.33],[19.714,-3.881,-1.341],[19.699,-4.56,-1.339],[19.7,-4.62,-1.336],[19.7,-4.643,-1.334],[19.699,-4.66,-1.326],[19.698,-4.675,-1.31],[19.697,-4.678,-1.279],[19.697,-4.678,-1.21],[19.704,-4.682,-1.187],[19.716,-4.682,-1.173],[19.736,-4.683,-1.164],[20.481,-4.817,-1.026],[20.529,-4.847,-0.984],[20.562,-4.89,-0.935],[20.585,-4.932,-0.909],[20.59,-4.992,-0.887],[20.565,-5.98,-0.847],[20.547,-6.08,-0.846],[20.541,-6.17,-0.86],[20.476,-6.21,-0.858],[19.847,-6.207,-0.808],[19.803,-6.22,-0.827],[19.775,-6.217,-0.885],[19.75,-6.188,-1.289],[19.743,-6.193,-1.341],[19.742,-6.207,-1.375],[19.75,-6.232,-1.401],[19.722,-6.905,-1.359],[19.723,-6.958,-1.352],[19.722,-6.987,-1.342],[19.721,-7.001,-1.31],[19.721,-7.004,-1.231],[19.734,-7.03,-0.976],[19.742,-7.041,-0.947],[19.747,-7.059,-0.922],[19.755,-7.284,-0.764],[19.761,-7.312,-0.731],[19.776,-7.337,-0.711],[19.795,-7.355,-0.702],[20.502,-7.453,-0.715],[20.578,-7.496,-0.715],[20.631,-7.557,-0.719],[20.66,-7.653,-0.718],[20.658,-8.639,-0.766],[20.654,-8.789,-0.763],[20.639,-8.856,-0.763],[20.605,-8.89,-0.76],[20.57,-8.916,-0.761],[20.539,-8.945,-0.773],[19.879,-9.028,-0.814],[19.853,-9.032,-0.828],[19.834,-9.033,-0.842],[19.83,-9.033,-0.876],[19.857,-9.033,-1.292],[19.837,-9.037,-1.333],[19.819,-9.051,-1.354],[19.812,-9.082,-1.381],[19.79,-9.184,-1.386]]
  23696. ,color:'#8c99aa', radius:0.02, height:-0, fromDataset:true, tension:0.01, spaceDis:0.02,visiEntity:'厨房'
  23697. }
  23698. ],
  23699. 'SG-t-RGUFiJAoxvL':[ //济南工地覆土后
  23700. {//--旧的 整条
  23701. path: [[23.522,-19.432,-1.744],[25.344,20.312,-1.855],[25.344,21.302,-1.861],[25.253,21.904,-1.861],[25.088,22.381,-1.859],[24.748,22.772,-1.861],[24.222,22.893,-1.873],[-24.547,16.774,-1.319]]
  23702. ,color:'#445', radius:0.08, height:-1.16, fromDataset:true, tension:0.01,// spaceDis:0.1
  23703. },
  23704. {
  23705. path:[[22.726,22.678,-1.938],[-24.541,16.782,-1.319]]
  23706. ,color:'#445', radius:0.08, height:-1.16, fromDataset:true, tension:0,// spaceDis:0.1
  23707. },
  23708. {
  23709. path:[[23.519,-19.473,-1.744],[25.117,15.447,-1.783]]
  23710. ,color:'#445', radius:0.08, height:-1.16, fromDataset:true, tension:0,// spaceDis:0.1
  23711. }
  23712. ],
  23713. 'SG-t-TK0S5EqWBxd':[ //济南工地
  23714. {
  23715. path:[[-25.768,-12.695,-1.305],[-26.334,-21.834,-1.511],[-26.355,-22.153,-1.514],[-26.366,-22.418,-1.513],[-26.31,-22.66,-1.515],[-26.126,-22.841,-1.519],[-25.871,-22.968,-1.525],[-25.443,-22.969,-1.532],[-24.953,-22.956,-1.585],[-23.697,-22.854,-1.637]]
  23716. ,color:'#445', radius:0.08, height:-1.16, fromDataset:true, spaceDis:0.2// tension:0.01,
  23717. },
  23718. ],*/
  23719. });
  23720. viewer.dispatchEvent('allLoaded');
  23721. };
  23722. if (!Potree.settings.originDatasetId) Potree.settings.originDatasetId = data[0].id;
  23723. var originDataset = data.find(e => e.id == Potree.settings.originDatasetId);
  23724. baseZ = originDataset.location[2];
  23725. /*originDataset.location[0] = 0
  23726. originDataset.location[1] = 0
  23727. let ano = data.find(e=>e.name == 'SG-t-Jw0xyhL6oSY')
  23728. ano.location[0] = 113.6060509967498
  23729. ano.location[1] = 22.381061273279244 */
  23730. {
  23731. //拿初始数据集作为基准。它的位置要放到000
  23732. var locationLonLat = originDataset.location.slice(0, 2);
  23733. Potree.setLonlat(locationLonLat[0], locationLonLat[1]);
  23734. viewer.mapViewer && viewer.mapViewer.mapLayer.maps[0].updateProjection();
  23735. }
  23736. data.forEach((dataset, index) => {
  23737. if (!ifReload) {
  23738. var datasetCode = dataset.sceneCode || dataset.name; //对应4dkk的场景码
  23739. if (Potree.settings.isLocal && dataset.mapping) {
  23740. var cloudPath = "".concat(Potree.settings.urls.prefix1, "/").concat(dataset.mapping, "/").concat(dataset.webBin); //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
  23741. } else {
  23742. var cloudPath = "".concat(Potree.settings.urls.prefix1, "/").concat(dataset.webBin); //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
  23743. }
  23744. //var cloudPath = `${Potree.scriptPath}/data/test/${dataset.name}/cloud.js`
  23745. var timeStamp = dataset.updateTime ? dataset.updateTime.replace(/[^0-9]/ig, '') : ''; //每重算一次后缀随updateTime更新一次
  23746. //console.warn(dataset.name, 'timeStamp', timeStamp)
  23747. Potree.loadPointCloud(cloudPath, dataset.name, datasetCode, timeStamp, e => {
  23748. var scene = viewer.scene;
  23749. var pointcloud = e.pointcloud;
  23750. var config = Potree.config.material;
  23751. var material = pointcloud.material;
  23752. pointcloud.datasetData = dataset;
  23753. pointcloud.dataset_id = dataset.id; //供漫游点找到属于的dataset点云
  23754. pointcloud.hasDepthTex = Potree.settings.useDepthTex && (!!dataset.has_depth || Potree.settings.isLocalhost && Potree.settings.number == 'SS-t-7DUfWAUZ3V'); //test
  23755. pointcloud.hasTempTex = !!dataset.has_ir;
  23756. material.minSize = config.minSize;
  23757. material.maxSize = config.maxSize;
  23758. material.pointSizeType = /* Potree.settings.isOfficial ? */config.pointSizeType; /* : 'ADAPTIVE' */ //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  23759. pointcloud.changePointSize(config.realPointSize); //material.size = config.pointSize;
  23760. pointcloud.changePointOpacity(1);
  23761. material.shape = Potree.PointShape.SQUARE;
  23762. pointcloud.color = pointcloud.material.color = dataset.color;
  23763. pointcloud.timeStamp = timeStamp;
  23764. transformPointcloud(pointcloud, dataset);
  23765. scene.addPointCloud(pointcloud);
  23766. if (!Potree.settings.isOfficial) {
  23767. Potree.settings.floorplanEnables[dataset.id] = true;
  23768. Potree.settings.floorplanType[dataset.id] = 'default';
  23769. }
  23770. pointcloudLoaded++;
  23771. if (pointcloudLoaded == datasetLength) pointcloudLoadDone();
  23772. Potree.loadPanos(dataset.id, data => {
  23773. //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
  23774. viewer.images360.addPanoData(data, pointcloud);
  23775. panosLoaded++;
  23776. var f = () => {
  23777. if (panosLoaded == datasetLength) {
  23778. Potree.loadImgVersion(function () {
  23779. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  23780. Potree.settings.panoVersion = e.imgVersion; //全景图被替换后
  23781. panosLoadDone();
  23782. });
  23783. }
  23784. };
  23785. if (dataset.has_ir) {
  23786. //红外热成像漫游点数据
  23787. pointcloud.typesUrl = "".concat(Potree.settings.urls.prefix1, "/").concat(Potree.settings.webSite2 || Potree.settings.webSite, "/").concat(pointcloud.sceneCode, "/data/").concat(pointcloud.sceneCode, "/imagemap/");
  23788. var typesUrl = pointcloud.typesUrl + 'types.json';
  23789. Potree.loadFile(typesUrl, null, e => {
  23790. e.imagemap_types.forEach(o => {
  23791. o.uuids.forEach(uuid => {
  23792. //if(o.property == 'temp')return //只要ir
  23793. var pano = viewer.images360.getPano("".concat(pointcloud.dataset_id, "|").concat(uuid), 'sid');
  23794. pano['has_' + o.property] = true;
  23795. });
  23796. });
  23797. f();
  23798. });
  23799. } else {
  23800. f();
  23801. }
  23802. });
  23803. });
  23804. } else {
  23805. var pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == dataset.id);
  23806. if (!pointcloud) {
  23807. Potree.Log('数据集id变了,自动使用第一个', {
  23808. font: {
  23809. color: '#500'
  23810. }
  23811. });
  23812. pointcloud = viewer.scene.pointclouds[0];
  23813. }
  23814. //先归零
  23815. Alignment.translate(pointcloud, pointcloud.translateUser.clone().negate());
  23816. Alignment.rotate(pointcloud, null, -pointcloud.orientationUser);
  23817. transformPointcloud(pointcloud, dataset);
  23818. }
  23819. });
  23820. if (ifReload) {
  23821. //loadDone()
  23822. }
  23823. };
  23824. number && Potree.loadDatasets(Potree.loadDatasetsCallback);
  23825. /*
  23826. //调试用,加载多个本地
  23827. Potree.loadDatasetsCallback([
  23828. {name:'webcloud_0',id:0, orientation:0, location:[0,0,0]},
  23829. {name:'webcloud_1',id:1, orientation:0.047234761795199476, location:[-0.07925513345058573,-0.0010590072536559839,-2.403613132687564]},
  23830. {name:'webcloud_2',id:2, orientation:-1.5299545647758208, location:[1.5603736310030292, -0.0009340812579088904, -2.4464530770974139]},
  23831. ]) */
  23832. window.testTransform = function (locationLonLat, location1, location2) {
  23833. proj4.defs("NAVVIS:test", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
  23834. var transform = proj4("WGS84", "NAVVIS:test"); //这个ok navvis里也是这两种转换 见proj4Factory
  23835. if (location1) {
  23836. //经纬度
  23837. return transform.forward(location1);
  23838. } else {
  23839. return transform.inverse(location2);
  23840. }
  23841. };
  23842. window.buttonFunction = function () {
  23843. viewer.scene.pointclouds.forEach(e => e.predictNodeMaxLevel());
  23844. /*
  23845. viewer.startScreenshot({type:'measure', measurement:viewer.scene.measurements[0]})
  23846. viewer.modules.RouteGuider.routeStart = new THREE.Vector3(0,0,-1.3)
  23847. viewer.modules.RouteGuider.routeEnd = new THREE.Vector3(-10,0,-1.3)
  23848. */
  23849. };
  23850. if (Potree.settings.isLocalhost) {
  23851. var before = {};
  23852. viewer.inputHandler.addEventListener('keydown', e => {
  23853. //测试的代码
  23854. if (e.event.key == 't') {
  23855. viewer.images360.cube.visible = true;
  23856. viewer.images360.cube.material.wireframe = true;
  23857. } else if (e.event.key == 'y') {
  23858. viewer.images360.cube.material.wireframe = false;
  23859. viewer.images360.cube.visible = Potree.settings.displayMode == 'showPanos';
  23860. }
  23861. });
  23862. //--------------------------------
  23863. /* if(!number){
  23864. Potree.settings.boundAddObjs = true
  23865. Potree.settings.intersectOnObjs = true
  23866. // Load untextured bunny from ply
  23867. viewer.loadModel({
  23868. fileType:'ply',
  23869. url:Potree.resourcePath + "/models/indoor.ply",
  23870. name:'test',
  23871. },
  23872. (object)=>{
  23873. object.isModel = true
  23874. viewer.updateModelBound()
  23875. }
  23876. )
  23877. } */
  23878. }
  23879. }
  23880. //=======================================================================
  23881. /*
  23882. 漫游点编辑
  23883. */
  23884. //=======================================================================
  23885. function panoEditStart(dom, number, EditCloudsArgs) {
  23886. Potree.settings.editType = 'pano';
  23887. Potree.settings.number = number;
  23888. Potree.settings.sizeFitToLevel = true; //当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  23889. var datasetData;
  23890. var viewer = new Potree.Viewer(dom);
  23891. var Alignment = viewer.modules.Alignment;
  23892. viewer.setEDLEnabled(false);
  23893. viewer.setFOV(Potree.config.view.fov);
  23894. //viewer.loadSettingsFromURL();
  23895. var datasetLoaded = 0;
  23896. if (!Potree.settings.isOfficial) {
  23897. viewer.loadGUI(() => {
  23898. viewer.setLanguage('en');
  23899. $("#menu_tools").next().show();
  23900. $("#panos").show();
  23901. $("#alignment").show();
  23902. viewer.toggleSidebar();
  23903. });
  23904. Potree.settings.sizeFitToLevel = true;
  23905. }
  23906. var pointcloudLoadDone = function pointcloudLoadDone() {
  23907. //所有点云cloud.js加载完毕后
  23908. viewer.scene.pointclouds.forEach(c => {
  23909. transformPointcloud(c);
  23910. });
  23911. viewer.images360.loadDone();
  23912. viewer.scene.add360Images(viewer.images360);
  23913. viewer.updateModelBound();
  23914. var {
  23915. boundSize,
  23916. center
  23917. } = viewer.bound;
  23918. Potree.Log("\u4E2D\u5FC3\u70B9: ".concat(math.toPrecision(center.toArray(), 2), ", boundSize: ").concat(math.toPrecision(boundSize.toArray(), 2), " "));
  23919. viewer.scene.view.setView({
  23920. position: center.clone().add(new Vector3(10, 5, 10)),
  23921. target: center
  23922. });
  23923. viewer.dispatchEvent({
  23924. type: 'loadPointCloudDone'
  23925. });
  23926. if (!Potree.settings.UserPointDensity) {
  23927. Potree.settings.UserPointDensity = 'panoEdit'; //'middle'
  23928. }
  23929. Potree.Log('loadPointCloudDone 点云加载完毕', {
  23930. font: [null, 10]
  23931. });
  23932. viewer.dispatchEvent('allLoaded');
  23933. };
  23934. var transformPointcloud = pointcloud => {
  23935. //初始化位置
  23936. viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud);
  23937. /* let orientation = pointcloud.panos[0].dataRotation.z + Math.PI
  23938. let location = pointcloud.panos[0].dataPosition.clone()//.negate()
  23939. Alignment.rotate(pointcloud, null, orientation )
  23940. Alignment.translate(pointcloud, location ) */
  23941. viewer.modules.PanoEditor.initCloud(pointcloud);
  23942. pointcloud.updateMatrixWorld();
  23943. };
  23944. var loadPanosDone = Potree.loadPanosDone = (datasetId, panoData) => {
  23945. //一个数据集获取到它的panos后
  23946. Potree.settings.datasetsPanos[datasetId] = {
  23947. panoData,
  23948. panos: []
  23949. };
  23950. console.log('panoData', datasetId, panoData);
  23951. var panoCount = panoData.length;
  23952. var pointcloudLoaded = 0;
  23953. var datasetsCount = Object.keys(Potree.settings.datasetsPanos).length;
  23954. var datasetData = Potree.datasetData.find(e => e.datasetId = datasetId);
  23955. panoData.forEach((pano, index) => {
  23956. //let cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${Potree.settings.number}/data/bundle_${Potree.settings.number}/building/uuidcloud/${pano.uuid}/cloud.js`
  23957. //2024.12.9: 加mapping
  23958. var mapping = Potree.settings.isLocal && (datasetData ? datasetData.mapping : browser.urlHasValue('mapping', true)) || '';
  23959. mapping && (mapping += '/');
  23960. var cloudPath = "".concat(Potree.settings.urls.prefix1, "/").concat(mapping).concat(Potree.settings.webSite, "/").concat(Potree.settings.number, "/data/bundle_").concat(Potree.settings.number, "/building/uuidcloud/").concat(pano.uuid, "/cloud.js");
  23961. /* if(Potree.settings.isLocal && dataset.mapping){
  23962. var cloudPath = `${Potree.settings.urls.prefix1}/${dataset.mapping}/${dataset.webBin}` //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
  23963. }else{
  23964. var cloudPath = `${Potree.settings.urls.prefix1}/${dataset.webBin}` //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
  23965. } */
  23966. var name = datasetId + '-' + pano.uuid;
  23967. var timeStamp = 0;
  23968. pano.index = index; //注意:index不等于uuid,因为有的uuid缺失。但是visibles中存的是下标!
  23969. Potree.loadPointCloud(cloudPath, name, number, timeStamp, e => {
  23970. //开始加载点云
  23971. var scene = viewer.scene;
  23972. var pointcloud = e.pointcloud;
  23973. var config = Potree.config.material;
  23974. var material = pointcloud.material;
  23975. material.minSize = config.minSize;
  23976. material.maxSize = config.maxSize;
  23977. material.pointSizeType = /* 'ADAPTIVE'// */config.pointSizeType; //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  23978. pointcloud.changePointSize(0.1 /* config.realPointSize */); //material.size = config.pointSize;
  23979. pointcloud.changePointOpacity(1);
  23980. material.shape = Potree.PointShape.SQUARE;
  23981. pointcloud.color = config.pointColor;
  23982. pointcloud.dataset_id = datasetId; //多个点云指向一个datasetId
  23983. pointcloud.panoUuid = pano.uuid;
  23984. pointcloud.timeStamp = timeStamp;
  23985. if (datasetData) {
  23986. //非4dkk
  23987. pointcloud.datasetData = datasetData;
  23988. pointcloud.hasDepthTex = Potree.settings.useDepthTex && !!datasetData.has_depth;
  23989. }
  23990. //transformPointcloud(pointcloud, pano)
  23991. scene.addPointCloud(pointcloud);
  23992. pointcloudLoaded++;
  23993. if (pointcloudLoaded == panoCount) {
  23994. datasetLoaded++;
  23995. viewer.images360.addPanoData(panoData, pointcloud);
  23996. if (datasetLoaded == datasetsCount) {
  23997. pointcloudLoadDone();
  23998. }
  23999. }
  24000. });
  24001. });
  24002. };
  24003. if (!Potree.settings.isOfficial) {
  24004. Potree.settings.datasetsPano = {
  24005. 'testDataset': null
  24006. };
  24007. Potree.loadPanosInfo(data => {
  24008. loadPanosDone('testDataset', data.sweepLocations);
  24009. });
  24010. }
  24011. Potree.loadPanosCloudStart = EditCloudsArgs => {
  24012. Potree.loadDatasets(datasets => {
  24013. Potree.datasetData = datasets; //4dkk的加载为空[]
  24014. Potree.loadImgVersion(function () {
  24015. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  24016. Potree.settings.panoVersion = e.imgVersion; //全景图被替换后
  24017. if (!(EditCloudsArgs instanceof Array)) EditCloudsArgs = [EditCloudsArgs];
  24018. EditCloudsArgs.forEach((e, i) => {
  24019. //加载点云和漫游点
  24020. if (e.datasetId == void 0) {
  24021. console.error('没有datasetId '); // 看看和看见没有或为0
  24022. e.datasetId = i; //经常没有datasetId所以自己加
  24023. }
  24024. Potree.settings.datasetsPanos[e.datasetId] = null;
  24025. Potree.loadPanosDone(e.datasetId, e.clouds);
  24026. });
  24027. });
  24028. }, number);
  24029. };
  24030. EditCloudsArgs && Potree.loadPanosCloudStart(EditCloudsArgs);
  24031. }
  24032. function mergeEditStart(dom, mapDom) {
  24033. var {
  24034. queryCloudLonLatUrl
  24035. } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  24036. Potree.settings.editType = 'merge';
  24037. Potree.settings.intersectOnObjs = true;
  24038. Potree.settings.boundAddObjs = true;
  24039. Potree.settings.unableNavigate = true;
  24040. if (queryCloudLonLatUrl) {
  24041. //点云使用其经纬度作为默认位置
  24042. Potree.settings.queryCloudLonLatUrl = queryCloudLonLatUrl;
  24043. Potree.loadControlPoint = /* async */function (callback, sceneCode, onError, prefix) {
  24044. //点云绑定地图
  24045. return Potree.loadFile(queryCloudLonLatUrl.replace('{sceneCode}', sceneCode), {
  24046. fetchMethod: 'post'
  24047. }, callback, onError);
  24048. };
  24049. }
  24050. var viewer = new Potree.Viewer(dom, mapDom);
  24051. var Alignment = viewer.modules.Alignment;
  24052. viewer.setEDLEnabled(false);
  24053. viewer.setFOV(Potree.config.view.fov);
  24054. //viewer.loadSettingsFromURL();
  24055. {
  24056. viewer.mainViewport.view.position.set(30, 30, 30);
  24057. viewer.mainViewport.view.lookAt(0, 0, 0);
  24058. viewer.updateModelBound(); //init
  24059. //this.bound = new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1))
  24060. viewer.transformationTool.setModeEnable(['translation', 'rotation']);
  24061. //viewer.ssaaRenderPass.sampleLevel = 1 // sampleLevel为1 的话,ground就不会变黑
  24062. viewer.inputHandler.fixSelection = true; //不通过点击屏幕而切换transfrom选中状态
  24063. }
  24064. Potree.settings.sizeFitToLevel = true; //当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  24065. Potree.loadPointCloudScene = function (url, type, id, title, done, onError, prefix1, prefix2) {
  24066. //对应4dkk的场景码
  24067. var dataset, useLonLat;
  24068. var loadCloud = _ref => {
  24069. var {
  24070. cloudPath,
  24071. sceneName,
  24072. sceneCode,
  24073. timeStamp,
  24074. color
  24075. } = _ref;
  24076. Potree.loadPointCloud(cloudPath, sceneName, sceneCode, timeStamp, e => {
  24077. var scene = viewer.scene;
  24078. var pointcloud = e.pointcloud;
  24079. var config = Potree.config.material;
  24080. var material = pointcloud.material;
  24081. pointcloud.datasetData = dataset;
  24082. pointcloud.hasDepthTex = dataset && Potree.settings.useDepthTex && !!dataset.has_depth;
  24083. pointcloud.initialPosition = pointcloud.position.clone();
  24084. pointcloud.pos1MatrixInvert = new Matrix4().setPosition(pointcloud.initialPosition).invert();
  24085. material.minSize = config.minSize;
  24086. material.maxSize = config.maxSize;
  24087. material.pointSizeType = config.pointSizeType; //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
  24088. pointcloud.changePointSize(config.realPointSize); //material.size = config.pointSize;
  24089. pointcloud.changePointOpacity(1);
  24090. dataset && useLonLat && (transformPointcloud(pointcloud, dataset), pointcloud.hasLonLat = true);
  24091. material.shape = Potree.PointShape.SQUARE;
  24092. color && (pointcloud.color = pointcloud.material.color = color);
  24093. pointcloud.timeStamp = timeStamp;
  24094. scene.addPointCloud(pointcloud);
  24095. {
  24096. viewer.updateModelBound();
  24097. var {
  24098. boundSize,
  24099. center
  24100. } = viewer.bound;
  24101. viewer.dispatchEvent({
  24102. type: 'loadPointCloudDone'
  24103. });
  24104. if (!Potree.settings.UserPointDensity) {
  24105. Potree.settings.UserPointDensity = 'high'; //'middle'
  24106. }
  24107. Potree.Log(' 点云加载完毕', sceneName, sceneCode);
  24108. }
  24109. viewer.dispatchEvent('allLoaded');
  24110. done(pointcloud);
  24111. }, onError);
  24112. };
  24113. if (type == 'laser') {
  24114. var sceneCode = url;
  24115. var load = () => {
  24116. Potree.loadDatasets(data => {
  24117. var originDataset = data.find(e => e.sceneCode == sceneCode); //只加载初始数据集
  24118. /* if(!originDataset){
  24119. //应该是data为空,原因未知
  24120. } */
  24121. Potree.settings.cloudAddMapping && (prefix2 += '/' + originDataset.mapping);
  24122. var timeStamp = originDataset.updateTime ? originDataset.updateTime.replace(/[^0-9]/ig, '') : ''; //每重算一次后缀随updateTime更新一次
  24123. //let cloudPath = `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${sceneCode}/data/${sceneCode}/webcloud/cloud.js`
  24124. var cloudPath = "".concat(prefix2, "/").concat(originDataset.webBin); //webBin添加原因:每次裁剪之类的操作会换路径,因为oss文件缓存太严重,更新慢
  24125. dataset = originDataset;
  24126. loadCloud({
  24127. cloudPath,
  24128. sceneName: originDataset.sceneName,
  24129. sceneCode,
  24130. timeStamp,
  24131. color: originDataset.color
  24132. });
  24133. }, sceneCode, onError, prefix1);
  24134. };
  24135. if (Potree.settings.queryCloudLonLatUrl) {
  24136. Potree.loadControlPoint(ctlData => {
  24137. useLonLat = ctlData.controlPoint.status == 1; //设置了地理位置
  24138. load();
  24139. }, sceneCode, e => {
  24140. console.error('loadControlPoint error', e);
  24141. load();
  24142. });
  24143. } else {
  24144. load();
  24145. }
  24146. } else {
  24147. //las or ply 直接用url
  24148. var name = type + '|' + id + '|' + title;
  24149. //有漫游点吗
  24150. if (url instanceof Array) {
  24151. if (url.length == 1) {
  24152. url = url[0];
  24153. } else {
  24154. console.error('有多个点云?暂时还不支持', url, name); //多个点云要一起移动没想好怎么写
  24155. }
  24156. }
  24157. var cloudPath = url + '/cloud.js';
  24158. loadCloud({
  24159. cloudPath,
  24160. sceneName: name,
  24161. sceneCode: name,
  24162. timeStamp: ''
  24163. });
  24164. }
  24165. };
  24166. var setMatrix = pointcloud => {
  24167. //为了漫游点变换,要算一下 类似setMatrix
  24168. /* pointcloud.transformMatrix = new THREE.Matrix4().multiplyMatrices(pointcloud.matrix, pointcloud.pos1MatrixInvert)//还原一点位移
  24169. pointcloud.transformInvMatrix.copy(pointcloud.transformMatrix).invert()
  24170. pointcloud.rotateMatrix = new THREE.Matrix4().makeRotationFromEuler(pointcloud.rotation);
  24171. pointcloud.rotateInvMatrix.copy(pointcloud.rotateMatrix).invert()
  24172. pointcloud.panos.forEach(e=>e.transformByPointcloud()) */
  24173. //pointcloud.updateBound()
  24174. //pointcloud.getPanosBound()
  24175. viewer.updateModelBound();
  24176. };
  24177. var moveModelWhenLoad = false;
  24178. var moveModel = e => {
  24179. //根据鼠标移动的位置改变位置
  24180. var {
  24181. x,
  24182. y
  24183. } = Potree.Utils.getPointerPosAtHeight(0, e.pointer);
  24184. //过后改为根据intersect的点来设置底部高度;这样的话,需要发送高度
  24185. /*let pos = new THREE.Vector3(x,y, planeZ )
  24186. modelEditing.updateMatrixWorld()
  24187. let boundCenter = modelEditing.boundingBox.getCenter(new THREE.Vector3).applyMatrix4(modelEditing.matrixWorld);
  24188. */
  24189. MergeEditor.moveBoundCenterTo(modelEditing, new Vector3(x, y, modelEditing.boundCenter.z)); //使模型中心的xy在鼠标所在位置
  24190. modelEditing.dispatchEvent("position_changed");
  24191. };
  24192. var cancelMove = () => {
  24193. modelEditing = null;
  24194. viewer.removeEventListener('global_mousemove', moveModel);
  24195. viewer.removeEventListener('global_click', confirmPos);
  24196. };
  24197. var confirmPos = () => {
  24198. MergeEditor.focusOn(modelEditing);
  24199. cancelMove();
  24200. return {
  24201. stopContinue: true
  24202. };
  24203. };
  24204. var modelType,
  24205. modelEditing,
  24206. MergeEditor = viewer.modules.MergeEditor;
  24207. Potree.addModel = function (prop, done, onProgress, onError) {
  24208. var _prop$raw, _prop$raw2, _prop$raw3;
  24209. //加载模型
  24210. var fromNew = ((_prop$raw = prop.raw) === null || _prop$raw === void 0 ? void 0 : _prop$raw.convertType) && prop.type == '3dtiles' && (((_prop$raw2 = prop.raw) === null || _prop$raw2 === void 0 ? void 0 : _prop$raw2.wgs84) || ((_prop$raw3 = prop.raw) === null || _prop$raw3 === void 0 ? void 0 : _prop$raw3.gcj02));
  24211. var loadDone = model => {
  24212. model.dataset_id = prop.id; //唯一标识
  24213. {
  24214. //设置下默认经纬度位置,当点击恢复默认时要恢复到此位置
  24215. if (!model.isPointcloud) {
  24216. //有经纬度 3dtiles
  24217. prop.baseRotation && model.rotation.copy(prop.baseRotation); //有的需要翻转90度
  24218. if (fromNew) {
  24219. //新的软件转出的带坐标的osgb,原本给cesium用的,把在球面的转为平面的坐标
  24220. var center = new Vector3().fromArray(model.runtime.getTileset().tileset.root.transform.slice(12, 15));
  24221. var pos = math.fromCes(center);
  24222. model.position.copy(pos);
  24223. //viewer.modules.MergeEditor.moveBoundCenterTo( model, new THREE.Vector3().fromArray(pos) )
  24224. //因为bound中心在原点所以上面两句都可以
  24225. model.hasLonLat = true;
  24226. } else {
  24227. var _prop$raw4;
  24228. var lonlat = /* prop.raw?.wgs84 || */(_prop$raw4 = prop.raw) === null || _prop$raw4 === void 0 ? void 0 : _prop$raw4.rtkLocation; //前者为素材库的osgb的
  24229. if (lonlat) {
  24230. var locationLonLat = lonlat.split(',').map(e => parseFloat(e));
  24231. var location = new Vector3().fromArray(viewer.transform.lonlatToLocal.forward(locationLonLat));
  24232. model.hasLonLat = true;
  24233. if (model.fileType == '3dTiles' && prop.is4dkkModel) {
  24234. //深时深光mesh
  24235. model.position.fromArray(model.runtime.getTileset().tileset.root.boundingVolume.box.slice(0, 3)); //必须要平移一段才能重合
  24236. model.position.copy(Potree.math.convertVector.ZupToYup(model.position));
  24237. //绕原点旋转 类似Alignment.setMatrix 和点云一样处理
  24238. if (prop.raw.orientation) {
  24239. model.updateMatrixWorld(); //此时和点云没有旋转平移时一样。
  24240. var rotMatrix = new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), parseFloat(prop.raw.orientation));
  24241. var pos2Matrix = new Matrix4().setPosition(location); //最后是平移
  24242. var matrix = new Matrix4().multiplyMatrices(pos2Matrix, rotMatrix);
  24243. model.matrix.premultiply(matrix);
  24244. model.matrix.decompose(model.position, model.quaternion, model.scale);
  24245. } else {
  24246. model.position.add(location);
  24247. }
  24248. } else {
  24249. var _prop$raw5;
  24250. MergeEditor.moveBoundCenterTo(model, location);
  24251. if ((_prop$raw5 = prop.raw) !== null && _prop$raw5 !== void 0 && _prop$raw5.orientation) {
  24252. model.rotation.y = parseFloat(prop.raw.orientation);
  24253. }
  24254. if (prop.is4dkkModel) {
  24255. console.warn('遇到is4dkkModel的且有经纬度的mesh,但不是3dtiles!看看位置准不准', model);
  24256. //4dkk应该是可以对的上的。但如果是3dtiles非4dkk的,目前没办法对准,cesium是可以
  24257. //看见的场景说是市场不会带rtk的。所以我们这边标品也没存rtk的坐标信息。和产品聊了,不处理。意思就是,只有激光场景开启了rtk的rtkLocation才有值
  24258. /* if(model.panos?.length){//只能通过漫游点经纬度来校准
  24259. //但这时候panos还没加载。。。。
  24260. let sceneCode = ...从url中解析
  24261. Potree.loadDatasets((data)=>{ //获取datasetId
  24262. let originDataset = data.find(e=>e.sceneCode == sceneCode);//只加载初始数据集
  24263. Potree.loadPanos(originDataset.datasetId,()=>{
  24264. shouldPos = 获取坐标 data[0].location经纬度
  24265. model.position.add(new THREE.Vector3().subVectors(shouldPos, model.panos[0].position))
  24266. })
  24267. }, sceneCode, (e)=>{
  24268. console.log(e)
  24269. } , prop.prefix)
  24270. } */
  24271. }
  24272. }
  24273. }
  24274. }
  24275. }
  24276. if (model.fileType == 'shp') {
  24277. if (model.prjNotSure) {
  24278. MergeEditor.moveBoundCenterTo(model, new Vector3()); //因为不确定坐标类型,而点坐标可能几万米,所以放原点好一些
  24279. }
  24280. model.hasLonLat = true;
  24281. }
  24282. MergeEditor.setModelBtmHeight(model, 0); // 离地高度为0 (因为不想在地图下方所以高程不管了,都在地面上即可)
  24283. if (model.hasLonLat) {
  24284. model.lonLatPos = model.position.clone();
  24285. model.lonLatRot = model.rotation.clone();
  24286. }
  24287. }
  24288. if (prop.position) {
  24289. if (prop.position.x != 0 || prop.position.y != 0 || prop.position.z != 0) {
  24290. //移动过后使用移动后的坐标
  24291. model.position.copy(prop.position);
  24292. } else {//用户没设置位置(首次添加后没按保存)
  24293. }
  24294. }
  24295. if (prop.rotation && (prop.rotation.x != 0 || prop.rotation.y != 0 || prop.rotation.z != 0)) {
  24296. //model.rotation.setFromVector3(prop.rotation)
  24297. model.rotation.copy(prop.rotation);
  24298. }
  24299. if (prop.scale != void 0) {
  24300. model.scale.set(prop.scale, prop.scale, prop.scale);
  24301. }
  24302. if (model.isPointcloud) {
  24303. model.renderOrder = Potree.config.renderOrders.model; //same as glb
  24304. }
  24305. if (Potree.settings.maintainBtmZ) {
  24306. //transform --------维持离地高度和中心点的版本(local ver)
  24307. var updateBound = () => {
  24308. model.updateMatrixWorld();
  24309. viewer.updateModelBound();
  24310. };
  24311. var maintainBtmZAndCenter = () => {
  24312. MergeEditor.maintainBoundXY(model);
  24313. MergeEditor.setModelBtmHeight(model);
  24314. updateBound();
  24315. model.dispatchEvent('transformChanged');
  24316. };
  24317. model.addEventListener('position_changed', () => {
  24318. updateBound();
  24319. MergeEditor.getBoundCenter(model); //更新boundcenter
  24320. MergeEditor.computeBtmHeight(model);
  24321. if (prop.bottomRange && (model.btmHeight > prop.bottomRange.max || model.btmHeight < prop.bottomRange.min)) {
  24322. model.btmHeight = MathUtils.clamp(model.btmHeight, prop.bottomRange.min, prop.bottomRange.max);
  24323. MergeEditor.setModelBtmHeight(model);
  24324. updateBound();
  24325. }
  24326. model.dispatchEvent('transformChanged');
  24327. });
  24328. model.addEventListener("rotation_changed", maintainBtmZAndCenter);
  24329. model.addEventListener("scale_changed", maintainBtmZAndCenter);
  24330. model.addEventListener('transformChanged', () => {
  24331. MergeEditor.modelTransformCallback(model);
  24332. });
  24333. //离地高度只是boundingbox在transform后的最低点的高度,而非模型transform后的最低点的高度,所以旋转过后看起来不太准确
  24334. } else {
  24335. //transform --------维持中心点的版本
  24336. var _updateBound = () => {
  24337. model.updateMatrixWorld();
  24338. viewer.updateModelBound();
  24339. };
  24340. var maintainCenter = e => {
  24341. //MergeEditor.maintainBoundXY(model)
  24342. e.by2d || model.atPath || MergeEditor.maintainBoundCenter(model);
  24343. _updateBound();
  24344. model.dispatchEvent({
  24345. type: 'transformChanged',
  24346. byControl: e.byControl
  24347. });
  24348. };
  24349. model.addEventListener('position_changed', e => {
  24350. //要先发送position_changed再其他
  24351. _updateBound();
  24352. MergeEditor.getBoundCenter(model); //更新boundcenter
  24353. model.dispatchEvent({
  24354. type: 'transformChanged',
  24355. byControl: e.byControl
  24356. });
  24357. });
  24358. model.addEventListener("rotation_changed", maintainCenter);
  24359. model.addEventListener("scale_changed", maintainCenter);
  24360. model.addEventListener('transformChanged', () => {
  24361. MergeEditor.modelTransformCallback(model);
  24362. });
  24363. }
  24364. model.updateMatrixWorld();
  24365. viewer.updateModelBound();
  24366. MergeEditor.getBoundCenter(model); //初始化
  24367. //model.lastMatrixWorld = model.matrixWorld.clone()
  24368. model.lastMatrixWorld = new Matrix4();
  24369. MergeEditor.modelTransformCallback(model, true);
  24370. prop.scale != void 0 && model.isPointcloud && model.changePointSize(); //有的被缩放的很小导致testMaxNodeLevel时距离较远时被return 但点云过大急需changesize
  24371. done && done(model); // 先发送成功,因为2d界面会随机执行changePosition等初始化,然后这边再将模型移到中心地面上
  24372. if (prop.isFirstLoad) {
  24373. if (model.hasLonLat || !moveModelWhenLoad) {
  24374. //setTimeout(()=>{MergeEditor.focusOn(model)} , 1) //由2d控制
  24375. } else {
  24376. MergeEditor.moveBoundCenterTo(model, new Vector3(0, 0, 0));
  24377. }
  24378. MergeEditor.setModelBtmHeight(model, 0); //初始加载设置离地高度为0
  24379. if (prop.mode != 'single') {
  24380. //如果不是模型展示页,模型会随着鼠标位置移动
  24381. modelEditing = model;
  24382. if (!model.hasLonLat && moveModelWhenLoad) {
  24383. viewer.addEventListener('global_mousemove', moveModel);
  24384. viewer.addEventListener('global_click', confirmPos, {
  24385. importance: 3
  24386. });
  24387. }
  24388. }
  24389. model.dispatchEvent("position_changed");
  24390. } else {
  24391. //MergeEditor.setModelBtmHeight(model, prop.bottom || 0) //默认离地高度为0
  24392. modelEditing = null;
  24393. }
  24394. MergeEditor.modelAdded(model);
  24395. };
  24396. if (prop.type == 'obj' || prop.type == 'glb') {
  24397. var callback = object => {
  24398. object.traverse(e => e.material && (e.material.transparent = true));
  24399. loadDone(object);
  24400. };
  24401. var info = {
  24402. prop,
  24403. fileType: prop.type,
  24404. id: prop.id,
  24405. unlit: prop.unlit,
  24406. url: prop.url,
  24407. name: prop.title
  24408. };
  24409. viewer.loadModel(info, callback, onProgress, onError);
  24410. } else if (prop.type == 'osgb' || prop.type == 'b3dm') {
  24411. //3d tiles
  24412. var _callback = object => {
  24413. loadDone(object);
  24414. };
  24415. viewer.loadModel({
  24416. fileType: '3dTiles',
  24417. id: prop.id,
  24418. name: prop.title,
  24419. maximumScreenSpaceError: prop.maximumScreenSpaceError,
  24420. url: prop.url,
  24421. is4dkkModel: prop.is4dkkModel,
  24422. side: fromNew ? 1 : 0
  24423. }, _callback, onprogress);
  24424. } else if (prop.type == 'shp') {
  24425. var _callback2 = object => {
  24426. loadDone(object);
  24427. };
  24428. viewer.loadModel({
  24429. fileType: 'shp',
  24430. id: prop.id,
  24431. name: prop.title,
  24432. url: prop.url
  24433. }, _callback2, onprogress);
  24434. } else if (prop.type == '3dgs') {
  24435. var _callback3 = object => {
  24436. loadDone(object);
  24437. };
  24438. viewer.loadModel({
  24439. fileType: '3dgs',
  24440. id: prop.id,
  24441. name: prop.title,
  24442. url: prop.url
  24443. }, _callback3, onprogress);
  24444. } else if (prop.type == 'media') {
  24445. var _callback4 = object => {
  24446. prop.model.add(object);
  24447. loadDone(object);
  24448. };
  24449. viewer.loadModel(Object.assign(prop, {
  24450. fileType: 'overlay'
  24451. }), _callback4, onprogress);
  24452. //Potree.addModel('photo') or Potree.addModel('video')
  24453. } else {
  24454. prop.url instanceof Array && (prop.url = prop.url[0]); //deal bug
  24455. var cloudPrefix = Potree.settings.urls.getPrefix(1, prop);
  24456. Potree.loadPointCloudScene(prop.url, prop.type, prop.modelId, prop.title, pointcloud => {
  24457. {
  24458. pointcloud.matrixAutoUpdate = true;
  24459. if (pointcloud.hasLonLat) {
  24460. pointcloud.matrix.decompose(pointcloud.position, pointcloud.quaternion, pointcloud.scale); //将数据集的经纬度和旋转应用到rotation和position (注意position和translateUser并不一样)
  24461. } else if (!prop.isFirstLoad) {
  24462. //点云一般加载后position都不是0, 但后台初始化为0所以先归零要不然撤销后容易错
  24463. pointcloud.position.set(0, 0, 0);
  24464. }
  24465. }
  24466. if (Potree.settings.mergeType2 && pointcloud.datasetData) {
  24467. Potree.loadPanos(pointcloud.datasetData.id, data => {
  24468. viewer.images360.addPanoData(data, pointcloud);
  24469. viewer.images360.loadDone();
  24470. viewer.scene.add360Images(viewer.images360);
  24471. loadDone(pointcloud);
  24472. }, prop.url);
  24473. } else {
  24474. loadDone(pointcloud);
  24475. }
  24476. }, onError, prop.prefix, cloudPrefix);
  24477. }
  24478. };
  24479. return {
  24480. THREE: THREE$1
  24481. };
  24482. }
  24483. var changeLog = () => {
  24484. var textarea = document.createElement('textarea');
  24485. textarea.id = "consoleLog";
  24486. textarea.style.width = '160px';
  24487. textarea.style.height = '200px';
  24488. textarea.style.position = 'fixed';
  24489. textarea.style.left = 0;
  24490. textarea.style.bottom = '50px';
  24491. textarea.style['z-index'] = 9999;
  24492. textarea.style.color = 'black';
  24493. textarea.style.opacity = 0.9;
  24494. textarea.style['font-size'] = '12px';
  24495. textarea.style['backgroundColor'] = '#ffffff';
  24496. document.getElementsByTagName("body")[0].appendChild(textarea);
  24497. var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"];
  24498. var exchange = function exchange(o) {
  24499. console["old" + o] = console[o];
  24500. console[o] = function () {
  24501. var args = Array.from(arguments);
  24502. console["old" + o].apply(this, arguments);
  24503. var t = document.getElementById("consoleLog").innerHTML;
  24504. var str = '';
  24505. args.forEach(a => {
  24506. str += a + ' ';
  24507. });
  24508. document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
  24509. };
  24510. };
  24511. for (var i = 0; i < list.length; i++) {
  24512. exchange(list[i]);
  24513. }
  24514. };
  24515. //screenshotTube({wallWidths:[1,0.5]}, 500) http://192.168.0.59:1234/examples/4dkk.html?m=SG-t-h8pBKI9M0WF#/
  24516. //隧道截图 暂时测试时要等当前全景图都加载完。要保持放大才会4k
  24517. window.screenshotTube = function () {
  24518. var width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2048;
  24519. var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1024;
  24520. var disToWall = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1.2;
  24521. var compress = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.7;
  24522. var initDir = arguments.length > 4 ? arguments[4] : undefined;
  24523. if (width.wallWidths) {
  24524. //根据其他参数计算
  24525. var wallWidths = width.wallWidths;
  24526. //disToWall : 相机到墙面的距离 1-2m 。 根据计算,截图width/height = 墙长/墙高 = half墙长 / camDis
  24527. //let longWallWidth = Math.max(wallWidths[0],wallWidths[1])
  24528. //let fullWidth = height * longWallWidth / disToWall
  24529. //let r = fullWidth / 2 / longWallWidth //比率
  24530. var r = height / 2 / disToWall;
  24531. width = [r * wallWidths[0], r * wallWidths[1]];
  24532. }
  24533. var offsetX;
  24534. if (width instanceof Array) {
  24535. //相机偏移,左右墙长度不同
  24536. var widths = width;
  24537. width = widths[0] + widths[1]; //相机左、右宽度
  24538. offsetX = (widths[1] - widths[0]) / 2;
  24539. }
  24540. var dataUrls = [];
  24541. var camera = viewer.mainViewport.camera;
  24542. var oldFov = camera.fov;
  24543. viewer.setFOV(90);
  24544. if (initDir) {
  24545. initDir = new Vector3(initDir.x, initDir.y, 0); //水平、垂直于墙面
  24546. viewer.mainViewport.view.direction = initDir; //初始角度
  24547. }
  24548. var yaw = viewer.mainViewport.view.yaw;
  24549. //let camDirs = [{yaw, pitch:0, offsetX}, {yaw:yaw + Math.PI, pitch:Math.PI/2, offsetX:-offsetX}, {yaw:yaw + Math.PI, pitch:0, offsetX:-offsetX}]
  24550. var camDirs = [{
  24551. yaw: yaw + Math.PI,
  24552. pitch: 0,
  24553. offsetX: -offsetX
  24554. }, {
  24555. yaw,
  24556. pitch: Math.PI / 2,
  24557. offsetX
  24558. }, {
  24559. yaw,
  24560. pitch: 0,
  24561. offsetX
  24562. }];
  24563. var screenshot = curIndex => {
  24564. viewer.mainViewport.view.yaw = camDirs[curIndex].yaw;
  24565. viewer.mainViewport.view.pitch = camDirs[curIndex].pitch;
  24566. if (offsetX) {
  24567. camera.setViewOffset(width, height, camDirs[curIndex].offsetX, 0, width, height);
  24568. }
  24569. var {
  24570. getImagePromise,
  24571. finishPromise
  24572. } = viewer.startScreenshot({
  24573. type: 'default',
  24574. hideMarkers: true
  24575. }, width, height);
  24576. finishPromise.done(_ref2 => {
  24577. var {
  24578. dataUrl
  24579. } = _ref2;
  24580. console.log('get', curIndex);
  24581. dataUrls.push(dataUrl);
  24582. if (curIndex == 2) {
  24583. //finish
  24584. dataUrls = [dataUrls.map(e => {
  24585. return {
  24586. dataUrl: e,
  24587. width,
  24588. height
  24589. };
  24590. })];
  24591. dataUrls[0][0].rot180 = true;
  24592. Potree.Utils.combineImgs(dataUrls, compress).then(dataUrlWhole => {
  24593. Potree.Common.downloadFile(dataUrlWhole, '隧道' + viewer.images360.currentPano.id + '.png');
  24594. viewer.setFOV(oldFov);
  24595. camera.clearViewOffset();
  24596. });
  24597. } else {
  24598. screenshot(++curIndex);
  24599. }
  24600. });
  24601. };
  24602. if (viewer.images360.latestRequestMode == 'showPanos') {
  24603. screenshot(0);
  24604. } else {
  24605. Potree.settings.displayMode = 'showPanos';
  24606. viewer.images360.addEventListener('endChangeMode', screenshot.bind(_this, 0), {
  24607. once: true
  24608. });
  24609. }
  24610. };
  24611. /*
  24612. 坐标转换问题:
  24613. 由于控制点可以随便输入,所以本地和地理位置的转换也是可拉伸的。而navvis的转换是等比由中心展开,
  24614. 所以对比两种转化方式时误差较大。
  24615. 另外地理注册控制点是有参考数据集的,若参考数据集和我放置在0,0,0的数据集一致,就可直接使用,否则要转换。
  24616. ---------
  24617. lonlat和空间坐标其实并非线性关系,因为lonlat其实是角度。当两个数据集在地球两端时,它们之间的夹角都相差180度了。
  24618. 所以若要准确展示的话,需要将点云内所有物体,如漫游点,都先获取lonlat再去算local。或者直接将点云整体的transformMatrix考虑上在地球上相对于初始数据集的偏转。
  24619. 支持ctrl+z、ctrl+Y 撤销回退的页面有:
  24620. 测量、土方量、空间模型 这三个页面的点线拖拽;点云裁剪、点云下载中的裁剪 的框; 点云编辑的变换; 数据集校准;
  24621. (所有数据一旦删除则无效 )
  24622. 其他快捷键:
  24623. 按alt鼠标滚轮或WS键放慢。
  24624. 测量or土方量: 按Alt键可以平行拖拽点。&dragPolyBeyondPoint 后缀则可平行拖拽到无点云区域 。
  24625. 按M键拖拽点可以复制出当前点
  24626. 点云按空格键+左键拖拽场景,可以不改相机位置的旋转视角
  24627. */
  24628. //xzw add
  24629. var labelorder = 5;
  24630. var config$1 = {
  24631. //配置参数 不可修改
  24632. displayMode: {
  24633. showPointCloud: {
  24634. atPano: {
  24635. showPoint: true,
  24636. showSkybox: false,
  24637. pointUsePanoTex: false
  24638. },
  24639. transition: {
  24640. showPoint: true,
  24641. showSkybox: false,
  24642. pointUsePanoTex: false
  24643. },
  24644. canLeavePano: true //是否能离开pano位置
  24645. },
  24646. showPanos: {
  24647. atPano: {
  24648. showPoint: false,
  24649. showSkybox: true,
  24650. pointUsePanoTex: false
  24651. },
  24652. transition: {
  24653. //showPoint: true,
  24654. showSkybox: true
  24655. //pointUsePanoTex: true //是否使用全景贴图
  24656. },
  24657. canLeavePano: false
  24658. },
  24659. showBoth: {
  24660. atPano: {
  24661. showPoint: true,
  24662. showSkybox: true,
  24663. pointUsePanoTex: false //?
  24664. },
  24665. transition: {
  24666. showPoint: true,
  24667. showSkybox: true,
  24668. pointUsePanoTex: true
  24669. },
  24670. canLeavePano: true //是否能离开pano位置 离开后自动变为showPointCloud
  24671. },
  24672. //test:
  24673. pointUsePanoTex: {
  24674. //---静止时调点云
  24675. atPano: {
  24676. showPoint: true,
  24677. showSkybox: false,
  24678. pointUsePanoTex: true
  24679. },
  24680. transition: {
  24681. showPoint: true,
  24682. showSkybox: true,
  24683. pointUsePanoTex: true //是否使用全景贴图
  24684. },
  24685. canLeavePano: false
  24686. }
  24687. },
  24688. urls: {
  24689. //prefix: //当前网站域名
  24690. prefix1: 'https://laser-oss.4dkankan.com',
  24691. //点云oss
  24692. prefix2: 'https://testlaser.4dkankan.com',
  24693. prefix3: 'https://4dkk.4dage.com',
  24694. //全景图oss
  24695. prefix4: 'https://uat-laser.4dkankan.com',
  24696. //测试服 线上当前网站接口域名
  24697. prefix5: 'https://laser.4dkankan.com/backend',
  24698. //正式服 线上当前网站接口域名
  24699. prefix6: 'https://mix3d.4dkankan.com/backend',
  24700. //融合
  24701. prefix7: 'https://xfhd.4dkankan.com/backend',
  24702. //融合
  24703. handlePrefix: prefix => {
  24704. //去掉最后一个/, 否则国外的一些服务器不能访问 //
  24705. if (prefix.slice(-1) == '/') {
  24706. prefix = prefix.slice(0, prefix.length - 1);
  24707. }
  24708. return prefix;
  24709. },
  24710. getName(num) {
  24711. var name;
  24712. if (num === 1) {
  24713. name = 'laserOSSRoot';
  24714. } else if (num === 3) {
  24715. name = 'panoOSSRoot';
  24716. } else if (num === 8) {
  24717. name = 'panoRoot';
  24718. }
  24719. return name;
  24720. },
  24721. setPrefix(num, url) {
  24722. //本地版融合有经过次设置
  24723. this['prefix' + num] = url;
  24724. this[this.getName(num)] = url;
  24725. },
  24726. getPrefix(num, object) {
  24727. var prefix,
  24728. name = this.getName(num);
  24729. var getFromModel = () => {
  24730. var _ref;
  24731. var prop = (_ref = object.props || object) === null || _ref === void 0 ? void 0 : _ref.raw;
  24732. return prop && prop[name];
  24733. };
  24734. prefix = this[name] || getFromModel() || this['prefix' + num];
  24735. return prefix;
  24736. },
  24737. templates: {}
  24738. },
  24739. transitionsTime: {
  24740. flyMinTime: 650,
  24741. // 毫秒/米
  24742. flytimeDistanceMultiplier: 120
  24743. },
  24744. view: {
  24745. fov: 70,
  24746. //navvis:50
  24747. near: 0.05,
  24748. // too small will result in z-fighting
  24749. far: 10000
  24750. },
  24751. map: {
  24752. //mapViewer
  24753. mapHeight: -1000,
  24754. //要比点云低。最低
  24755. cameraHeight: 1000 //最高 ,注意(如sitemodel)其他的物体不能超过这个高度
  24756. },
  24757. minNodeSize: 30,
  24758. // perspectiveCamera允许加载的node的最小可见像素宽度。越大越省性能
  24759. tiles3DMaxMemory: 200,
  24760. //M. 最大支持3dTiles的内存大小 超出会崩溃。 改太小太大都会卡,太大崩溃
  24761. //崩溃历史: 200罗敏电脑崩
  24762. pointDensity: {
  24763. magnifier: {
  24764. maxLevelPercent: 1,
  24765. pointBudget: 1 * 1000 * 1000,
  24766. //至少显示这么多
  24767. minNodeSize: 5 //pick时调高精度
  24768. },
  24769. panorama: {
  24770. //显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
  24771. maxLevelPercent: 0.6,
  24772. pointBudget: /* 4*1000*1000// */browser.isMobile() ? 0.2 * 1000 * 1000 : 0.4 * 1000 * 1000,
  24773. //点云总最大数
  24774. minNodeSize: 100
  24775. },
  24776. fourViewports: {
  24777. //分四屏时防止卡顿
  24778. maxLevelPercent: 0.9,
  24779. pointBudget: 3 * 1000 * 1000,
  24780. // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
  24781. minNodeSize: 70
  24782. },
  24783. fourViewportsMain: {
  24784. //分四屏时防止卡顿
  24785. maxLevelPercent: 0.9,
  24786. pointBudget: 3 * 1000 * 1000,
  24787. // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
  24788. minNodeSize: 70
  24789. },
  24790. panoEdit: {
  24791. maxLevelPercent: 1,
  24792. //在远处时由于pointBudget限制而展示稀疏,凑近时就变为最高质量了
  24793. pointBudget: 4 * 1000 * 1000,
  24794. //要使点云达到200个以上时还不卡
  24795. percentByUser: true,
  24796. minNodeSize: 80 //点云多的话远处的尽量就不可见吧
  24797. },
  24798. low: {
  24799. //highPerformance
  24800. maxLevelPercent: 0.4,
  24801. //最小为0
  24802. percentByUser: true,
  24803. //如果用户定义了percent,使用用户的
  24804. pointBudget: browser.isMobile() ? 1 * 1000 * 1000 : 2 * 1000 * 1000,
  24805. minNodeSize: 40 / window.devicePixelRatio
  24806. },
  24807. middle: {
  24808. //balanced //不同场景相同级别所产生的numVisibleNodes和numVisiblePoints不同,如果分层比较细,可能要到level8才能看清,那么level5看到的点就很大且很少,如隧道t-e2Kb2iU
  24809. maxLevelPercent: 0.7,
  24810. percentByUser: true,
  24811. pointBudget: browser.isMobile() ? 1.5 * 1000 * 1000 : 3.5 * 1000 * 1000,
  24812. minNodeSize: 30 / window.devicePixelRatio
  24813. },
  24814. high: {
  24815. //highQuality
  24816. maxLevelPercent: 1,
  24817. percentByUser: true,
  24818. pointBudget: browser.isMobile() ? 3 * 1000 * 1000 : 6 * 1000 * 1000,
  24819. //原本最高是8,但是大部分电脑都太卡了,降
  24820. minNodeSize: 20 / window.devicePixelRatio //手机上因为像素点小,远一点的时候更需要加载密集的点云。(没事,有pointBudget限制着,会先从近处加载高级node,再远就不加载了)
  24821. },
  24822. screenshot: {
  24823. maxLevelPercent: 1,
  24824. pointBudget: browser.isMobile() ? 4 * 1000 * 1000 : 10 * 1000 * 1000,
  24825. //一般只有电脑需要截图,手机的加载多会崩
  24826. minNodeSize: 40 / window.devicePixelRatio
  24827. },
  24828. screenshot2: {
  24829. maxLevelPercent: 1,
  24830. pointBudget: browser.isMobile() ? 8 * 1000 * 1000 : 15 * 1000 * 1000,
  24831. minNodeSize: 20 / window.devicePixelRatio
  24832. },
  24833. ultraHigh: {
  24834. maxLevelPercent: 1,
  24835. pointBudget: 20 * 1000 * 1000,
  24836. minNodeSize: 10 / window.devicePixelRatio
  24837. }
  24838. //数值由testLevelSteps得来,其中nodeMaxLevel为2时,low和middle的都是1,如果真有这么低的点云就单独处理下。
  24839. //多个viewport尽量保证pointBudget一样,或者pointBudget不能太低于所需,否则会反复加载了又清除
  24840. },
  24841. clip: {
  24842. color: '#FFC266' //map
  24843. },
  24844. measure: {
  24845. color: '#00C8AF',
  24846. default: {
  24847. color: "#64C8BB",
  24848. //"#00c7b2",
  24849. opacity: 0.7
  24850. },
  24851. highlight: {
  24852. color: '#00C8AF',
  24853. //"#00c7b2",
  24854. opacity: 1,
  24855. labelOpacity: 0.7 //1会挡住线和端点
  24856. },
  24857. guide: {
  24858. color: '#FFFFFF',
  24859. opacity: 0.8
  24860. },
  24861. backColor: '#333333',
  24862. lineWidth: 3,
  24863. textColor: "#000000",
  24864. //"#FFFFFF"
  24865. mulLabelHideFaraway: false,
  24866. // 多折线根据远近显示label
  24867. adsorptMinDis: 30,
  24868. //最小吸附距离(像素)
  24869. showName: true
  24870. },
  24871. material: {
  24872. //初始化
  24873. pointSize: 0.1,
  24874. realPointSize: 0.1,
  24875. //实际上的ui滑动条默认大小(兼容旧的版本)
  24876. minSize: 0.1,
  24877. maxSize: 10000,
  24878. pointSizeType: 'ATTENUATED',
  24879. //'ADAPTIVE'//'ADAPTIVE' \ FIXED //ADAPTIVE的在小房间里大小会不太匹配,但在远景似乎更好
  24880. /*
  24881. ATTENUATED : 衰减 真实大小,靠近时感觉是点云一点点变多,缝隙变小
  24882. ADAPTIVE: 自适应 大小根据level变化,越高越小。靠近时感觉点云由大慢慢细分成小份。这个感觉更佳但是navvis为何不用这个
  24883. */
  24884. absolutePanoramaSize: 1.3,
  24885. //全景漫游时的size 是fixed的模式
  24886. //sizeAtPanoRtEDL : 2000,
  24887. pointColor: '#ffffff'
  24888. //sizeAddAtPanoRtEDL : 0.5, //全景模式静止时的size
  24889. //ADAPTIVE : 字会失真扭曲
  24890. //'ATTENUATED' 往旁边看有缝隙、点在浮动
  24891. },
  24892. skyboxBgWidth: 100,
  24893. renderLayers: {
  24894. //渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。(数字不能太大)
  24895. sceneObjects: 0,
  24896. //default
  24897. skybox: 1,
  24898. pointcloud: 2,
  24899. model: 3,
  24900. monitor: 4,
  24901. light: 5,
  24902. //measure:4,
  24903. //tags:5,
  24904. magnifier: 6,
  24905. magnifierContent: 7,
  24906. volume: 8,
  24907. transformationTool: 9,
  24908. map: 10,
  24909. mapObjects: 11,
  24910. //default
  24911. bothMapAndScene: 12,
  24912. onlyMapVisi: 13,
  24913. //只能mapViewer可见
  24914. mapUnvisi: 14,
  24915. //只有mapViewer不可见
  24916. sideVisi: 15,
  24917. //只有侧面可见
  24918. bg: 16,
  24919. bg2: 17,
  24920. layer1: 18,
  24921. // 备用1
  24922. layer2: 19,
  24923. // 备用2
  24924. dontIntersect: 20
  24925. },
  24926. renderOrders: {
  24927. //会影响到绘制、pick时的顺序。
  24928. line: 3,
  24929. reticule: 5,
  24930. measureMarker: 6,
  24931. measureLabelSub: 7,
  24932. measureLabel: 8,
  24933. sorptionSign: 10,
  24934. model: 10,
  24935. path: {
  24936. label: labelorder,
  24937. edge: labelorder,
  24938. line: labelorder,
  24939. //会被edge遮住一些,不过无碍
  24940. marker: labelorder + 1 //cover edge
  24941. },
  24942. tag: {
  24943. label: labelorder,
  24944. spot: labelorder,
  24945. line: labelorder - 1,
  24946. onMesh: {
  24947. line: labelorder,
  24948. spot: labelorder - 1
  24949. }
  24950. },
  24951. magnifier: 50
  24952. /*
  24953. renderOrder:
  24954. 理想情况是大家渲染层级都一样,用真实的遮挡情况。(depthTest为false的话会three会自动根据深度调整渲染顺序, 只是随着角度变化常有错) 但有时候为了处理特殊情况,如希望热点的线永在热点之后不穿出,需要增加层级。但热点和热点之间、热点和其他物品是平等的,而降低的层级总被远处的高层级遮挡。
  24955. 因此无论何时尽量减少层级数目。如有必要,可临时将容易被忽视穿帮的线条设置为低层级。
  24956. */
  24957. },
  24958. siteModel: {
  24959. names: {
  24960. 'building': '建筑',
  24961. 'floor': '楼层',
  24962. 'room': '房间'
  24963. },
  24964. floorHeightDefault: 5 //一层楼的高度
  24965. },
  24966. panosEdit: {},
  24967. tiling: {
  24968. panoPreRenderRepeatDelay: 2500,
  24969. panoPreRenderDelay: 500,
  24970. preRenderTourPanos: browser.valueFromHash("tileprerender", 0),
  24971. tilingFlagNames: ["usetiles", "tiles"],
  24972. maxNavPanoQuality: browser.valueFromHash("maxtileq", null),
  24973. maxZoomPanoQuality: browser.valueFromHash("maxztileq", null),
  24974. overlayStyle: browser.valueFromHash("tileoverlay", 0),
  24975. uploadIntervalDelay: browser.valueFromHash("tileupdelay", 10),
  24976. initialIntervalDelay: browser.valueFromHash("itiledelay", 0),
  24977. maxNonBaseUploadsPerFrame: browser.valueFromHash("maxnbtpf", 1),
  24978. maxBaseUploadsPerFrame: browser.valueFromHash("maxbtpf", 6),
  24979. customCompression: browser.valueFromHash("tilecustcomp", 0),
  24980. mobileHighQualityOverride: !1,
  24981. allowUltraHighResolution: !0
  24982. },
  24983. navigation: {
  24984. panoScores: !1,
  24985. mouseDirection: !0,
  24986. filterStrictness: .75,
  24987. angleFactor: -30,
  24988. directionFactor: 10,
  24989. distanceFactor: -1,
  24990. optionalityFactor: 3
  24991. },
  24992. axis: {
  24993. 'x': {
  24994. color: '#ea3f3f' /* '#d0021b' */ /* 'red' */
  24995. },
  24996. 'y': {
  24997. color: '#86c215' /* '#86c542' */ /* 'green' */
  24998. },
  24999. 'z': {
  25000. color: '#3396f8' /* '#3399c8' */ /* 'blue' */
  25001. },
  25002. 'xyz': {
  25003. color: '#ccc'
  25004. }
  25005. },
  25006. shelterMargin: 0.15,
  25007. //多少米内不算遮挡 (有的场景深度图不准,和点云差别蛮大如SG-t-24F0iT3pKAO)
  25008. highQualityMaxZoom: 2,
  25009. ultraHighQualityMaxZoom: 3,
  25010. panoFieldRadius: 10,
  25011. //当前位置多远范围内可以切全景模式
  25012. clickMaxDragDis: 3,
  25013. clickMaxPressTime: 200,
  25014. //ms
  25015. doubleClickTime: 300,
  25016. //双击间隔时间
  25017. testNodeCount1: browser.isMobile() ? 6 : 4,
  25018. //testMaxNode次数达到这个数字时,changePointSize才使用nodeMaxLevel。 (调试时比较卡,在线上实际只需要3)
  25019. background: '#232323',
  25020. mapBG: /* '#232323', */'#F5F5F5',
  25021. //地图的clearColor
  25022. pickFrontPointRatio: 50,
  25023. colors: {
  25024. //from navvis
  25025. red: [213, 0, 0],
  25026. pink: [197, 17, 98],
  25027. purple: [170, 0, 255],
  25028. "deep purple": [98, 0, 234],
  25029. blue: [41, 98, 255],
  25030. "light blue": [0, 145, 234],
  25031. cyan: [0, 184, 212],
  25032. teal: [0, 191, 165],
  25033. green: [0, 200, 83],
  25034. "light green": [100, 221, 23],
  25035. lime: [174, 234, 0],
  25036. yellow: [255, 214, 0],
  25037. amber: [255, 171, 0],
  25038. orange: [255, 109, 0],
  25039. "deep orange": [255, 61, 0]
  25040. },
  25041. maxLRUPoints: 40e6,
  25042. depthTexUVyLimit: 0.141,
  25043. // 在这个范围内是没有深度的,从图片算的0.14003, 设置为稍大于这个数值
  25044. maxSplatCount: 2000000 //整个网页最大支持显示多少个
  25045. //neighbourPath:'data/1111/extraNeighbours.js' //本地版手动额外配置,权重最高
  25046. };
  25047. config$1.OrthoCameraLimit = {
  25048. standard: {
  25049. zoom: {
  25050. min: 0.0004,
  25051. max: 500
  25052. },
  25053. //如果camera缩太小,地图会因为数字边界问题而扭曲
  25054. latPad: 20,
  25055. xBound: [-4e6, 4e6]
  25056. },
  25057. expand: {
  25058. zoom: {
  25059. min: 0.0004,
  25060. max: 500
  25061. },
  25062. //如果camera缩太小,地图会因为数字边界问题而扭曲
  25063. latPad: 20,
  25064. xBound: [-6e6, 6e6]
  25065. }
  25066. };
  25067. /* 显示模式:
  25068. 1只显示点云: 滚轮为前进后退,方向键可以行走。进入漫游点时自动变为混合(这样全景可以弥补缝隙),过渡时只显示点云。
  25069. 2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
  25070. 3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
  25071. */
  25072. window.testLevelSteps = function (steps) {
  25073. //[0.4,0.7,1]
  25074. if (!steps) {
  25075. var s = Potree.config.pointDensity;
  25076. steps = [s.low.maxLevelPercent, s.middle.maxLevelPercent, s.high.maxLevelPercent];
  25077. }
  25078. var max = 1;
  25079. while (++max <= 12) {
  25080. var r1 = steps.map(e => e * max);
  25081. var r2 = steps.map(e => Math.round(e * max));
  25082. console.log("\u5F53nodeMaxLevel\u4E3A".concat(max, "\u65F6\uFF0C\u6BCF\u4E00\u7EA7\u7684level\u5206\u522B\u4E3A").concat(r2, ", (\u5C0F\u6570\uFF1A").concat(r1, ")"));
  25083. }
  25084. console.log('请检查每一层的三个level是否有重复');
  25085. };
  25086. function getPrefix() {
  25087. var u = window.location.href.split('//');
  25088. var v = u[1].split('/');
  25089. return v[0];
  25090. }
  25091. var isTest = browser.urlHasValue('test');
  25092. var settings = {
  25093. //设置 可修改
  25094. editType: '',
  25095. number: '',
  25096. //场景序号
  25097. originDatasetId: '',
  25098. //场景原本的数据集id,应该就是数据集第一个吧
  25099. isOfficial: false,
  25100. webSite: 'testdata',
  25101. //正式:'datav1', //不同环境对应的静态文件的地址不同
  25102. // language : "zh"
  25103. isLocal: false,
  25104. //是否本地 局域网版本
  25105. libsUrl: '../libs/',
  25106. displayMode: '',
  25107. isTest,
  25108. prefix: getPrefix(),
  25109. maxLRUPoints: config$1.maxLRUPoints,
  25110. pointDensity: '',
  25111. UserPointDensity: '',
  25112. //pointDensity会随着进入不同的模块而自动改变,UserPointDensity记录了用户的设置
  25113. UserDensityPercent: null,
  25114. //点云密度百分比
  25115. ifShowMarker: true,
  25116. //显示漫游点
  25117. floorplanType: {},
  25118. //平面图类型 'default' | 'diy' 不同数据集不同{datasetId:...}
  25119. floorplanEnable: false,
  25120. floorplanEnables: {},
  25121. floorplanRequests: {},
  25122. //开始加载了的
  25123. mapEnable: true,
  25124. //地图区域是否加载地图
  25125. cameraFar: config$1.view.far,
  25126. //相机最远范围 1-300
  25127. //limitFar: true, //是否使用setting的cameraFar来限制(如在点云裁剪时为false)
  25128. showPanoMesh: false,
  25129. //显示小球,
  25130. dblToFocusPoint: false,
  25131. //调试时如果需要双击飞向某个点云的点,就打开。此时不在漫游点的话单击将无法漫游。//因和单击漫游冲突
  25132. unableNavigate: false,
  25133. //进入如裁剪界面时 禁止漫游
  25134. sizeFitToLevel: false,
  25135. //当type为衰减模式时自动根据level调节大小。每长一级,大小就除以2
  25136. zoom: {
  25137. enabled: true,
  25138. min: 1,
  25139. max: config$1.highQualityMaxZoom
  25140. },
  25141. navConstantly: true,
  25142. navTileClass: /* browser.isMobile() ? '1k' : */'2k',
  25143. //默认加载到
  25144. tileClass: '4k',
  25145. //最高可达
  25146. /* loadTilesWhenUnfocus:false, //页面unfocus时也仍在加载tiles
  25147. loadPointsWhenUnfocus:true, //页面unfocus时也仍在加载点云 */
  25148. //initialShowPano:true
  25149. drawEntityData: false,
  25150. //包括marker、线
  25151. zoomFromPointert: {
  25152. //定点缩放(包括点云模式、全景模式、地图)
  25153. whenPanos: true,
  25154. whenPointCloud: true,
  25155. map: true
  25156. },
  25157. rotAroundPoint: true,
  25158. //点云模式是否能绕intersectPoint旋转
  25159. tourTestCameraMove: false,
  25160. //测试镜头时,不移动真实的镜头, 只移动frustum
  25161. cameraAniSmoothRatio: 20,
  25162. //镜头动画平滑系数,越高越平滑
  25163. urls: $.extend({}, config$1.urls, {
  25164. prefix: config$1.urls.prefix4 //主要使用的 是测试环境,根据不同工程更改
  25165. }),
  25166. useDepthTex: true,
  25167. //使用深度贴图,但不代表一定有(得到的intersect更快速准确和稳定) SS-t-7DUfWAUZ3V
  25168. //matUseDepth:false,
  25169. //panoEdit:
  25170. datasetsPanos: {},
  25171. //mergeModel:
  25172. boundAddObjs: false,
  25173. intersectOnObjs: false,
  25174. intersectWhenHover: true,
  25175. depTexLocBindDataset: true,
  25176. //是否在pano模式下,使用深度图得到intersect的话,改intersect能属于该pano所在的点云。也就相当于在全景模式下intersect的点属于该全景图
  25177. notAdditiveBlending: false,
  25178. //点云是否使用普通的blend, 否则会曝光过渡
  25179. precision: 2,
  25180. // 两位小数
  25181. unit: 'm',
  25182. useV4url: true,
  25183. //v4的全景图等路径不一样 scene_view_data
  25184. useRTskybox: true,
  25185. //直接使用rtEDL绘制到屏幕,当是全景模式时. 在降4倍时能给render节省1毫秒,gpu时间未测
  25186. useRTPoint: true,
  25187. //直接使用rtEDL绘制到屏幕,当是点云模式时。可以大大节省gpu时间。但有锯齿
  25188. pointEnableRT: false,
  25189. //点云模式时是否绘制到rtEDL。如果不需要遮挡效果就不需绘制
  25190. cloudSameMat: true,
  25191. //因为点云个数较多,就使用相同的材质,可见降低绘制速度(要保证所有点云的maxNodelevel一样,且要算出 material.spacing的平均值)
  25192. showCompass: false,
  25193. showAxis: isTest,
  25194. //testCube : true,
  25195. // moveToCenter:true, //针对数据集间隔很远的场景 dis>5000 容易抖动
  25196. tiles3DMaxMemory: config$1.tiles3DMaxMemory,
  25197. adsorption: false,
  25198. //测量时吸附点
  25199. pickFrontPointRatio: config$1.pickFrontPointRatio,
  25200. //默认pick点云时选中靠近镜头的点的偏向
  25201. dragPolyBeyondPoint: browser.urlHasValue('dragPolyBeyondPoint'),
  25202. //ctrlPolygon是否可以拖拽到没点云的地方
  25203. panoZoomByPointer: false,
  25204. //全景图是否定点缩放
  25205. areaAtNotPlane: false,
  25206. showNeighSetGui: browser.urlHasValue('neighGui'),
  25207. selectShowBox: true,
  25208. //fastTran: isTest
  25209. pathSmooth: true,
  25210. // window.location.href.includes('192.168.0.59') //true //smooth曲线, 非折线
  25211. maxClipFadeTime: 0.6,
  25212. showMap3d: browser.urlHasValue('map3d')
  25213. };
  25214. Potree.config = config$1;
  25215. Potree.settings = settings;
  25216. settings.isLocalhost = settings.prefix.includes('localhost:') || settings.prefix.includes('localhost:');
  25217. settings.isFormal = browser.urlHasValue('formal'); //正式环境 本地测试
  25218. if (settings.isFormal) {
  25219. settings.urls.prefix = settings.urls.prefix5;
  25220. settings.webSite = 'datav1';
  25221. }
  25222. /* let sid = 0
  25223. let getName = ()=>{
  25224. return sid ++
  25225. } */
  25226. class BasicMaterial extends ShaderMaterial {
  25227. constructor() {
  25228. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  25229. var color = o.color ? o.color instanceof Color ? o.color : new Color(o.color) : new Color("#FFF");
  25230. super(Object.assign({}, {
  25231. uniforms: {
  25232. color: {
  25233. type: 'v3',
  25234. value: color
  25235. },
  25236. map: {
  25237. type: 't',
  25238. value: o.map
  25239. },
  25240. opacity: {
  25241. type: 'f',
  25242. value: o.opacity == void 0 ? 1 : o.opacity
  25243. }
  25244. },
  25245. vertexShader: Shaders['basicTextured.vs'],
  25246. fragmentShader: Shaders['basicTextured.fs'],
  25247. defines: {
  25248. HasColor: ''
  25249. }
  25250. }, o));
  25251. //this.opacity = o.opacity == void 0 ? 1 : o.opacity
  25252. }
  25253. copy(source) {
  25254. super.copy(source);
  25255. //console.log('copy', source.name111, this.name111, !!source.map )
  25256. this.map = source.map;
  25257. return this;
  25258. }
  25259. set opacity(o) {
  25260. this.uniforms && (this.uniforms.opacity.value = o);
  25261. //this.transparent = o<1
  25262. }
  25263. get opacity() {
  25264. return this.uniforms.opacity.value;
  25265. }
  25266. set map(o) {
  25267. this.uniforms.map.value = o;
  25268. if (o) {
  25269. this.defines.HasMap = '';
  25270. } else {
  25271. delete this.defines.HasMap;
  25272. }
  25273. //可能需要needsUpdate
  25274. //console.log('hasMap', !!o, this.name111 )
  25275. }
  25276. get map() {
  25277. return this.uniforms.map.value;
  25278. }
  25279. }
  25280. window.showTileName = false;
  25281. //将原先的map写成3d的
  25282. var radius = 6378137; //.050041738 //地图mapSizeM / 2 / Math.PI
  25283. var makeSphere = false;
  25284. var earthCenter = new Vector3(0, 0, -radius);
  25285. var camDisToEarth = 0; //离地面的最近距离
  25286. function getPosOnEarth(vertice, transform) {
  25287. vertice = new Vector2().fromArray(transform.forward(vertice));
  25288. var disToZoroAxis = vertice.length(); //到(0,0,1)轴的距离
  25289. var z = Math.sqrt(radius * radius - disToZoroAxis * disToZoroAxis); //在(0,0,1)轴的垂足距离球心
  25290. return new Vector3(vertice.x, vertice.y, z - radius); //(0,0)处地表z为0,其余都在0之下
  25291. }
  25292. var texLoader$2 = new TextureLoader();
  25293. texLoader$2.crossOrigin = "anonymous";
  25294. var createErrorMaterial = function createErrorMaterial() {
  25295. var t = new MeshBasicMaterial({
  25296. transparent: !0,
  25297. depthWrite: !1,
  25298. depthTest: !0,
  25299. opacity: 1,
  25300. side: DoubleSide
  25301. });
  25302. return t.color = new Color(3355443), t;
  25303. };
  25304. var tempVector = new Vector3(),
  25305. //sharedata
  25306. face1 = new Face3(0, 1, 2),
  25307. face2 = new Face3(2, 3, 0),
  25308. errorMaterial = createErrorMaterial(),
  25309. uv00 = new Vector2(0, 0),
  25310. uv01 = new Vector2(0, 1),
  25311. uv10 = new Vector2(1, 0),
  25312. uv11 = new Vector2(1, 1),
  25313. face1UV = [uv00, uv10, uv11],
  25314. face2UV = [uv11, uv01, uv00];
  25315. var HALF_WORLD_SIZE = 21e6; //略大于半个周长(mapSizeM/2)
  25316. var MAX_VERTICAL_DIST = 2;
  25317. var MAX_VERTICAL_DIST_TO_BEST = 1;
  25318. var getSid = function () {
  25319. var sid = 0;
  25320. return function () {
  25321. return sid++;
  25322. };
  25323. }();
  25324. //高德坐标拾取工具 : https://lbs.amap.com/tools/picker
  25325. class MapLayer extends EventDispatcher {
  25326. // 包括了 MapLayerBase SceneLayer
  25327. constructor(viewer_, viewport, is3d) {
  25328. super();
  25329. this.is3d = is3d;
  25330. this.sceneGroup = new Object3D();
  25331. this.sceneGroup.name = "MapLayer";
  25332. this.waitQueue = []; //等待加载的
  25333. this.loadingInProgress = 0;
  25334. this.maps = [];
  25335. this.frustum = new Frustum();
  25336. this.frustumMatrix = new Matrix4();
  25337. this.tileColor = new Color(16777215);
  25338. this.viewport = viewport;
  25339. this.changeViewer(viewer_);
  25340. //添加地图
  25341. var map = new TiledMapOpenStreetMap(this, this.tileColor);
  25342. this.addMap(map);
  25343. //map.setEnable(false)
  25344. this.sceneGroup.addEventListener('isVisible', () => {
  25345. this.viewer.mapChanged = true;
  25346. });
  25347. }
  25348. addMapEntity(data, datasetId) {
  25349. if (!data || !data[0]) {
  25350. Potree.Log('平面图无数据', {
  25351. font: 'red'
  25352. });
  25353. return;
  25354. }
  25355. data[0].datasetId = datasetId;
  25356. var floorplan = new TiledMapFromEntity(this, this.tileColor, data[0]); //[0]?
  25357. if (floorplan) {
  25358. floorplan.name += "_" + datasetId;
  25359. this.addMap(floorplan);
  25360. floorplan.updateProjection();
  25361. floorplan.updateObjectGroup();
  25362. var visible = false;
  25363. if (datasetId in Potree.settings.floorplanEnables) {
  25364. visible = Potree.settings.floorplanEnables[datasetId];
  25365. } else {
  25366. visible = Potree.settings.floorplanEnable;
  25367. }
  25368. if (visible) {
  25369. this.needUpdate = true;
  25370. } else {
  25371. floorplan.setEnable(false);
  25372. }
  25373. this.dispatchEvent({
  25374. type: 'floorplanLoaded',
  25375. floorplan
  25376. });
  25377. }
  25378. return floorplan;
  25379. }
  25380. getFloorplan(datasetId) {
  25381. return this.maps.find(e => e.name == 'floorplan' + "_" + datasetId);
  25382. }
  25383. addMap(t) {
  25384. this.maps.push(t);
  25385. //this.view.invalidateScene()
  25386. this.needUpdate = true;
  25387. this.viewer.mapChanged = true;
  25388. }
  25389. removeMap(t) {
  25390. var e = this.maps.indexOf(t);
  25391. if (e >= 0) {
  25392. t.cacheAutoClear('all');
  25393. t.removeFromSceneGroup(this.sceneGroup);
  25394. this.maps.splice(e, 1);
  25395. }
  25396. /* this.view.invalidateScene() */
  25397. this.needUpdate = true;
  25398. this.viewer.mapChanged = true;
  25399. }
  25400. changeViewer(viewer_) {
  25401. //add
  25402. this.viewer = viewer_;
  25403. }
  25404. initProjection() {
  25405. this.maps.forEach(map => {
  25406. map.updateProjection();
  25407. map.updateObjectGroup();
  25408. });
  25409. }
  25410. visibilityChanged() {
  25411. if (!this.visible) for (var t = 0, e = this.maps; t < e.length; t++) {
  25412. e[t].removeFromSceneGroup(this.sceneGroup);
  25413. }
  25414. }
  25415. update() {
  25416. this.needUpdate = false;
  25417. if (this.disabled || !this.maps.find(e => !e.disabled) || !this.maps.find(e => e.objectGroup.visible)) return; //add
  25418. this.viewer.mapChanged = true;
  25419. var e, n, i, r, o;
  25420. this.updateTimer = void 0, e = this.viewport.camera, n = e.projectionMatrix.clone();
  25421. var expandRatio = 1.3;
  25422. n.elements[0] /= expandRatio;
  25423. n.elements[5] /= expandRatio; // 为了缓存吗,使边界处也提前加载,扩大显示区域
  25424. this.frustumMatrix.multiplyMatrices(n, e.matrixWorldInverse), this.frustum.setFromProjectionMatrix(this.frustumMatrix), this.frustum.planes[4].setComponents(0, 0, 0, 0), this.frustum.planes[5].setComponents(0, 0, 0, 0), i = !0;
  25425. camDisToEarth = makeSphere ? e.position.distanceTo(earthCenter) - radius : e.position.z - this.sceneGroup.position.z;
  25426. //console.log('-------------update-----------')
  25427. for (r = 0; r < this.maps.length; r++) {
  25428. var map = this.maps[r];
  25429. i = map.update(this.frustum, this.sceneGroup) && i;
  25430. }
  25431. return [2, i];
  25432. }
  25433. updateProjection() {
  25434. for (var t = 0, e = this.maps; t < e.length; t++) {
  25435. var n = e[t];
  25436. n.clearProjection(), n.updateObjectGroup();
  25437. }
  25438. }
  25439. }
  25440. class TiledMapBase extends EventDispatcher {
  25441. constructor(name, mapLayer, tileColor, projection) {
  25442. var maxTotalCount = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 100;
  25443. super();
  25444. this.name = name;
  25445. this.mapLayer = mapLayer, this.tileColor = tileColor, this.bias = 0;
  25446. this.zIndex = -1;
  25447. this.objectGroup = new Object3D();
  25448. this.objectGroup.name = name;
  25449. this.objectGroupAdded = !1, this.baseTile = new MapTile(this, this.objectGroup, this.tileColor, null, '0'), this.isTileVisibleBox = new Box3(), this.isTileVisibleVec = new Vector3();
  25450. this.projection = projection;
  25451. this._zoomLevel = 0; //1-20
  25452. this.objectGroup.addEventListener('isVisible', () => {
  25453. this.mapLayer.viewer.mapChanged = true;
  25454. });
  25455. this.computeCount = 0;
  25456. this.maxLoading = 3;
  25457. this.loadFailCount = 0;
  25458. this.loadingInProgress = 0;
  25459. //add:
  25460. this.cache = []; //缓存。要删除的tile不立刻dispose,以便迅速再显示。每次都从第一个删除。
  25461. this.maxTotalCount = maxTotalCount;
  25462. }
  25463. cacheAutoClear(type) {
  25464. //清除超出数量的缓存 add
  25465. var len = this.cache.length,
  25466. cacheCopy = this.cache.slice();
  25467. var overCount = this.objectGroup.children.length + len - (type == 'all' ? 0 : this.maxTotalCount);
  25468. if (overCount > 0) {
  25469. var i = 0,
  25470. delCount = Math.min(len, overCount);
  25471. var dels = this.cache.splice(0, delCount);
  25472. dels.forEach(mesh => {
  25473. var _mesh$material$map;
  25474. mesh.material.dispose();
  25475. mesh.geometry.dispose();
  25476. (_mesh$material$map = mesh.material.map) === null || _mesh$material$map === void 0 || _mesh$material$map.dispose();
  25477. mesh.tile._mesh = null;
  25478. });
  25479. //console.log('dispose mesh', dels.map(e=>e.name))
  25480. }
  25481. }
  25482. get zoomLevel() {
  25483. return this._zoomLevel;
  25484. }
  25485. set zoomLevel(zoomLevel) {
  25486. if (this._zoomLevel != zoomLevel) {
  25487. this._zoomLevel = zoomLevel;
  25488. this.dispatchEvent({
  25489. type: 'zoomLevelChange',
  25490. zoomLevel
  25491. });
  25492. //if(this.name == 'map')console.log(zoomLevel,viewer.mapViewer.camera.zoom)
  25493. }
  25494. }
  25495. updateObjectGroup() {
  25496. this.position && this.objectGroup.position.copy(this.position).setZ(0), this.quaternion && this.objectGroup.quaternion.copy(this.quaternion), this.objectGroup.updateMatrixWorld(!0);
  25497. }
  25498. updateProjection() {
  25499. if (!this.transformMapToLocal) {
  25500. this.transformMapToLocal = proj4(this.projection, "LOCAL" /* _MAP" */); //由地图原本的坐标转为本地坐标
  25501. }
  25502. }
  25503. clearProjection() {
  25504. this.transformMapToLocal = void 0;
  25505. this.projection !== 'LOCAL' /* _MAP' */ && this.baseTile.remove();
  25506. }
  25507. setEnable(enable) {
  25508. //add
  25509. if (!this.disabled == enable) return;
  25510. if (enable) {
  25511. //console.log('setEnable',true)
  25512. }
  25513. this.disabled = !enable;
  25514. Potree.Utils.updateVisible(this.objectGroup, 'setEnable', enable);
  25515. if (!enable) {
  25516. this.baseTile.remove();
  25517. } else {
  25518. this.mapLayer.needUpdate = true;
  25519. }
  25520. }
  25521. update(frustum, sceneGroup) {
  25522. this.computeCount = 0;
  25523. var unavailable = this.disabled || !this.objectGroup.visible; //地图即使不显示也要获得zoomlevel
  25524. if (this.name != 'map' && unavailable) return;
  25525. this.updateProjection();
  25526. if (!this.transformMapToLocal) return;
  25527. if (!this.isTileVisible(new Vector3(0, 0, 0), this.mapSizeM, frustum)) return this.removeFromSceneGroup(sceneGroup), !0;
  25528. var viewport = this.mapLayer.viewport;
  25529. var i = new Vector3(-.5 * this.mapSizeM, 0, 0);
  25530. i.applyMatrix4(this.objectGroup.matrixWorld), i.project(viewport.camera);
  25531. var o = new Vector3(.5 * this.mapSizeM, 0, 0);
  25532. o.applyMatrix4(this.objectGroup.matrixWorld), o.project(viewport.camera);
  25533. var rx = viewport.resolution.x,
  25534. ry = viewport.resolution.y;
  25535. if (rx <= 0 || ry <= 0 || isNaN(i.x) || isNaN(i.y) || isNaN(o.z)) return !1;
  25536. i.sub(o), i.x *= rx / 2, i.y *= ry / 2;
  25537. var scale = 1,
  25538. level;
  25539. if (this.name == 'map' && !this.mapLayer.is3d) {
  25540. //add 高纬度的因倾斜而造成tile较小,所以放大些,否则会造成显示的tile过多而卡
  25541. var lonlat = viewer.transform.lonlatToLocal.inverse(viewport.camera.position.clone());
  25542. var cos = Math.cos(MathUtils.degToRad(lonlat.y)); //越小就在纬度上越高,tile表现越小
  25543. //为什么lonlat.y会超出90?
  25544. cos = MathUtils.clamp(cos, 0, 1);
  25545. var lonShift = Math.abs(viewer.mapViewer.camera.position.x / this.mapSizeM * 16); //越大就在经度离中心越远,tile表现越大 。
  25546. lonShift = MathUtils.clamp(lonShift, 0, Math.PI);
  25547. lonShift = (1 - Math.sin(1 / 2 * lonShift + Math.PI / 2)) * Math.PI; // 0-Math.PI sin增速向上
  25548. scale = 0.5 * cos * (1 + lonShift) + 0.5 * Math.pow(cos, lonShift);
  25549. }
  25550. if (this.mapLayer.is3d) {
  25551. level = this.maxDepth;
  25552. } else {
  25553. var c = this.tileSizePx / i.length() / scale; //多除以一个scale缩放因子,scale越大level越小
  25554. level = Math.ceil(-math.getBaseLog(2, c) - this.bias);
  25555. if (this.style == 'dark-standard') {
  25556. //该模式贴图比较小放大点
  25557. level -= 1;
  25558. }
  25559. level = Math.max(level, 0);
  25560. level = Math.min(level, void 0 === this.maxDepth ? 1 / 0 : this.maxDepth);
  25561. this.zoomLevel = level; //add
  25562. /* if(isNaN(this.zoomLevel )){
  25563. console.log(level, cos , scale , lonlat )
  25564. } */
  25565. }
  25566. if (!unavailable) {
  25567. this.addToSceneGroup(sceneGroup);
  25568. /* return */
  25569. this.baseTile.update(this, frustum, level, this.mapSizeM, 0, 0, "", viewport);
  25570. this.cacheAutoClear();
  25571. }
  25572. }
  25573. isTileVisible(tileCenter, tileSize, frustum, viewport, name) {
  25574. if (tileSize > HALF_WORLD_SIZE) return !0; //root must visible
  25575. var halfSize = .5 * tileSize; //在地图上的size和local的差不多是吗
  25576. var vertices = [];
  25577. //简单版:
  25578. if (makeSphere) {
  25579. tileCenter = getPosOnEarth(tileCenter.toArray(), this.transformMapToLocal);
  25580. } else {
  25581. this.transformMapToLocal.forward(tileCenter); //e转化为local
  25582. //tileCenter.sub(this.objectGroup.parent.position)
  25583. }
  25584. this.isTileVisibleBox.makeEmpty();
  25585. this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y - halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld);
  25586. vertices.push(this.isTileVisibleVec.clone());
  25587. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec);
  25588. this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y + halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld);
  25589. vertices.push(this.isTileVisibleVec.clone());
  25590. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec);
  25591. this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y - halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld);
  25592. vertices.push(this.isTileVisibleVec.clone());
  25593. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec);
  25594. this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y + halfSize, tileCenter.z).applyMatrix4(this.objectGroup.matrixWorld);
  25595. vertices.push(this.isTileVisibleVec.clone());
  25596. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec);
  25597. var visi = frustum.intersectsBox(this.isTileVisibleBox);
  25598. if (viewport && visi) {
  25599. var canTraverse,
  25600. vecs = [];
  25601. var dis = tileCenter.distanceTo(viewport.camera.position);
  25602. //if(window.not111){
  25603. var centerToCam = tileCenter.clone().applyMatrix4(viewport.camera.matrixWorldInverse); //相对位置
  25604. centerToCam.normalize(); //dir
  25605. var n = 1.1,
  25606. v1 = 3,
  25607. v2 = 7,
  25608. v3 = 14;
  25609. var a = dis / camDisToEarth;
  25610. var r1 = math.linearClamp(a, [1, v1, v2, v3], [1, n, 1, 0.8]); //最近距离v1倍率处稍微提高
  25611. var r2 = math.linearClamp(Math.abs(centerToCam.x), [0, 0.7, 0.8], [1, 1.3, 1]); //相机两旁的提高
  25612. var r = r1 * r2; //使画面最近点附近的level提高些
  25613. r *= math.linearClamp(viewport.view.direction.z, [-1, -0.8], [a / r, 1]); //相机几乎垂直地面时,使全部level相同,类似2d
  25614. canTraverse = tileSize / dis * r > (window.number2 || 0.6);
  25615. /* }else{
  25616. canTraverse = tileSize / dis > (window.number2 || 0.6)
  25617. }
  25618. */
  25619. /* let pos2ds = vertices.map(e=> e.clone().project( viewport.camera)) //不管是否在背面了,太麻烦
  25620. //对角线长度
  25621. vecs.push(new THREE.Vector2().subVectors(pos2ds[0],pos2ds[2]))
  25622. vecs.push(new THREE.Vector2().subVectors(pos2ds[1],pos2ds[3]))
  25623. let lens = vecs.map(vec=>vec.multiply(viewport.resolution).length())
  25624. let px = Math.max(...lens)
  25625. canTraverse = px > this.tileSizePx * 4//1.414 */
  25626. visi = {
  25627. canTraverse
  25628. };
  25629. }
  25630. /* //仿造createMesh写的准确版,但会因为大的tile非矩形,而视口是矩形,若视口刚好在tile的曲线边缘外却识别为可见,就会创建冗余tile。 但上面那个简单版在zoomlevel低的时候地球边缘容易有识别不到的tile,造成黑色三角形。
  25631. //容易出现奇怪的mesh
  25632. this.isTileVisibleBox.makeEmpty()
  25633. this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y - halfSize, tileCenter.z)
  25634. this.transformMapToLocal.forward(this.isTileVisibleVec)
  25635. this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
  25636. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
  25637. this.isTileVisibleVec.set(tileCenter.x - halfSize, tileCenter.y + halfSize, tileCenter.z)
  25638. this.transformMapToLocal.forward(this.isTileVisibleVec)
  25639. this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
  25640. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
  25641. this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y - halfSize, tileCenter.z)
  25642. this.transformMapToLocal.forward(this.isTileVisibleVec)
  25643. this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
  25644. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
  25645. this.isTileVisibleVec.set(tileCenter.x + halfSize, tileCenter.y + halfSize, tileCenter.z)
  25646. this.transformMapToLocal.forward(this.isTileVisibleVec)
  25647. this.isTileVisibleVec.applyMatrix4(this.objectGroup.matrixWorld)
  25648. this.isTileVisibleBox.expandByPoint(this.isTileVisibleVec)
  25649. */
  25650. return visi;
  25651. }
  25652. addToSceneGroup(t) {
  25653. this.objectGroupAdded || (t.add(this.objectGroup), this.objectGroupAdded = !0);
  25654. }
  25655. removeFromSceneGroup(t) {
  25656. this.baseTile.remove(), this.objectGroupAdded && (t.remove(this.objectGroup), this.objectGroupAdded = !1);
  25657. }
  25658. }
  25659. var loadDone = (tile, success) => {
  25660. tile.map.mapLayer.loadingInProgress--;
  25661. tile.map.loadingInProgress--;
  25662. //console.log('loaddone', tile.name, 'loadingInProgress',tile.map.mapLayer.loadingInProgress, Date.now())
  25663. tile.loading = false;
  25664. var next = tile.map.mapLayer.waitQueue[0];
  25665. if (next) {
  25666. addLoadTile(next);
  25667. } else {
  25668. if (tile.map.mapLayer.loadingInProgress == 0) {
  25669. //注意这时候不一定就加载完了,300ms后可能还会有新的tile加载
  25670. //console.log('loadDone All ?', Date.now())
  25671. tile.map.mapLayer.dispatchEvent('loadDone');
  25672. }
  25673. }
  25674. var mesh = tile.mesh || tile._mesh;
  25675. mesh && (mesh.material.needsUpdate = true);
  25676. };
  25677. function addLoadTile(tile) {
  25678. /* if(tile.texURL && tile.texURL.includes('testdata') ){
  25679. console.error('addLoadTile', tile.texURL.split('map_tiles/')[1] )
  25680. } */
  25681. if (tile.map.loadingInProgress < tile.map.maxLoading) {
  25682. if (!tile.mesh) return; //有时候会遇到这种情况, 为什么没有被cancelLoad呢?
  25683. tile.map.mapLayer.loadingInProgress++;
  25684. tile.map.loadingInProgress++;
  25685. tile.map.mapLayer.dispatchEvent('startLoad');
  25686. //console.log('addLoad', 'loadingInProgress',tile.map.mapLayer.loadingInProgress, Date.now())
  25687. //tile.texURL && tile.texURL.includes('testdata') && console.log('startloadTile ', tile.texURL.split('map_tiles/')[1] )
  25688. tile.loading = true;
  25689. var index = tile.map.mapLayer.waitQueue.indexOf(tile);
  25690. index > -1 && tile.map.mapLayer.waitQueue.splice(index, 1);
  25691. var tex = tile.mesh.material.map = texLoader$2.load(tile.texURL, tex => {
  25692. //如果一直加载不了会影响其他的加载,如google地图没有vpn会使全景图一直加载不了
  25693. var mesh = tile.mesh || tile._mesh;
  25694. if (mesh) {
  25695. //如果还存在的话
  25696. tile.textureLoaded = true;
  25697. mesh.material.opacity = mesh.clockwise ? 0 : 1;
  25698. if (tile.mesh) {
  25699. //显示的话
  25700. tile.map.mapLayer.viewer.mapChanged = true;
  25701. tile.map.mapLayer.needUpdate = true; //表示还要继续update(以removeChildren)
  25702. if (tile.map instanceof TiledMapOpenStreetMap) {
  25703. tile.map.maxLoading = 10;
  25704. browser.isMobile() && (tile.map.maxLoading /= 2), tile.map.mapLayer.is3d && (tile.map.maxLoading /= 3); //怕转动卡
  25705. }
  25706. tile.map.mapLayer.dispatchEvent('tileLoaded');
  25707. }
  25708. } else {
  25709. //tile.texURL && tile.texURL.includes('testdata') && console.log('loadDone and dispose', tile.texURL.split('map_tiles/')[1] )
  25710. tex.dispose();
  25711. }
  25712. loadDone(tile, true);
  25713. }, void 0, () => {
  25714. //error
  25715. tile.textureLoaded = !0;
  25716. if (tile.mesh) {
  25717. tile.mesh.material.dispose();
  25718. tile.mesh.material = errorMaterial;
  25719. tile.map.mapLayer.viewer.mapChanged = true;
  25720. }
  25721. loadDone(tile, false);
  25722. tile.map.loadFailCount++;
  25723. if (tile.map instanceof TiledMapOpenStreetMap && Potree.settings.mapCompany == 'google' && tile.map.loadFailCount > 3) {
  25724. //极有可能没有vpn为了防止影响到其他资源加载,减少加载的个数
  25725. tile.map.maxLoading = 2;
  25726. }
  25727. });
  25728. if (tile.map.mapLayer.is3d) {
  25729. tex.anisotropy = 2;
  25730. } else {
  25731. tex.anisotropy = 0;
  25732. tex.generateMipmaps = !1;
  25733. tex.minFilter = LinearFilter;
  25734. tex.magFilter = LinearFilter;
  25735. }
  25736. } else {
  25737. tile.map.mapLayer.waitQueue.includes(tile) || tile.map.mapLayer.waitQueue.push(tile);
  25738. }
  25739. }
  25740. function cancelLoad(tile, log) {
  25741. //如果等待加载,但还没开始加载,取消加载
  25742. if (!tile.loading) {
  25743. var index = tile.map.mapLayer.waitQueue.indexOf(tile);
  25744. index > -1 && tile.map.mapLayer.waitQueue.splice(index, 1);
  25745. //index > -1 && tile.texURL && tile.texURL.includes('testdata') && console.log('cancelLoad', tile.texURL.split('map_tiles/')[1]/* , (log && waitQueue.indexOf(tile)>-1) ? log:'' , tile.loading */ )
  25746. }
  25747. }
  25748. class MapTile {
  25749. constructor(map, e, n, parent, name) {
  25750. this.map = map;
  25751. this.name = name;
  25752. this.parent = parent;
  25753. this.objectGroup = e, this.tileColor = n, this.meshAdded = !1, this.textureLoaded = !1, this.children = [];
  25754. this.id = getSid();
  25755. }
  25756. update(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport) {
  25757. var canTraverse = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true;
  25758. if (!this.doesNotContainTilesToBeDisplayed(entity)) {
  25759. var canTraverse_ = this.map.mapLayer.is3d ? canTraverse : level > 0;
  25760. return canTraverse_ ? this.updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport) : this.updateTileLeaf(entity, tileSize, centerX, centerY);
  25761. }
  25762. }
  25763. doesNotContainTilesToBeDisplayed(entity) {
  25764. return entity.tilePresenceMap && entity.tilePresenceMap.empty;
  25765. }
  25766. updateTileLeaf(entity, tileSize, centerX, centerY) {
  25767. //真正显示mesh的是这一层,最高level
  25768. //if(this.map.name.includes('floorplan'))console.log('updateTileLeaf',this.name)
  25769. if (!this.mesh) {
  25770. this.createTileObject(entity, tileSize, centerX, centerY);
  25771. }
  25772. if (!this.meshAdded) {
  25773. this.objectGroup.add(this.mesh);
  25774. this.meshAdded = !0;
  25775. }
  25776. if (this.textureLoaded) {
  25777. //贴图加载完就不需要子集了
  25778. this.removeChildren();
  25779. } else {
  25780. this.cancelChildren(); //add 停止加载子集
  25781. }
  25782. return this.textureLoaded;
  25783. }
  25784. updateSubTiles(entity, frustum, level, tileSize, centerX, centerY, treeStr, viewport) {
  25785. //if(entity.name.includes('floorplan'))console.log('updateSubTiles',this.name) //名字越长代表level越高
  25786. var shiftX = [-.25 * tileSize, .25 * tileSize, -.25 * tileSize, .25 * tileSize],
  25787. shiftY = [.25 * tileSize, .25 * tileSize, -.25 * tileSize, -.25 * tileSize];
  25788. for (var childrenLoaded = !0, p = 0; p < 4; ++p) {
  25789. var childTreeStr = treeStr + p.toString(10);
  25790. //一级(512):0 1 2 3分别为左上、右上、左下、右下。二级(1024)就是把一级的每一块分裂,如00 01 02 03分别是0的左上、右上、左下、右下……
  25791. if (!entity.tilePresenceMap || entity.tilePresenceMap[childTreeStr]) {
  25792. //去掉判断,直接显示
  25793. var childCenterX = centerX + shiftX[p],
  25794. childCenterY = centerY + shiftY[p];
  25795. tempVector.set(childCenterX, childCenterY, 0);
  25796. this.map.computeCount++;
  25797. //console.log(this.map.computeCount, this.name, 'level:',level)
  25798. var checkLevel = entity.mapLayer.is3d && level > 1;
  25799. if (entity.name == 'map' && checkLevel && entity.minDepth) checkLevel = level < entity.maxDepth - entity.minDepth; //禁止地球显示层级过低否则无图且变形
  25800. var visi = entity.isTileVisible(tempVector, .5 * tileSize, frustum, checkLevel && viewport, this.name + p);
  25801. if (visi) {
  25802. //entity.name == 'map' && console.log('visi', childTreeStr, childCenterX,childCenterY, tileSize)
  25803. this.children[p] || (this.children[p] = new MapTile(this.map, this.objectGroup, this.tileColor, this, this.name + p));
  25804. //childrenLoaded = childrenLoaded && this.children[p].update(entity, frustum, level - 1, .5 * tileSize, childCenterX, childCenterY, childTreeStr) //这句会使若有一个tile还在加载,就阻断了。原版是这么写的。但是为了加快加载速度,改成下面两行。感觉直接全部updateTile也没太卡,不知道很大的场景会不会卡,单帧updateTile次数超过100次的话(应该不会吧,地图大小会限制住个数) -- 2023.12
  25805. var childLoaded = this.children[p].update(entity, frustum, level - 1, .5 * tileSize, childCenterX, childCenterY, childTreeStr, viewport, level > 1 && visi.canTraverse);
  25806. childrenLoaded = childrenLoaded && childLoaded;
  25807. } else {
  25808. //entity.name == 'map' && console.log('not visi', childTreeStr, childCenterX,childCenterY, tileSize)
  25809. if (this.children[p]) {
  25810. this.children[p].remove();
  25811. delete this.children[p];
  25812. }
  25813. }
  25814. }
  25815. }
  25816. return childrenLoaded && this.removeObject3D(), childrenLoaded; //子项加载完,母项mesh可以去除。(最后母项的母项以及前面的都会被删除,只留最后的叶子结点)
  25817. }
  25818. /*
  25819. 一层层往后加载。加入第一次加载到第4层(因为level精细度是第4层),给第4层可见tile加上mesh。
  25820. 然后下一次加载到第5层,那么第4层的mesh就要被清空(当它所属的第5层子集都加载完后)
  25821. */
  25822. createTileObject(entity, tileSize, centerXatMap, centerYatMap) {
  25823. var mesh;
  25824. var meshIndex = this.map.cache.findIndex(e => e.name == this.name);
  25825. if (meshIndex != -1) {
  25826. mesh = this.map.cache.splice(meshIndex, 1)[0];
  25827. this.textureLoaded = !0;
  25828. } else {
  25829. mesh = this.createMesh(entity.transformMapToLocal, tileSize, centerXatMap, centerYatMap), mesh.name = this.name;
  25830. if (showTileName) {
  25831. this.textureLoaded = !0; //add
  25832. } else {
  25833. this.textureLoaded = !1;
  25834. var c = entity.mapSizeM / tileSize,
  25835. z = math.getBaseLog(2, c) //以2为底c的对数
  25836. ,
  25837. x = centerXatMap / tileSize + .5 * (c - 1),
  25838. y = -centerYatMap / tileSize + .5 * (c - 1),
  25839. p = entity.getTileUrl(Math.round(x), Math.round(y), Math.round(z));
  25840. Potree.Utils.setObjectLayers(mesh, 'map');
  25841. mesh.renderOrder = -(1e6 - z - 100 * (entity.zIndex || 0));
  25842. this.texURL = p;
  25843. }
  25844. //console.log('创建mesh',this.name)
  25845. }
  25846. this.mesh = mesh;
  25847. mesh.tile = this;
  25848. meshIndex == -1 && addLoadTile(this);
  25849. }
  25850. /* getVertices(transform, tileSize, centerXatMap, centerYatMap){
  25851. this.vertices = []
  25852. tempVector.set(centerXatMap - tileSize / 2, centerYatMap - tileSize / 2, 0),
  25853. this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
  25854. tempVector.set(centerXatMap + tileSize / 2, centerYatMap - tileSize / 2, 0),
  25855. this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
  25856. tempVector.set(centerXatMap + tileSize / 2, centerYatMap + tileSize / 2, 0),
  25857. this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector))),
  25858. tempVector.set(centerXatMap - tileSize / 2, centerYatMap + tileSize / 2, 0),
  25859. this.vertices.push(new THREE.Vector3().copy(transform.forward(tempVector)))
  25860. } */
  25861. createMesh(transform, tileSize, centerXatMap, centerYatMap) {
  25862. var a = new Geometry();
  25863. var vertices = [[centerXatMap - tileSize / 2, centerYatMap - tileSize / 2], [centerXatMap + tileSize / 2, centerYatMap - tileSize / 2], [centerXatMap + tileSize / 2, centerYatMap + tileSize / 2], [centerXatMap - tileSize / 2, centerYatMap + tileSize / 2]];
  25864. vertices.forEach(vertice => {
  25865. //计算在球面上的位置, xy已经有了,算z
  25866. if (makeSphere) {
  25867. a.vertices.push(getPosOnEarth(vertice, transform)); //(0,0)处地表z为0,其余都在0之下
  25868. } else {
  25869. a.vertices.push(new Vector3().fromArray([...transform.forward(vertice), 0]));
  25870. }
  25871. });
  25872. a.faces.push(face1), a.faces.push(face2), a.faceVertexUvs[0].push(face1UV), a.faceVertexUvs[0].push(face2UV);
  25873. var label;
  25874. if (showTileName) {
  25875. //let center = this.tilePos || new THREE.Vector3().fromArray(transform.forward([centerXatMap,centerYatMap,0]))
  25876. label = new TextSprite$2({
  25877. text: this.name,
  25878. sizeInfo: {
  25879. width2d: 200
  25880. },
  25881. fontsize: 60,
  25882. textColor: {
  25883. r: 30,
  25884. g: 30,
  25885. b: 30,
  25886. a: 1
  25887. },
  25888. backgroundColor: {
  25889. r: 255,
  25890. g: 255,
  25891. b: 255,
  25892. a: 0.98
  25893. }
  25894. });
  25895. /* label.position.copy(center)
  25896. mesh.add(label) */
  25897. }
  25898. var mesh = new Mesh(a, this.createMaterial(label));
  25899. if (this.map.mapLayer.is3d) {
  25900. var clockwise = math.getArea(a.vertices) > 0;
  25901. mesh.clockwise = clockwise;
  25902. showTileName && (mesh.material.opacity = clockwise ? 0 : 1); //soon
  25903. }
  25904. return mesh;
  25905. }
  25906. createMaterial(label) {
  25907. var color;
  25908. if (Potree.settings.isTest) {
  25909. var colorHue = Math.random();
  25910. color = new Color().setHSL(colorHue, 0.6, 0.92);
  25911. } else {
  25912. color = this.tileColor ? this.tileColor : new Color(16777215);
  25913. }
  25914. var t = new MeshBasicMaterial({
  25915. transparent: !0,
  25916. depthWrite: !1,
  25917. depthTest: !1,
  25918. //!0
  25919. opacity: 0,
  25920. side: DoubleSide,
  25921. color
  25922. });
  25923. label && (t.map = label.sprite.material.map); //add
  25924. return t;
  25925. }
  25926. traverse(f) {
  25927. //add
  25928. return Mesh.prototype.traverse.call(this, f);
  25929. }
  25930. remove() {
  25931. this.removeObject3D(), this.removeChildren();
  25932. }
  25933. removeObject3D() {
  25934. var hasMesh = !!this.mesh;
  25935. if (this.mesh) {
  25936. if (this.mesh.material.map) {
  25937. //add 已经有图或在加载图
  25938. this._mesh = this.mesh;
  25939. this.map.cache.push(this.mesh); //加入缓存
  25940. //console.log('加入缓存', this.name)
  25941. } else {
  25942. cancelLoad(this);
  25943. }
  25944. this.objectGroup.remove(this.mesh);
  25945. /* if (this.textureLoaded){
  25946. var t = this.mesh.material.map;
  25947. t && t.dispose()
  25948. }else{
  25949. cancelLoad(this)
  25950. }
  25951. this.mesh.material.dispose() //o.disposeMeshMaterial(this.mesh),
  25952. this.mesh.geometry.dispose() */
  25953. this.mesh = void 0;
  25954. }
  25955. this.meshAdded = !1;
  25956. this.textureLoaded = !1;
  25957. //this.texURL && this.texURL.includes('testdata') && console.log('removeObject3D', this.id, 'hasMesh',hasMesh, this.texURL.split('map_tiles/')[1] )
  25958. }
  25959. removeChildren() {
  25960. for (var t = 0, e = this.children; t < e.length; t++) {
  25961. var n = e[t];
  25962. n && (n.removeObject3D(), n.removeChildren());
  25963. }
  25964. this.children.length = 0;
  25965. }
  25966. cancelChildren() {
  25967. //子集全部停止加载
  25968. for (var t = 0, e = this.children; t < e.length; t++) {
  25969. var n = e[t];
  25970. n && (cancelLoad(n, '提前'), n.cancelChildren());
  25971. }
  25972. }
  25973. }
  25974. //墨卡托全球矩形,无任何偏移: (地图资源是按照这个来获取的,不能偏移;而每个tile的具体位置则是这映射到local坐标后得到的,可以通过变换local的定义来改变transform映射。 )
  25975. proj4.defs("EPSG:3857", "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs");
  25976. //注意在traverse四叉树会因为local的偏移而使边缘tile分裂为2块以上,尤其在子结点createMesh时就能看到那些图片拉伸的怪怪的tile, 我通过过滤掉clockwise来过滤掉这些错误mesh,因此缺少了一部分,全局看map左右不完整
  25977. class TiledMapOpenStreetMap extends TiledMapBase {
  25978. constructor(mapLayer, tileColor) {
  25979. var projection = Potree.settings.mapCompany == 'google' ? "EPSG:900913" : "EPSG:3857";
  25980. var maxTotalCount = mapLayer.is3d ? 1400 : 300;
  25981. browser.isMobile() && (maxTotalCount /= 2);
  25982. super('map', mapLayer, tileColor, projection, maxTotalCount); //EPSG projection
  25983. //this.baseUrl = "https://wprd03.is.autonavi.com/appmaptile?style=7&x=${x}&y=${y}&z=${z}",
  25984. //this.baseUrl = "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x=${x}&y=${y}&z=${z}" //最高只到18 level
  25985. this.switchStyle();
  25986. this.tileSizePx = 256;
  25987. this.mapSizeM = Math.floor(6378137 * Math.PI * 2); //40075016, 不要超出地图projection范围 // 40075017 //总占据多少米(地球赤道周长) 和三维空间的不一样 - -, 空间上的是直径,地图上的是半个圆周
  25988. this.bias = 0.5;
  25989. this.minDepth = 1; //add 因0的无图或不全
  25990. /* if(Potree.settings.mapCompany == 'google'){
  25991. this.attribution = "© PopSmart, © 谷歌地图"
  25992. this.projection = "EPSG:900913" //"EPSG:4326"//4550
  25993. }else{
  25994. this.attribution = "© PopSmart, © 高德地图"
  25995. this.projection = "EPSG:3857"
  25996. } */
  25997. }
  25998. getTileUrl(x, y, z) {
  25999. return this.baseUrl.replace(/\${x}/, x.toString(10)).replace(/\${y}/, y.toString(10)).replace(/\${z}/, z.toString(10));
  26000. }
  26001. switchStyle() {
  26002. var style = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'standard';
  26003. //if(Potree.settings.mapCompany == 'google')return
  26004. if (style == this.style) return;
  26005. if (Potree.settings.mapCompany == 'google') {
  26006. var [lang, glPos] = {
  26007. 'zh': ["zh-CN", "cn"],
  26008. 'en': ["en-US"],
  26009. //范围大所以不指定地理位置 。
  26010. 'ja': ["ja-JP", "JP"],
  26011. 'kr': ["ko-KR", "KR"]
  26012. }[Potree.settings.language] || [];
  26013. this.baseUrl = "https://mt2.google.com/vt/lyrs=" + (style == 'satellite' ? "y" : "m") + "@159000000" + (lang ? "&hl=" + lang : '') + (glPos ? "&gl=" + glPos : '') + "&x=${x}&y=${y}&z=${z}&s=mt1";
  26014. this.maxDepth = 22;
  26015. /* 1)lyrs= 表示的是图层类型,即瓦片类型,具体含义如下:
  26016. m:路线图
  26017. t:地形图
  26018. p:带标签的地形图
  26019. s:卫星图
  26020. y:带标签的卫星图
  26021. h:标签层(路名、地名等)
  26022. 2)& gl=CN 指定地理区域
  26023. 谷歌地图针对中国有两套坐标,一套做了偏移,一套没有。经测试在url加入gl=cn地图会有偏移。
  26024. Tips:如果谷歌地图和RTK测量的WGS84坐标有偏差,可以尝试在url里去掉& gl=cn。(摘自网上)
  26025. 通义千问:如果不指定gl参数,Google将使用默认值或基于其他因素(如IP地址)来推断用户的地理区域。这通常不会导致地图数据的不准确性,但可能会影响本地化信息的显示。地图上的标签(如街道名称、城市名称等)可能不会以最合适的语言显示。地址格式和拼写可能不符合当地标准
  26026. 5)&hl=
  26027. 设置地图注记文字语言类型,缺省默认为中文。
  26028. hl=nl 中英双语
  26029. hl=zh-CN 中文
  26030. */
  26031. } else {
  26032. //baseUrl = "https://webst01.is.autonavi.com/appmaptile?lang=zh_cn&style=6&yrs=m&x=${x}&y=${y}&z=${z}" //卫星 maxDepth = 18
  26033. //搜索高德地图瓦片url
  26034. if (Potree.settings.isJiangMen) {
  26035. if (style == 'satellite') {
  26036. //卫星
  26037. this.maxDepth = 18;
  26038. this.baseUrl = "http://a.map.jms.gd/tile/weixing/${z}/${x}/${y}.png";
  26039. } else {
  26040. this.maxDepth = 18;
  26041. this.baseUrl = "http://a.map.jms.gd/tile/gd_xiangtu/${z}/${x}/${y}.png";
  26042. }
  26043. } else {
  26044. if (style == 'satellite') {
  26045. //卫星
  26046. this.maxDepth = 18;
  26047. this.baseUrl = "https://webst01.is.autonavi.com/appmaptile?lang=zh_cn&style=6&yrs=m&x=${x}&y=${y}&z=${z}";
  26048. } else if (style == 'dark-standard') {
  26049. this.maxDepth = 18;
  26050. this.baseUrl = "https://wprd01.is.autonavi.com/appmaptile?lang=zh_cn&style=8&yrs=m&x=${x}&y=${y}&z=${z}"; //路网 加上scl=2后去掉名字
  26051. } else {
  26052. this.maxDepth = 19;
  26053. this.baseUrl = "https://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&style=7&yrs=m&x=${x}&y=${y}&z=${z}"; //加这个才会精细lang=zh_cn
  26054. }
  26055. } //详解 https://www.cnblogs.com/lucio110/p/17310054.html
  26056. }
  26057. this.style = style;
  26058. this.setEnable(false);
  26059. this.setEnable(true);
  26060. this.cacheAutoClear('all');
  26061. viewer.dispatchEvent('content_changed');
  26062. }
  26063. }
  26064. class TiledMapFromEntity extends TiledMapBase {
  26065. constructor(mapLayer, tileColor, data) {
  26066. super('floorplan', mapLayer, tileColor, "LOCAL" /* "EPSG:3857" */ /* "WGS84" */); //直接就是本地坐标,没有projec
  26067. var entity = this.tiledMapEntity = this.fillFromData(data);
  26068. var time = entity.updateTime || entity.createTime;
  26069. this.tileSizePx = entity.tileSizePx, this.mapSizeM = entity.mapSizeM, this.maxDepth = entity.maxDepth;
  26070. this.postStamp = time ? time.replace(/[^0-9]/ig, '') : new Date().getTime();
  26071. //this.projection = n.crsLocal,
  26072. this.zIndex = 0, this.tilePresenceMap = this.decodeBitStream(this.tiledMapEntity.quadtree); //包含tile分裂信息,如果写错了会造成tile显示不全
  26073. this.maxLoading = 5;
  26074. this.bias = 0.5; //越大加载层级越低,越模糊
  26075. if (window.devicePixelRatio >= 2 && window.innerHeight * window.innerWidth < 768 * 1024) {
  26076. //手机还是加载高清点(反正也不需要截图等待),但平板太大了,要铺满屏幕可能慢,所以稍微模糊点?(反正可以继续放大去看)
  26077. this.bias = 0; //level更高些
  26078. }
  26079. }
  26080. fillFromData(e) {
  26081. var data = {};
  26082. data.id = e.id;
  26083. data.globalLocation = Potree.Utils.VectorFactory.fromArray3(e.location);
  26084. data.orientation = Potree.Utils.QuaternionFactory.fromArray(e.orientation); //数据集支持其他方向旋转后不用这个了
  26085. var pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == e.datasetId);
  26086. if (pointcloud.datasetData.mapping) {
  26087. data.filePath = "".concat(Potree.settings.urls.prefix1, "/").concat(pointcloud.datasetData.mapping).concat(e.file_path);
  26088. } else {
  26089. data.filePath = "".concat(Potree.settings.urls.prefix1).concat(e.file_path);
  26090. }
  26091. this.pointcloud = pointcloud;
  26092. data.fileName = '$DEPTH/$X/$Y.png';
  26093. data.type = e.type, data.mapSizeM = e.map_size_m, data.tileSizePx = e.tile_size_px, data.maxDepth = e.max_depth, data.quadtree = e.quadtree, data.floorId = e.floor_id, data.bundleId = e.bundle_id;
  26094. //this.computeLocalCoordinates()
  26095. return data;
  26096. }
  26097. computeLocalCoordinates() {
  26098. if (proj4.defs("LOCAL" /* _MAP" */)) {
  26099. var lonlat = this.tiledMapEntity.globalLocation;
  26100. /* if(window.AMapWith84){//需要转换
  26101. lonlat = AMapWith84.wgs84ToAMap(lonlat)
  26102. } */
  26103. lonlat = viewer.transform.lonlatToLocal.forward(lonlat);
  26104. this.tiledMapEntity.location = new Vector3().copy(lonlat);
  26105. }
  26106. }
  26107. updateProjection() {
  26108. super.updateProjection();
  26109. if (!this.position) {
  26110. this.computeLocalCoordinates();
  26111. }
  26112. /* this.projection = this.TransformService.crsLocal,
  26113. t.prototype.updateProjection.call(this) */
  26114. }
  26115. get position() {
  26116. return this.tiledMapEntity.location;
  26117. }
  26118. get quaternion() {
  26119. //return this.tiledMapEntity.orientation//数据集支持其他方向旋转后不用这个了
  26120. return typeof this.pointcloud.orientationUser == 'number' ? this.tiledMapEntity.orientation : this.pointcloud.orientationUser.clone();
  26121. }
  26122. getTileUrl(x, y, z) {
  26123. var i = (this.tiledMapEntity.filePath + "/" + this.tiledMapEntity.fileName).replace(/\$DEPTH/g, z.toString(10)).replace(/\$X/g, x.toString(10)).replace(/\$Y/g, y.toString(10));
  26124. return i += "?t=" + this.postStamp;
  26125. //this.RestService.addAuthorizationQueryParameter(i) //????
  26126. }
  26127. decodeBitStream(t) {
  26128. if (!t) return {
  26129. empty: !0
  26130. };
  26131. for (var e = {}, n = [e], i = 0; i < t.length; i++) {
  26132. var r = n.shift(),
  26133. o = parseInt(t.substr(i, 1), 16);
  26134. if (1 & o) {
  26135. var a = {};
  26136. r[0] = a, n.push(a);
  26137. }
  26138. 2 & o && (a = {}, r[1] = a, n.push(a)), 4 & o && (a = {}, r[2] = a, n.push(a)), 8 & o && (a = {}, r[3] = a, n.push(a));
  26139. }
  26140. var s = {
  26141. empty: !0
  26142. };
  26143. return this.computeHashes(s, e, ""), s;
  26144. }
  26145. computeHashes(t, e, n) {
  26146. for (var i = 0; i < 4; i++) e[i] && (t[n + i.toString(10)] = !0, t.empty = !1, this.computeHashes(t, e[i], n + i.toString(10)));
  26147. }
  26148. }
  26149. /*
  26150. note:
  26151. google地图看国内某个84经纬度和矫正后的高德的不一样,和未矫正后的高德接近.
  26152. map3d效果和高德地图差不多,原来高德也有三维的 https://www.amap.com/
  26153. 高德限制了相机高度,使之不会到没有图的低level;且支持x轴无限滚动连接
  26154. 目前缩小了能看出形态是一个地球。相机在高空朝下观测,地球平放着。
  26155. 所以越靠近赤道和地球朝上的那面所在的中央经度(也就是local 0,0,0所对应的初始经度),tile越接近正方形。
  26156. 所以在两极地区要怎么显示?
  26157. 注册地理坐标时需要滚动地球吗?(修改初始经度、重定义NAVVIS:TMERC, 就需要更新所有三维世界中的物体位置)
  26158. 切换中心点:
  26159. var locationLonLat = viewer.transform.lonlatToLocal.inverse(viewer.mapViewer.camera.position.clone())
  26160. proj4.defs("LOCAL_MAP", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat.x.toPrecision(15) + " +lat_0=" + locationLonLat.y.toPrecision(15));
  26161. viewer.mapViewer.mapLayer.maps[0].transformMapToLocal = null
  26162. 地理注册部分地图上的1和2标记有两层意思。当地图全屏展示时,标记的是当前右侧经纬度的位置;当地图为小窗时,标记的是对应场景里三维位置。(所以感觉最好换一个ui?)且在2023.2.1之前才改好,之前都是后者。
  26163. 为什么边缘总是有奇怪的mesh,是因为有顶点到背面了吗
  26164. https://lbs.amap.com/tools/picker 高德坐标拾取器(手机登录),但和这里展示的不一样, 要用AMapWith84.aMapToWgs84({x: ,y: })转成84。 (qq or 手机登录) 所以potree本地和有AMapWith84函数的laser地图展现不一样
  26165. https://www.google.com/maps/@77.7730021,-34.4952712,4z google取点
  26166. 打印所有mapTile的名字,字符串最长的代表有显示的mesh。
  26167. viewer.mapViewer.mapLayer.maps[0].baseTile.traverse(function(e){console.log(e.name)})
  26168. 能查看有几个显示的mesh
  26169. viewer.mapViewer.mapLayer.maps[0].objectGroup.children
  26170. 图片地址中 tiles/4/3/9.png 第一个数字越高代表level越高,放得越大 . (tile.name.length也能反映出
  26171. viewer.mapViewer.mapLayer.maps[1].objectGroup.children.map(e=>e.name.length-1)
  26172. 目前看的几个场景floorplan原图是1米=33.03个像素 图宽度= 512*2^(max_depth-1) , map_size_m 代表整个地图是多少米
  26173. 经纬度精度小数点后5位为米级别,6位为分米,7位是厘米
  26174. */
  26175. /**
  26176. * @author mschuetz / http://mschuetz.at
  26177. *
  26178. * adapted from THREE.OrbitControls by
  26179. *
  26180. * @author qiao / https://github.com/qiao
  26181. * @author mrdoob / http://mrdoob.com
  26182. * @author alteredq / http://alteredqualia.com/
  26183. * @author WestLangley / http://github.com/WestLangley
  26184. * @author erich666 / http://erichaines.com
  26185. *
  26186. *
  26187. *
  26188. */
  26189. var Buttons = Potree.defines.Buttons;
  26190. class FirstPersonControls extends EventDispatcher {
  26191. constructor(viewer, viewport) {
  26192. var _this;
  26193. super();
  26194. _this = this;
  26195. this.viewer = viewer;
  26196. this.renderer = viewer.renderer;
  26197. this.scene = viewer.scene;
  26198. this.rotationSpeed = 200;
  26199. this.moveSpeed = 10;
  26200. this.setCurrentViewport({
  26201. hoverViewport: viewport,
  26202. force: true
  26203. }); //this.currentViewport = viewport
  26204. this.keys = {
  26205. FORWARD: ['W'.charCodeAt(0), 38],
  26206. BACKWARD: ['S'.charCodeAt(0), 40],
  26207. LEFT: ['A'.charCodeAt(0), 37],
  26208. RIGHT: ['D'.charCodeAt(0), 39],
  26209. UP: ['Q'.charCodeAt(0)],
  26210. DOWN: ['E'.charCodeAt(0)],
  26211. //SHIFT : [16],
  26212. ALT: [18],
  26213. SPACE: [32],
  26214. Rotate_LEFT: ['L'.charCodeAt(0)],
  26215. Rotate_RIGHT: ['J'.charCodeAt(0)],
  26216. Rotate_UP: ['K'.charCodeAt(0)],
  26217. Rotate_DOWN: ['I'.charCodeAt(0)]
  26218. };
  26219. this.fadeFactor = 20;
  26220. this.yawDelta = 0;
  26221. this.pitchDelta = 0;
  26222. this.translationDelta = new Vector3(0, 0, 0);
  26223. this.translationWorldDelta = new Vector3(0, 0, 0);
  26224. this.tweens = [];
  26225. this.dollyStart = new Vector2();
  26226. this.dollyEnd = new Vector2();
  26227. //this.enableChangePos = true
  26228. this.viewer.addEventListener('camera_changed', e => {
  26229. if (this.viewer.name == 'mapViewer' || e.changeInfo && e.changeInfo.positionChanged && !viewer.mainViewport.view.isFlying()) {
  26230. this.setFPCMoveSpeed(e.viewport);
  26231. }
  26232. });
  26233. var drag = e => {
  26234. if (!this.enabled) return;
  26235. var viewport = e.dragViewport;
  26236. if (!viewport) return;
  26237. var camera = viewport.camera;
  26238. var mode;
  26239. if (e.isTouch) {
  26240. if (e.touches.length == 1) {
  26241. mode = !e.dragViewport || e.dragViewport.name == 'MainView' ? 'rotate' : 'pan';
  26242. } else if (e.touches.length == 2) {
  26243. mode = Potree.settings.displayMode == 'showPanos' ? 'scale' : 'pan-scale';
  26244. } else {
  26245. mode = !e.dragViewport || e.dragViewport.name == 'MainView' ? 'pan' : 'scale';
  26246. }
  26247. } else {
  26248. //mode = e.buttons === Buttons.LEFT && (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'rotate' : 'pan'
  26249. mode = e.buttons === Buttons.LEFT && camera.type != 'OrthographicCamera' ? 'rotate' : 'pan';
  26250. }
  26251. //console.log('mode ', mode )
  26252. var moveSpeed = this.currentViewport.getMoveSpeed();
  26253. if (e.drag.startHandled === undefined) {
  26254. ///???????
  26255. e.drag.startHandled = true;
  26256. this.dispatchEvent({
  26257. type: 'start'
  26258. });
  26259. }
  26260. if (mode.includes('rotate')) {
  26261. //旋转
  26262. //来自panoramaControl updateRotation
  26263. if (!this.pointerDragStart) {
  26264. return this.pointerDragStart = e.pointer.clone();
  26265. }
  26266. var view = this.scene.view;
  26267. if (this.rotateStartInfo.rotAroundPoint) {
  26268. //定点旋转: 以当前intersect的点为target旋转,不改点在屏幕中的位置
  26269. var distance = camera.position.distanceTo(this.rotateStartInfo.rotCenter /* this.intersectStart.location */); //不按下ctrl的话
  26270. var posDir = new Vector3().subVectors(this.rotateStartInfo.rotCenter, view.position);
  26271. if (posDir.dot(view.direction) < 0) distance *= -1; //在背面
  26272. //按照orbitControl的方式旋转:
  26273. var rotationSpeed = 2;
  26274. this.yawDelta -= e.drag.pointerDelta.x * rotationSpeed;
  26275. this.pitchDelta += e.drag.pointerDelta.y * rotationSpeed;
  26276. /* //旋转方向和偏移量尽量和在漫游点处旋转方式的一样
  26277. this.yawDelta += e.drag.pointerDelta.x / 500 * viewport.resolution.x
  26278. this.pitchDelta -= e.drag.pointerDelta.y / 500 * viewport.resolution.y */
  26279. //先更新一下相机:
  26280. this.update();
  26281. view.applyToCamera(camera);
  26282. //然后得到新的相机角度下,原先点在屏幕中的位置所对应的3d点现在的坐标。只需要平移一下新旧坐标差值即可。//感觉貌似也可以用project和unproject后的差值的方式,还不用判断z背面
  26283. var newPointerDir = viewer.inputHandler.getMouseDirection(this.rotateStartInfo.rotCenter2d).direction.clone().multiplyScalar(distance);
  26284. var pivot = new Vector3().addVectors(camera.position, newPointerDir); //新的3d点
  26285. var moveVec = new Vector3().subVectors(pivot, this.rotateStartInfo.rotCenter);
  26286. this.translationWorldDelta.copy(moveVec.negate());
  26287. //立即更新下,防止因update和此drag频率不同而打滑。
  26288. this.update();
  26289. view.applyToCamera(camera);
  26290. } else {
  26291. var _matrixWorld = camera.matrixWorld;
  26292. camera.matrixWorld = new Matrix4(); //unproject 前先把相机置于原点
  26293. var e1 = new Vector3(this.pointerDragStart.x, this.pointerDragStart.y, -1).unproject(camera),
  26294. t = new Vector3(e.pointer.x, e.pointer.y, -1).unproject(camera),
  26295. i = Math.sqrt(e1.x * e1.x + e1.z * e1.z),
  26296. n = Math.sqrt(t.x * t.x + t.z * t.z),
  26297. o = Math.atan2(e1.y, i),
  26298. a = Math.atan2(t.y, n);
  26299. this.pitchDelta += o - a; //上下旋转
  26300. e1.y = 0, t.y = 0;
  26301. var s = Math.acos(e1.dot(t) / e1.length() / t.length());
  26302. if (!isNaN(s)) {
  26303. var yawDelta = s; //左右旋转
  26304. this.pointerDragStart.x > e.pointer.x && (yawDelta *= -1);
  26305. this.yawDelta += yawDelta;
  26306. }
  26307. //console.log('rotate:', this.pitchDelta, e.pointer.toArray(), this.pointerDragStart.toArray())
  26308. this.pointerDragStart.copy(e.pointer);
  26309. camera.matrixWorld = _matrixWorld;
  26310. }
  26311. }
  26312. if (mode.includes('pan')) {
  26313. //平移
  26314. if (!this.canMovePos(viewport)) {
  26315. return;
  26316. }
  26317. if (camera.type == "OrthographicCamera") {
  26318. //console.log(e.drag.pointerDelta, e.pointer, e.drag.end)
  26319. var _moveVec = Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, camera); //最近一次移动向量
  26320. var pointclouds;
  26321. var Alignment = window.viewer.modules.Alignment;
  26322. var MergeEditor = window.viewer.modules.MergeEditor;
  26323. var handleState = Alignment.handleState;
  26324. //右键平移视图、左键操作点云
  26325. var _a = e.buttons === Buttons.LEFT && viewport.alignment && handleState && viewport.alignment[handleState];
  26326. if (Potree.settings.editType == 'pano') {
  26327. var PanoEditor = window.viewer.modules.PanoEditor;
  26328. if (_a && PanoEditor.selectedPano) {
  26329. if ( /* !PanoEditor.selectedGroup || */!PanoEditor.checkIfAllLinked({
  26330. group: PanoEditor.selectedGroup
  26331. })) {
  26332. if (handleState == 'translate' && (e.drag.intersectStart.pointclouds && Common$1.getMixedSet(PanoEditor.selectedClouds, e.drag.intersectStart.pointclouds).length || PanoEditor.selectedPano.hovered) //平移时 拖拽到点云上 或 circle。(其中点云只需要intersect的点云中包含选择的点云中之一即可)
  26333. || handleState == 'rotate')
  26334. //旋转模式不需要intersect
  26335. {
  26336. pointclouds = PanoEditor.selectedClouds;
  26337. }
  26338. } else {
  26339. PanoEditor.dispatchEvent('needToDisConnect');
  26340. console.warn('选中的漫游点连通了整个数据集,不允许移动');
  26341. }
  26342. }
  26343. if (!pointclouds && e.buttons === Buttons.LEFT && viewport.rotateSide) {
  26344. //侧视图 (有时候会卡顿,是mousemove执行延迟了,一般发生在突然加载很多点云时)
  26345. //console.log('rotateSide', -e.drag.pointerDelta.x )
  26346. return PanoEditor.rotateSideCamera(-e.drag.pointerDelta.x);
  26347. }
  26348. } else if (Potree.settings.editType == 'merge') {
  26349. if (e.buttons === Buttons.LEFT && viewport.rotateSide) {
  26350. return MergeEditor.rotateSideCamera(-e.drag.pointerDelta.x);
  26351. }
  26352. } else {
  26353. /* if(Alignment.selectedClouds && Alignment.selectedClouds.length){//多个点云
  26354. pointclouds = a && e.drag.intersectStart.pointclouds && Common.getMixedSet(Alignment.selectedClouds, e.drag.intersectStart.pointclouds).length && Alignment.selectedClouds
  26355. }else{ */
  26356. //pointclouds = a && e.drag.intersectStart.pointcloud && [e.drag.intersectStart.pointcloud]
  26357. //}
  26358. if (_a && e.drag.intersectStart.pointcloud) {
  26359. pointclouds = [e.drag.intersectStart.pointcloud];
  26360. if (e.drag.intersectStart.pointcloud.dataset_id == Potree.settings.originDatasetId) {
  26361. var p = e.drag.intersectStart.pointclouds.find(p => p.dataset_id != Potree.settings.originDatasetId);
  26362. if (p) pointclouds = [p];
  26363. }
  26364. }
  26365. }
  26366. if (pointclouds) {
  26367. if (handleState == 'translate' && viewport.alignment.translateVec) {
  26368. //只能沿某个方向移动
  26369. _moveVec.projectOnVector(viewport.alignment.translateVec);
  26370. }
  26371. this.dispatchEvent({
  26372. type: "transformPointcloud",
  26373. intersect: e.intersect.orthoIntersect,
  26374. intersectStart: e.drag.intersectStart.orthoIntersect,
  26375. moveVec: _moveVec,
  26376. pointclouds,
  26377. camera
  26378. });
  26379. } else {
  26380. this.translationWorldDelta.add(_moveVec.negate());
  26381. }
  26382. } else {
  26383. //perspectiveCamera:
  26384. if (e.drag.intersectStart) {
  26385. //如果拖拽着点云
  26386. var ifInit = e.drag.z == void 0;
  26387. var pointerStartPos2d = e.drag.intersectStart.location.clone().project(camera); //识别到的点云点的位置
  26388. e.drag.z = pointerStartPos2d.z; //记录z,保持拖拽物体到屏幕距离不变,所以z深度不变(如果拖拽过程中没有缩放,这个z其实不变)
  26389. if (ifInit) {
  26390. //拖拽开始
  26391. e.drag.projectionMatrixInverse = camera.projectionMatrixInverse.clone();
  26392. //防止吸附到最近点上(因为鼠标所在位置并非识别到的点云点的位置,需要得到鼠标所在位置的3d坐标。)
  26393. var pointerStartPos2dReal = new Vector3(this.pointerDragStart.x, this.pointerDragStart.y, e.drag.z);
  26394. e.drag.translateStartPos = pointerStartPos2dReal.clone().unproject(camera);
  26395. //console.log('开始拖拽', e.pointer.clone())
  26396. }
  26397. //拖拽的过程中将projectionMatrixInverse替换成开始拖拽时的,因为near、far一直在变,会导致unproject计算出的3d坐标改变很大而闪烁。
  26398. var _projectionMatrixInverse = camera.projectionMatrixInverse;
  26399. camera.projectionMatrixInverse = e.drag.projectionMatrixInverse;
  26400. var newPos2d = new Vector3(e.pointer.x, e.pointer.y, e.drag.z);
  26401. var newPos3d = newPos2d.clone().unproject(camera);
  26402. var _moveVec2 = newPos3d.clone().sub(e.drag.translateStartPos /* e.drag.intersectStart.location */); //移动相机,保持鼠标下的位置永远不变,所以用鼠标下的新位置减去鼠标下的原始位置
  26403. camera.projectionMatrixInverse = _projectionMatrixInverse;
  26404. this.translationWorldDelta.copy(_moveVec2.negate()); //这里没法用add,原因未知,打开console时会跳动
  26405. //console.log('pan 1', this.translationWorldDelta.clone())
  26406. //四指松开剩三指时会偏移一下,暂不知道哪里的问题,或许跟开头防止点云吸附有关?
  26407. } else {
  26408. //如果鼠标没有找到和点云的交点,就假设移动整个模型(也可以去扩大范围寻找最近点云)
  26409. /* let center = viewer.scene.pointclouds[0].position;
  26410. let radius = camera.position.distanceTo(center);
  26411. let ratio = radius * Math.tan(THREE.Math.degToRad(camera.fov)/2) / 1000 */
  26412. /* let speed = this.currentViewport.getMoveSpeed()
  26413. if(FirstPersonControls.boundPlane){
  26414. speed = FirstPersonControls.boundPlane.distanceToPoint(this.currentViewport.position)
  26415. speed = Math.max(1 , speed)
  26416. } */
  26417. var lastIntersect = this.target || viewport.lastIntersect && (viewport.lastIntersect.location || viewport.lastIntersect); //该viewport的最近一次鼠标和点云的交点
  26418. if (!lastIntersect || !(lastIntersect instanceof Vector3)) lastIntersect = viewer.bound.center;
  26419. var speed = camera.position.distanceTo(lastIntersect);
  26420. var fov = cameraLight.getHFOVForCamera(camera, true);
  26421. var ratio = speed * Math.tan(fov / 2);
  26422. this.translationDelta.x -= e.drag.pointerDelta.x * ratio;
  26423. this.translationDelta.z -= e.drag.pointerDelta.y * ratio;
  26424. //console.log('pan2', e.drag.pointerDelta)
  26425. }
  26426. }
  26427. this.useAttenuation = false;
  26428. }
  26429. if (mode.includes('scale')) {
  26430. //触屏缩放
  26431. this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  26432. //if(!this.dollyStart)return
  26433. var scale = this.dollyEnd.length() / this.dollyStart.length();
  26434. var pointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5); //两个指头的中心点
  26435. dolly({
  26436. pointer,
  26437. scale,
  26438. camera,
  26439. drag: e.drag
  26440. });
  26441. this.dollyStart.copy(this.dollyEnd);
  26442. }
  26443. //最好按ctrl可以变为dollhouse的那种旋转
  26444. };
  26445. var drop = e => {
  26446. if (!this.enabled) return;
  26447. this.dispatchEvent({
  26448. type: 'end'
  26449. });
  26450. };
  26451. var dolly = function dolly() {
  26452. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  26453. if (Potree.settings.displayMode == 'showPanos' && _this.currentViewport == viewer.mainViewport /* this.currentViewport.unableChangePos */) {
  26454. //全景时
  26455. _this.dispatchEvent({
  26456. type: 'dollyStopCauseUnable',
  26457. delta: e.delta,
  26458. scale: e.scale
  26459. });
  26460. return;
  26461. }
  26462. var camera = e.camera;
  26463. if (camera.type == "OrthographicCamera") {
  26464. var ratio;
  26465. if (e.delta != void 0) {
  26466. //滚轮缩放
  26467. if (e.delta == 0) {
  26468. //mac
  26469. return;
  26470. } else if (e.delta < 0) {
  26471. ratio = 0.9;
  26472. } else if (e.delta > 0) {
  26473. ratio = 1.12; //增加的需要比减少的多一些,否则缩放相同次数下,r0 * ([1+s)(1-s)]^n = r0 * (1-s^2)^n < r0
  26474. }
  26475. } else {
  26476. ratio = e.scale; //触屏缩放
  26477. }
  26478. var zoom = camera.zoom * ratio;
  26479. var limit = camera.zoomLimit;
  26480. if (limit) zoom = MathUtils.clamp(zoom, limit.min, limit.max);
  26481. var pointerPos = new Vector3(e.pointer.x, e.pointer.y, 0.5);
  26482. var oldPos = pointerPos.clone().unproject(camera);
  26483. if (camera.zoom != zoom) {
  26484. camera.zoom = zoom;
  26485. camera.updateProjectionMatrix();
  26486. }
  26487. var newPos = pointerPos.clone().unproject(camera);
  26488. //定点缩放, 恢复一下鼠标所在位置的位置改变量
  26489. var moveVec = new Vector3().subVectors(newPos, oldPos);
  26490. _this.translationWorldDelta.add(moveVec.negate());
  26491. _this.useAttenuation = false;
  26492. } else {
  26493. var speed = _this.currentViewport.getMoveSpeed() * 7,
  26494. direction;
  26495. if (e.delta != void 0) {
  26496. //滚轮缩放
  26497. if (e.delta == 0) return; //mac
  26498. /*if(this.target && !e.intersect){//如果没有intersect点云且有target的话,就朝target的方向. 但无限靠近时有问题,且到背面时前进却是后退
  26499. direction = new THREE.Vector3().subVectors(this.target, camera.position).normalize()
  26500. }else{ */
  26501. direction = _this.viewer.inputHandler.getMouseDirection().direction; //定点缩放
  26502. if (e.intersect && e.intersect.location) {
  26503. //和intersect的墙越接近,速度越慢,便于focus细节
  26504. var dis = camera.position.distanceTo(e.intersect.location);
  26505. speed = MathUtils.clamp(dis * 0.1, 0.3, speed);
  26506. }
  26507. if (e.delta < 0) {
  26508. speed *= -1;
  26509. }
  26510. var slightly = _this.keys.ALT.some(e => _this.viewer.inputHandler.pressedKeys[e]);
  26511. slightly && (speed *= 0.2);
  26512. _this.useAttenuation = true;
  26513. } else {
  26514. //触屏缩放
  26515. direction = _this.viewer.inputHandler.getMouseDirection(e.pointer).direction; //定点缩放
  26516. if (e.drag.intersectStart) {
  26517. //和intersect的墙越接近,速度越慢,便于focus细节
  26518. var _dis = camera.position.distanceTo(e.drag.intersectStart.location);
  26519. var r = 1 - 1 / e.scale;
  26520. var closeMin = 0.1,
  26521. standardMin = 0.001,
  26522. disBound1 = 2,
  26523. disBound2 = 5;
  26524. if (math.closeTo(e.scale, 1, 0.03)) {
  26525. //如果偏差小于0.01,就不限制最小值,因为平移容易正负抖动,近距离有最小值的话抖动明显
  26526. closeMin = 0; //所以若缩放不明显(双指滑动慢),就不设置最低值。(这时候穿越障碍物会比较困难。)
  26527. }
  26528. //console.log('closeMin',closeMin)
  26529. var min = math.linearClamp(_dis, [disBound1, disBound2], [closeMin, standardMin]); //触屏和滚轮不一样,触发较为连续,所以最小值设低一点。若要保持双指相对点云位置不变,理想最小值是0,但那样就无法穿越点云(最小值太小的话穿越密集点云如树丛很困难;太大会打滑)所以当离点云近时增大最小值
  26530. speed = Math.sign(r) * MathUtils.clamp(_dis * Math.abs(r), min, speed);
  26531. //console.log(speed, dis, e.scale)
  26532. } else {
  26533. _this.useAttenuation = true;
  26534. var accelerate = 40;
  26535. if (math.closeTo(e.scale, 1, 0.02)) {
  26536. //缩放小的时候很可能是双指平移时,容易抖动,所以降低移动速度
  26537. accelerate *= Math.min(40 * Math.abs(e.scale - 1), 0.8);
  26538. }
  26539. // console.log('accelerate',accelerate)
  26540. var constantDis = _this.currentViewport.getMoveSpeed() * accelerate; //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
  26541. speed = (e.scale - 1) * constantDis;
  26542. }
  26543. }
  26544. var vec = direction.multiplyScalar(speed);
  26545. //this.translationWorldDelta.copy(vec)
  26546. _this.translationWorldDelta.add(vec);
  26547. //console.log(direction.toArray(), speed, e.scale)
  26548. }
  26549. return true;
  26550. };
  26551. var scroll = e => {
  26552. if (!this.enabled || !e.hoverViewport) return;
  26553. this.setCurrentViewport(e);
  26554. e.camera = e.hoverViewport.camera;
  26555. dolly(e);
  26556. };
  26557. var dblclick = e => {
  26558. if (!this.enabled) return;
  26559. if (!Potree.settings.dblToFocusPoint) return; //调试时才可双击
  26560. if (Potree.settings.displayMode == 'showPointCloud' /* !viewer.images360.isAtPano() */) this.zoomToLocation(e.mouse);
  26561. };
  26562. this.viewer.addEventListener('global_drag', drag);
  26563. /* this.viewer.addEventListener('global_touchmove', (e)=>{
  26564. if(!this.enabled)return
  26565. if(e.touches.length>1){//单指的就触发上一句
  26566. //console.log('global_touchmove' )
  26567. drag(e)
  26568. }
  26569. }); */
  26570. this.viewer.addEventListener('global_drop', drop);
  26571. this.viewer.addEventListener('global_mousewheel', scroll);
  26572. this.viewer.addEventListener('global_dblclick', dblclick);
  26573. var prepareScale = e => {
  26574. //触屏的scale
  26575. this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  26576. e.drag.camDisToPointStart = null;
  26577. };
  26578. var prepareRotate = e => {
  26579. this.pointerDragStart = e.pointer.clone();
  26580. if (e.viewer.name != 'mainViewer') return;
  26581. var intersect = e.intersect || e.dragViewport.lastIntersect;
  26582. //在数据集外部时绕中心点旋转,在数据集内部时绕intersect点旋转(其他数据集的点也可以) 或者 原地旋转镜头
  26583. var 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];
  26584. var rotCenter2d, rotCenter;
  26585. if (rotAroundPoint) {
  26586. var pivotType = this.target ? 'target' : viewer.atDatasets.length > 0 || Potree.settings.editType == 'pano' ? 'intersect' : viewer.inputHandler.selection.length ? 'selection' : this.target2 ? 'target2' : 'boundCenter';
  26587. rotCenter = pivotType == 'target' ? this.target : pivotType == 'intersect' ? intersect === null || intersect === void 0 ? void 0 : intersect.location : pivotType == 'selection' ? viewer.inputHandler.selection[0].position : pivotType == 'target2' ? this.target2 : viewer.bound && viewer.bound.center;
  26588. if (rotCenter) {
  26589. rotCenter2d = rotCenter.clone().project(e.dragViewport.camera); //点在屏幕中的位置。 若z>1 则在背面 或 超出far范围
  26590. } else {
  26591. rotAroundPoint = false;
  26592. }
  26593. }
  26594. this.rotateStartInfo = {
  26595. rotAroundPoint,
  26596. //定点旋转
  26597. rotCenter,
  26598. rotCenter2d
  26599. };
  26600. //缺点:多数据集绕中心点转很难操作,感觉可以也改为绕lastIntersect
  26601. //console.log('prepareRotate' )
  26602. };
  26603. var preparePan = e => {
  26604. //触屏的pan点云 还是会偏移
  26605. this.pointerDragStart = e.pointer.clone();
  26606. e.drag.z = void 0; //清空
  26607. drag(e); //触屏点击时更新的pointer直接用一次drag
  26608. //console.log('preparePan ' )
  26609. };
  26610. this.viewer.addEventListener('global_mousedown' /* 'startDragging' */, e => {
  26611. if (!this.enabled) return;
  26612. this.setCurrentViewport(e);
  26613. prepareRotate(e);
  26614. });
  26615. //注意,每次增减指头都会修改pointer,需要更新下状态
  26616. this.viewer.addEventListener('global_touchstart', e => {
  26617. if (!this.enabled) return;
  26618. if (e.touches.length == 2) {
  26619. //只监听开头两个指头
  26620. prepareScale(e);
  26621. preparePan(e);
  26622. } else if (e.touches.length >= 3) {
  26623. preparePan(e);
  26624. }
  26625. });
  26626. this.viewer.addEventListener('global_touchend', e => {
  26627. //e.touches是剩余的指头
  26628. if (!this.enabled) return;
  26629. if (e.touches.length == 2) {
  26630. //停止平移,开始scale
  26631. prepareScale(e);
  26632. preparePan(e);
  26633. } else if (e.touches.length == 1) {
  26634. //停止scale,开始rotate
  26635. prepareRotate(e);
  26636. } else if (e.touches.length >= 3) {
  26637. //重新准备下平移(因为抬起的指头可能包含平移使用的数据),否则抬起时漂移
  26638. preparePan(e);
  26639. }
  26640. });
  26641. /* this.viewer.addEventListener('enableChangePos', (e)=>{
  26642. if(!this.enabled)return
  26643. this.enableChangePos = e.canLeavePano
  26644. }) */
  26645. }
  26646. canMovePos(viewport) {
  26647. if (viewport == viewer.mainViewport && (Potree.settings.displayMode == 'showPanos' || viewer.images360.bumping || viewer.images360.latestToPano)) return false;else return true;
  26648. }
  26649. setEnable(enabled) {
  26650. this.enabled = enabled;
  26651. if (!enabled) {
  26652. this.yawDelta = this.pitchDelta = 0;
  26653. this.translationDelta.set(0, 0, 0);
  26654. this.translationWorldDelta.set(0, 0, 0);
  26655. }
  26656. }
  26657. setTarget(target, index) {
  26658. //绕该点旋转,类似orbitControl
  26659. if (index == 2) this.target2 = target;else this.target = target;
  26660. }
  26661. setFPCMoveSpeed(viewport) {
  26662. if (viewport.camera.type == 'OrthographicCamera') {
  26663. var s = 1 / viewport.camera.zoom;
  26664. viewport.setMoveSpeed(s);
  26665. } else {
  26666. //根据和漫游点的最短距离算moveSpeed。缺点:对于导入的无漫游点的数据集没有意义。
  26667. if (viewport == viewer.mainViewport && viewer.images360) {
  26668. var position = viewer.mainViewport.view.position;
  26669. var speed;
  26670. var pano = viewer.images360.findNearestPano();
  26671. if (!pano) {
  26672. if (!viewer.bound || viewer.bound.boundSize.x == 0) return;
  26673. var boundFloor = viewer.bound.boundingBox.clone();
  26674. boundFloor.max.z = boundFloor.min.z;
  26675. speed = boundFloor.distanceToPoint(viewer.mainViewport.view.position);
  26676. speed = Math.sqrt(speed) / 50;
  26677. } else {
  26678. var dis = pano.position.distanceTo(position);
  26679. var minSpeed = 0.05,
  26680. minDis = 3,
  26681. multiplier = 0.005;
  26682. speed = dis <= minDis ? minSpeed : minSpeed + (dis - minDis) * multiplier;
  26683. //console.log('dis', dis, 'speed', speed, pano.id )
  26684. }
  26685. viewer.setMoveSpeed(speed * 2);
  26686. }
  26687. //调试场景t-FhDWmV5xur 两个数据集,大的数据集没有漫游点。
  26688. }
  26689. }
  26690. setCurrentViewport() {
  26691. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  26692. //add
  26693. if (!this.enabled && !o.force) return;
  26694. if (o.hoverViewport && this.currentViewport != o.hoverViewport) {
  26695. this.currentViewport = o.hoverViewport;
  26696. //this.viewer.setMoveSpeed(this.currentViewport.radius/100);
  26697. this.setFPCMoveSpeed(this.currentViewport);
  26698. }
  26699. if (this.currentViewport.camera.type == 'OrthographicCamera') {
  26700. this.lockElevationOri = true;
  26701. this.lockRotation = true;
  26702. } else {
  26703. this.lockElevationOri = false;
  26704. this.lockRotation = false;
  26705. }
  26706. }
  26707. setScene(scene) {
  26708. this.scene = scene;
  26709. }
  26710. stop() {
  26711. this.yawDelta = 0;
  26712. this.pitchDelta = 0;
  26713. this.translationDelta.set(0, 0, 0);
  26714. }
  26715. zoomToLocation(mouse) {
  26716. if (!this.enabled) return;
  26717. var camera = this.scene.getActiveCamera();
  26718. /* let I = Utils.getMousePointCloudIntersection(
  26719. mouse,
  26720. camera,
  26721. this.viewer,
  26722. this.scene.pointclouds); */
  26723. var I = this.viewer.inputHandler.intersect;
  26724. if (!I) {
  26725. return;
  26726. }
  26727. var targetRadius = 0;
  26728. {
  26729. var minimumJumpDistance = 0.2;
  26730. var domElement = this.renderer.domElement;
  26731. var ray = Utils.mouseToRay(this.viewer.inputHandler.pointer, camera);
  26732. var {
  26733. origin,
  26734. direction
  26735. } = this.viewer.inputHandler.getMouseDirection();
  26736. var raycaster = new Raycaster();
  26737. raycaster.ray.set(origin, direction);
  26738. var nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  26739. var nodes2 = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, raycaster.ray);
  26740. var lastNode = nodes[nodes.length - 1];
  26741. var radius = lastNode.getBoundingSphere(new Sphere()).radius;
  26742. targetRadius = Math.min(this.scene.view.radius, radius);
  26743. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  26744. }
  26745. var d = this.scene.view.direction.multiplyScalar(-1);
  26746. var cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  26747. // TODO Unused: let controlsTargetPosition = I.location;
  26748. var animationDuration = 600;
  26749. var easing = TWEEN.Easing.Quartic.Out;
  26750. {
  26751. // animate
  26752. var value = {
  26753. x: 0
  26754. };
  26755. var tween = new TWEEN.Tween(value).to({
  26756. x: 1
  26757. }, animationDuration);
  26758. tween.easing(easing);
  26759. this.tweens.push(tween);
  26760. var startPos = this.scene.view.position.clone();
  26761. var targetPos = cameraTargetPosition.clone();
  26762. var startRadius = this.scene.view.radius;
  26763. var _targetRadius = cameraTargetPosition.distanceTo(I.location);
  26764. tween.onUpdate(() => {
  26765. var t = value.x;
  26766. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  26767. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  26768. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  26769. this.scene.view.radius = (1 - t) * startRadius + t * _targetRadius;
  26770. this.viewer.setMoveSpeed(this.scene.view.radius / 2.5);
  26771. });
  26772. tween.onComplete(() => {
  26773. this.tweens = this.tweens.filter(e => e !== tween);
  26774. });
  26775. tween.start();
  26776. }
  26777. }
  26778. update() {
  26779. var delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
  26780. if (!this.enabled) return;
  26781. //console.log('update')
  26782. var view = this.currentViewport.view;
  26783. {
  26784. // cancel move animations on user input
  26785. var changes = [this.yawDelta, this.pitchDelta, this.translationDelta.length(), this.translationWorldDelta.length()];
  26786. var changeHappens = changes.some(e => Math.abs(e) > 0.001);
  26787. if (changeHappens && this.tweens.length > 0) {
  26788. this.tweens.forEach(e => e.stop());
  26789. this.tweens = [];
  26790. }
  26791. }
  26792. {
  26793. // accelerate while input is given
  26794. var ih = this.viewer.inputHandler;
  26795. var moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  26796. var moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  26797. var moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  26798. var moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  26799. var moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  26800. var moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  26801. var rotateLeft = this.keys.Rotate_LEFT.some(e => ih.pressedKeys[e]);
  26802. var rotateRight = this.keys.Rotate_RIGHT.some(e => ih.pressedKeys[e]);
  26803. var rotateUp = this.keys.Rotate_UP.some(e => ih.pressedKeys[e]);
  26804. var rotateDown = this.keys.Rotate_DOWN.some(e => ih.pressedKeys[e]);
  26805. this.lockElevation = this.lockElevationOri || this.keys.SPACE.some(e => ih.pressedKeys[e]);
  26806. var slightly = this.keys.ALT.some(e => ih.pressedKeys[e]);
  26807. if (!this.lockRotation) {
  26808. if (rotateLeft) {
  26809. this.yawDelta -= 0.01;
  26810. } else if (rotateRight) {
  26811. this.yawDelta += 0.01;
  26812. }
  26813. if (rotateUp) {
  26814. this.pitchDelta -= 0.01;
  26815. } else if (rotateDown) {
  26816. this.pitchDelta += 0.01;
  26817. }
  26818. }
  26819. if (this.canMovePos(this.currentViewport) && !this.lockKey) {
  26820. if (this.lockElevation) {
  26821. var dir = view.direction;
  26822. dir.z = 0;
  26823. dir.normalize();
  26824. if (moveForward && moveBackward) {
  26825. this.translationWorldDelta.set(0, 0, 0);
  26826. } else if (moveForward) {
  26827. this.translationWorldDelta.copy(dir.multiplyScalar(this.currentViewport.getMoveSpeed()));
  26828. } else if (moveBackward) {
  26829. this.translationWorldDelta.copy(dir.multiplyScalar(-this.currentViewport.getMoveSpeed()));
  26830. }
  26831. } else {
  26832. if (moveForward && moveBackward) {
  26833. this.translationDelta.y = 0;
  26834. } else if (moveForward) {
  26835. this.translationDelta.y = this.currentViewport.getMoveSpeed() * (slightly ? 0.2 : 1);
  26836. } else if (moveBackward) {
  26837. this.translationDelta.y = -this.currentViewport.getMoveSpeed() * (slightly ? 0.2 : 1);
  26838. }
  26839. }
  26840. if (moveLeft && moveRight) {
  26841. this.translationDelta.x = 0;
  26842. } else if (moveLeft) {
  26843. this.translationDelta.x = -this.currentViewport.getMoveSpeed();
  26844. } else if (moveRight) {
  26845. this.translationDelta.x = this.currentViewport.getMoveSpeed();
  26846. }
  26847. if (moveUp && moveDown) {
  26848. this.translationWorldDelta.z = 0;
  26849. } else if (moveUp) {
  26850. this.translationWorldDelta.z = this.currentViewport.getMoveSpeed();
  26851. } else if (moveDown) {
  26852. this.translationWorldDelta.z = -this.currentViewport.getMoveSpeed();
  26853. }
  26854. if (moveUp || moveDown || moveForward || moveBackward) {
  26855. this.useAttenuation = false;
  26856. }
  26857. }
  26858. }
  26859. {
  26860. // apply rotation
  26861. var yaw = view.yaw;
  26862. var pitch = view.pitch;
  26863. yaw += this.yawDelta; /* * delta; */
  26864. pitch += this.pitchDelta; /* * delta; */
  26865. view.yaw = yaw;
  26866. view.pitch = pitch;
  26867. if (this.yawDelta || this.pitchDelta) {
  26868. view.cancelFlying('rotate');
  26869. }
  26870. this.yawDelta = 0;
  26871. this.pitchDelta = 0;
  26872. }
  26873. /* if(this.translationWorldDelta.length()>0) {
  26874. // console.log('translationDelta')
  26875. } */
  26876. {
  26877. // apply translation
  26878. view.translate(this.translationDelta.x, /* * delta, */
  26879. this.translationDelta.y, /* * delta, */
  26880. this.translationDelta.z /* * delta */);
  26881. this.translationDelta.set(0, 0, 0);
  26882. //if(this.translationWorldDelta.length())console.log(translationWorldDelta)
  26883. view.translateWorld(this.translationWorldDelta.x /* * delta */, this.translationWorldDelta.y /* * delta */, this.translationWorldDelta.z /* * delta */);
  26884. //this.translationWorldDelta.set(0,0,0)
  26885. }
  26886. {// set view target according to speed
  26887. //view.radius = 1 * this.currentViewport.getMoveSpeed();
  26888. /* if(viewer.bound) view.radius = view.position.distanceTo(viewer.bound.center)
  26889. let speed = view.radius/100;
  26890. this.viewer.setMoveSpeed(speed); */
  26891. //this.setMoveSpeed()
  26892. }
  26893. if (this.useAttenuation) {
  26894. //只有滚轮缩放时开启
  26895. var attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  26896. /*this.yawDelta *= attenuation;
  26897. this.pitchDelta *= attenuation;
  26898. this.translationDelta.multiplyScalar(attenuation);*/
  26899. this.translationWorldDelta.multiplyScalar(attenuation);
  26900. } else {
  26901. this.translationWorldDelta.set(0, 0, 0);
  26902. }
  26903. }
  26904. }
  26905. ;
  26906. /**
  26907. * @author mschuetz / http://mschuetz.at
  26908. *
  26909. *
  26910. */
  26911. var {
  26912. Buttons: Buttons$1
  26913. } = Potree.defines;
  26914. class InputHandler extends EventDispatcher {
  26915. constructor(viewer, scene) {
  26916. super();
  26917. this.viewer = viewer;
  26918. this.renderer = viewer.renderer;
  26919. this.domElement = this.renderer.domElement;
  26920. this.enabled = true;
  26921. this.scene = scene;
  26922. this.interactiveScenes = [];
  26923. this.interactiveObjects = new Set();
  26924. this.inputListeners = [];
  26925. this.blacklist = new Set();
  26926. this.drag = null;
  26927. this.mouse = new Vector2(0, 0);
  26928. //add:
  26929. this.pointer = new Vector2(0, 0); //交互点的屏幕坐标,有别于DOM坐标,在此存放NDC坐标。(NDC,三维常用坐标系,二维坐标,整个屏幕映射范围(-1,1),屏幕中心为原点,+Y朝上,+X朝右)
  26930. this.mouseDownMouse = new Vector2(0, 0);
  26931. this.selection = [];
  26932. this.hoveredElements = [];
  26933. this.pressedKeys = {};
  26934. this.wheelDelta = 0;
  26935. this.speed = 1;
  26936. this.logMessages = false;
  26937. if (this.domElement.tabIndex === -1) {
  26938. this.domElement.tabIndex = 2222;
  26939. }
  26940. this.lastPointerUpTime = 0;
  26941. this.touches = [];
  26942. this.interactHistory = {
  26943. move: 0
  26944. }; //add
  26945. this.hoverViewport = viewer.viewports[0];
  26946. document.addEventListener('mouseup', function (event) {
  26947. event.preventDefault();
  26948. }, {
  26949. passive: false
  26950. });
  26951. this.domElement.addEventListener('contextmenu', event => {
  26952. event.preventDefault();
  26953. }, false);
  26954. this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);
  26955. this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), {
  26956. passive: false,
  26957. useCapture: false
  26958. });
  26959. window.addEventListener('mouseup', this.onMouseUp.bind(this), {
  26960. passive: false,
  26961. useCapture: false
  26962. });
  26963. if (Potree.isIframeChild) {
  26964. //子页面的话在父页面也要加侦听(应该不会有多层吧?否则要一直加到最外层)
  26965. //window.parent.addEventListener('mouseup', this.onMouseUp.bind(this), false); //可能跨域
  26966. //window.parent.postMessage('listenMouseup', '*');
  26967. window.addEventListener('mouseout', this.onMouseUp.bind(this), false); //cancel drag
  26968. }
  26969. this.domElement.addEventListener('mouseout', () => {
  26970. this.containsMouse = false;
  26971. }, false);
  26972. this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), {
  26973. passive: false,
  26974. useCapture: false
  26975. });
  26976. //add
  26977. /* this.domElement.addEventListener("pointerout", this.onMouseUp.bind(this)),
  26978. this.domElement.addEventListener("pointercancel", this.onMouseUp.bind(this)),
  26979. */
  26980. this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);
  26981. this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox
  26982. //this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this)); //因为双击时间间隔是跟随系统的所以不好判断
  26983. window.addEventListener('keydown', this.onKeyDown.bind(this)); //原先是this.domElement,这样的话一开始要点击屏幕后才能监听到
  26984. window.addEventListener('keyup', this.onKeyUp.bind(this));
  26985. window.addEventListener('blur', this.onKeyUp.bind(this)); //add
  26986. this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));
  26987. this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));
  26988. this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));
  26989. {
  26990. this.measuring = []; //正在编辑的measure
  26991. //let mesureInfo = new THREE.EventDispatcher()
  26992. this.addEventListener('measuring', e => {
  26993. //true优先级高于false, 正在添加时dropMarker也不会停止
  26994. //Potree.Utils.updateVisible(mesureInfo, e.situation, e.v, 0, e.v?'add':'cancel' )//借用该函数,使true优先级高于false,防止正在添加时dropMarker而停止
  26995. if (e.v) {
  26996. this.measuring.includes(e.object) || this.measuring.push(e.object);
  26997. } else {
  26998. var index = this.measuring.indexOf(e.object);
  26999. index > -1 && this.measuring.splice(index, 1);
  27000. }
  27001. if (this.measuring.length == 0 && this.measuring.length > 0) {
  27002. this.viewer.viewports.forEach(viewport => {
  27003. this.collectClosePoints(viewport, true); //forceUpdate
  27004. });
  27005. }
  27006. //console.log('measuring',e.v, e.cause, e.situation, this.measuring.length )
  27007. });
  27008. }
  27009. window.viewer.addEventListener('loopStart', () => {
  27010. this.interactHistory = {}; //清空
  27011. });
  27012. }
  27013. /* addInputListener (listener) {
  27014. this.inputListeners.push(listener);
  27015. }
  27016. removeInputListener (listener) {
  27017. this.inputListeners = this.inputListeners.filter(e => e !== listener);
  27018. }
  27019. getSortedListeners(){
  27020. return this.inputListeners.sort( (a, b) => {
  27021. let ia = (a.importance !== undefined) ? a.importance : 0;
  27022. let ib = (b.importance !== undefined) ? b.importance : 0;
  27023. return ib - ia;
  27024. });
  27025. } */
  27026. //统一跟第一个触碰的viewport相同
  27027. updateTouchesInfo(e) {
  27028. var viewport, pointer, camera;
  27029. var oldTouches = this.touches;
  27030. var changedTouches = Array.from(e.changedTouches);
  27031. var touches = Array.from(e.touches);
  27032. this.touches = touches.map(touch => {
  27033. var touch_ = oldTouches.find(a => a.touch.identifier == touch.identifier);
  27034. var pointer = touch_ && touch_.pointer; //复制原先的值
  27035. return {
  27036. touch,
  27037. pointer
  27038. };
  27039. });
  27040. if (e.touches.length > 0) {
  27041. var newTouches = touches.filter(e => !oldTouches.some(a => a.touch.identifier == e.identifier) && !changedTouches.some(a => a.identifier == e.identifier)); //从按钮处划过时e.touches中会出现this.touches和changedTouches中都没有的identifier
  27042. if (newTouches.length > 0) {
  27043. console.warn('has new', newTouches.map(e => e.identifier));
  27044. }
  27045. newTouches.concat(changedTouches).forEach(touch => {
  27046. //修改changedTouches的
  27047. var touch_ = this.touches.find(a => a.touch.identifier == touch.identifier);
  27048. if (touch_) {
  27049. var a = this.getPointerInViewport(touch.pageX, touch.pageY, this.dragViewport || viewport, new Vector2());
  27050. touch_.pointer = a.pointer.clone();
  27051. viewport = a.viewport;
  27052. camera = a.camera;
  27053. }
  27054. });
  27055. //使用当前touches的平均
  27056. if (e.touches.length > 1) {
  27057. var pageX = Common$1.average(e.touches, "pageX");
  27058. var pageY = Common$1.average(e.touches, "pageY");
  27059. var a = this.getPointerInViewport(pageX, pageY, viewport, new Vector2());
  27060. this.pointer.copy(a.pointer);
  27061. //console.log('updateTouchesInfo', this.pointer.clone())
  27062. } else {
  27063. this.pointer = this.touches[0].pointer.clone(); //更新,使用当前touches中的第一个
  27064. }
  27065. /* if(this.touches.find(e=>!e.pointer)){
  27066. console.error(' touches has no pointer', oldTouches.map(e=>e.touch.identifier),
  27067. Array.from(e.touches).map(e=>e.identifier), Array.from(e.changedTouches).map(e=>e.identifier) )
  27068. } */
  27069. //console.log(this.touches)
  27070. //console.log('更新pointer1',this.pointer.toArray())
  27071. return {
  27072. viewport,
  27073. camera /* , pointer:this.pointer */
  27074. };
  27075. }
  27076. }
  27077. onTouchStart(e) {
  27078. if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');
  27079. e.preventDefault();
  27080. /* if (e.touches.length === 1 || !this.drag) { //!this.drag代表一次性下了两个指头
  27081. let rect = this.domElement.getBoundingClientRect();
  27082. let x = e.touches[0].pageX
  27083. let y = e.touches[0].pageY
  27084. this.dealPointerDown(x,y,e,true)
  27085. }else{
  27086. this.updateTouchesInfo(e)
  27087. this.drag.end.copy(this.pointer)
  27088. } */
  27089. this.dealPointerDown(e, true);
  27090. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, true), {
  27091. type: 'global_' + e.type,
  27092. changedTouches: e.changedTouches
  27093. }));
  27094. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  27095. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  27096. ) */
  27097. //console.log('')
  27098. }
  27099. onTouchMove(e) {
  27100. if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');
  27101. e.preventDefault();
  27102. /* if (e.touches.length === 1) {
  27103. let rect = this.domElement.getBoundingClientRect();
  27104. let x = e.touches[0].pageX;
  27105. let y = e.touches[0].pageY;
  27106. }else{
  27107. this.updateTouchesInfo(e)
  27108. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
  27109. this.drag.end.copy(this.pointer)
  27110. }
  27111. */
  27112. this.dealPointerMove(e, true);
  27113. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, true), {
  27114. type: 'global_' + e.type,
  27115. changedTouches: e.changedTouches
  27116. }));
  27117. /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
  27118. 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
  27119. ) */
  27120. }
  27121. onTouchEnd(e) {
  27122. if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');
  27123. e.preventDefault();
  27124. //console.log('onTouchEnd')
  27125. this.updateTouchesInfo(e);
  27126. /* if (e.touches.length === 0) {
  27127. let rect = this.domElement.getBoundingClientRect();
  27128. let x = e.changedTouches[0].pageX //万一一次松开两个指头的怎么办
  27129. let y = e.changedTouches[0].pageY
  27130. this.dealPointerUp(x,y,e,true)
  27131. }else {
  27132. this.drag.end.copy(this.pointer)
  27133. } */
  27134. this.dealPointerUp(e, true);
  27135. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, true), {
  27136. type: 'global_' + e.type
  27137. }));
  27138. //console.log('touchend length '+e.touches.length, this.touches.length)
  27139. }
  27140. onKeyDown(e) {
  27141. if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
  27142. if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') return; //正在输入文字 或e.srcElement
  27143. if (!this.containsMouse) return; //在别的ui上无效
  27144. // DELETE
  27145. /* if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {
  27146. this.dispatchEvent({
  27147. type: 'delete',
  27148. selection: this.selection
  27149. });
  27150. this.deselectAll();
  27151. } */
  27152. this.dispatchEvent({
  27153. type: 'keydown',
  27154. keyCode: e.keyCode,
  27155. event: e
  27156. });
  27157. // for(let l of this.getSortedListeners()){
  27158. // l.dispatchEvent({
  27159. // type: "keydown",
  27160. // keyCode: e.keyCode,
  27161. // event: e
  27162. // });
  27163. // }
  27164. this.pressedKeys[e.keyCode] = true;
  27165. // e.preventDefault();
  27166. }
  27167. onKeyUp(e) {
  27168. if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');
  27169. if (e.keyCode != void 0) {
  27170. delete this.pressedKeys[e.keyCode];
  27171. } else {
  27172. this.pressedKeys = {};
  27173. }
  27174. e.preventDefault();
  27175. }
  27176. onDoubleClick(e) {
  27177. if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');
  27178. var consumed = false;
  27179. for (var hovered of this.hoveredElements) {
  27180. if (hovered._listeners && hovered._listeners['dblclick']) {
  27181. hovered.object.dispatchEvent({
  27182. type: 'dblclick',
  27183. mouse: this.mouse,
  27184. object: hovered.object
  27185. });
  27186. consumed = true;
  27187. break;
  27188. }
  27189. }
  27190. if (!consumed) {
  27191. /* for (let inputListener of this.getSortedListeners()) {
  27192. inputListener. */
  27193. this.viewer.dispatchEvent({
  27194. type: 'global_dblclick',
  27195. mouse: this.mouse,
  27196. object: null
  27197. });
  27198. //}
  27199. }
  27200. this.needSingleClick = false; //add
  27201. e.preventDefault();
  27202. }
  27203. onMouseClick(e) {
  27204. if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');
  27205. e.preventDefault();
  27206. }
  27207. dealPointerDown(e, isTouch) {
  27208. e.preventDefault();
  27209. //重新获取一下pointer, 因点击了浏览器的按钮展开列表时 move回来不会触发onmousemove,所以pointer是旧的
  27210. if (isTouch) {
  27211. var {
  27212. camera,
  27213. viewport
  27214. } = this.updateTouchesInfo(e);
  27215. if (this.drag) {
  27216. //因为触屏在按下前缺少pointermove所以要更新下
  27217. this.drag.end = this.pointer.clone();
  27218. }
  27219. } else {
  27220. var {
  27221. camera,
  27222. viewport
  27223. } = this.getPointerInViewport(e.clientX, e.clientY);
  27224. }
  27225. this.dragViewport = this.hoverViewport = viewport;
  27226. //if(isTouch || !Potree.settings.intersectWhenHover ){
  27227. if (isTouch || !this.dragViewport.view.isFlying() && Potree.settings.intersectWhenHover && Potree.settings.editType != 'pano') {
  27228. //漫游点编辑如果拖拽前getIntersect旋转会延迟
  27229. //isTouch必须更新 否则是旧的
  27230. this.hoveredElements = this.getHoveredElements();
  27231. var dontIntersect = false;
  27232. this.intersect = this.getIntersect({
  27233. viewport,
  27234. dontIntersect,
  27235. clientX: e.clientX,
  27236. clientY: e.clientY
  27237. }); //更新intersect,避免在没有mousemove但flyToPano后intersect未更新。
  27238. //this.intersect = this.getWholeIntersect()
  27239. }
  27240. if (!viewport) return; //why add this?
  27241. if (!this.drag) {
  27242. var target = (isTouch || e.button == MOUSE.LEFT) && this.hoveredElements.find(el =>
  27243. //只有左键能拖拽
  27244. el.object._listeners && el.object._listeners['drag'] && el.object._listeners['drag'].length > 0);
  27245. if (target) {
  27246. this.startDragging(target.object, {
  27247. location: target.point
  27248. });
  27249. } else {
  27250. this.startDragging(null);
  27251. }
  27252. }
  27253. this.drag.intersectStart = this.intersect;
  27254. if (!isTouch || e.touches.length == 1) {
  27255. var consumed = false;
  27256. var consume = () => {
  27257. return consumed = true;
  27258. };
  27259. //if (this.hoveredElements.length === 0) {
  27260. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27261. type: 'global_mousedown'
  27262. }));
  27263. for (var hovered of this.hoveredElements) {
  27264. var object = hovered.object;
  27265. object.dispatchEvent({
  27266. type: 'mousedown',
  27267. viewer: this.viewer,
  27268. consume: consume
  27269. });
  27270. if (consumed) {
  27271. break;
  27272. }
  27273. }
  27274. }
  27275. this.mouseDownMouse = this.mouse.clone();
  27276. this.pointerDownTime = Date.now();
  27277. }
  27278. onMouseDown(e) {
  27279. if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');
  27280. this.dealPointerDown(e);
  27281. }
  27282. /* getWholeIntersect(hoveredElements, intersectPoint){//add
  27283. hoveredElements = hoveredElements || this.hoveredElements
  27284. intersectPoint = intersectPoint || this.intersectPoint
  27285. if(Potree.settings.intersectOnObjs && hoveredElements[0] && hoveredElements[0].object.isModel){
  27286. return {//模拟点云的intersectPoint的结构写法
  27287. hoveredElement : hoveredElements[0] ,
  27288. location: hoveredElements[0].point,
  27289. point: {normal: hoveredElements[0].face.normal },
  27290. distance: hoveredElements[0].distance,
  27291. object: hoveredElements[0].object
  27292. }
  27293. }else return intersectPoint
  27294. } */
  27295. getEventDesc(e, isTouch) {
  27296. //搜集dispatchEvent要给的一般数据
  27297. var o = {
  27298. viewer: this.viewer,
  27299. mouse: this.mouse,
  27300. pointer: this.pointer,
  27301. drag: this.drag,
  27302. isTouch,
  27303. dragViewport: this.dragViewport,
  27304. hoverViewport: this.hoverViewport,
  27305. // button: isTouch ? 0 : e.button,
  27306. //intersectPoint:this.intersectPoint,
  27307. hoveredElement: this.hoveredElements[0],
  27308. intersect: this.intersect //this.getWholeIntersect() , //可能包含mesh上的,针对融合页面
  27309. };
  27310. if (e) {
  27311. o.isAtDomElement = e.target == this.domElement;
  27312. }
  27313. if (isTouch) {
  27314. o.touches = this.touches;
  27315. } else if (e) {
  27316. o.button = e.button;
  27317. o.buttons = e.buttons;
  27318. }
  27319. return o;
  27320. }
  27321. dealPointerUp(e, isTouch) {
  27322. if (!this.drag) {
  27323. // 在canvas外mousedown
  27324. return;
  27325. }
  27326. this.drag.end.copy(this.pointer);
  27327. if (isTouch && e.touches.length >= 1) {
  27328. return;
  27329. }
  27330. var now = Date.now();
  27331. if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
  27332. e.preventDefault();
  27333. var pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
  27334. var pressTime = now - this.pointerDownTime;
  27335. var noMovement = this.drag.pointerDelta.length() == 0; //this.getNormalizedDrag().length() === 0;
  27336. var consumed = false;
  27337. var consume = () => {
  27338. return consumed = true;
  27339. };
  27340. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27341. type: 'global_mouseup',
  27342. pressDistance,
  27343. consume
  27344. }));
  27345. if (this.hoveredElements.length > 0) {
  27346. var hovered = this.hoveredElements.map(e => e.object).find(e => e._listeners && e._listeners['mouseup']);
  27347. if (hovered) {
  27348. hovered.dispatchEvent({
  27349. type: 'mouseup',
  27350. viewer: this.viewer,
  27351. consume: consume
  27352. });
  27353. }
  27354. }
  27355. if (this.drag) {
  27356. //拖拽结束
  27357. if (this.drag.object /* && e.button == THREE.MOUSE.LEFT */) {
  27358. //add LEFT
  27359. if (this.logMessages) console.log("".concat(this.constructor.name, ": drop ").concat(this.drag.object.name));
  27360. this.drag.object.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27361. type: 'drop',
  27362. pressDistance
  27363. }));
  27364. } else {
  27365. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27366. type: 'global_drop',
  27367. pressDistance
  27368. }));
  27369. }
  27370. // check for a click
  27371. if (!Potree.settings.disableClick && pressDistance < Potree.config.clickMaxDragDis && pressTime < Potree.config.clickMaxPressTime && !e.unableClick) {
  27372. var clickElement;
  27373. if (this.hoveredElements) {
  27374. clickElement = this.hoveredElements.find(e => e.object._listeners['click']);
  27375. if (clickElement) {
  27376. var canceled;
  27377. var cancel = () => {
  27378. return canceled = true;
  27379. };
  27380. //console.log('clickElement',clickElement)
  27381. if (this.logMessages) console.log("".concat(this.constructor.name, ": click ").concat(clickElement.name));
  27382. clickElement.object.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27383. type: 'click',
  27384. pressDistance,
  27385. cancel,
  27386. consume
  27387. }));
  27388. if (canceled) {
  27389. //比如只需要右键的话,可以忽视左键的点击
  27390. clickElement = null;
  27391. }
  27392. }
  27393. }
  27394. var selectable;
  27395. if ( /* !consumed && */!this.fixSelection) {
  27396. if (e.button === MOUSE.LEFT) {
  27397. //if (noMovement) {
  27398. selectable = this.hoveredElements.find(el => el.object._listeners && el.object._listeners['select']);
  27399. if (selectable) {
  27400. selectable = selectable.object;
  27401. if (this.isSelected(selectable)) {
  27402. this.deselectAll();
  27403. } else {
  27404. this.deselectAll();
  27405. this.toggleSelection(selectable);
  27406. }
  27407. consumed = true; //add
  27408. } else {
  27409. if (this.selection.length > 0) consumed = true; //add 取消选择后,阻断后续
  27410. this.deselectAll();
  27411. }
  27412. //}
  27413. } else if (e.button === MOUSE.RIGHT /* && noMovement */) {
  27414. this.deselectAll();
  27415. }
  27416. }
  27417. var desc = this.getEventDesc(e, isTouch);
  27418. if (!consumed) {
  27419. this.viewer.dispatchEvent($.extend(desc, {
  27420. type: 'global_click',
  27421. pressDistance,
  27422. clickElement: clickElement /* || selectable */,
  27423. consume
  27424. }));
  27425. }
  27426. //增加 单击:
  27427. this.needSingleClick = true;
  27428. consumed || setTimeout(() => {
  27429. if (this.needSingleClick) {
  27430. this.viewer.dispatchEvent($.extend(desc, {
  27431. type: 'global_single_click',
  27432. pressDistance,
  27433. clickElement
  27434. }));
  27435. }
  27436. }, Potree.config.doubleClickTime + 1);
  27437. //自行执行双击:
  27438. if (!consumed && now - this.lastClickTime < Potree.config.doubleClickTime) {
  27439. this.onDoubleClick(e);
  27440. }
  27441. consumed || (this.lastClickTime = now);
  27442. }
  27443. this.drag = null;
  27444. }
  27445. this.dragViewport = null;
  27446. }
  27447. onMouseUp(e) {
  27448. this.dealPointerUp(e);
  27449. }
  27450. getPointerInViewport(clientX, clientY, viewForceAt, pointer) {
  27451. var rect = this.domElement.getBoundingClientRect();
  27452. var x = clientX - rect.left;
  27453. var y = clientY - rect.top;
  27454. var camera;
  27455. var viewport;
  27456. pointer = pointer || this.pointer;
  27457. //if(this.viewer.viewports || viewForceAt){
  27458. var getDimension = view => {
  27459. var left = Math.ceil(this.domElement.clientWidth * view.left),
  27460. bottom = Math.ceil(this.domElement.clientHeight * view.bottom),
  27461. width = Math.ceil(this.domElement.clientWidth * view.width),
  27462. height = Math.ceil(this.domElement.clientHeight * view.height),
  27463. top = this.domElement.clientHeight - bottom - height;
  27464. return {
  27465. left,
  27466. bottom,
  27467. width,
  27468. height,
  27469. top
  27470. };
  27471. };
  27472. var getView = (view, left, bottom, width, height, top) => {
  27473. this.mouse.set(x - left, y - top);
  27474. Utils.convertScreenPositionToNDC(pointer, this.mouse, width, height);
  27475. //console.log('更新pointer2',this.pointer.toArray())
  27476. camera = view.camera;
  27477. viewport = view;
  27478. };
  27479. if (viewForceAt) {
  27480. var {
  27481. left: _left,
  27482. bottom: _bottom,
  27483. width: _width,
  27484. height: _height,
  27485. top: _top
  27486. } = getDimension(viewForceAt);
  27487. getView(viewForceAt, _left, _bottom, _width, _height, _top);
  27488. } else {
  27489. var length = this.viewer.viewports.length;
  27490. //var getif = false
  27491. for (var i = 0; i < length; i++) {
  27492. var view = this.viewer.viewports[i];
  27493. if (!view.active) continue;
  27494. var {
  27495. left,
  27496. bottom,
  27497. width,
  27498. height,
  27499. top
  27500. } = getDimension(view);
  27501. if (x >= left && x <= left + width && y >= top && y <= top + height) {
  27502. getView(view, left, bottom, width, height, top);
  27503. //getif = true
  27504. break;
  27505. }
  27506. }
  27507. }
  27508. return {
  27509. camera,
  27510. viewport,
  27511. pointer
  27512. };
  27513. }
  27514. ifBlockedByIntersect() {
  27515. var {
  27516. point,
  27517. margin = 0,
  27518. cameraPos,
  27519. pickWindowSize,
  27520. pano,
  27521. useDepthTex,
  27522. viewport
  27523. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  27524. //某点是否被遮挡(不允许camera修改位置, 因为depthTex不好置换)
  27525. viewport = viewport || this.hoverViewport || viewer.mainViewport;
  27526. var intersect = this.getIntersect({
  27527. viewport,
  27528. onlyGetIntersect: true,
  27529. pickWindowSize,
  27530. useDepthTex,
  27531. point,
  27532. cameraPos,
  27533. pano
  27534. });
  27535. var cameraPos_ = !cameraPos && pano ? pano.position : cameraPos || viewport.view.position;
  27536. if (intersect && intersect.distance + margin <= point.distanceTo(cameraPos_)) {
  27537. return intersect; //被遮挡
  27538. }
  27539. //点云模式,对没加载出的点云不准确。 尤其是需要修改相机位置时,因临时修改并不能使点云加载。
  27540. }
  27541. collectClosePoints(viewport, forceUpdate) {
  27542. //获取吸附点
  27543. if (!Potree.settings.adsorption) return;
  27544. var point2ds = [];
  27545. //吸附测量线端点
  27546. viewer.scene.measurements.forEach(e => {
  27547. if (this.measuring.includes(e)) return; //不吸附到正在拖拽的自身
  27548. point2ds.push(...e.getPointsPos2d(viewport, forceUpdate));
  27549. });
  27550. return point2ds;
  27551. }
  27552. getIntersect() {
  27553. var {
  27554. viewport,
  27555. onlyGetIntersect,
  27556. pickWindowSize,
  27557. dontIntersect,
  27558. usePointcloud,
  27559. useDepthTex,
  27560. all,
  27561. highLevelCloud,
  27562. cameraPos,
  27563. pointSize,
  27564. pointclouds,
  27565. point,
  27566. pano,
  27567. clientX,
  27568. clientY,
  27569. resolution
  27570. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  27571. // usePointcloud:必须使用点云
  27572. var intersect, intersectPoint, intersectOnModel, allElements;
  27573. var camera = viewport.camera;
  27574. var raycaster;
  27575. viewer.addTimeMark('getIntersect', 'start');
  27576. var getByDepthTex = () => {
  27577. var intersect;
  27578. if (point) {
  27579. var _cameraPos = pano ? pano.position : camera.position;
  27580. var _dir = new Vector3().subVectors(point, _cameraPos).normalize();
  27581. intersect = {
  27582. dir: _dir
  27583. };
  27584. } else {
  27585. intersect = Utils.getIntersect(camera, [viewer.images360.cube], this.pointer, raycaster);
  27586. }
  27587. intersectPoint = viewer.images360.depthSampler.sample(intersect, pano, !!point); //可能不准确, 因pano可能未加载depthTex
  27588. if (intersectPoint && Potree.settings.depTexLocBindDataset) {
  27589. intersectPoint.pointcloud = (pano || viewer.images360.currentPano).pointcloud;
  27590. //在全景模式下,虽然深度图上的点可能对应别的pointcloud,但因为是在当前全景图处得到的,所以即使将原本对应的点云移走,该点也不移动是有道理的。它可以永远跟着该全景图。
  27591. }
  27592. };
  27593. var getByCloud = () => {
  27594. var pointer, mouse, ifCenter;
  27595. if (point) {
  27596. //指定了目标点,而非只是用pointer所在位置
  27597. cameraPos && camera.position.copy(cameraPos);
  27598. camera.lookAt(point);
  27599. camera.updateMatrixWorld();
  27600. ifCenter = true;
  27601. //pointer = this.pointer.clone()
  27602. //mouse = this.mouse.clone()
  27603. //this.pointer.set(0,0) //画布中心
  27604. //this.mouse.set(Math.round(viewport.resolution.x/2), Math.round(viewport.resolution.y/2))
  27605. }
  27606. intersectPoint = viewport.noPointcloud || dontIntersect ? null : Utils.getMousePointCloudIntersection(viewport, this.mouse, this.pointer, camera, this.viewer, pointclouds || this.viewer.scene.pointclouds, {
  27607. pickClipped: true,
  27608. ifCenter,
  27609. all,
  27610. measuring: this.measuring.length > 0 || highLevelCloud,
  27611. pickWindowSize,
  27612. cameraChanged: !!point,
  27613. pointSize,
  27614. resolution
  27615. });
  27616. //恢复
  27617. if (point) {
  27618. viewport.view.applyToCamera(camera);
  27619. //this.pointer.copy(pointer)
  27620. //this.mouse.copy(mouse)
  27621. }
  27622. };
  27623. if (this.measuring.length && Potree.settings.adsorption) {
  27624. //吸附
  27625. var points = this.collectClosePoints(viewport);
  27626. var points2 = points.filter(e => e.trueSide && e.inSight && math.closeTo(this.mouse, e.posInViewport, Potree.config.measure.adsorptMinDis));
  27627. var disArr = points2.map(e => e.pos.distanceToSquared(this.mouse));
  27628. var min = points2.slice().sort((a, b) => disArr[points.indexOf(a)] - disArr[points.indexOf(b)]);
  27629. if (min[0]) {
  27630. intersect = {
  27631. //hoveredElement
  27632. location: min[0].pos3d,
  27633. //point: {normal: allElements[0].face.normal },
  27634. //normal
  27635. //distance
  27636. object: min[0].object,
  27637. adsorption: true
  27638. };
  27639. console.log('找到吸附点', min[0].pos3d, min[0].object.uuid);
  27640. }
  27641. }
  27642. if (!intersect) {
  27643. var _intersect;
  27644. var canUseDepthTex = (Potree.settings.displayMode == 'showPanos' || useDepthTex) && viewer.images360.currentPano.pointcloud.hasDepthTex && viewport == viewer.mainViewport && !usePointcloud;
  27645. if (canUseDepthTex) getByDepthTex();else if (Potree.settings.mergeType2 && Potree.settings.displayMode == 'showPanos' && !viewer.images360.currentPano.pointcloud.isPointcloud) {} //融合页面进入非点云的场景的全景模式不用pick
  27646. else getByCloud();
  27647. /* if(canUseDepthTex && this.measuring.length){
  27648. getByDepthTex()
  27649. }else{
  27650. getByCloud()
  27651. if(!intersectPoint && canUseDepthTex ){ //若在测量,先尝试点云,再用全景 //后来发现有深度图的点云全景visibleNode为空,pick不到的
  27652. getByDepthTex()
  27653. }
  27654. } */
  27655. //console.log(viewport.name , intersectPoint && intersectPoint.location )
  27656. if (Potree.settings.intersectOnObjs && !dontIntersect) {
  27657. if (point) {
  27658. raycaster = new Raycaster();
  27659. raycaster.camera = camera;
  27660. var dir = new Vector3().subVectors(point, camera.position).normalize();
  27661. raycaster.set(camera.position, dir); //var origin = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
  27662. }
  27663. allElements = this.getHoveredElements(viewer.objs.children, true, raycaster);
  27664. if (allElements[0]) {
  27665. var normal, localNormal;
  27666. if (allElements[0].object.fileType == '3dgs') {
  27667. normal = allElements[0].normal;
  27668. } else {
  27669. localNormal = allElements[0].face && allElements[0].face.normal;
  27670. if (localNormal) {
  27671. var quaternion = new Quaternion();
  27672. allElements[0].oriObject.matrixWorld.decompose(new Vector3(), quaternion, new Vector3());
  27673. normal = localNormal.clone().applyQuaternion(quaternion);
  27674. allElements[0].object.matrix.decompose(new Vector3(), quaternion, new Vector3());
  27675. localNormal = normal.clone().applyQuaternion(quaternion.invert()); //改为在最外层model上无旋转时的normal
  27676. }
  27677. }
  27678. intersectOnModel = {
  27679. //模拟点云的intersectPoint的结构写法
  27680. hoveredElement: allElements[0],
  27681. location: allElements[0].point,
  27682. localNormal,
  27683. normal,
  27684. distance: allElements[0].distance,
  27685. object: allElements[0].object
  27686. };
  27687. }
  27688. }
  27689. if (intersectPoint && intersectOnModel) {
  27690. if (intersectPoint.distance < intersectOnModel.distance) {
  27691. intersect = intersectPoint;
  27692. } else {
  27693. intersect = intersectOnModel;
  27694. }
  27695. } else {
  27696. intersect = intersectOnModel || intersectPoint;
  27697. }
  27698. if ((_intersect = intersect) !== null && _intersect !== void 0 && _intersect.normal) {
  27699. //尤其是点云屋顶上的normal都指向屋内了,需要根据站位反向一下
  27700. if (viewport.view.direction.angleTo(intersect.normal) < Math.PI / 2) {
  27701. var _intersect$localNorma;
  27702. intersect.normal.negate();
  27703. (_intersect$localNorma = intersect.localNormal) === null || _intersect$localNorma === void 0 || _intersect$localNorma.negate();
  27704. }
  27705. }
  27706. }
  27707. if (viewport.camera.type == 'OrthographicCamera' /* == 'mapViewport' */) {
  27708. var pos3d = new Vector3(this.pointer.x, this.pointer.y, -1).unproject(viewport.camera); //z:-1朝外
  27709. if (!intersect) {
  27710. intersect = {};
  27711. }
  27712. intersect.orthoIntersect = pos3d.clone();
  27713. }
  27714. //记录全部hover到的:
  27715. if (intersect) {
  27716. intersect.allElements = allElements;
  27717. intersect.pointclouds = intersectPoint ? intersectPoint.pointclouds : [];
  27718. }
  27719. viewer.addTimeMark('getIntersect', 'end');
  27720. //点云费时:2-15ms
  27721. //深度图费时: 0.1-0.2ms
  27722. /*
  27723. intersect && intersect.location && intersect.location.applyMatrix4(viewer.scene.scene.matrix)//add
  27724. */
  27725. if (onlyGetIntersect) {
  27726. return intersect;
  27727. }
  27728. if (intersect) {
  27729. if (viewer.showCoordType) {
  27730. //显示坐标位置时
  27731. var pos = intersect.point.position.toArray();
  27732. if (viewer.showCoordType == "local") {} else if (viewer.showCoordType == "lonlat") {
  27733. pos = viewer.transform.lonlatToLocal.inverse(pos);
  27734. } else {
  27735. pos = viewer.transform.lonlatToLocal.inverse(pos);
  27736. pos = viewer.transform.lonlatTo4550.forward(pos);
  27737. }
  27738. viewer.dispatchEvent({
  27739. type: "coordinateChange",
  27740. pos
  27741. });
  27742. }
  27743. }
  27744. //console.log('getIntersect', !!intersectPoint)
  27745. this.intersect = intersect;
  27746. intersect && (this.hoverViewport.lastIntersect = intersect);
  27747. return intersect;
  27748. }
  27749. onMouseMove(e) {
  27750. return this.dealPointerMove(e);
  27751. }
  27752. dealPointerMove(e, isTouch) {
  27753. if (this.interactHistory.move) return; //一帧只触发一次
  27754. this.interactHistory.move = 1;
  27755. if (isTouch) {
  27756. var {
  27757. camera,
  27758. viewport
  27759. } = this.updateTouchesInfo(e);
  27760. } else {
  27761. var {
  27762. camera,
  27763. viewport
  27764. } = this.getPointerInViewport(e.clientX, e.clientY, this.dragViewport);
  27765. }
  27766. this.hoverViewport = viewport;
  27767. if (!viewport) return; //刚变化viewport时会找不到
  27768. var isFlying = this.viewer.viewports.some(e => e.view.isFlying()) || viewer.scene.cameraAnimations.some(c => c.onUpdate);
  27769. var intersect;
  27770. if (e.onlyGetIntersect || !this.drag || this.drag.object || viewport.alignment) {
  27771. //没有拖拽物体,但按下鼠标了的话,不intersect。触屏的就能直接避免intersect
  27772. var dontIntersect = this.drag && viewport.alignment || isFlying || !Potree.settings.intersectWhenHover; // flying 时可能卡顿
  27773. //console.log('dontIntersectPointcloud',dontIntersectPointcloud)
  27774. intersect = this.getIntersect(Object.assign({}, e, {
  27775. viewport,
  27776. dontIntersect,
  27777. clientX: e.clientX,
  27778. clientY: e.clientY
  27779. })); //数据集多的时候卡顿
  27780. }
  27781. if (e.onlyGetIntersect) {
  27782. return intersect;
  27783. }
  27784. e.preventDefault();
  27785. if (this.drag) {
  27786. //有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
  27787. this.drag.mouse = isTouch ? 1 : e.buttons;
  27788. //add:
  27789. //this.drag.pointer = this.pointer.clone();
  27790. //this.drag.hoverViewport = this.hoverViewport
  27791. this.drag.pointerDelta.subVectors(this.pointer, this.drag.end);
  27792. this.drag.end.copy(this.pointer);
  27793. var dragConsumed = false;
  27794. if (this.drag.object && (e.buttons == Buttons$1.NONE || !this.drag.notPressMouse)) {
  27795. //如果是本不需要按鼠标的拖拽,但按下了鼠标,就不执行这段(改为拖拽场景,如添加测量时突然拖拽画面)
  27796. if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
  27797. var refused;
  27798. this.drag.object.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27799. type: 'drag',
  27800. //拖拽物体
  27801. refuse: () => {
  27802. refused = true;
  27803. }
  27804. }));
  27805. if (!refused) dragConsumed = true;
  27806. viewer.dispatchEvent('content_changed');
  27807. }
  27808. if (!dragConsumed) {
  27809. if (this.logMessages) console.log(this.constructor.name + ': drag: ');
  27810. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27811. type: 'global_drag' //拖拽画面
  27812. //consume: () => {dragConsumed = true;}
  27813. }));
  27814. }
  27815. }
  27816. if (!isTouch || e.touches.length == 1) {
  27817. if ((!this.drag || this.drag.notPressMouse || Potree.settings.intersectOnObjs && this.drag.object) && !isFlying) {
  27818. var _curr$_listeners;
  27819. /* let blacklist = this.drag && this.drag */
  27820. var hoveredElements = this.getHoveredElements();
  27821. if (hoveredElements.length > 0) {
  27822. var names = hoveredElements.map(h => h.object.name).join(", ");
  27823. if (this.logMessages) console.log("".concat(this.constructor.name, ": onMouseMove; hovered: '").concat(names, "'"));
  27824. }
  27825. var cur = hoveredElements.find(a => a.object);
  27826. var curr = cur && cur.object; //hoveredElements.map(a => a.object).find(a => true);//只取第一个
  27827. var prev = this.lastMouseoverElement; //this.hoveredElements.map(a => a.object).find(a => true);
  27828. if (curr !== prev) {
  27829. if (curr) {
  27830. if (this.logMessages) console.log("".concat(this.constructor.name, ": mouseover: ").concat(curr.name));
  27831. curr.dispatchEvent({
  27832. type: 'mouseover',
  27833. object: curr,
  27834. hoveredElement: cur
  27835. });
  27836. }
  27837. if (prev) {
  27838. if (this.logMessages) console.log("".concat(this.constructor.name, ": mouseleave: ").concat(prev.name));
  27839. prev.dispatchEvent({
  27840. type: 'mouseleave',
  27841. object: prev
  27842. });
  27843. }
  27844. this.lastMouseoverElement = curr;
  27845. viewer.dispatchEvent('content_changed');
  27846. }
  27847. if (curr !== null && curr !== void 0 && (_curr$_listeners = curr._listeners) !== null && _curr$_listeners !== void 0 && _curr$_listeners.mousemove) {
  27848. if (curr) {
  27849. //xzw改为只取第一个
  27850. curr.dispatchEvent($.extend(this.getEventDesc(e), {
  27851. type: 'mousemove',
  27852. hoveredElement: cur
  27853. }));
  27854. }
  27855. }
  27856. /* if(hoveredElements.length > 0){
  27857. let object = hoveredElements
  27858. .map(e => e.object)
  27859. .find(e => (e._listeners && e._listeners['mousemove']));
  27860. if(object){
  27861. object.dispatchEvent($.extend(
  27862. this.getEventDesc(e),
  27863. {
  27864. type: 'mousemove',
  27865. hoveredElement: hoveredElements.find(e=>e.object == object)
  27866. }
  27867. ));
  27868. }
  27869. } */
  27870. this.hoveredElements = hoveredElements;
  27871. }
  27872. //this.intersect = this.getWholeIntersect()
  27873. this.viewer.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27874. type: 'global_mousemove'
  27875. }));
  27876. this.containsMouse = true;
  27877. }
  27878. }
  27879. onMouseWheel(e) {
  27880. if (!this.enabled) return;
  27881. if (this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
  27882. e.preventDefault();
  27883. var delta = 0;
  27884. if (e.wheelDelta !== undefined) {
  27885. // WebKit / Opera / Explorer 9
  27886. delta = e.wheelDelta;
  27887. } else if (e.detail !== undefined) {
  27888. // Firefox
  27889. delta = -e.detail;
  27890. }
  27891. var ndelta = Math.sign(delta);
  27892. // this.wheelDelta += Math.sign(delta);
  27893. if (!this.hoverViewport) {
  27894. //调试手机版时会无
  27895. var {
  27896. viewport
  27897. } = this.getPointerInViewport(e.clientX, e.clientY);
  27898. this.hoverViewport = viewport;
  27899. }
  27900. if (this.hoveredElement) {
  27901. this.hoveredElement.object.dispatchEvent($.extend(this.getEventDesc(e, isTouch), {
  27902. type: 'mousewheel',
  27903. delta: ndelta,
  27904. object: this.hoveredElement.object
  27905. }));
  27906. } else {
  27907. this.viewer.dispatchEvent($.extend(this.getEventDesc(e), {
  27908. type: 'global_mousewheel',
  27909. delta: ndelta
  27910. }));
  27911. }
  27912. setTimeout(() => {
  27913. this.dealPointerMove(e); //add 在更新完view后重新获取intersect 和 drag
  27914. }, 1); //只延迟1会崩溃吗
  27915. }
  27916. startDragging(object) {
  27917. var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  27918. var name = object ? object.name : "no name";
  27919. if (this.logMessages) console.log("".concat(this.constructor.name, ": startDragging: '").concat(name, "'"));
  27920. this.drag = {
  27921. start: this.pointer.clone(),
  27922. end: this.pointer.clone(),
  27923. pointerDelta: new Vector2(0, 0),
  27924. object: object,
  27925. hoverViewport: this.hoverViewport,
  27926. //会变化
  27927. dragViewport: this.hoverViewport //不变
  27928. };
  27929. if (args) {
  27930. for (var key of Object.keys(args)) {
  27931. this.drag[key] = args[key];
  27932. }
  27933. }
  27934. if (object) {
  27935. object.dispatchEvent($.extend(this.getEventDesc(), {
  27936. type: 'startDragging'
  27937. }));
  27938. }
  27939. }
  27940. /* getMousePointCloudIntersection (mouse) {
  27941. return Utils.getMousePointCloudIntersection(
  27942. this.mouse,
  27943. this.scene.getActiveCamera(),
  27944. this.viewer,
  27945. this.scene.pointclouds);
  27946. } */
  27947. toggleSelection(object) {
  27948. var oldSelection = this.selection;
  27949. var index = this.selection.indexOf(object);
  27950. if (index === -1) {
  27951. this.selection.push(object);
  27952. object.dispatchEvent({
  27953. type: 'select'
  27954. });
  27955. } else {
  27956. this.selection.splice(index, 1);
  27957. object.dispatchEvent({
  27958. type: 'deselect'
  27959. });
  27960. }
  27961. this.dispatchEvent({
  27962. type: 'selection_changed',
  27963. oldSelection: oldSelection,
  27964. selection: this.selection
  27965. });
  27966. viewer.dispatchEvent('content_changed');
  27967. }
  27968. deselect(object) {
  27969. var oldSelection = this.selection;
  27970. var index = this.selection.indexOf(object);
  27971. if (index >= 0) {
  27972. this.selection.splice(index, 1);
  27973. object.dispatchEvent({
  27974. type: 'deselect'
  27975. });
  27976. this.dispatchEvent({
  27977. type: 'selection_changed',
  27978. oldSelection: oldSelection,
  27979. selection: this.selection
  27980. });
  27981. }
  27982. viewer.dispatchEvent('content_changed');
  27983. }
  27984. deselectAll() {
  27985. for (var object of this.selection) {
  27986. object.dispatchEvent({
  27987. type: 'deselect'
  27988. });
  27989. }
  27990. var oldSelection = this.selection;
  27991. if (this.selection.length > 0) {
  27992. this.selection = [];
  27993. this.dispatchEvent({
  27994. type: 'selection_changed',
  27995. oldSelection: oldSelection,
  27996. selection: this.selection
  27997. });
  27998. }
  27999. viewer.dispatchEvent('content_changed');
  28000. }
  28001. isSelected(object) {
  28002. var index = this.selection.indexOf(object);
  28003. return index !== -1;
  28004. }
  28005. registerInteractiveObject(object) {
  28006. this.interactiveObjects.add(object);
  28007. }
  28008. removeInteractiveObject(object) {
  28009. this.interactiveObjects.delete(object);
  28010. }
  28011. registerInteractiveScene(scene) {
  28012. var index = this.interactiveScenes.indexOf(scene);
  28013. if (index === -1) {
  28014. this.interactiveScenes.push(scene);
  28015. }
  28016. }
  28017. unregisterInteractiveScene(scene) {
  28018. var index = this.interactiveScenes.indexOf(scene);
  28019. if (index > -1) {
  28020. this.interactiveScenes.splice(index, 1);
  28021. }
  28022. }
  28023. getHoveredElement() {
  28024. var hoveredElements = this.getHoveredElements();
  28025. if (hoveredElements.length > 0) {
  28026. return hoveredElements[0];
  28027. } else {
  28028. return null;
  28029. }
  28030. }
  28031. getHoveredElements(interactables, dontCheckDis, raycaster) {
  28032. if (!interactables) {
  28033. var scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
  28034. var interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
  28035. interactables = [];
  28036. for (var scene of scenes) {
  28037. scene.traverseVisible(node => {
  28038. //检测加了侦听的object
  28039. if (node._listeners && node.visible && !this.blacklist.has(node)) {
  28040. var hasInteractableListener = interactableListeners.filter(e => {
  28041. return node._listeners[e] !== undefined;
  28042. }).length > 0;
  28043. if (hasInteractableListener) {
  28044. interactables.push(node);
  28045. }
  28046. }
  28047. });
  28048. }
  28049. } else interactables = interactables.filter(e => e.visible);
  28050. var camera = this.hoverViewport.camera;
  28051. if (!raycaster) {
  28052. var ray = Utils.mouseToRay(this.pointer, camera);
  28053. raycaster = new Raycaster();
  28054. raycaster.ray.set(ray.origin, ray.direction);
  28055. raycaster.camera = camera; //add
  28056. }
  28057. if (camera.type == "OrthographicCamera") {
  28058. //使无论多远,threshold区域都是一样宽的
  28059. raycaster.params.Line.threshold = 20 / camera.zoom;
  28060. } else {
  28061. raycaster.params.Line.threshold = 0.04; //相对长度
  28062. }
  28063. raycaster.params.Line2 = {
  28064. threshold: browser.isMobile() ? 100 : 20
  28065. }; //拓宽的lineWidth
  28066. //raycaster.layers.enableAll()//add
  28067. var layers = ['sceneObjects', 'mapObjects', /* 'measure', */'transformationTool', 'model', 'bothMapAndScene']; //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
  28068. if (Potree.settings.mergeType2 && Potree.settings.modelSkybox && Potree.settings.displayMode == 'showPanos' && !viewer.images360.currentPano.pointcloud.hasDepthTex) layers.push('skybox'); //model变成skybox了
  28069. Potree.Utils.setCameraLayers(raycaster, layers, this.hoverViewport && this.hoverViewport.extraEnableLayers);
  28070. //this.hoverViewport.beforeRender && this.hoverViewport.beforeRender()
  28071. viewer.dispatchEvent({
  28072. type: 'raycaster',
  28073. viewport: this.hoverViewport,
  28074. raycaster,
  28075. viewer: this.viewer,
  28076. interactables
  28077. }); //add
  28078. var intersections = raycaster.intersectObjects(interactables, true, null, true); //原本是false 检测不到children
  28079. var intersectionsCopy = intersections.slice();
  28080. if (this.intersect && this.intersect.distance != void 0 && !dontCheckDis) {
  28081. //add
  28082. intersections = intersections.filter(e => {
  28083. var _material$defines;
  28084. if (this.intersect.hoveredElement && this.intersect.hoveredElement.oriObject == e.object) return true;
  28085. var material = e.object.material;
  28086. return e.object.pickDontCheckDis || (((_material$defines = material.defines) === null || _material$defines === void 0 ? void 0 : _material$defines.FadeFar) == void 0 || e.distance < material.uniforms.fadeFar.value * 1.2) && (
  28087. //在几乎完全消失的距离内
  28088. (material.depthTest == false || material.depthWrite == false) && !material.realUseDepth //!material.depthTestWhenPick
  28089. || (material.useDepth ? e.distance <= this.intersect.distance + material.uniforms.clipDistance.value : e.distance <= this.intersect.distance));
  28090. //maxClipFactor是否需要考虑?
  28091. });
  28092. }
  28093. intersections = intersections.map(e => {
  28094. //add 转化为interactables
  28095. var object = e.object;
  28096. do {
  28097. if (interactables.includes(object)) {
  28098. e.oriObject = e.object;
  28099. e.object = object;
  28100. break;
  28101. }
  28102. object = object.parent;
  28103. } while (object);
  28104. return e;
  28105. });
  28106. //add for测量线,在检测到sphere时优先选中sphere而非线
  28107. //intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
  28108. intersections = intersections.sort(function (a, b) {
  28109. var order2 = b.object.pickOrder || 0;
  28110. var order1 = a.object.pickOrder || 0;
  28111. return order2 - order1;
  28112. }); // 降序
  28113. //console.log('getHoveredElement ', intersections)
  28114. return intersections;
  28115. }
  28116. /* setScene (scene) {
  28117. this.deselectAll();
  28118. this.scene = scene;
  28119. } */
  28120. update(delta) {}
  28121. /*getNormalizedDrag () {
  28122. if (!this.drag) {
  28123. return new THREE.Vector2(0, 0);
  28124. }
  28125. let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
  28126. diff.x = diff.x / this.domElement.clientWidth;
  28127. diff.y = diff.y / this.domElement.clientHeight;
  28128. return diff;
  28129. }
  28130. getNormalizedLastDrag () {
  28131. if (!this.drag) {
  28132. return new THREE.Vector2(0, 0);
  28133. }
  28134. let mouseDelta = this.drag.mouseDelta.clone();
  28135. mouseDelta.x = mouseDelta.x / this.domElement.clientWidth;
  28136. mouseDelta.y = mouseDelta.y / this.domElement.clientHeight;
  28137. return mouseDelta;
  28138. } */
  28139. getMouseDirection(pointer) {
  28140. //add
  28141. pointer = pointer || this.pointer;
  28142. var camera = this.hoverViewport.camera;
  28143. var t = new Vector3(pointer.x, pointer.y, -1).unproject(camera),
  28144. i = new Vector3(pointer.x, pointer.y, 1).unproject(camera);
  28145. return {
  28146. origin: t,
  28147. direction: i.clone().sub(t).normalize()
  28148. };
  28149. }
  28150. }
  28151. class ViewerBase extends EventDispatcher {
  28152. constructor(domElement) {
  28153. var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  28154. super();
  28155. this.name = args.name;
  28156. this.renderArea = domElement;
  28157. this.oldResolution = new Vector2();
  28158. this.oldResolution2 = new Vector2();
  28159. this.screenSizeInfo = {
  28160. W: 0,
  28161. H: 0,
  28162. pixelRatio: 1,
  28163. windowWidth: 0,
  28164. windowHeight: 0
  28165. };
  28166. this.initContext(args);
  28167. this.addEventListener('content_changed', () => {
  28168. //画面改变,需要渲染
  28169. this.needRender = true;
  28170. //console.log('needRender')
  28171. });
  28172. }
  28173. initContext(args) {
  28174. //console.log(`initializing three.js ${THREE.REVISION}`);
  28175. var width = this.renderArea.clientWidth;
  28176. var height = this.renderArea.clientHeight;
  28177. var contextAttributes = {
  28178. alpha: true,
  28179. //支持透明
  28180. depth: true,
  28181. stencil: false,
  28182. antialias: !!args.antialias,
  28183. preserveDrawingBuffer: args.preserveDrawingBuffer || false,
  28184. powerPreference: "high-performance"
  28185. };
  28186. var canvas = document.createElement("canvas");
  28187. //Potree.settings.renderAllViewports = browser.maybeQilin() && this.renderer.capabilities.maxCubemapSize <= 2048 && //麒麟chromium若获取过webgl2只渲染一个viewport的话其他的会变黑
  28188. var webglVer = args.webgl1 || Potree.browser.urlHasValue('webgl1') || !Potree.Features.webgl2RealSupport() ? 'webgl' : 'webgl2';
  28189. var context = canvas.getContext(webglVer, contextAttributes);
  28190. this.renderer = new WebGLRenderer({
  28191. premultipliedAlpha: false,
  28192. canvas: canvas,
  28193. context: context
  28194. });
  28195. this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效
  28196. //this.renderer.setSize(width, height);
  28197. this.renderer.autoClear = args.autoClear || false;
  28198. //args.clearColor = args.clearColor || '#aa0033'
  28199. args.clearColor && this.renderer.setClearColor(args.clearColor);
  28200. this.renderArea.appendChild(this.renderer.domElement);
  28201. this.renderer.domElement.tabIndex = '2222';
  28202. this.renderer.domElement.style.position = 'absolute';
  28203. this.renderer.domElement.addEventListener('mousedown', () => {
  28204. this.renderer.domElement.focus();
  28205. });
  28206. {
  28207. var oldRender = this.renderer.render;
  28208. this.renderer.render = function (scene, camera) {
  28209. Potree.currentRender = {
  28210. renderer: this,
  28211. scene,
  28212. camera
  28213. };
  28214. oldRender.apply(this, arguments);
  28215. };
  28216. }
  28217. //this.renderer.domElement.focus();
  28218. // NOTE: If extension errors occur, pass the string into this.renderer.extensions.get(x) before enabling
  28219. // enable frag_depth extension for the interpolation shader, if available
  28220. var gl = this.renderer.getContext();
  28221. gl.getExtension('EXT_frag_depth');
  28222. gl.getExtension('WEBGL_depth_texture');
  28223. gl.getExtension('WEBGL_color_buffer_float'); // Enable explicitly for more portability, EXT_color_buffer_float is the proper name in WebGL 2
  28224. if (gl.createVertexArray == null) {
  28225. var extVAO = gl.getExtension('OES_vertex_array_object');
  28226. if (!extVAO) {
  28227. throw new Error("OES_vertex_array_object extension not supported");
  28228. }
  28229. gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
  28230. gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
  28231. }
  28232. /* let oldClear = gl.clear;
  28233. gl.clear = (bits)=>{
  28234. console.error('clear')
  28235. }
  28236. */
  28237. }
  28238. updateScreenSize() {
  28239. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  28240. //有可能需要让viewport来判断,当窗口大小不变但viewport大小变时
  28241. if (this.screenshoting && !o.forceUpdateSize) return; //截图时不允许因窗口改变大小而updateScreenSize
  28242. var render = false,
  28243. ratio,
  28244. w,
  28245. h;
  28246. //记录应当render的大小
  28247. if (o.width != void 0 && o.height != void 0) {
  28248. w = o.width;
  28249. h = o.height;
  28250. render = true;
  28251. ratio = 1;
  28252. } else {
  28253. w = this.renderArea.clientWidth;
  28254. h = this.renderArea.clientHeight;
  28255. if (w !== this.screenSizeInfo.W || h !== this.screenSizeInfo.H || o.forceUpdateSize || this.screenSizeInfo.pixelRatio != window.devicePixelRatio) {
  28256. this.screenSizeInfo.W = w;
  28257. this.screenSizeInfo.H = h;
  28258. render = true;
  28259. this.screenSizeInfo.pixelRatio = window.devicePixelRatio; //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变
  28260. //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio)
  28261. ratio = window.devicePixelRatio;
  28262. }
  28263. }
  28264. if (render) {
  28265. this.setSize(w, h, ratio, o.forTarget);
  28266. }
  28267. }
  28268. setSize(width, height, devicePixelRatio, onlyForTarget) {
  28269. //console.log('setSize', width)
  28270. if (!onlyForTarget) {
  28271. //onlyForTarget表示不更改当前renderer,只是为了rendertarget才要改变viewport
  28272. this.renderer.setPixelRatio(devicePixelRatio);
  28273. this.renderer.setSize(width, height); // resize之后会自动clear(似乎因为setScissor ),所以一定要立刻绘制,所以setSize要在cameraChanged、update之前
  28274. }
  28275. //this.composer && this.composer.setSize(width, height);
  28276. if (this.viewports) {
  28277. this.viewports.forEach((view, i) => {
  28278. //if(!view.active)return
  28279. var width_ = width * view.width;
  28280. var height_ = height * view.height;
  28281. view.setResolution(Math.ceil(width_), Math.ceil(height_), width, height);
  28282. if (height_ == 0) return; //avoid NAN
  28283. var aspect = width_ / height_; //camera的参数精确些,不用视口的归整的resolution像素值,否则hasChange无法为true, 导致canvasResize了但map没update从而闪烁
  28284. view.camera.aspect = aspect;
  28285. if (view.camera.type == "OrthographicCamera") {
  28286. /* //不改宽度 同4dkk
  28287. var heightHalf = view.camera.right / aspect
  28288. view.camera.top = heightHalf
  28289. view.camera.bottom = -heightHalf */
  28290. //高宽都改 使大小不随视口大小改变 navvis (直接和视口大小一致即可,通过zoom来定大小)
  28291. view.camera.left = -width_ / 2;
  28292. view.camera.right = width_ / 2;
  28293. view.camera.bottom = -height_ / 2;
  28294. view.camera.top = height_ / 2;
  28295. } else {}
  28296. view.camera.updateProjectionMatrix();
  28297. });
  28298. }
  28299. if (!onlyForTarget) {
  28300. //因为onlyForTarget不传递devicePixelRatio所以不发送了
  28301. this.dispatchEvent('viewerResize');
  28302. this.viewports.forEach(e => {
  28303. this.ifEmitResize({
  28304. viewport: e,
  28305. deviceRatio: devicePixelRatio
  28306. });
  28307. });
  28308. }
  28309. }
  28310. ifEmitResize(e) {
  28311. //切换viewport渲染时, 若这些viewport大小不同就发送一次, 通知一些材质更新resolution。
  28312. //console.log('ifEmitResize',e.viewport.name,e.viewport.resolution2 )
  28313. if (!e.viewport.resolution.equals(this.oldResolution) || !e.viewport.resolution2.equals(this.oldResolution2)) {
  28314. this.dispatchEvent($.extend(e, {
  28315. type: 'resize'
  28316. }));
  28317. this.oldResolution.copy(e.viewport.resolution);
  28318. this.oldResolution2.copy(e.viewport.resolution2);
  28319. }
  28320. }
  28321. cameraChanged() {
  28322. //判断相机是否改变
  28323. var changed = false;
  28324. /* if(this.needRender){
  28325. this.needRender = false
  28326. return true
  28327. } */
  28328. for (var i = 0, j = this.viewports.length; i < j; i++) {
  28329. var viewport = this.viewports[i];
  28330. var changeInfo = viewport.cameraChanged();
  28331. if (changeInfo.changed) {
  28332. changed = true;
  28333. //if(!this.changeTime ||this.changeTime<100){
  28334. this.dispatchEvent({
  28335. type: "camera_changed",
  28336. camera: viewport.camera,
  28337. viewport,
  28338. changeInfo
  28339. });
  28340. //this.changeTime = (this.changeTime || 0) +1
  28341. //}
  28342. viewport.needRender = true; //直接写这咯
  28343. if (changeInfo.resolutionChanged) {
  28344. this.ifEmitResize({
  28345. viewport
  28346. }); //for map
  28347. }
  28348. }
  28349. }
  28350. return changed;
  28351. }
  28352. makeScreenshot(size, viewports, compressRatio) {
  28353. //暂时不要指定viewports渲染,但也可以
  28354. var {
  28355. width,
  28356. height
  28357. } = size;
  28358. /* let oldBudget = Potree.pointBudget;
  28359. Potree.pointBudget = Math.max(10 * 1000 * 1000, 2 * oldBudget);
  28360. let result = Potree.updatePointClouds(this.scene.pointclouds, camera, size );
  28361. Potree.pointBudget = oldBudget;
  28362. this.dispatchEvent({ //resize everything such as lines targets
  28363. type: 'resize',
  28364. resolution: new THREE.Vector2(width,height),
  28365. });*/
  28366. var target = new WebGLRenderTarget(width, height, {
  28367. format: RGBAFormat
  28368. });
  28369. this.setSize(width, height, 1, true);
  28370. this.render({
  28371. target,
  28372. //camera ,
  28373. viewports: viewports || this.viewports,
  28374. screenshot: true,
  28375. width,
  28376. height,
  28377. resize: true //需要resize
  28378. });
  28379. var dataUrl = Potree.Utils.renderTargetToDataUrl(target, width, height, this.renderer, compressRatio);
  28380. /* let pixelCount = width * height;
  28381. let buffer = new Uint8Array(4 * pixelCount);
  28382. this.renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer);
  28383. let dataUrl = Potree.Utils.pixelsArrayToDataUrl(buffer, width, height, compressRatio) */
  28384. target.dispose();
  28385. //resize back
  28386. //this.updateScreenSize({forceUpdateSize:true})
  28387. return {
  28388. width,
  28389. height,
  28390. dataUrl
  28391. };
  28392. }
  28393. dispose() {
  28394. var scene = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.scene;
  28395. scene.clear();
  28396. this.renderer.dispose();
  28397. this.renderer.forceContextLoss();
  28398. var gl = this.renderer.getContext();
  28399. gl.getExtension("WEBGL_lose_context") && gl.getExtension("WEBGL_lose_context").loseContext();
  28400. this.renderArea.removeChild(this.renderer.domElement);
  28401. this.dispatchEvent('dispose');
  28402. }
  28403. }
  28404. class Viewport extends EventDispatcher {
  28405. constructor(view, camera) {
  28406. var prop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  28407. //目前不支持换camera
  28408. super();
  28409. this.left = prop.left;
  28410. this.bottom = prop.bottom;
  28411. this.width = prop.width;
  28412. this.height = prop.height;
  28413. this.name = prop.name;
  28414. this.view = view;
  28415. this.camera = camera;
  28416. this.active = true;
  28417. this.unableChangePos = false;
  28418. this.noPointcloud;
  28419. //this.keys = [...] firstPersonCtl....
  28420. this.resolution = new Vector2();
  28421. this.resolution2 = new Vector2();
  28422. this.offset = new Vector2(); //viewportOffset 范围从0-整个画布的像素
  28423. this.extraEnableLayers = prop.extraEnableLayers || []; //额外可展示的层
  28424. this.cameraLayers = prop.cameraLayers;
  28425. this.pixelRatio = prop.pixelRatio; //如果规定pixelRatio的话要传,这样就覆盖devicePicelRatio, 如magnifier
  28426. }
  28427. clone() {
  28428. return Common$1.CloneClassObject(this);
  28429. }
  28430. getMoveSpeed() {
  28431. return this.moveSpeed;
  28432. }
  28433. setMoveSpeed(e) {
  28434. this.moveSpeed = e;
  28435. }
  28436. layersAdd(name) {
  28437. this.extraEnableLayers.includes(name) || this.extraEnableLayers.push(name);
  28438. }
  28439. layersRemove(name) {
  28440. var index = this.extraEnableLayers.indexOf(name);
  28441. if (index > -1) {
  28442. this.extraEnableLayers.splice(index, 1);
  28443. }
  28444. }
  28445. cameraChanged() {
  28446. var copy = () => {
  28447. this.previousState = {
  28448. projectionMatrix: this.camera.projectionMatrix.clone(),
  28449. //worldMatrix在this.control时归零了所以不用了吧,用position和qua也一样
  28450. position: this.camera.position.clone(),
  28451. quaternion: this.camera.quaternion.clone(),
  28452. active: this.active,
  28453. resolution: this.resolution.clone(),
  28454. resolution2: this.resolution2.clone() //有时clientWidth没变但是ratio缩放了
  28455. };
  28456. };
  28457. var projectionChanged = true,
  28458. positionChanged = true,
  28459. quaternionChanged = true,
  28460. activeChanged = true,
  28461. resolutionChanged = true;
  28462. var getChanged = () => {
  28463. return {
  28464. projectionChanged,
  28465. positionChanged,
  28466. quaternionChanged,
  28467. activeChanged,
  28468. resolutionChanged,
  28469. changed: projectionChanged || positionChanged || quaternionChanged || activeChanged || resolutionChanged
  28470. };
  28471. };
  28472. if (this.previousState) {
  28473. projectionChanged = !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix);
  28474. positionChanged = !this.camera.position.equals(this.previousState.position);
  28475. quaternionChanged = !this.camera.quaternion.equals(this.previousState.quaternion);
  28476. activeChanged = this.active != this.previousState.active;
  28477. resolutionChanged = !this.resolution.equals(this.previousState.resolution) || !this.resolution2.equals(this.previousState.resolution2);
  28478. }
  28479. copy();
  28480. return getChanged();
  28481. }
  28482. setResolution(w, h) {
  28483. var wholeW = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  28484. var wholeH = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  28485. this.resolution.set(w, h); //是client的width height
  28486. this.resolution2.copy(this.resolution).multiplyScalar(this.pixelRatio || window.devicePixelRatio);
  28487. this.offset.set(wholeW, wholeH).multiply(new Vector2(this.left, this.bottom)); //.multiplyScalar(window.devicePixelRatio)
  28488. this.dispatchEvent({
  28489. type: 'resize'
  28490. });
  28491. }
  28492. }
  28493. var 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;\n attribute vec3 position;\n attribute vec3 normal;\n attribute vec2 uv;\n";
  28494. var prefixFragment = "#extension GL_EXT_frag_depth : enable \n precision highp float;\nprecision highp int;\n\nuniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n";
  28495. // otherwise error: 'GL_EXT_frag_depth' : extension is disabled
  28496. var getClassificationLUT = () => {
  28497. var [width, height] = [256, 1];
  28498. var data = new Uint8Array(width * 4);
  28499. var tex = new DataTexture(data, width, height, RGBAFormat);
  28500. tex.magFilter = NearestFilter;
  28501. tex.needsUpdate = true;
  28502. return tex;
  28503. };
  28504. var shader = {
  28505. uniforms: {
  28506. opacity: {
  28507. type: "f"
  28508. // value: 1
  28509. },
  28510. progress: {
  28511. type: "f",
  28512. value: 0
  28513. },
  28514. pano0Map: {
  28515. type: "t",
  28516. value: null
  28517. },
  28518. pano1Map: {
  28519. type: "t",
  28520. value: null
  28521. },
  28522. depthMap0: {
  28523. type: "t",
  28524. value: null
  28525. },
  28526. depthMap1: {
  28527. type: "t",
  28528. value: null
  28529. },
  28530. pano0ClassMap: {
  28531. type: "t",
  28532. value: null
  28533. },
  28534. pano1ClassMap: {
  28535. type: "t",
  28536. value: null
  28537. },
  28538. pano0TempMap: {
  28539. type: "t",
  28540. value: null
  28541. },
  28542. pano1TempMap: {
  28543. type: "t",
  28544. value: null
  28545. },
  28546. gradient: {
  28547. type: "t",
  28548. value: null
  28549. },
  28550. classificationLUT: {
  28551. type: "t",
  28552. value: null
  28553. },
  28554. pano0Position: {
  28555. type: "v3",
  28556. value: new Vector3()
  28557. },
  28558. pano0Matrix: {
  28559. type: "m4",
  28560. value: new Matrix4()
  28561. },
  28562. pano1Position: {
  28563. type: "v3",
  28564. value: new Vector3()
  28565. },
  28566. pano1Matrix: {
  28567. type: "m4",
  28568. value: new Matrix4()
  28569. },
  28570. /* pano1Matrix2: {
  28571. type: "m4",
  28572. value: new THREE.Matrix4
  28573. },
  28574. */
  28575. inverseProjectionMatrix: {
  28576. value: new Matrix4()
  28577. },
  28578. /* projectionMatrix:{//需要再写一遍吗
  28579. value: new THREE.Matrix4
  28580. }, */
  28581. viewport: {
  28582. value: new Vector4()
  28583. },
  28584. //如 {x: 0, y: 0, z: 428, w: 969} xy应该是offset, zw是宽高
  28585. cameraHeight0: {
  28586. type: "f",
  28587. value: 1
  28588. },
  28589. cameraHeight1: {
  28590. type: "f",
  28591. value: 1
  28592. },
  28593. ceilHeight0: {
  28594. type: "f",
  28595. value: 2
  28596. },
  28597. ceilHeight1: {
  28598. type: "f",
  28599. value: 2
  28600. },
  28601. temperRange: {
  28602. //温度范围
  28603. type: 'vec2',
  28604. value: new Vector2(math.getKelvinFromCelsius(15), math.getKelvinFromCelsius(60))
  28605. }
  28606. },
  28607. vertexShader: prefixVertex + "\n\n uniform vec3 pano0Position;\n uniform mat4 pano0Matrix;\n \n uniform vec3 pano1Position;\n uniform mat4 pano1Matrix; \n\n \n varying vec2 vUv; \n varying vec3 vWorldPosition0;\n varying vec3 vWorldPosition1;\n varying vec3 vWorldPosition12;\n \n vec3 transformAxis( vec3 direction ) //navvis->4dkk\n {\n float y = direction.y;\n direction.y = direction.z;\n direction.z = -y;\n return direction;\n }\n \n \n void main() {\n \n vUv = uv;\n vec4 worldPosition = modelMatrix * vec4(position, 1.0);\n \n \n \n vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;\n vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;\n vWorldPosition0.x *= -1.0;\n vWorldPosition0 = transformAxis(vWorldPosition0);\n \n vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;\n vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;\n vWorldPosition1.x *= -1.0;\n vWorldPosition1 = transformAxis(vWorldPosition1);\n \n /* \n vec3 positionLocalToPanoCenter12 = worldPosition.xyz - pano1Position;\n vWorldPosition12 = (vec4(positionLocalToPanoCenter12, 1.0) * pano1Matrix2).xyz;\n vWorldPosition12.x *= -1.0;\n vWorldPosition12 = transformAxis(vWorldPosition12);\n */\n \n \n \n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n \n }\n\n ",
  28608. fragmentShader: prefixFragment + "\n \n \n #define PI 3.141592653 \n \n \n uniform float modelAlpha;\n uniform float opacity;\n uniform float progress;\n uniform int tranType;\n uniform vec3 pano0Position;\n uniform vec3 pano1Position;\n uniform float maxDistance;\n uniform float minDistance;\n uniform float minOpa;\n \n uniform samplerCube pano0Map;\n uniform samplerCube pano1Map;\n #if defined(useTempMap0) || defined(useTempMap1)\n uniform sampler2D gradient; \n uniform vec2 temperRange; \n #endif \n #if defined(useClassMap0) || defined(useClassMap1)\n uniform sampler2D classificationLUT;\n #endif\n #if defined(useTempMap0)\n uniform sampler2D pano0TempMap;\n #endif\n #if defined(useTempMap1)\n uniform sampler2D pano1TempMap;\n #endif\n #if defined(useClassMap0)\n uniform sampler2D pano0ClassMap;\n #endif\n #if defined(useClassMap1)\n uniform sampler2D pano1ClassMap;\n #endif\n varying vec2 vUv; \n varying vec3 vWorldPosition0;\n varying vec3 vWorldPosition1; \n \n \n /* vec2 getSamplerCoord( vec3 direction ) \n {\n direction = normalize(direction);\n float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;\n float ty=acos(direction.z)/PI;\n\n return vec2(tx,ty);\n } */\n\n vec2 getSamplerCoord2( vec3 direction ) \n { \n direction = normalize(direction);\n float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;\n float ty=acos(direction.y)/PI;\n\n return vec2(tx,ty); \n }\n \n \n #if defined(GL_EXT_frag_depth) && defined(hasDepthTex) \n uniform sampler2D depthMap0;\n uniform sampler2D depthMap1;\n uniform mat4 inverseProjectionMatrix;\n uniform mat4 projectionMatrix;\n uniform vec4 viewport; \n uniform float cameraHeight0;\n uniform float cameraHeight1;\n uniform float ceilHeight0;\n uniform float ceilHeight1;\n \n \n vec2 getDepth(vec3 dir, sampler2D depthMap, float heightDown, float heightUp, vec4 eyePos){\n vec2 depthValue = vec2(0.0, 0.0);\n vec2 uv2 = getSamplerCoord2( dir.xyz); //\u6682\u65F6\u53EA\u7528\u57FA\u4E8E\u76EE\u6807\u6F2B\u6E38\u70B9\u7684\u65B9\u5411\n uv2.x -= 0.25; //\u5168\u666F\u56FE\u548CCube\u7684\u6C34\u5E73\u91C7\u6837\u8D77\u59CB\u5750\u6807\u76F8\u5DEE90\u5EA6\uFF0C\u8FD9\u91CC\u77EB\u6B63 0.25 \u4E2A\u91C7\u6837\u504F\u79FB\n vec4 depth = texture2D(depthMap, uv2);\n //float distance = depth.r + 256. * (depth.g + 256. * depth.b);\n //distance *= 255. * .001; // distance is now in meters\n \n //\u66F4\u6539\n float distance = (depth.g + depth.r / 256.) * 255.; \n \n if(distance == 0.0){//\u6F2B\u6E38\u70B9\u5E95\u90E8\u8BC6\u522B\u4E0D\u5230\u7684\u533A\u57DF\uFF0C\u7ED9\u4E00\u4E2A\u5730\u677F\u9AD8\u5EA6 \n if(uv2.y < depthTexUVyLimit) distance = heightUp / dir.y; \n else if(uv2.y > 1.0 - depthTexUVyLimit) distance = heightDown / -dir.y; \n else distance = 100000.0;//\u7ED9\u4E2A\u8D85\u7EA7\u8FDC\u7684\u503C\n } \n \n if(distance == 0.0)distance = 100000.0;//\u7ED9\u4E2A\u8D85\u7EA7\u8FDC\u7684\u503C\n \n depthValue.x = distance;\n \n distance += .1; // add a safety margin\n\n vec4 eyePos2 = vec4(normalize(eyePos.xyz) * distance, 1.);\n vec4 clipPos2 = projectionMatrix * eyePos2;\n vec4 ndcPos2 = clipPos2 * 1. / clipPos2.w;\n\n \n depthValue.y = 0.5 * ((gl_DepthRange.far - gl_DepthRange.near) * ndcPos2.z\n + gl_DepthRange.near + gl_DepthRange.far); \n \n #if defined(depth_background) \n //\u540E\u6392\u7684 skybox \u4E0D\u80FD\u6321\u4F4Fchunk \n depthValue.y += 0.3;\n #endif\n \n \n \n return depthValue; \n }\n //\u6CE8\uFF1A\u672A\u52A0\u8F7D\u597D\u7684\u8BDD\uFF0Cdepth\u4E3A0\uFF0C\u5BFC\u81F4\u7B2C\u4E00\u6B21\u6F2B\u6E38\u8FC7\u53BB\u7684\u65F6\u5019\u8BB8\u591Amesh\u4F1A\u7ACB\u523B\u88AB\u906E\u6321\uFF0C\u6240\u4EE5\u8981\u786E\u4FDD\u52A0\u8F7D\u5B8C\n #endif\n \n \n \n int getIntFromColor(sampler2D map, vec3 dir){//uint16-> int 0-65536 \n vec2 uv = getSamplerCoord2(dir.xyz); \n uv.x -= 0.25; \n vec4 color = texture2D(map, uv); \n return int(round(color.r * 255.0)) + (int(round(color.g * 255.0)) << 8) ; //some phone needs round,such as vivo x30\n } \n \n \n /*vec4 getColorFromMap(sampler2D map, vec3 dir){\n vec2 uv = getSamplerCoord2(dir.xyz); \n uv.x -= 0.25; \n vec4 color = texture2D(map, uv); \n return color;\n }*/\n \n \n //ir\u70ED\u6210\u50CF \n #if defined(useTempMap0) || defined(useTempMap1)\n \n vec4 getTemperature(sampler2D map, vec3 dir){ \n \n float temperature = float(getIntFromColor(map, dir))/ 10.0 ; \n \n float w = (temperature - temperRange.x) / (temperRange.y - temperRange.x);\n w = clamp(w,0.0,1.0);\n vec4 color = vec4(texture2D(gradient, vec2(w,1.0-w)).rgb, 1.0); \n return color;\n \n }\n #endif \n \n #if defined(useClassMap0) || defined(useClassMap1)\n \n /*vec4 getClassification(sampler2D map, vec3 dir, vec4 originColor){ \n vec4 color = getColorFromMap(map, dir); \n float v = color.r * 255.0; \n if(v<=2.01&&v>=1.99){\n color = vec4(1.0,0.0,0.0,1.0);\n } else{\n color = vec4(0.0,0.0,0.0,1.0);\n } \n return color;\n } */\n \n \n \n vec4 getClassification(sampler2D map, vec3 dir, vec4 originColor){ \n \n int classIndex = getIntFromColor(map, dir); \n \n vec2 uv = vec2(float(classIndex) / 255.0, 0.5); //copy from pointcloud_new.vs\n vec4 classColor = texture2D(classificationLUT, uv);\n\t\n float blendRatio = 0.5;\n float classAlpha = classColor.a * blendRatio; \n vec4 color = vec4(classColor.rgb * classAlpha + originColor.rgb * (1.0-classAlpha), 1.0); //mix with old rgba\n return color;\n } \n #endif \n \n \n void main()\n { \n \n \n vec3 vWorldPosition0N = normalize(vWorldPosition0);\n vec3 vWorldPosition1N = normalize(vWorldPosition1);\n float progress_ = progress;\n \n vec4 colorFromPano0 = vec4(0.0,0.0,0.0,0.0);\n #if defined(usePanoMap0)\n //\u5373progress < 1.0 \u901A\u5E38\u662F1 \n \n #if defined(useTempMap0) \n colorFromPano0 = getTemperature(pano0TempMap,vWorldPosition0N.xyz); \n #else \n colorFromPano0 = textureCube(pano0Map,vWorldPosition0N.xyz);\n #if defined(useClassMap0) \n colorFromPano0 = getClassification(pano0ClassMap,vWorldPosition0N.xyz, colorFromPano0); \n #endif\n #endif\n \n #else \n progress_ = 1.0;\n #endif\n \n \n vec4 colorFromPano1 = vec4(0.0,0.0,0.0,0.0);\n #if defined(useTempMap1) \n colorFromPano1 = getTemperature(pano1TempMap,vWorldPosition1N.xyz);\n #else \n colorFromPano1 = textureCube(pano1Map,vWorldPosition1N.xyz);\n #if defined(useClassMap1) \n colorFromPano1 = getClassification(pano1ClassMap,vWorldPosition1N.xyz, colorFromPano1); \n #endif\n #endif\n \n \n gl_FragColor = mix(colorFromPano0,colorFromPano1,progress_);\n \n \n \n \n \n //\u6DF1\u5EA6\u56FE\u4FEE\u6539\u6DF1\u5EA6\n \n #if defined(GL_EXT_frag_depth) && defined(hasDepthTex) \n vec4 ndcPos;\n ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1.;\n ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /\n (gl_DepthRange.far - gl_DepthRange.near);\n ndcPos.w = 1.0;\n\n vec4 clipPos = ndcPos / gl_FragCoord.w;\n vec4 eyePos = inverseProjectionMatrix * clipPos;\n vec2 depth0 = vec2(0.0,0.0);\n vec2 depth1 = vec2(0.0,0.0);\n float depth = 0.0;\n \n bool useDepth0 = false;\n bool useDepth1 = true;\n \n \n #if defined(usePanoMap0) \n useDepth0 = true;\n #if defined(UnableMixTwoDepth) \n if(progress_<0.5){\n useDepth1 = false;\n }else{\n useDepth0 = false; \n }\n #endif\n if(useDepth0) depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, ceilHeight0, eyePos);\n #endif\n \n if(useDepth1) depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, ceilHeight1, eyePos);\n \n \n #if defined(UnableMixTwoDepth)\n depth = useDepth0 ? depth0.y : depth1.y;//\u4E0D\u652F\u6301\u53E0\u52A0\uFF0C\u53EA\u80FD\u7528\u5176\u4E2D\u4E00\u4E2A\uFF0C\u8FC7\u6E21\u65F6\u65E0\u6CD5\u6E10\u53D8\n #else\n depth = mix(depth0.y,depth1.y,progress_); \n #endif\n gl_FragDepthEXT = clamp(depth, 0.0, 1.0); //\u9632\u6B62\u90E8\u5206\u624B\u673A\u51FA\u73B0\u9ED1\u5757\u3002ios 16 \u3002 \u56E0\u4E3A\u6211\u7ED9\u7684\u8D85\u8FDC\u503C\u8D85\u51FA\u8303\u56F4\n \n\n #endif\n\n \n }\n "
  28609. };
  28610. //注:gl_FragDepthEXT 修改了确实能像真实mesh那样遮挡住在后面的物体。但是为过渡时不能直接像有模型那样,和角度有关。
  28611. class ModelTextureMaterial extends RawShaderMaterial {
  28612. constructor() {
  28613. var defines = {
  28614. depthTexUVyLimit: Potree.config.depthTexUVyLimit
  28615. };
  28616. if (Potree.browser.maybeQilin()) {
  28617. defines.UnableMixTwoDepth = 1; //该系统在开启硬件加速后,webgl容易出bug。如过渡时黑屏报错,因无法将两个depth叠加。见bug记录
  28618. }
  28619. var {
  28620. vs,
  28621. fs
  28622. } = Common$1.changeShaderToWebgl2(shader.vertexShader, shader.fragmentShader, 'RawShaderMaterial');
  28623. if (!Potree.settings.isWebgl2) {
  28624. defines['round(x)'] = 'floor(x + 0.5)'; //webgl1 unsupport round
  28625. fs = fs.replace('int(round(color.g * 255.0)) << 8', 'int(round(color.g * 255.0 * pow(2.0, 8.0)))'); //unsupport <<
  28626. }
  28627. super({
  28628. fragmentShader: fs,
  28629. vertexShader: vs,
  28630. uniforms: UniformsUtils.clone(shader.uniforms),
  28631. side: DoubleSide,
  28632. name: "ModelTextureMaterial",
  28633. defines
  28634. });
  28635. this.glslVersion = Potree.settings.isWebgl2 && '300 es';
  28636. this.uniforms.classificationLUT.value = this.classificationTexture = getClassificationLUT();
  28637. var setSize = e => {
  28638. var viewport = e.viewport;
  28639. //let viewportOffset = viewport.offset || new Vector2()
  28640. var resolution = viewport.resolution2;
  28641. //this.uniforms.viewport.value.set(viewportOffset.x, viewportOffset.y, resolution.x, resolution.y)
  28642. this.uniforms.viewport.value.set(0, 0, resolution.x, resolution.y); // xy是在viewport中的left和bottom,和整个窗口没有关系,所以不是viewportOffset。几乎都是0,0
  28643. };
  28644. var viewport = viewer.mainViewport;
  28645. setSize({
  28646. viewport
  28647. });
  28648. viewer.addEventListener('resize', e => {
  28649. if (e.viewport.name != "MainView") return;
  28650. setSize(e);
  28651. });
  28652. //var supportExtDepth = !!Features.EXT_DEPTH.isSupported()
  28653. {
  28654. //add
  28655. viewer.addEventListener('camera_changed', e => {
  28656. if (e.viewport.name != "MainView") return;
  28657. //this.uniforms.projectionMatrix.value.copy(e.camera.projectionMatrix)
  28658. e.camera && this.uniforms.inverseProjectionMatrix.value.copy(e.camera.projectionMatrixInverse);
  28659. });
  28660. var setClass = () => {
  28661. this.classification = viewer.classifications;
  28662. ExtendPointCloudMaterial.prototype.recomputeClassification.call(this);
  28663. };
  28664. viewer.addEventListener('classifications_changed', setClass);
  28665. setClass();
  28666. this._gradient = Gradients.ir; //海拔贴图种类,火灾也是这个
  28667. this.uniforms.gradient.value = ExtendPointCloudMaterial.generateGradientTexture(this._gradient);
  28668. }
  28669. var progress = 0;
  28670. Object.defineProperty(this.uniforms.progress, 'value', {
  28671. get: function get() {
  28672. return progress;
  28673. },
  28674. set: e => {
  28675. if (e < 1 && !Potree.settings.fastTran) {
  28676. if (!('usePanoMap0' in this.defines)) {
  28677. this.defines.usePanoMap0 = '';
  28678. this.needsUpdate = true;
  28679. }
  28680. } else {
  28681. if ('usePanoMap0' in this.defines) {
  28682. delete this.defines.usePanoMap0;
  28683. this.needsUpdate = true;
  28684. }
  28685. }
  28686. progress = e;
  28687. }
  28688. });
  28689. //-------------------------------------
  28690. }
  28691. setProjectedPanos(pano0, pano1, progressValue) {
  28692. progressValue != void 0 && (this.uniforms.progress.value = progressValue);
  28693. //pano0.ensureSkyboxReadyForRender();
  28694. if (pano0) {
  28695. this.uniforms.pano0Map.value = pano0.getSkyboxTexture(); //pano0.texture
  28696. this.uniforms.pano0Position.value.copy(pano0.position);
  28697. this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix /* pano0.mesh.matrixWorld */);
  28698. //pano1.ensureSkyboxReadyForRender();
  28699. }
  28700. this.uniforms.pano1Map.value = pano1.getSkyboxTexture(); //pano1.texture;
  28701. this.uniforms.pano1Position.value.copy(pano1.position);
  28702. this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */);
  28703. this.pano0 = pano0;
  28704. this.pano1 = pano1;
  28705. this.updateDepthTex(pano0);
  28706. this.updateDepthTex(pano1);
  28707. this.updateTempEnable();
  28708. this.updateClassEnable();
  28709. //console.log('setProjectedPanos', pano0&&pano0.id, pano1&&pano1.id)
  28710. this.needsUpdate = true;
  28711. }
  28712. updateDepthTex(pano, extra) {
  28713. if (!Potree.settings.useDepthTex || !pano || !pano.depthTex || pano != this.pano0 && pano != this.pano1) return;
  28714. //console.log('updateDepthTex', pano.id, this.pano0 && this.pano0.id, this.pano1 && this.pano1.id)
  28715. if (this.pano0) {
  28716. this.uniforms.depthMap0.value = this.pano0.entered ? this.pano0.depthTex : null; //dispose了就不要赋值否则dispose会失败
  28717. this.uniforms.cameraHeight0.value = this.pano0.floorPosition.distanceTo(this.pano0.position);
  28718. this.uniforms.ceilHeight0.value = this.pano0.getCeilHeight() - this.pano0.position.z;
  28719. }
  28720. if (this.pano1) {
  28721. this.uniforms.depthMap1.value = this.pano1.depthTex; //pano1还没entered时也需要,可能在飞入
  28722. this.uniforms.cameraHeight1.value = this.pano1.floorPosition.distanceTo(this.pano1.position);
  28723. this.uniforms.ceilHeight1.value = this.pano1.getCeilHeight() - this.pano1.position.z;
  28724. }
  28725. if (this.dontChangeDepth) return;
  28726. var hasDepthTex = this.pano0 && this.pano1 && this.pano0.pointcloud.hasDepthTex && this.pano1.pointcloud.hasDepthTex; //暂时不知道一个有图一个没图怎么写所以
  28727. Potree.Utils.addOrRemoveDefine(this, 'hasDepthTex', hasDepthTex ? 'add' : 'remove');
  28728. }
  28729. updateTempEnable() {
  28730. var tex0 = Potree.settings.showHotTemp && this.pano0.tempTex || Potree.settings.showHotIr && this.pano0.irTex;
  28731. var tex1 = Potree.settings.showHotTemp && this.pano1.tempTex || Potree.settings.showHotIr && this.pano1.irTex;
  28732. this.uniforms.pano0TempMap.value = tex0;
  28733. this.uniforms.pano1TempMap.value = tex1;
  28734. Potree.Utils.addOrRemoveDefine(this, 'useTempMap0', tex0 ? 'add' : 'remove');
  28735. Potree.Utils.addOrRemoveDefine(this, 'useTempMap1', tex1 ? 'add' : 'remove');
  28736. viewer.dispatchEvent('content_changed');
  28737. }
  28738. updateClassEnable() {
  28739. var hasClassTex0 = Potree.settings.showClass && this.pano0.segTex;
  28740. var hasClassTex1 = Potree.settings.showClass && this.pano1.segTex;
  28741. this.uniforms.pano0ClassMap.value = this.pano0.segTex;
  28742. this.uniforms.pano1ClassMap.value = this.pano1.segTex;
  28743. Potree.Utils.addOrRemoveDefine(this, 'useClassMap0', hasClassTex0 ? 'add' : 'remove');
  28744. Potree.Utils.addOrRemoveDefine(this, 'useClassMap1', hasClassTex1 ? 'add' : 'remove');
  28745. viewer.dispatchEvent('content_changed');
  28746. }
  28747. }
  28748. ModelTextureMaterial.prototype.setTempRange = ExtendPointCloudMaterial.prototype.setTempRange;
  28749. class FastTranPass {
  28750. constructor(renderer) {
  28751. this.renderer = renderer;
  28752. this.coverRenderTarget = new WebGLRenderTarget(100, 100, {
  28753. minFilter: LinearFilter,
  28754. magFilter: LinearFilter,
  28755. format: RGBAFormat
  28756. });
  28757. this.coverTex = this.coverRenderTarget.texture;
  28758. this.enabled = false;
  28759. /* this.oldClearColor = new THREE.Color();
  28760. this.oldClearAlpha = 1;
  28761. this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  28762. this.scene = new THREE.Scene(); */
  28763. this.material = this.getMaskMaterial();
  28764. /* var copyShader = THREE.CopyShader;
  28765. this.materialCopy = new THREE.ShaderMaterial( {
  28766. uniforms: this.copyUniforms,
  28767. vertexShader: copyShader.vertexShader,
  28768. fragmentShader: copyShader.fragmentShader,
  28769. blending: THREE.NoBlending,
  28770. depthTest: false,
  28771. depthWrite: false,
  28772. transparent: true
  28773. } );
  28774. this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), this.material);
  28775. this.quad.frustumCulled = false; // Avoid getting clipped
  28776. this.scene.add( this.quad );
  28777. this.renderToScreen = true*/
  28778. }
  28779. setSize(width, height) {
  28780. this.coverRenderTarget.setSize(width, height);
  28781. }
  28782. start() {
  28783. this.enabled = true;
  28784. var {
  28785. x,
  28786. y
  28787. } = viewer.mainViewport.resolution2;
  28788. this.setSize(x, y);
  28789. //draw coverTex
  28790. var oldTarget = this.renderer.getRenderTarget();
  28791. //let oldClearColor = this.renderer.getClearColor()
  28792. this.renderer.setRenderTarget(this.coverRenderTarget);
  28793. //this.renderer.setClearColor( 0x000000, 0)
  28794. var oldLayer = viewer.mainViewport.camera.layers.mask;
  28795. Potree.Utils.setCameraLayers(viewer.mainViewport.camera, ['skybox']);
  28796. this.renderer.render(viewer.scene.scene, viewer.mainViewport.camera);
  28797. //this.renderer.setClearColor( 0x000000, 0)
  28798. this.renderer.setRenderTarget(oldTarget);
  28799. viewer.mainViewport.camera.layers.mask = oldLayer;
  28800. this.material.uniforms.progress.value = 1;
  28801. console.log('start111');
  28802. }
  28803. render(scene, camera, viewports, renderer, writeBuffer, readBuffer) {
  28804. /* var oldAutoClear = renderer.autoClear;
  28805. renderer.autoClear = false;
  28806. */
  28807. var {
  28808. x,
  28809. y
  28810. } = viewer.mainViewport.resolution2;
  28811. var uniforms = this.material.uniforms;
  28812. //uniforms.bgTex.value = readBuffer.texture; //更新
  28813. uniforms.coverTex.value = this.coverTex;
  28814. uniforms.progress.value = viewer.images360.cube.material.uniforms.progress.value;
  28815. uniforms.screenRatio.value = x / y; // 使波纹为圆形
  28816. uniforms.screenRatio.value *= uniforms.screenRatio.value;
  28817. Potree.Utils.screenPass.render(viewer.renderer, viewer.images360.fastTranMaskPass.material);
  28818. //renderer.autoClear = oldAutoClear;
  28819. }
  28820. stop() {
  28821. this.enabled = false;
  28822. //console.log('stop111')
  28823. }
  28824. getMaskMaterial() {
  28825. return new ShaderMaterial({
  28826. uniforms: {
  28827. coverTex: {
  28828. type: "t",
  28829. value: null
  28830. },
  28831. progress: {
  28832. type: "f",
  28833. value: 0
  28834. },
  28835. screenRatio: {
  28836. type: "f",
  28837. value: 1
  28838. }
  28839. },
  28840. vertexShader: " \n varying vec2 vUv;\n \n void main() \n {\n vUv = uv;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n } \n \n ",
  28841. fragmentShader: " \n uniform sampler2D coverTex; \n uniform float progress; \n uniform float screenRatio;\n varying vec2 vUv;\n \n void main() {\n \n const float maxRadius = 0.708; // sqrt(0.5^2+0.5^2)\n const float minRadius = 0.0 ;\n \n float radius = screenRatio>1.0 ? sqrt((vUv.x - 0.5)*(vUv.x - 0.5) + (vUv.y - 0.5)*(vUv.y - 0.5)/screenRatio) : sqrt((vUv.x - 0.5)*(vUv.x - 0.5)*screenRatio+ (vUv.y - 0.5)*(vUv.y - 0.5));\n float diff = 0.292; //1.0-maxRadius;\n float radiusIn = maxRadius * progress + minRadius * (1.0-progress);\n float radiusOut = radiusIn + diff;\n if(radius < radiusIn) {\n \n discard;\n \n }else if(radius>radiusOut){\n gl_FragColor = texture2D(coverTex, vUv) ;\n //gl_FragColor = vec4(1.0,1.0,0.0,1.0);//\n \n }else{\n \n /* vec4 color1 = texture2D(bgTex, vUv);\n vec4 color2 = texture2D(coverTex, vUv);\n float rotio = smoothstep(radiusIn ,radiusOut,radius);\n \n gl_FragColor = mix(color1, color2, rotio); */\n \n float rotio = smoothstep(radiusIn ,radiusOut, radius);\n \n vec4 color2 = texture2D(coverTex, vUv);\n color2.a = rotio;\n \n \n }\n }\n "
  28842. });
  28843. }
  28844. /* getMaskMaterial(){
  28845. return new THREE.ShaderMaterial( {
  28846. uniforms: {
  28847. coverTex: {
  28848. type: "t",
  28849. value: null
  28850. },
  28851. bgTex: {
  28852. type: "t",
  28853. value: null
  28854. },
  28855. progress:{
  28856. type: "f",
  28857. value: 0
  28858. },
  28859. screenRatio:{
  28860. type: "f",
  28861. value: 1
  28862. }
  28863. },
  28864. vertexShader: `
  28865. varying vec2 vUv;
  28866. void main()
  28867. {
  28868. vUv = uv;
  28869. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  28870. }
  28871. `,
  28872. fragmentShader: `
  28873. uniform sampler2D coverTex;
  28874. uniform sampler2D bgTex;
  28875. uniform float progress;
  28876. uniform float screenRatio;
  28877. varying vec2 vUv;
  28878. void main() {
  28879. const float maxRadius = 0.708; // sqrt(0.5^2+0.5^2)
  28880. const float minRadius = 0.0 ;
  28881. float radius = screenRatio>1.0 ? sqrt((vUv.x - 0.5)*(vUv.x - 0.5) + (vUv.y - 0.5)*(vUv.y - 0.5)/screenRatio) : sqrt((vUv.x - 0.5)*(vUv.x - 0.5)*screenRatio+ (vUv.y - 0.5)*(vUv.y - 0.5));
  28882. float diff = 0.292; //1.0-maxRadius;
  28883. float radiusIn = maxRadius * progress + minRadius * (1.0-progress);
  28884. float radiusOut = radiusIn + diff;
  28885. if(radius < radiusIn) {
  28886. gl_FragColor = texture2D(bgTex, vUv);
  28887. //gl_FragColor = vec4(0.0,0.0,1.0,1.0);//
  28888. }else if(radius>radiusOut){
  28889. gl_FragColor = texture2D(coverTex, vUv) ;
  28890. //gl_FragColor = vec4(1.0,1.0,0.0,1.0);//
  28891. }else{
  28892. vec4 color1 = texture2D(bgTex, vUv);
  28893. vec4 color2 = texture2D(coverTex, vUv);
  28894. float rotio = smoothstep(radiusIn ,radiusOut,radius);
  28895. gl_FragColor = mix(color1, color2, rotio);
  28896. }
  28897. }
  28898. `
  28899. } );
  28900. } */
  28901. }
  28902. var GLCubeFaces$1 = Potree.defines.GLCubeFaces;
  28903. var TileUtils = {};
  28904. TileUtils.TILE_SIZE = 512, TileUtils.FACES_PER_PANO = 6, TileUtils.LocationOnTile = {
  28905. Center: 0,
  28906. UpperLeft: 1,
  28907. UpperRight: 2,
  28908. LowerRight: 3,
  28909. LowerLeft: 4
  28910. },
  28911. /*
  28912. * 获取某tile在cube中的方向 direction (向量起点在cube中心,终点在tile图的指定位置)。spherical通过先求uv,再直接得到dir
  28913. * @param {*} size 面分辨率
  28914. * @param {*} cubeFace 所在面
  28915. * @param {*} Center 在tile上的目标位置,默认为中心,其他位置就是四个顶点
  28916. * @param {*} c 似乎是在tile的缩进百分比,根据所在面的不同,分别向不同方向缩进,但都是向tile的中心
  28917. * @param {*} dir 所求方向
  28918. */
  28919. TileUtils.getTileVector = function () {
  28920. //获取某tile在cube中的方向 direction (向量起点在cube中心,终点在tile图的中心)
  28921. return function (size, tileSize, cubeFace, tileX, tileY, Center, c, dir) {
  28922. //c似乎是缩进百分比
  28923. Center = Center || TileUtils.LocationOnTile.Center;
  28924. //假设该cube边长为2:
  28925. var u = size / tileSize,
  28926. d = tileX / u;
  28927. tileY = -tileY + (u - 1);
  28928. var p = tileY / u,
  28929. f = tileSize / size,
  28930. g = 2 * f //一个tile的宽度 (乘以2是因为cube边长是2)
  28931. ,
  28932. m = g / 2,
  28933. v = 2 * d - 1 + m,
  28934. A = 2 * p - 1 + m;
  28935. switch (Center) {
  28936. //计算在tile中指定位置带来的偏移
  28937. case TileUtils.LocationOnTile.UpperLeft:
  28938. //1
  28939. v -= m, A += m, v += c * g; //似乎是向内缩进
  28940. break;
  28941. case TileUtils.LocationOnTile.UpperRight:
  28942. v += m, A += m, A -= c * g;
  28943. break;
  28944. case TileUtils.LocationOnTile.LowerRight:
  28945. v += m, A -= m, v -= c * g;
  28946. break;
  28947. case TileUtils.LocationOnTile.LowerLeft:
  28948. v -= m, A -= m, A += c * g;
  28949. break;
  28950. case TileUtils.LocationOnTile.Center: //0
  28951. }
  28952. switch (cubeFace) {
  28953. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  28954. MathLight.setVector(dir, -1, A, -v);
  28955. break;
  28956. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  28957. MathLight.setVector(dir, 1, A, v);
  28958. break;
  28959. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  28960. //顶面
  28961. MathLight.setVector(dir, -v, 1, -A);
  28962. break;
  28963. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  28964. MathLight.setVector(dir, -v, -1, A);
  28965. break;
  28966. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  28967. MathLight.setVector(dir, -v, A, 1);
  28968. break;
  28969. case GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  28970. MathLight.setVector(dir, v, A, -1);
  28971. }
  28972. MathLight.normalize(dir);
  28973. };
  28974. }(),
  28975. /*
  28976. * 获取该tile在第几个面(简易装载法)
  28977. */
  28978. TileUtils.getFaceForTile = function (size, index) {
  28979. //获取该tile在第几个面
  28980. var tileSize = TileUtils.TILE_SIZE;
  28981. size < TileUtils.TILE_SIZE && (tileSize = size);
  28982. var n = Math.floor(size / tileSize),
  28983. sum = n * n; //得每个面tile总数
  28984. return Math.floor(index / sum);
  28985. }, TileUtils.getTileLocation = function (size, t, result) {
  28986. var tileSize = TileUtils.TILE_SIZE;
  28987. size < TileUtils.TILE_SIZE && (tileSize = size);
  28988. var r = TileUtils.getFaceForTile(size, t),
  28989. a = Math.floor(size / tileSize),
  28990. s = a * a,
  28991. l = t - r * s;
  28992. result.tileX = l % a;
  28993. result.tileY = Math.floor(l / a);
  28994. result.face = r;
  28995. result.faceTileIndex = l;
  28996. return result;
  28997. },
  28998. /*
  28999. * 求size分辨率需要多少张tile
  29000. */
  29001. TileUtils.getTileCountForSize = function (e) {
  29002. if (e <= TileUtils.TILE_SIZE) return TileUtils.FACES_PER_PANO;
  29003. var t = Math.floor(e / TileUtils.TILE_SIZE),
  29004. i = t * t,
  29005. n = i * TileUtils.FACES_PER_PANO;
  29006. return n;
  29007. }, TileUtils.getRelativeDirection = function () {
  29008. var e = new MathLight.Matrix4(),
  29009. t = new MathLight.Quaternion();
  29010. return function (i, n) {
  29011. //i是pano.quaternion, n是camera的direction
  29012. t.copy(i), t.inverse(), e.makeRotationFromQuaternion(t), e.applyToVector3(n), MathLight.normalize(n);
  29013. };
  29014. }(),
  29015. /*
  29016. * 根据方向寻找合适的tile加载
  29017. */
  29018. TileUtils.matchingTilesInDirection = function () {
  29019. var e = new MathLight.Vector3(),
  29020. t = new MathLight.Vector3(0, 0, -1),
  29021. i = new MathLight.Quaternion(),
  29022. n = function n(e, t) {
  29023. e.push({
  29024. face: t.face,
  29025. faceTileIndex: t.faceTileIndex,
  29026. tileX: t.tileX,
  29027. tileY: t.tileY
  29028. });
  29029. },
  29030. a = function () {
  29031. var e = {
  29032. face: -1,
  29033. faceTileIndex: -1,
  29034. tileX: -1,
  29035. tileY: -1
  29036. };
  29037. return function (size, i, r) {
  29038. for (var a = TileUtils.getTileCountForSize(size), s = 0, l = 0; l < a; l++) TileUtils.getTileLocation(size, l, e), i && !i(e) || (s++, r && n(r, e));
  29039. return s;
  29040. };
  29041. }();
  29042. return function (pano, size, dir, hFov, vFov, result) {
  29043. var d = size < TileUtils.TILE_SIZE ? size : TileUtils.TILE_SIZE;
  29044. //TileUtils.getTileCountForSize(size);
  29045. if (!hFov && !vFov) return a(size, null, result);
  29046. var p = !!vFov;
  29047. vFov = vFov || hFov, vFov = Math.max(0, Math.min(vFov, 360)), hFov = Math.max(0, Math.min(hFov, 360)), MathLight.copyVector(dir, e), TileUtils.getRelativeDirection(pano.quaternion4dkk, e);
  29048. if (p) {
  29049. //如果有vFov hFov
  29050. i.setFromUnitVectors(e, t);
  29051. var f = function f(e) {
  29052. return TileUtils.isTileWithinFrustum(size, d, e.face, e.tileX, e.tileY, i, hFov, vFov); //在视野中的
  29053. };
  29054. return a(size, f, result);
  29055. }
  29056. var g = function g(t) {
  29057. //如果仅有hFov
  29058. return TileUtils.isTileWithinFOV(size, d, t.face, t.tileX, t.tileY, e, hFov);
  29059. };
  29060. return a(size, g, result);
  29061. };
  29062. }(),
  29063. /*
  29064. * 是否在屏幕范围内
  29065. */
  29066. TileUtils.isTileWithinFrustum = function () {
  29067. var e = new MathLight.Vector3(),
  29068. t = 1e-5;
  29069. return function (i, n, a, s, l, c, h, u) {
  29070. for (var d = Math.tan(.5 * u * MathLight.RADIANS_PER_DEGREE), p = -d, f = Math.tan(.5 * h * MathLight.RADIANS_PER_DEGREE), g = -f, m = TileUtils.mapFaceToCubemapFace(a), v = 0, A = 0, y = 0, C = 0, I = 0, E = 0, b = TileUtils.LocationOnTile.Center; b <= TileUtils.LocationOnTile.LowerLeft; b++) {
  29071. TileUtils.getTileVector(i, n, m, s, l, b, 0, e),
  29072. //get e // size, tileSize, cubeFace, tileX, tileY, Center, c, dir
  29073. MathLight.applyQuaternionToVector(c, e);
  29074. if (e.z >= -t)
  29075. //似乎是在相机背面
  29076. I++;else {
  29077. var w = -1 / e.z,
  29078. _ = e.x * w,
  29079. T = e.y * w;
  29080. T > d ? v++ : T < p && A++,
  29081. //这四种似乎代表在这个画框之外,如在左、在上、在下、在右
  29082. _ > f ? y++ : _ < g && C++, E++;
  29083. }
  29084. }
  29085. return A !== E && v !== E && y !== E && C !== E; //如果有一项和E相等代表要么是在相机背面要么是tile的四个顶点都画在画布的同一边,所以肯定不在画布上
  29086. };
  29087. }(),
  29088. /*
  29089. * 是否在FOV范围内
  29090. */
  29091. TileUtils.isTileWithinFOV = function () {
  29092. var e = new MathLight.Vector3(),
  29093. t = new MathLight.Vector3(0, 1, 0),
  29094. i = new MathLight.Vector3(1, 0, 0);
  29095. return function (panoSize, tileSize, face, tileX, tileY, direction, fov) {
  29096. //direction是作用了pano.quaternion的camera.direction
  29097. var d = TileUtils.mapFaceToCubemapFace(face);
  29098. MathLight.cross(direction, t, i); //get i 好像没用到
  29099. TileUtils.getTileVector(panoSize, tileSize, d, tileX, tileY, TileUtils.LocationOnTile.Center, 0, e);
  29100. if (TileUtils.isWithinFOV(e, direction, fov, null))
  29101. //先判断tile中心在不在FOV内
  29102. return !0;
  29103. for (var p = fov / 360, f = Math.floor(1 / p), g = 0, m = 0; m < f; m++) {
  29104. for (var v = TileUtils.LocationOnTile.UpperLeft; v <= TileUtils.LocationOnTile.LowerLeft; v++) if (TileUtils.getTileVector(panoSize, tileSize, d, tileX, tileY, v, g, e), TileUtils.isWithinFOV(e, direction, fov, null)) return !0;
  29105. g += p; //可能是考虑到有可能tile比fov覆盖了fov(虽然一般不可能,除非fov特别小),所以将tile分成若干段,取tile中的点再检测下
  29106. }
  29107. return !1;
  29108. };
  29109. }(), TileUtils.isWithinFOV = function () {
  29110. var e = new MathLight.Vector3(),
  29111. t = new MathLight.Vector3();
  29112. return function (dir, cameraDir, fov, a) {
  29113. if (MathLight.copyVector(dir, t), a) {
  29114. MathLight.copyVector(a, e), MathLight.normalize(e);
  29115. var s = MathLight.dot(e, dir);
  29116. e.x *= s, e.y *= s, e.z *= s, MathLight.subVector(t, e);
  29117. }
  29118. var l = fov / 2 * MathLight.RADIANS_PER_DEGREE,
  29119. c = Math.cos(l),
  29120. h = MathLight.dot(t, cameraDir);
  29121. return h >= c;
  29122. };
  29123. }(), TileUtils.mapFaceToCubemapFace = function () {
  29124. var e = {
  29125. 0: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
  29126. 1: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
  29127. 2: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_POSITIVE_X,
  29128. 3: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
  29129. 4: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
  29130. 5: GLCubeFaces$1.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
  29131. };
  29132. return function (t) {
  29133. return e[t];
  29134. };
  29135. }();
  29136. var {
  29137. PanoRendererEvents,
  29138. PanoramaEvents,
  29139. PanoSizeClass
  29140. } = Potree.defines;
  29141. var texLoader$3 = new TextureLoader();
  29142. var markerOpacitys = {
  29143. default: 0.4,
  29144. hovered: 1
  29145. };
  29146. var labelProp = {
  29147. sizeInfo: {
  29148. minSize: 200,
  29149. maxSize: 250,
  29150. nearBound: 0.8,
  29151. farBound: 10
  29152. },
  29153. backgroundColor: {
  29154. r: 255,
  29155. g: 255,
  29156. b: 255,
  29157. a: 0.4
  29158. },
  29159. textColor: {
  29160. r: 0,
  29161. g: 0,
  29162. b: 0,
  29163. a: 1
  29164. },
  29165. borderRadius: 15,
  29166. renderOrder: 10,
  29167. useDepth: true,
  29168. clipDistance: 30,
  29169. maxClipFactor: 0.3,
  29170. occlusionDistance: 3
  29171. };
  29172. var labelProp2 = {
  29173. //sizeInfo: {minSize : 200 , maxSize : 250, nearBound : 0.8, farBound : 10},
  29174. backgroundColor: {
  29175. r: 255,
  29176. g: 255,
  29177. b: 255,
  29178. a: 0
  29179. },
  29180. textColor: {
  29181. r: 255,
  29182. g: 255,
  29183. b: 255,
  29184. a: 1
  29185. },
  29186. textBorderColor: {
  29187. r: 30,
  29188. g: 30,
  29189. b: 30,
  29190. a: 1
  29191. },
  29192. textBorderThick: 3,
  29193. dontFixOrient: true,
  29194. renderOrder: 10,
  29195. fontsize: 30
  29196. };
  29197. var markerTex;
  29198. //显示全景图时marker没有被遮挡,如果需要,要换成depthBasicMaterial 或者直接把skybox的深度修改(拿到深度贴图后更如此)
  29199. var planeGeo = new PlaneBufferGeometry(0.4, 0.4);
  29200. var sg = new SphereGeometry(0.1, 8, 8);
  29201. var smHovered = new MeshBasicMaterial({
  29202. /* side: THREE.BackSide, */color: 0xff0000
  29203. });
  29204. var sm = new MeshBasicMaterial({/* side: THREE.BackSide */});
  29205. var rot90 = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2); //使用的是刚好适合全景图的,给cube贴图需要转90°
  29206. //var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI/2 ); //4dkk->navvis
  29207. //var rot901 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0), -Math.PI/2 ); //整张球幕图要旋转下
  29208. //rot90 = new THREE.Quaternion().multiplyQuaternions( rot901, rot90)
  29209. var rotQua2 = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), Math.PI);
  29210. var old = null;
  29211. /*
  29212. 转成四维看看的axis:
  29213. var a = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), THREE.Math.degToRad(-90)) 因为四维的要绕y转90
  29214. 这里的quaternion.multiply(a);
  29215. 先乘再换顺序 w : q.w, x:q.x , y:-q.z, z:q.y
  29216. */
  29217. //暂时直接用4dkkconsole输出的数据
  29218. class Panorama extends EventDispatcher {
  29219. constructor(o, images360) {
  29220. super();
  29221. this.id = o.id; //唯一标识
  29222. this.images360 = images360;
  29223. this.visible = true; //for updateVisible
  29224. this.enabled = true; //是否可以走
  29225. this.addEventListener('isVisible', e => {
  29226. //是否显示该点的mesh(不显示也能走)
  29227. //console.log('pano isVisible', this.id, e.visible)
  29228. Potree.Utils.updateVisible(this.marker, 'panoVisi', e.visible);
  29229. Potree.settings.showPanoMesh && (this.mesh.visible = e.visible);
  29230. if (e.reason == 'screenshot' || e.visible) {
  29231. this.label && (this.label.visible = e.visible); //截图时隐藏下
  29232. }
  29233. this.label2 && Potree.Utils.updateVisible(this.label2, 'panoVisi', e.visible);
  29234. });
  29235. /*
  29236. 漫游点可见性:新
  29237. level reason 类型
  29238. 2(最高)buildingChange(不在此楼层) unvisible
  29239. 1 ifShowMarker(marker显示开关) unvisible
  29240. 0 pointcloudVisi(隐藏了数据集) unvisible
  29241. */
  29242. if (Potree.settings.editType == 'pano') {
  29243. //漫游点拼合编辑
  29244. this.uuid = this.originID = o.uuid; //对应4dkk中的id,可能不连续
  29245. this.index = o.index; //下标, 用于visibles
  29246. this.pointcloud = viewer.scene.pointclouds.find(e => e.panoUuid == o.uuid);
  29247. this.pointcloud.panos.push(this);
  29248. this.sid = this.pointcloud.dataset_id + '|' + this.uuid; //不会更改的标记 用于entity.panos里的标记
  29249. delete o.pointcloud;
  29250. this.panoData = o;
  29251. /* //数据中原本的位置朝向
  29252. this.dataPosition = new THREE.Vector3().copy(o.pose.translation)
  29253. this.dataQuaternion = new THREE.Quaternion().copy(o.pose.rotation)
  29254. this.dataRotation = new THREE.Euler().setFromQuaternion(this.dataQuaternion) */
  29255. //因为位置朝向随着点云位置改变,所以直接改变点云,这里清零
  29256. this.originPosition = new Vector3();
  29257. this.quaternion = new Quaternion().copy(rotQua2);
  29258. this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion); //4dkk内使用的quaternion
  29259. this.quaternion2 = this.quaternion.clone();
  29260. this.quaternion = new Quaternion().multiplyQuaternions(this.quaternion, rot90); //全景图和Cube的水平采样起始坐标相差90度,cubeTex转90度
  29261. var height = 1.4; //相机高度
  29262. this.originFloorPosition = this.originPosition.clone();
  29263. this.originFloorPosition.z -= height;
  29264. } else {
  29265. this.originPosition = new Vector3().fromArray(o.dataset_location); //完全对应vision.txt的translation
  29266. this.originFloorPosition = new Vector3().fromArray(o.dataset_floor_location);
  29267. this.originID = parseInt(o.file_id); //"file_id":"00022" 对应是4dkk的id --来自vision.txt
  29268. this.pointcloud = o.pointcloud; //viewer.scene.pointclouds.find(e=>e.dataset_id == o.dataset_id) || viewer.scene.pointclouds[0]
  29269. this.pointcloud.panos.push(this);
  29270. //this.sid = this.pointcloud.sceneCode + '|' + this.originID //不会更改的标记
  29271. this.sid = this.pointcloud.dataset_id + '|' + this.originID; //不会更改的标记
  29272. //全景图和Cube的水平采样起始坐标相差90度
  29273. /* if(from4dkk){
  29274. var qua = o.dataset_orientation
  29275. var quaternion = new THREE.Quaternion().fromArray(qua)
  29276. quaternion = new THREE.Quaternion().multiplyQuaternions(quaternion, rot901);//整张球幕图要旋转下 因为在4dkk里转过,还原。如果是tiles的不用
  29277. this.quaternion = new THREE.Quaternion(quaternion.x, -quaternion.z, quaternion.y, quaternion.w) //转化坐标
  29278. }else{ */
  29279. var qua = o.dataset_orientation; //完全对应vision.txt的rotation
  29280. qua = [qua[1], qua[2], qua[3], qua[0]];
  29281. this.quaternion = new Quaternion().fromArray(qua);
  29282. this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion); //4dkk内使用的quaternion
  29283. this.quaternion2 = this.quaternion.clone();
  29284. this.quaternion = new Quaternion().multiplyQuaternions(this.quaternion, rot90); //全景图和Cube的水平采样起始坐标相差90度,cubeTex转90度
  29285. this.rotation4dkk = new Euler().setFromQuaternion(this.quaternion4dkk);
  29286. }
  29287. this.neighbours = [];
  29288. this.rotation = new Euler().setFromQuaternion(this.quaternion);
  29289. this.build();
  29290. this.transformByPointcloud(); //初始化位移
  29291. {
  29292. //tile
  29293. this.minimumTiledPanoLoaded = !1;
  29294. this.highestPartialTileRenderOpCompleted = 0;
  29295. this.highestFullTileRenderOpCompleted = 0;
  29296. this.shouldRedrawOnBaseLoaded = !1;
  29297. this.resolutionPromise = {};
  29298. this.tiledPanoRenderTarget = null;
  29299. this.zoomed = !1;
  29300. images360.panoRenderer.addEventListener(PanoRendererEvents.TileRenderSuccess, this.onTileRendered.bind(this));
  29301. images360.panoRenderer.addEventListener(PanoRendererEvents.PanoRenderComplete, this.onPanoRendered.bind(this));
  29302. images360.panoRenderer.addEventListener(PanoRendererEvents.TileRenderFailure, this.onTileRenderFail.bind(this));
  29303. images360.panoRenderer.addEventListener(PanoRendererEvents.UploadAttemptedForAllTiles, this.onUploadAttemptedForAllTiles.bind(this));
  29304. }
  29305. this.addEventListener('hoverOn', e => {
  29306. //from Map
  29307. if (!e.byMainView) {
  29308. this.hoverOn(e);
  29309. }
  29310. });
  29311. this.addEventListener('hoverOff', e => {
  29312. if (!e.byMainView) {
  29313. this.hoverOff(e);
  29314. }
  29315. });
  29316. }
  29317. get noNeighbour() {
  29318. //是否绝对到不到的孤立点
  29319. for (var i = 0, j = this.images360.panos.length; i < j; i++) {
  29320. if (this.images360.neighbourMap[this.id][i] !== false) {
  29321. return false;
  29322. }
  29323. }
  29324. return true;
  29325. //return this.neighbours.length == 0
  29326. }
  29327. setEnable(enable) {
  29328. //是否可以走
  29329. Potree.Utils.updateVisible(this, 'isEnabled', enable); //令所有marker不可见
  29330. this.enabled = enable;
  29331. viewer.dispatchEvent('content_changed');
  29332. //如果当前在全景模式且在这个点,需要切换显示吗? 目前用不到
  29333. }
  29334. loadDepthImg() {
  29335. if (!this.pointcloud.hasDepthTex || this.depthTex || this.depthTexLoading) return;
  29336. this.depthTexLoading = true;
  29337. var mapping = Potree.settings.isLocal2 ? '' : this.pointcloud.datasetData.mapping; //非离线包的话加mapping
  29338. var src;
  29339. if (Potree.settings.urls.templates.depthTex) {
  29340. src = Potree.Common.replaceAll(Potree.settings.urls.templates.depthTex, '{sceneCode}', this.pointcloud.sceneCode) + "/".concat(this.originID, ".png");
  29341. } else {
  29342. var prefix = Potree.settings.urls.getPrefix(1, this.pointcloud); //Potree.settings.urls.laserOSSRoot || this.pointcloud.prop?.raw?.laserOssRoot || Potree.settings.urls.prefix1
  29343. src = "".concat(prefix, "/").concat(mapping ? mapping + '/' : '').concat(Potree.settings.webSite, "/").concat(this.pointcloud.sceneCode, "/data/").concat(this.pointcloud.sceneCode, "/depthmap/").concat(this.originID, ".png");
  29344. }
  29345. //console.log('开始下载depthImg', this.id)
  29346. var texture = texLoader$3.load(src, () => {
  29347. this.depthTex = texture;
  29348. this.dispatchEvent({
  29349. type: 'loadedDepthImg',
  29350. loaded: true
  29351. });
  29352. this.images360.dispatchEvent({
  29353. type: 'loadedDepthImg',
  29354. pano: this
  29355. });
  29356. this.depthTexLoading = false;
  29357. this.images360.updateDepthTex(this);
  29358. }, null, e => {
  29359. //error
  29360. console.error('loadDepthImg失败, 数据集sceneCode' + this.pointcloud.sceneCode, this.id);
  29361. this.pointcloud.hasDepthTex = false;
  29362. this.dispatchEvent({
  29363. type: 'loadedDepthImg'
  29364. });
  29365. });
  29366. texture.wrapS = RepeatWrapping;
  29367. texture.flipY = false;
  29368. texture.magFilter = LinearFilter;
  29369. texture.minFilter = LinearFilter;
  29370. texture.generateMipmaps = false;
  29371. //平均一张0.75M。2048*1024。 和tile一样加载后永不删除,是否会造成崩溃?
  29372. }
  29373. /* loadTypeImg(type){
  29374. if(!this['has_'+type] || this[type+'Tex'] || this[type+'Loading'])return
  29375. let url = `${Potree.settings.urls.prefix1}/testdata/${Potree.settings.number}/data/${this.pointcloud.sceneCode}/imagemap/${this.originID}_${type}.png`
  29376. //let url = `${Potree.settings.urls.prefix1}/testdata/${Potree.settings.number}/data/${this.pointcloud.sceneCode}/imagemap/${this.originID}_temp.png`
  29377. let texture = texLoader.load( url, ()=>{
  29378. this[type+'Tex'] = texture
  29379. this.dispatchEvent({type:'loaded_'+type, loaded:true})
  29380. this.images360.dispatchEvent({type:'loaded_'+type, pano:this})
  29381. this[type+'Loading'] = false
  29382. },null,(e)=>{//error
  29383. console.error('load '+type+'Img失败, 数据集sceneCode'+ this.pointcloud.sceneCode, this.id )
  29384. this['has_'+type] = false
  29385. this['loadFailed_'+type] = false
  29386. this.dispatchEvent({type:'loaded_'+type })
  29387. });
  29388. texture.wrapS = THREE.RepeatWrapping;
  29389. texture.flipY = false
  29390. texture.magFilter = THREE.LinearFilter
  29391. texture.minFilter = THREE.LinearFilter
  29392. texture.generateMipmaps = false
  29393. } */
  29394. loadTypeImg(type) {
  29395. if (!this['has_' + type] || this[type + 'Tex'] || this[type + 'Loading']) return;
  29396. var url = this.pointcloud.typesUrl + "".concat(this.originID, "_").concat(type, ".png");
  29397. //let url = `${Potree.settings.urls.prefix1}/testdata/${this.pointcloud.sceneCode}/data/${this.pointcloud.sceneCode}/imagemap/${this.originID}_temp.png`
  29398. var range = {
  29399. min: Infinity,
  29400. max: -Infinity,
  29401. minPixel: null,
  29402. maxPixel: null
  29403. };
  29404. var pixels;
  29405. var getRangeFun = (type == 'ir' || type == 'temp') && function (uint16Value, index, pixelCount) {
  29406. if (type == 'ir') {
  29407. pixels || (pixels = new Uint16Array(pixelCount));
  29408. pixels[index] = uint16Value;
  29409. }
  29410. if (uint16Value != 0 && uint16Value < range.min) {
  29411. range.min = uint16Value;
  29412. range.minPixel_ = index;
  29413. }
  29414. if (uint16Value != 0 && uint16Value > range.max) {
  29415. range.max = uint16Value;
  29416. range.maxPixel_ = index;
  29417. }
  29418. };
  29419. var texture = Potree.Common.load16bitPngTex(url, () => {
  29420. this[type + 'Tex'] = texture;
  29421. if (getRangeFun) {
  29422. if (type == 'ir') {
  29423. var p = [range.minPixel_, range.maxPixel_].map(index => {
  29424. var row = Math.floor(index / texture.image.width);
  29425. var col = index % texture.image.width;
  29426. return {
  29427. x: col,
  29428. y: row
  29429. };
  29430. });
  29431. range.minPixel = p[0];
  29432. range.maxPixel = p[1];
  29433. var pixelCount = texture.image.width * texture.image.height;
  29434. var stopMemberCount = 50;
  29435. ['min', 'max'].forEach(name => {
  29436. var _groups2$;
  29437. var value = range[name];
  29438. var groups = [];
  29439. var isNeigh = (A, B) => {
  29440. return (Math.abs(A.x - B.x) <= 1 || Math.abs(A.x - B.x) == texture.image.width - 1) && Math.abs(A.y - B.y) <= 1;
  29441. };
  29442. for (var i = 0; i < pixelCount; i++) {
  29443. if (Math.abs(value - pixels[i]) == 0) {
  29444. var row = Math.floor(i / texture.image.width);
  29445. var col = i % texture.image.width;
  29446. var data = {
  29447. x: col,
  29448. y: row,
  29449. value: pixels[i]
  29450. };
  29451. Potree.Common.pushToGroupAuto([data], groups, isNeigh);
  29452. if (groups.some(e => e.length > stopMemberCount && e.some(e => e == range[name]))) {
  29453. break;
  29454. }
  29455. }
  29456. }
  29457. var groups2 = groups.filter(e => e.length > 1);
  29458. if (groups2.length < 3) groups2 = groups;
  29459. groups2.forEach(group => {
  29460. //x的因边界不好写,就只判断y尽量接近中间且范围不大不小即可
  29461. group.sort((a, b) => {
  29462. return a.y - b.y;
  29463. });
  29464. var minY = group[0].y;
  29465. var maxY = group[group.length - 1].y;
  29466. var centerY = (minY + maxY) / 2;
  29467. var rectRatio = (maxY - minY) * 1; //除非竖的一列,否则一般y范围越大越好 Math.abs(2 - Potree.math.getBaseLog(maxY - minY, group.length)) //范围圆润度, 最好个数是y范围的平方
  29468. group.score = group.length * 0.2 + rectRatio - Math.abs(texture.image.height / 2 - centerY) * 0.5; //y尽量接近中间
  29469. group.center = group[Math.floor(group.length / 2)]; //忽略是否横向的中间
  29470. });
  29471. groups2.sort((b, a) => {
  29472. return a.score - b.score;
  29473. });
  29474. range[name + 'Pixel'] = (_groups2$ = groups2[0]) === null || _groups2$ === void 0 ? void 0 : _groups2$.center;
  29475. //range[name+'PixelGroup'] = groups2
  29476. console.log('groups2', this.id, name, groups2);
  29477. });
  29478. }
  29479. range.min /= 10, range.max /= 10;
  29480. texture.image.range = range;
  29481. viewer.gatherTempRange(type, range);
  29482. }
  29483. this.dispatchEvent({
  29484. type: 'loaded_' + type,
  29485. loaded: true
  29486. });
  29487. this.images360.dispatchEvent({
  29488. type: 'loaded_' + type,
  29489. pano: this
  29490. });
  29491. this[type + 'Loading'] = false;
  29492. }, e => {
  29493. console.error('load ' + type + 'Img失败, 数据集sceneCode' + this.pointcloud.sceneCode, e, this.id);
  29494. this['has_' + type] = false;
  29495. this['loadFailed_' + type] = false;
  29496. this.dispatchEvent({
  29497. type: 'loaded_' + type
  29498. });
  29499. }, getRangeFun);
  29500. texture.wrapS = RepeatWrapping;
  29501. texture.flipY = false;
  29502. texture.magFilter = LinearFilter;
  29503. texture.minFilter = LinearFilter;
  29504. texture.generateMipmaps = false;
  29505. }
  29506. build() {
  29507. {
  29508. // orientation
  29509. //add
  29510. //var quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion, rot901);//改 为球目全
  29511. //quaternion.premultiply(rot90)
  29512. this.panoMatrix = new Matrix4().makeRotationFromQuaternion(this.quaternion);
  29513. this.oriPanoMatrix = this.panoMatrix.clone();
  29514. if (this.quaternion2) this.oriPanoMatrix2 = new Matrix4().makeRotationFromQuaternion(this.quaternion2);
  29515. //console.log(this.quaternion)
  29516. //this.quaternion = quaternion
  29517. }
  29518. var marker = new Mesh(planeGeo, this.getMarkerMat()); //new Sprite({mat:this.getMarkerMat(), dontFixOrient:true })
  29519. marker.name = 'marker_' + this.id;
  29520. marker.up.set(0, 0, 1);
  29521. this.addEventListener('changeMarkerTex', e => {
  29522. marker.material.map = markerTex[e.name];
  29523. });
  29524. this.marker = marker;
  29525. marker.pano = this;
  29526. this.images360.node.add(marker);
  29527. Potree.settings.isTest && this.addLabel();
  29528. marker.addEventListener('mouseover', this.hoverOn.bind(this));
  29529. marker.addEventListener('mouseleave', this.hoverOff.bind(this));
  29530. }
  29531. transformByPointcloud() {
  29532. this.ceilZ = null; //need reset
  29533. var position = this.originPosition.clone().applyMatrix4(this.pointcloud.transformMatrix); //也可以用datasetPosTransform算
  29534. var floorPosition = this.originFloorPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);
  29535. this.setPosition(position, floorPosition);
  29536. this.panoMatrix = new Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix);
  29537. //this.panoMatrix2 = Potree.Utils.datasetRotTransform({fromDataset:true, pointcloud:this.pointcloud, matrix:this.oriPanoMatrix, getMatrix:true}) //和上一行结果一样
  29538. //quaternion也变下
  29539. if (this.oriPanoMatrix2) {
  29540. this.panoMatrix2 = new Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix2); //供DepthImageSampler使用
  29541. this.panoMatrix2Inverse = this.panoMatrix2.clone().invert();
  29542. }
  29543. this.dispatchEvent('rePos');
  29544. }
  29545. setPosition(position, floorPosition) {
  29546. this.position = position;
  29547. this.floorPosition = floorPosition;
  29548. //this.mesh.position.copy(this.position)
  29549. this.marker.position.copy(this.floorPosition);
  29550. this.marker.lookAt(position); //融合页面marker可能跟随模型倾斜
  29551. var upVec = new Vector3().subVectors(position, floorPosition).normalize().multiplyScalar(0.04 * this.pointcloud.scale.x);
  29552. this.marker.position.add(upVec); //this.marker.position.z+=0.04//会被点云遮住
  29553. if (this.label) {
  29554. if (Potree.settings.editType == 'pano') {
  29555. this.label.position.copy(this.position);
  29556. } else {
  29557. this.label.position.copy(this.floorPosition);
  29558. }
  29559. this.label.position.z += 0.14;
  29560. this.label.updatePose();
  29561. }
  29562. }
  29563. /* getRealPos(){//当整体移动以后
  29564. return this.position.clone().applyMatrix4(viewer.scene.scene.matrix)
  29565. } */
  29566. getMarkerMat() {
  29567. if (!markerTex) {
  29568. markerTex = {
  29569. default: texLoader$3.load(Potree.resourcePath + '/textures/marker.png'),
  29570. ring: texLoader$3.load(Potree.resourcePath + '/textures/marker2.png')
  29571. };
  29572. markerTex.default.anisotropy = 4; // 各向异性过滤 .防止倾斜模糊
  29573. markerTex.ring.anisotropy = 4;
  29574. //有可能被点云遮住吗。
  29575. }
  29576. var mat = new DepthBasicMaterial({
  29577. opacity: markerOpacitys.default,
  29578. side: DoubleSide,
  29579. map: markerTex.default,
  29580. transparent: true,
  29581. clipDistance: 2,
  29582. occlusionDistance: 1,
  29583. //不能设置太短,因为过渡时深度不准确
  29584. useDepth: !!(Potree.settings.useDepthTex && this.pointcloud.hasDepthTex || Potree.settings.modelSkybox && this.pointcloud.is4dkkModel),
  29585. autoDepthTest: true
  29586. //改为DepthBasicMaterial是因为原Basic的材质在有深度图时过渡会先隐藏后出现。 注:没有深度图时全景模式的marker无法遮挡
  29587. });
  29588. mat.mapTransparent = true;
  29589. return mat;
  29590. }
  29591. hoverOn() {
  29592. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  29593. //console.log("hoverOn " + this.id )
  29594. transitions.start(lerp.property(this.marker.material, "opacity", markerOpacitys.hovered, () => {
  29595. viewer.dispatchEvent('content_changed');
  29596. }), this.marker.visible ? 250 : 0);
  29597. if (!e.byMap) this.dispatchEvent({
  29598. type: 'hoverOn',
  29599. byMainView: true
  29600. });
  29601. if (!e.byImages360) this.images360.dispatchEvent({
  29602. type: 'markerHover',
  29603. hovered: true,
  29604. pano: this
  29605. });
  29606. }
  29607. hoverOff() {
  29608. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  29609. //console.log("hoverOff " + this.id )
  29610. transitions.start(lerp.property(this.marker.material, "opacity", markerOpacitys.default, () => {
  29611. viewer.dispatchEvent('content_changed');
  29612. }), this.marker.visible ? 250 : 0);
  29613. if (!e.byMap) this.dispatchEvent({
  29614. type: 'hoverOff',
  29615. byMainView: true
  29616. });
  29617. if (!e.byImages360) this.images360.dispatchEvent({
  29618. type: 'markerHover',
  29619. hovered: false,
  29620. pano: this
  29621. });
  29622. }
  29623. setZoomed(zoomed) {
  29624. this.zoomed = zoomed;
  29625. Potree.settings.displayMode == 'showPanos' && this.updateSkyboxForZoomLevel(); //放大后换成zoomTarget贴图
  29626. viewer.dispatchEvent({
  29627. type: 'panoSetZoom',
  29628. zoomed
  29629. });
  29630. }
  29631. enter() {
  29632. this.entered = true;
  29633. this.setZoomed(!1);
  29634. viewer.dispatchEvent({
  29635. type: PanoramaEvents.Enter,
  29636. oldPano: old,
  29637. newPano: this
  29638. });
  29639. old = this;
  29640. //console.log("enter pano "+ this.id)
  29641. }
  29642. exit() {
  29643. this.clearWaitDeferreds();
  29644. this.minimumTiledPanoLoaded = !1;
  29645. this.tiledPanoRenderTarget = null;
  29646. this.setZoomed(!1);
  29647. this.images360.panoRenderer.deactivateTiledPano(this);
  29648. this.highestPartialTileRenderOpCompleted = 0;
  29649. this.highestFullTileRenderOpCompleted = 0;
  29650. this.depthTex && this.depthTex.dispose(); //贴图不使用后先dispose,下次到该点时会自动还原
  29651. this.entered = false; //add
  29652. //console.log("exit pano "+ this.id)
  29653. viewer.dispatchEvent({
  29654. type: PanoramaEvents.Exit,
  29655. pano: this
  29656. });
  29657. }
  29658. updateSkyboxForZoomLevel() {
  29659. if (this.minimumTiledPanoLoaded) {
  29660. this.images360.updateProjectedPanos();
  29661. }
  29662. }
  29663. getSkyboxTexture() {
  29664. if (this.minimumTiledPanoLoaded) {
  29665. if (this.zoomed && this.images360.qualityManager.maxRenderTargetSize > this.images360.qualityManager.maxNavPanoSize)
  29666. //change 如果放大后和不放大都是2k就不用这个
  29667. {
  29668. return this.images360.panoRenderer.zoomRenderTarget.texture;
  29669. } else {
  29670. this.tiledPanoRenderTarget.texture.mapping = UVMapping; //add
  29671. return this.tiledPanoRenderTarget.texture;
  29672. }
  29673. } else {
  29674. return null;
  29675. }
  29676. }
  29677. isLoaded(e) {
  29678. if (e && "string" == typeof e) console.error("Wrong panoSize given to Panorama.isLoaded(); a tiled pano uses PanoSizeClass");
  29679. return !!this.minimumTiledPanoLoaded && (!e || this.highestFullTileRenderOpCompleted >= e); //改:原本是:this.highestPartialTileRenderOpCompleted >= e, 希望这代表全部加载完
  29680. }
  29681. getWaitDeferred(size) {
  29682. //获取不同size的tile贴图的promiss
  29683. var t = this.resolutionPromise[this.id];
  29684. t || (t = {}, this.resolutionPromise[this.id] = t);
  29685. var i = t[size];
  29686. return i || (i = {
  29687. deferred: $.Deferred(),
  29688. active: !1
  29689. }, t[size] = i), i;
  29690. }
  29691. clearWaitDeferreds() {
  29692. var e = this.resolutionPromise[this.id];
  29693. e || (e = {}, this.resolutionPromise[this.id] = e);
  29694. for (var t in e) if (e.hasOwnProperty(t)) {
  29695. var i = e[t];
  29696. i.active = !1, i.deferred = $.Deferred();
  29697. }
  29698. }
  29699. resetWaitDeferred(e) {
  29700. var t = this.getWaitDeferred(e);
  29701. t.active = !1;
  29702. t.deferred = $.Deferred();
  29703. }
  29704. onTileRendered(ev) {
  29705. ev.id === this.id && this.dispatchEvent({
  29706. type: PanoramaEvents.TileLoaded,
  29707. size: ev.panoSize,
  29708. index: ev.tileIndex,
  29709. count: ev.totalTiles
  29710. });
  29711. }
  29712. onPanoRendered(ev) {
  29713. if (ev.id === this.id) {
  29714. this.minimumTiledPanoLoaded = !0;
  29715. this.updateSkyboxForZoomLevel(); //更新贴图 setProjected
  29716. ev.panoSize > this.highestPartialTileRenderOpCompleted && (this.highestPartialTileRenderOpCompleted = ev.panoSize); //应该是更新最高获取到的Partial size
  29717. ev.updateFullComplete && ev.panoSize > this.highestFullTileRenderOpCompleted && (this.highestFullTileRenderOpCompleted = ev.panoSize); //应该是更新最高获取到的Full size
  29718. //this.dispatchEvent("load", ev.panoSize);
  29719. viewer.ifAllLoaded(this);
  29720. this.dispatchEvent({
  29721. type: PanoramaEvents.LoadComplete,
  29722. size: ev.panoSize,
  29723. count: ev.totalTiles
  29724. });
  29725. }
  29726. }
  29727. onTileRenderFail(ev) {
  29728. ev.id === this.id && this.dispatchEvent({
  29729. type: PanoramaEvents.LoadFailed
  29730. });
  29731. }
  29732. onUploadAttemptedForAllTiles(ev) {
  29733. if (ev.id === this.id) {
  29734. var n = this.images360.qualityManager.getPanoSize(PanoSizeClass.BASE);
  29735. if (ev.panoSize === n && this.shouldRedrawOnBaseLoaded)
  29736. //shouldRedrawOnBaseLoaded一直是false。在4dkk里只有初始点在quickstart后变为true。
  29737. {
  29738. this.shouldRedrawOnBaseLoaded = !1;
  29739. this.panoRenderer.resetRenderStatus(this.id, !0, !1);
  29740. this.panoRenderer.renderPanoTiles(this.id, null, !0, !0);
  29741. }
  29742. }
  29743. }
  29744. addLabel() {
  29745. this.removeTextLabel();
  29746. this.label = new TextSprite$2(Object.assign({}, labelProp, {
  29747. text: this.id + "(" + this.originID + ")"
  29748. }) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  29749. );
  29750. this.images360.node.add(this.label);
  29751. this.floorPosition && this.label.position.copy(this.floorPosition);
  29752. }
  29753. addLabel2() {
  29754. if (this.label2) return;
  29755. this.label2 = new TextSprite$2(Object.assign({}, labelProp2, {
  29756. text: /* this.originID */parseInt(this.id) + 1
  29757. }) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  29758. );
  29759. //this.images360.node.add(this.label2);
  29760. this.marker.add(this.label2);
  29761. //this.floorPosition && this.label2.position.copy(this.floorPosition)
  29762. var s = 0.2;
  29763. this.label2.scale.set(s, s, s);
  29764. Potree.Utils.updateVisible(this.label2, 'notDisplay', false);
  29765. Potree.Utils.updateVisible(this.label2, 'panoVisi', this.visible);
  29766. //Potree.Utils.setObjectLayers(this.label2, 'bothMapAndScene')
  29767. }
  29768. removeTextLabel() {
  29769. if (this.label) {
  29770. this.label.parent.remove(this.label);
  29771. }
  29772. }
  29773. dispose() {
  29774. var i = viewer.images360.panos.indexOf(this);
  29775. if (i == -1) return;
  29776. viewer.images360.panos.splice(i, 1);
  29777. i = this.pointcloud.panos.indexOf(this);
  29778. this.pointcloud.panos.splice(i, 1);
  29779. this.marker.parent.remove(this.marker);
  29780. this.removeTextLabel();
  29781. if (this.depthTex) this.depthTex.dispose();
  29782. this.dispatchEvent('dispose');
  29783. //删除tile贴图、depthTex等以后再写
  29784. }
  29785. getCeilHeight() {
  29786. //天花板高度值 (假设不存在depth为0的点,所有为0的要么是在盲区,要么是无穷远。)
  29787. if (this.ceilZ == void 0) {
  29788. //const depthTiming = Potree.timeCollect.depthSampler.median //pc firefox达到4. chrome为0.01
  29789. //用三个间隔120度散开,和中心垂直线成一定夹角的三个向量去求 最高高度 (不求平均的原因:万一是0不好算)
  29790. var rotMat = new Matrix4().makeRotationX((Potree.config.depthTexUVyLimit + 0.01) * Math.PI); // 角度不能小于天花板中空的半径
  29791. var dir0 = new Vector3(0, 0, 1).applyMatrix4(rotMat);
  29792. var dirs = [dir0, dir0.clone().applyMatrix4(new Matrix4().makeRotationZ(Math.PI * 2 / 3)), dir0.clone().applyMatrix4(new Matrix4().makeRotationZ(-Math.PI * 2 / 3))];
  29793. /* if(depthTiming < 1){
  29794. let rotMat1 = new THREE.Matrix4().makeRotationZ(Math.PI*2 / 3);
  29795. dirs.push(dirs[0].clone().applyMatrix4(rotMat1))
  29796. }
  29797. if(depthTiming < 0.3){
  29798. let rotMat2 = new THREE.Matrix4().makeRotationZ(-Math.PI*2 / 3);
  29799. dirs.push(dirs[0].clone().applyMatrix4(rotMat2));
  29800. } */
  29801. var zs = dirs.map(dir_ => {
  29802. var dir = dir_.clone().applyMatrix4(this.panoMatrix2); //pano不一定是垂直的, 需要把之前的dirInPano先转成真实的dir,防止超出角度限制
  29803. var intersect = viewer.images360.getIntersect(this, dir);
  29804. var z = intersect ? intersect.location.z : Infinity; /* this.position.z+skyHeight */ //没有intersect代表可能是天空
  29805. return z;
  29806. });
  29807. zs.sort((a, b) => {
  29808. return b - a;
  29809. }); //得最大值 (不用中位数的原因:在屋檐处,如果仅有一个intersect是天空,因到了室外所以也用天空高度)
  29810. this.ceilZ = zs[0];
  29811. var min = this.position.z + 1; // 防止意外太低
  29812. this.ceilZ = Math.max(min, this.ceilZ);
  29813. //console.log(this.id, 'ceilZ:', this.ceilZ )
  29814. }
  29815. return this.ceilZ;
  29816. }
  29817. }
  29818. ;
  29819. Panorama.prototype.loadTiledPano = function () {
  29820. //var downloads = [] , t = [];
  29821. var downloaded = {},
  29822. eventAdded = {},
  29823. latestPartialRequest = {}; //每个pano对应一组这些
  29824. return function (size, dirs, fov, o, a, download) {
  29825. var dir = dirs.datasetsLocal.find(e => e.datasetId == this.pointcloud.dataset_id).direction;
  29826. //var dir = dirs
  29827. null !== o && void 0 !== o || (o = !0), null !== a && void 0 !== a || (a = !0);
  29828. var l = this.getWaitDeferred(size),
  29829. c = l.deferred,
  29830. h = null,
  29831. u = null;
  29832. fov && ("number" == typeof fov ? h = fov : (h = fov.hFov, u = fov.vFov));
  29833. if (!this.isLoaded(size)) {
  29834. //console.log('loadTiledPano', this.id, size, fov)
  29835. if (!l.active) {
  29836. l.active = !0;
  29837. var name = this.id + ":" + size;
  29838. downloaded[name] = downloaded[name] || [];
  29839. /*
  29840. this.downloaded = downloaded
  29841. this.latestPartialRequest = latestPartialRequest
  29842. */
  29843. latestPartialRequest[name] = null;
  29844. if (fov) {
  29845. var tileArr = []; //add
  29846. var d = TileUtils.matchingTilesInDirection(this, size, dir, h, u, tileArr);
  29847. latestPartialRequest[name] = tileArr;
  29848. downloaded[name].forEach(e => {
  29849. var item = latestPartialRequest[name].find(a => e.faceTileIndex == a.faceTileIndex && e.face == a.face);
  29850. if (item) {
  29851. item.loaded = true;
  29852. }
  29853. });
  29854. if (!latestPartialRequest[name].some(e => !e.loaded)) {
  29855. //所需要的全部加载成功
  29856. //let total = TileUtils.getTileCountForSize(size)
  29857. //this.onPanoRendered(this.id, size, total, !0);
  29858. c.resolve(size /* , total */);
  29859. this.resetWaitDeferred(size);
  29860. //console.log('该部分早已经加载好了'+size, this.id)
  29861. latestPartialRequest[name] = null;
  29862. }
  29863. //console.log("Loading partial pano: " + this.id + " with " + d + " tiles")
  29864. }
  29865. if (!eventAdded[this.id]) {
  29866. eventAdded[this.id] = !0;
  29867. this.addEventListener(PanoramaEvents.LoadComplete, function (ev /* e, t */) {
  29868. //本次任务全部加载完毕
  29869. //console.warn('点位(可能部分)下载完成 ', 'id:'+this.id, 'size:'+ev.size )
  29870. var i = this.getWaitDeferred(ev.size).deferred; //"pending"为还未完成
  29871. i && "pending" === i.state() && this.highestPartialTileRenderOpCompleted >= ev.size && (i.resolve(ev.size, ev.count), this.resetWaitDeferred(ev.size)); //恢复active为false
  29872. }.bind(this));
  29873. this.addEventListener(PanoramaEvents.LoadFailed, function (ev) {
  29874. var t = this.getWaitDeferred(e).deferred;
  29875. t && "pending" === t.state() && this.highestPartialTileRenderOpCompleted >= ev.t && (t.reject(ev.t), this.resetWaitDeferred(ev.t)); //恢复active为false
  29876. }.bind(this));
  29877. this.addEventListener(PanoramaEvents.TileLoaded, function (ev /* t, i, n */) {
  29878. //每张加载完时
  29879. //console.log('tileLoaded', 'id:'+this.id, 'size:'+ev.size, 'tileIndex:'+ev.index )
  29880. var tileIndex = ev.index;
  29881. var total = ev.count;
  29882. var size = ev.size;
  29883. var name = this.id + ":" + size;
  29884. downloaded[name] = downloaded[name] || []; //不是所有的加载都是从loadTiledPano获取的所以会有未定义的情况
  29885. var {
  29886. faceTileIndex,
  29887. face
  29888. } = TileUtils.getTileLocation(size, tileIndex, {});
  29889. downloaded[name].push({
  29890. faceTileIndex,
  29891. face
  29892. });
  29893. var r = this.getWaitDeferred(size).deferred;
  29894. if (r && "pending" === r.state()) {
  29895. r.notify(size, tileIndex, total);
  29896. if (latestPartialRequest[name]) {
  29897. var item = latestPartialRequest[name].find(e => e.faceTileIndex == faceTileIndex && e.face == face);
  29898. item && (item.loaded = true);
  29899. if (!latestPartialRequest[name].some(e => !e.loaded)) {
  29900. //所需要的局部tiles全部加载成功
  29901. this.onPanoRendered(this.id, size, total, !0); //onPanoRendered还会触发 PanoramaEvents.LoadComplete
  29902. r.resolve(size, total);
  29903. this.resetWaitDeferred(size);
  29904. //console.log('该部分加载好了'+size, this.id)
  29905. latestPartialRequest[name] = null;
  29906. }
  29907. }
  29908. }
  29909. viewer.dispatchEvent('content_changed');
  29910. /* var r = this.getWaitDeferred(ev.size).deferred;
  29911. if (r && "pending" === r.state()) {
  29912. r.notify(ev.size, ev.index, ev.count);
  29913. var o = downloads[this.id + ":" + ev.size];
  29914. if(o){//如果有规定下载哪些tile,只需要下载这些tile则LoadComplete
  29915. o.tileCount++
  29916. if(o.tileCount === o.targetTileCount){//达到下载目标数
  29917. this.onPanoRendered(this.id, ev.size, ev.count, !0);
  29918. r.resolve(ev.size, ev.count);
  29919. this.resetWaitDeferred(ev.size)
  29920. }
  29921. }
  29922. } */
  29923. }.bind(this));
  29924. }
  29925. }
  29926. this.images360.tileDownloader.clearForceQueue();
  29927. this.images360.tileDownloader.forceQueueTilesForPano(this, size, dir, h, u, download);
  29928. this.tiledPanoRenderTarget = this.images360.panoRenderer.activateTiledPano(this, this.images360.qualityManager.getMaxNavPanoSize(), o);
  29929. this.images360.panoRenderer.renderPanoTiles(this.id, dirs, a); //将512的先贴上
  29930. } else {
  29931. //console.log('早已经全加载好了' +size, this.id)
  29932. c.resolve(size);
  29933. }
  29934. return c.promise();
  29935. };
  29936. }();
  29937. var {
  29938. ModelManagerEvents,
  29939. PanoSizeClass: PanoSizeClass$1
  29940. } = Potree.defines;
  29941. class QualityManager {
  29942. constructor(e, t, i) {
  29943. this.maxNavPanoSize = -1;
  29944. this.maxZoomPanoSize = -1;
  29945. this.devicePixelDensity = e;
  29946. this.deviceScreenSize = t;
  29947. this.clientBandwidth = i;
  29948. this.panoSizeClassMap = {};
  29949. this.useHighResolutionPanos = !0; //是否能够使用2k及以上图
  29950. this.useUltraHighResolutionPanos = !1;
  29951. this.modelHasUltraHighPanos = !1;
  29952. this.qualityManager = this;
  29953. this.maxRenderTargetSize = browser.isMobile() ? 2048 : 4096; //add
  29954. this.maxRenderTargetSize = Math.min(viewer.renderer.capabilities.maxCubemapSize, this.maxRenderTargetSize); //部分系统老浏览器只能2048
  29955. this.init();
  29956. }
  29957. init(e) {
  29958. //var metadata = store.getters['scene/metadata'] ;//有时候请求不到
  29959. //if(metadata.sceneSource == 11 || metadata.sceneScheme == 12){
  29960. /* if(config.tileClass == '1k'){
  29961. this.useHighResolutionPanos = false //xzw add 只加载1k
  29962. } */
  29963. this.buildPanoSizeClassMap(this.devicePixelDensity, this.deviceScreenSize, this.clientBandwidth);
  29964. this.ultraHighSize = this.getPanoSize(PanoSizeClass$1.ULTRAHIGH);
  29965. this.highSize = this.getPanoSize(PanoSizeClass$1.HIGH);
  29966. this.standardSize = this.getPanoSize(PanoSizeClass$1.STANDARD);
  29967. this.baseSize = this.getPanoSize(PanoSizeClass$1.BASE);
  29968. config$1.tiling.maxZoomPanoQuality && this.ultraHighSize <= config$1.tiling.maxZoomPanoQuality && (config$1.tiling.allowUltraHighResolution = !0);
  29969. this.highQualityThreshold = browser.valueFromHash("threshold2k", config$1.windowHeightHighQualityThreshold);
  29970. this.updateMaximums();
  29971. //e.on(ModelManagerEvents.ActiveModelChanged, this.onModelChanged.bind(this));
  29972. }
  29973. updateFromModel(e) {
  29974. //this.updateHighResolutionSettings(e)
  29975. this.updateUltraHighResolutionSettings(e);
  29976. }
  29977. /* updateHighResolutionSettings(e) {
  29978. this.useHighResolutionPanos = !0
  29979. this.updateMaximums()
  29980. } */
  29981. updateUltraHighResolutionSettings(e) {
  29982. if (config$1.tiling.allowUltraHighResolution && this.modelHasUltraHighPanos) {
  29983. this.useUltraHighResolutionPanos = !0;
  29984. } else {
  29985. this.useUltraHighResolutionPanos = !1;
  29986. }
  29987. this.updateMaximums();
  29988. }
  29989. enableUltraHighQualityMode() {
  29990. this.modelHasUltraHighPanos = !0;
  29991. this.updateUltraHighResolutionSettings(null);
  29992. }
  29993. ultraHighQualityModeEnabled() {
  29994. return this.modelHasUltraHighPanos;
  29995. }
  29996. onModelChanged(e) {
  29997. this.updateFromModel(e.model), this.updateMaximums();
  29998. }
  29999. updateMaximums() {
  30000. this.maxNavPanoSize = config$1.tiling.maxNavPanoQuality || this.detectMaxNavPanoSize(), this.maxZoomPanoSize = config$1.tiling.maxZoomPanoQuality || this.detectMaxZoomPanoSize(), this.maxZoomPanoSize < this.maxNavPanoSize && (this.maxNavPanoSize = this.maxZoomPanoSize);
  30001. }
  30002. buildPanoSizeClassMap() {
  30003. this.panoSizeClassMap[PanoSizeClass$1.BASE] = 512, this.panoSizeClassMap[PanoSizeClass$1.STANDARD] = 1024, this.panoSizeClassMap[PanoSizeClass$1.HIGH] = 2048, this.panoSizeClassMap[PanoSizeClass$1.ULTRAHIGH] = 4096;
  30004. }
  30005. getPanoSize(e) {
  30006. return this.panoSizeClassMap[e];
  30007. }
  30008. getMaxPossiblePanoSize() {
  30009. return this.getPanoSize(PanoSizeClass$1.ULTRAHIGH);
  30010. }
  30011. getMaxPanoSize() {
  30012. return this.maxZoomPanoSize;
  30013. }
  30014. getMaxNavPanoSize() {
  30015. return this.maxNavPanoSize;
  30016. }
  30017. getMaxZoomPanoSize() {
  30018. return this.maxZoomPanoSize;
  30019. }
  30020. detectMaxNavPanoSizeClass() {
  30021. //return this.useHighResolutionPanos ? browser.isMobile() ? PanoSizeClass.STANDARD : window.innerHeight < this.highQualityThreshold ? PanoSizeClass.STANDARD : PanoSizeClass.HIGH : PanoSizeClass.STANDARD
  30022. /* if(config.name == 'decor'){
  30023. return PanoSizeClass.STANDARD
  30024. }
  30025. return PanoSizeClass.HIGH */
  30026. switch (Potree.settings.navTileClass) {
  30027. case '1k':
  30028. return PanoSizeClass$1.STANDARD;
  30029. break;
  30030. case '2k':
  30031. default:
  30032. return PanoSizeClass$1.HIGH;
  30033. }
  30034. }
  30035. detectMaxNavPanoSize() {
  30036. var e = this.detectMaxNavPanoSizeClass();
  30037. return this.getPanoSize(e);
  30038. }
  30039. detectMaxZoomPanoSize() {
  30040. //获取当前zoomRenderTarget应下载的最高级别
  30041. //若是有三个级别,每次只需要加载到当前的zoomLevel;而两级时因为有zoomed来判断是使用基本贴图还是zoomRenderTarget,所以只需要返回最大的即可
  30042. if (this.zoomLevelResolution) {
  30043. //有三个级别
  30044. if (this.zoomLevelResolution == '4k' && this.useUltraHighResolutionPanos) {
  30045. return this.getPanoSize(PanoSizeClass$1.ULTRAHIGH);
  30046. } else if (this.zoomLevelResolution == '1k' || !this.useHighResolutionPanos) {
  30047. return this.getPanoSize(PanoSizeClass$1.STANDARD);
  30048. } else {
  30049. return this.getPanoSize(PanoSizeClass$1.HIGH);
  30050. }
  30051. } else {
  30052. if (this.useHighResolutionPanos) {
  30053. /* if (browser.isMobile()) {//手机版如果要2k的将这里去掉
  30054. if (settings.tiling.mobileHighQualityOverride) {
  30055. return this.getPanoSize(PanoSizeClass.HIGH);
  30056. } else {
  30057. return this.getPanoSize(PanoSizeClass.STANDARD);
  30058. }
  30059. } else */
  30060. if (this.useUltraHighResolutionPanos) {
  30061. return this.getPanoSize(PanoSizeClass$1.ULTRAHIGH);
  30062. } else {
  30063. return this.getPanoSize(PanoSizeClass$1.HIGH);
  30064. }
  30065. } else {
  30066. return this.getPanoSize(PanoSizeClass$1.STANDARD);
  30067. }
  30068. }
  30069. }
  30070. }
  30071. var {
  30072. DownloadStatus
  30073. } = Potree.defines;
  30074. var h = Object.freeze({
  30075. None: 0,
  30076. DirectionalFOV: 1
  30077. });
  30078. var u = function () {
  30079. var e = function e(t, i) {
  30080. var n = e._panoSpaceDir,
  30081. r = e._fovThreshold,
  30082. o = e._fovThresholdNarrow,
  30083. a = Math.max(Math.min(n.dot(t.direction), 1), -1),
  30084. s = Math.max(Math.min(n.dot(i.direction), 1), -1);
  30085. return t._dot = a, i._dot = s, a >= r && s < r ? -1 : a < r && s >= r ? 1 : a >= o && s < o ? -1 : a < o && s >= o ? 1 : t.panoSize > i.panoSize ? 1 : i.panoSize > t.panoSize ? -1 : -(a - s);
  30086. };
  30087. return e._panoSpaceDir = new Vector3(), e._fovThreshold = -1, e._fovThresholdNarrow = -1, e;
  30088. }();
  30089. class TilePrioritizer {
  30090. //优先级处理序列
  30091. constructor(e, t, i, o, a) {
  30092. this.qualityManager = e;
  30093. this.maxNavQuality = this.qualityManager.getMaxNavPanoSize();
  30094. this.maxZoomQuality = this.qualityManager.getMaxZoomPanoSize();
  30095. this.baseSize = t;
  30096. this.standardSize = i;
  30097. this.highSize = o;
  30098. this.ultraHighSize = a;
  30099. this.priorityCriteria = new TilePrioritizer.PriorityCriteria(null, new Vector3(0, 0, 0), new Vector3(0, 0, -1), new Vector3(0, 0, -1));
  30100. }
  30101. updateCriteria(e, t, i, n) {
  30102. //由player更新
  30103. this.priorityCriteria.pano = e, this.priorityCriteria.cameraPosition.copy(t),
  30104. //this.priorityCriteria.cameraDir.copy(i),
  30105. this.priorityCriteria.cameraDirs = i;
  30106. this.priorityCriteria.upcomingPanos = n, this.maxNavQuality = this.qualityManager.getMaxNavPanoSize(), this.maxZoomQuality = this.qualityManager.getMaxZoomPanoSize();
  30107. }
  30108. canDownloadSize(e) {
  30109. return this.maxNavQuality >= e || this.maxZoomQuality >= e && this.zoomingActive;
  30110. }
  30111. /* populateNeighborPanos(e, t, i) {
  30112. i = i || [],
  30113. i.length = 0;
  30114. var n = t.getNeighbours(e);
  30115. for (var r in n)
  30116. if (n.hasOwnProperty(r)) {
  30117. var o = t.get(r);
  30118. if(!o){
  30119. console.log(1)
  30120. }
  30121. i.push(o)
  30122. }
  30123. return i
  30124. } */
  30125. getNearPanos(panos) {
  30126. if (!this.priorityCriteria.pano || viewer.mainViewport.view.isFlying()) return;
  30127. var cameraDirLocals = this.priorityCriteria.cameraDirs.vectorForward;
  30128. this.populateScoredPanos(panos, [], cameraDirLocals, Infinity, true);
  30129. }
  30130. filterDepthTex(panos) {
  30131. // 下载depthTex
  30132. if (!Potree.settings.useDepthTex) return;
  30133. viewer.addTimeMark('filterDepthTex', 'start');
  30134. var dlCount = 1; //window.slowDown ? 0 : (browser.isMobile() ? 1 : Common.getBestCountFPS('loadDepTexCount', false, 1, 2, 57, 62 ) )
  30135. var loadingCount = panos.filter(p => p.depthTexLoading).length;
  30136. if (viewer.mapViewer) {
  30137. var mapLayer = viewer.mapViewer.mapLayer;
  30138. loadingCount += mapLayer.loadingInProgress * 1.5 + mapLayer.waitQueue.length;
  30139. }
  30140. if (loadingCount < dlCount) {
  30141. //console.log('dlCount-loadingCount', dlCount-loadingCount)
  30142. (this.nearPanos || panos).filter(p => !p.depthTex).slice(0, dlCount - loadingCount).forEach(p => p.loadDepthImg());
  30143. }
  30144. viewer.addTimeMark('filterDepthTex', 'end');
  30145. }
  30146. populateScoredPanos( /* e, */t, i, dirs, count, dontFilterDir) {
  30147. i = i || [], i.length = 0;
  30148. viewer.addTimeMark('populateScoredPanos', 'start');
  30149. var s = [Images360.filters.not(this.priorityCriteria.pano)],
  30150. l = [Images360.scoreFunctions.distanceSquaredNew(this.priorityCriteria.pano), Images360.scoreFunctions.direction(this.priorityCriteria.pano.position, dirs)];
  30151. /* if(!dontFilterDir){//太耗时了,尤其是点多时,直接去掉,反正有count限制。如果必须的话,使用direction中得到的值
  30152. s.push(Images360.filters.inPanoDirection(this.priorityCriteria.pano.position, dirs, TilePrioritizer.DIRECTION_SCORE_STRICTNESS) )
  30153. } */
  30154. var c = Common$1.sortByScore(t, s, l);
  30155. //900个点的时候populateScoredPanos已经耗时1.8
  30156. viewer.addTimeMark('populateScoredPanos', 'end');
  30157. this.nearPanos = c.map(e => e.item); //xzw add 用于获得邻近点位序列
  30158. if (c) for (var h = 0; h < c.length && h < count; h++) {
  30159. var u = c[h].item;
  30160. i.push(u);
  30161. }
  30162. return i;
  30163. }
  30164. queueTilesForPanos(e, t, i, n, r) {
  30165. for (var o = 0, a = 0; a < t.length; a++) {
  30166. var s = t[a],
  30167. l = this.queueTilesForPano(e, i, s, n);
  30168. if (o += l > 0 ? 1 : 0, r && o >= r) break;
  30169. }
  30170. return o;
  30171. }
  30172. /* queueTilesInDirectionForPanos(e, t, i, n, r, o, a, s) {//没用到
  30173. for (var l = 0, c = 0; c < i.length; c++) {
  30174. var h = i[c],
  30175. u = this.queueTilesInDirectionForPano(e, t, h, n, o, a);
  30176. if (l += u > 0 ? 1 : 0,
  30177. s && l >= s)
  30178. break
  30179. }
  30180. return l
  30181. }
  30182. */
  30183. canIncludeDescriptor(e) {
  30184. return e.status !== DownloadStatus.Downloading && e.status !== DownloadStatus.Downloaded;
  30185. }
  30186. canIncludePano(e, t) {
  30187. return !e.isLoaded(t);
  30188. }
  30189. getFOVDotThreshold(e) {
  30190. return Math.cos(MathUtils.degToRad(e / 2));
  30191. }
  30192. setZoomingActive(e) {
  30193. e !== this.zoomingActive && (this.zoomingActive = e);
  30194. }
  30195. }
  30196. TilePrioritizer.PriorityCriteria = function (e, t, i, n, o) {
  30197. this.pano = e, this.cameraPosition = new Vector3().copy(t),
  30198. //this.cameraDir = (new THREE.Vector3).copy(i),
  30199. this.cameraDirs = [],
  30200. //
  30201. this.panoSpaceDir = new Vector3().copy(n), this.upcomingPanos = o, this.copy = function (e) {
  30202. this.pano = e.pano, this.cameraPosition.copy(e.cameraPosition),
  30203. //this.cameraDir.copy(e.cameraDir),
  30204. this.cameraDirs = e.cameraDirs;
  30205. this.panoSpaceDir.copy(e.panoSpaceDir), this.upcomingPanos = o;
  30206. }, this.zoomingActive = !1;
  30207. };
  30208. TilePrioritizer.DIRECTIONAL_FOV = 180;
  30209. TilePrioritizer.DIRECTIONAL_FOV_NARROW = 120;
  30210. TilePrioritizer.MAX_SCORED_PANOS_TOCONSIDER = 6;
  30211. TilePrioritizer.MAX_SCORED_PANOS_TOADD = 2;
  30212. TilePrioritizer.MAX_UPCOMING_PANOS_TOADD = 3;
  30213. TilePrioritizer.DIRECTION_SCORE_STRICTNESS = .75;
  30214. TilePrioritizer.appendQueue = function (e, t) {
  30215. if (e && t) for (var i = 0; i < t.length; i++) {
  30216. e.push(t[i]);
  30217. //console.log(t[i])
  30218. }
  30219. };
  30220. TilePrioritizer.sortPanoTiles = function (descriptors, pano, dir) {
  30221. if (dir.datasetsLocal) dir = dir.datasetsLocal.find(e => e.datasetId == pano.pointcloud.dataset_id).direction; //add
  30222. u._panoSpaceDir.copy(dir);
  30223. TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir); //应该是将dir根据quaternion转化下
  30224. u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  30225. u._fovThreshold = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV);
  30226. descriptors.sort(u);
  30227. };
  30228. TilePrioritizer.insertSortedPanoTile = function (e, t, pano, dir) {
  30229. if (dir.datasetsLocal) dir = dir.datasetsLocal.find(e => e.datasetId == pano.pointcloud.dataset_id).direction; //add
  30230. u._panoSpaceDir.copy(dir), TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir), u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW), u._fovThreshold = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV);
  30231. for (var o = -1, a = 0; a < e.length; a++) {
  30232. var s = u(t, e[a]);
  30233. if (s <= 0) {
  30234. o = a;
  30235. break;
  30236. }
  30237. }
  30238. if (o === -1) e[e.length] = t;else {
  30239. for (var h = e.length; h > o; h--) e[h] = e[h - 1];
  30240. e[o] = t;
  30241. }
  30242. };
  30243. TilePrioritizer.prototype.filterAndPrioritize = function () {
  30244. //挑选出优先加载的 pano和tile (有点复杂,没看很懂)
  30245. var e = [],
  30246. t = [],
  30247. i = [];
  30248. return function (queue, panos, tileDownloader) {
  30249. //this.populateNeighborPanos(this.priorityCriteria.pano, panos, e);
  30250. /* let cameraDirLocals = this.priorityCriteria.cameraDirs.map(e=>{ //add
  30251. var dataset = viewer.scene.pointclouds.find(u=>u.dataset_id == e.datasetId)
  30252. var matrix = new THREE.Matrix4().copy(dataset.rotateMatrix)
  30253. var direction = math.convertVector.YupToZup(e.direction)
  30254. return {
  30255. datasetId:e.datasetId,
  30256. direction: direction.clone().applyMatrix4(matrix)
  30257. }
  30258. }) */
  30259. var cameraDirLocals = this.priorityCriteria.cameraDirs.vectorForward;
  30260. //获得视野范围内的邻近点位序列t
  30261. this.populateScoredPanos( /* this.priorityCriteria.pano, */panos, t, cameraDirLocals, TilePrioritizer.MAX_SCORED_PANOS_TOCONSIDER);
  30262. //t.filter(p=>!p.depthTex).slice(0, Potree.config.depTexDlCount).forEach(p=>p.loadDepthImg()) //add
  30263. var s = this.baseSize //512
  30264. ,
  30265. l = this.standardSize //1024
  30266. ,
  30267. c = this.highSize //2048
  30268. ,
  30269. h = this.ultraHighSize; //4096
  30270. this.queueTilesForPano(queue, tileDownloader, this.priorityCriteria.pano, s); //把当前pano的512下载了
  30271. if (this.priorityCriteria.upcomingPanos) {
  30272. // 添加即将走到的点(之前用于导览路线)512 tiles
  30273. this.queueTilesForPanos(queue, this.priorityCriteria.upcomingPanos, tileDownloader, s, TilePrioritizer.MAX_UPCOMING_PANOS_TOADD);
  30274. }
  30275. i.length = 0;
  30276. //把当前pano角度范围内的tile按照分辨率从低到高加入队列
  30277. if (this.canDownloadSize(l)) {
  30278. //1024如果在限制范围内的话
  30279. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, l, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  30280. }
  30281. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs); //排序
  30282. TilePrioritizer.appendQueue(queue, i);
  30283. //添加邻近点t 512的tiles
  30284. this.queueTilesForPanos(queue, t, tileDownloader, s, TilePrioritizer.MAX_SCORED_PANOS_TOADD);
  30285. i.length = 0;
  30286. //NARROW :
  30287. if (this.canDownloadSize(c)) {
  30288. //2048
  30289. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  30290. }
  30291. if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {
  30292. //4096
  30293. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  30294. }
  30295. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs); //排序
  30296. TilePrioritizer.appendQueue(queue, i);
  30297. i.length = 0;
  30298. if (this.canDownloadSize(l)) {
  30299. //1024
  30300. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, l, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  30301. }
  30302. if (this.canDownloadSize(c)) {
  30303. //2048
  30304. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  30305. }
  30306. if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {
  30307. //4096
  30308. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  30309. }
  30310. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs); //排序
  30311. TilePrioritizer.appendQueue(queue, i);
  30312. this.queueTilesForPanos(queue, e, tileDownloader, s); // 如果前面有populateNeighborPanos的话,这步就是加neibour
  30313. };
  30314. }();
  30315. TilePrioritizer.prototype.queueTilesInDirectionForPano = function () {
  30316. var e = {
  30317. filter: h.DirectionalFOV,
  30318. direction: new Vector3(),
  30319. fov: 60
  30320. },
  30321. t = new Vector3();
  30322. return function (i, n, pano, o, a, dirs, c) {
  30323. var dir = dirs.datasetsLocal.find(e => e.datasetId == pano.pointcloud.dataset_id).direction; //add
  30324. //var dir = dirs
  30325. t.copy(dir);
  30326. TileUtils.getRelativeDirection(pano.quaternion4dkk, t);
  30327. e.direction.copy(t);
  30328. e.fov = c;
  30329. return this.filterAndQueueTileDownloadDescriptors(i, n, pano, o, e);
  30330. };
  30331. }();
  30332. TilePrioritizer.prototype.filterAndQueueTileDownloadDescriptors = function () {
  30333. var e = [];
  30334. return function (t, i, n, r, o) {
  30335. var a = i.getTileDownloadDescriptors(n, r);
  30336. e.length = 0, this.filterTileDownloadDescriptors(n, a, e, o);
  30337. for (var s = 0, l = 0; l < e.length; l++) {
  30338. var c = e[l];
  30339. if (c) {
  30340. t.push(c);
  30341. s++;
  30342. }
  30343. }
  30344. return s;
  30345. };
  30346. }();
  30347. TilePrioritizer.prototype.filterTileDownloadDescriptors = function () {
  30348. new Vector3();
  30349. return function (e, t, i, n) {
  30350. var r, o;
  30351. switch (n.filter) {
  30352. case h.DirectionalFOV:
  30353. for (r = 0; r < t.length; r++) o = t[r], TileUtils.isTileWithinFOV(o.panoSize, o.tileSize, o.face, o.tileX, o.tileY, n.direction, n.fov) && i.push(o);
  30354. break;
  30355. default:
  30356. for (r = 0; r < t.length; r++) o = t[r], i.push(o);
  30357. }
  30358. for (r = 0; r < i.length; r++) o = i[r], this.canIncludeDescriptor(o) || (i[r] = null);
  30359. };
  30360. }();
  30361. TilePrioritizer.prototype.queueTilesForPano = function () {
  30362. var e = {
  30363. filter: h.None
  30364. };
  30365. return function (t, i, n, r) {
  30366. return this.filterAndQueueTileDownloadDescriptors(t, i, n, r, e);
  30367. };
  30368. }();
  30369. /* TilePrioritizer.prototype.queueTilesForPanosInDirection = function () { //没用到
  30370. var e = new THREE.Vector3;
  30371. return function (t, i, n, r, o, a, s, l) {
  30372. for (var h = 0, u = 0; u < n.length; u++) {
  30373. var d = n[u];
  30374. e.copy(d.position),
  30375. e.sub(o),
  30376. e.normalize();
  30377. var p = Math.max(Math.min(a.dot(e), 1), -1),
  30378. f = c.getFOVDotThreshold(s);
  30379. if (p >= f) {
  30380. var g = this.queueTilesInDirectionForPano(t, i, d, r, o, a, s);
  30381. if (h += g > 0 ? 1 : 0,
  30382. l && h >= l)
  30383. break
  30384. }
  30385. }
  30386. return h
  30387. }
  30388. }() */
  30389. //import { i18n } from "@/lang/index"
  30390. // 媒体名称
  30391. /* export const mediaTypes = {
  30392. image: i18n.t("common.photo"),
  30393. video: i18n.t("common.video"),
  30394. audio: i18n.t("common.voice"),
  30395. } */
  30396. // 媒体扩展类型
  30397. var mediaMimes = {
  30398. image: ["jpg", "png", "jpeg", "bmp", "gif"],
  30399. audio: ["mp3", "aac", "ogg", "wav" /* , "m4a" */],
  30400. video: ["mp4", "mov", "quicktime", "webm" /* "rmvb", "wmv" */] //ios:mov
  30401. };
  30402. // 媒体大小显示(MB)
  30403. var mediaMaxSize = {
  30404. image: 10,
  30405. video: 20,
  30406. audio: 5
  30407. };
  30408. /**
  30409. * 获取媒体扩展类型
  30410. * @param {Stirng} filename 文件名称
  30411. */
  30412. var getMime = filename => {
  30413. if (!filename || filename.indexOf(".") === -1) {
  30414. return "";
  30415. }
  30416. return filename.split(".").pop().toLowerCase();
  30417. };
  30418. /**
  30419. * 在路径中获取文件名
  30420. * @param {*} path
  30421. */
  30422. var getFilename = path => {
  30423. var segment = (path || "").split("/");
  30424. return segment[segment.length - 1];
  30425. };
  30426. /**
  30427. * 检测媒体文件是否超过预设限制
  30428. * @param {String} type 媒体类型
  30429. * @param {Number} size 文件大小
  30430. */
  30431. var checkSizeLimit = (type, size) => {
  30432. size = size / 1024 / 1024;
  30433. return size <= mediaMaxSize[type];
  30434. };
  30435. var checkSizeLimitFree = (size, limit) => {
  30436. size = size / 1024 / 1024;
  30437. return size <= limit;
  30438. };
  30439. /**
  30440. * 检测媒体类型
  30441. * @param {String} type 媒体类型
  30442. * @param {String} filename 文件名称
  30443. */
  30444. var checkMediaMime = (type, filename) => {
  30445. var mime = getMime(filename);
  30446. var find = mediaMimes[type];
  30447. if (!find) {
  30448. return false;
  30449. }
  30450. return find.indexOf(mime) !== -1;
  30451. };
  30452. var checkMediaMimeByAccept = (accept, filename) => {
  30453. var mime = getMime(filename);
  30454. var type = accept;
  30455. if (type && type.indexOf("jpg") == -1 && type.indexOf("jpeg") != -1) {
  30456. type += ",image/jpg";
  30457. }
  30458. return (type || "").indexOf(mime) != -1;
  30459. };
  30460. var base64ToBlob = base64 => {
  30461. var arr = base64.split(","),
  30462. mime = arr[0].match(/:(.*?);/)[1],
  30463. bstr = atob(arr[1]),
  30464. n = bstr.length,
  30465. u8arr = new Uint8Array(n);
  30466. while (n--) {
  30467. u8arr[n] = bstr.charCodeAt(n);
  30468. }
  30469. return new Blob([u8arr], {
  30470. type: mime
  30471. });
  30472. };
  30473. var base64ToDataURL = base64 => {
  30474. return window.URL.createObjectURL(base64ToBlob(base64));
  30475. };
  30476. var blobToBase64 = function blobToBase64(blob) {
  30477. return new Promise(resolve => {
  30478. var reader = new FileReader();
  30479. reader.onload = function () {
  30480. resolve(reader.result);
  30481. };
  30482. reader.readAsDataURL(blob);
  30483. });
  30484. };
  30485. /*
  30486. * @Author: Rindy
  30487. * @Date: 2019-08-06 16:25:08
  30488. * @LastEditors: Rindy
  30489. * @LastEditTime: 2021-08-27 12:33:49
  30490. * @Description: Request
  30491. */
  30492. //import { $alert, $confirm, $loginTips } from "@/components/shared/message"
  30493. //import { $waiting } from "@/components/shared/loading"
  30494. //import { checkLogin } from "@/api"
  30495. //import { LoginDetector } from "@/core/starter"
  30496. //import { i18n } from "@/lang"
  30497. //import { password } from "@/utils/string"
  30498. //import store from "../Store"
  30499. // 空函数
  30500. var noop = function noop() {};
  30501. // 请求回调队列
  30502. var postQueue = [];
  30503. /**
  30504. * @property {number} NEXT - 继续执行
  30505. * @property {number} SUCCESS - 成功
  30506. * @property {number} EXCEPTION - 异常错误
  30507. * @property {number} FAILURE_CODE_3001 - 缺少必要参数
  30508. * @property {number} FAILURE_CODE_3002 - 访问异常
  30509. * @property {number} FAILURE_CODE_3003 - 非法访问
  30510. * @property {number} FAILURE_CODE_3004 - 用户未登录
  30511. * @property {number} FAILURE_CODE_3005 - 验证码已过期
  30512. * @property {number} FAILURE_CODE_3006 - 验证码错误
  30513. * @property {number} FAILURE_CODE_3007 - 昵称已存在
  30514. * @property {number} FAILURE_CODE_3008 - 该手机已被注册
  30515. * @property {number} FAILURE_CODE_3009 - 两次输入的密码不一致
  30516. * @property {number} FAILURE_CODE_3010 - 昵称长度错误
  30517. * @property {number} FAILURE_CODE_3011 - 密码长度错误
  30518. * @property {number} FAILURE_CODE_3012 - 昵称包含敏感词
  30519. * @property {number} FAILURE_CODE_3013 - 手机号码格式错误
  30520. * @property {number} FAILURE_CODE_3014 - 账号或密码不正确
  30521. * @property {number} FAILURE_CODE_3015 - 用户不存在
  30522. * @property {number} FAILURE_CODE_3016 - 您没有权限,请联系管理员
  30523. * @property {number} FAILURE_CODE_3017 - 空文件
  30524. * @property {number} FAILURE_CODE_3018 - 需要上传或使用的文件不存在
  30525. * @property {number} FAILURE_CODE_5010 - 找不到该场景对应的相机
  30526. * @property {number} FAILURE_CODE_5012 - 数据不正常
  30527. * @property {number} FAILURE_CODE_5014 - 无权操作该场景
  30528. * @property {number} FAILURE_CODE_5005 - 场景不存在
  30529. */
  30530. var statusCode = {
  30531. NEXT: -999,
  30532. SUCCESS: 0,
  30533. EXCEPTION: -1,
  30534. FAILURE_CODE_3001: 3001,
  30535. FAILURE_CODE_3002: 3002,
  30536. FAILURE_CODE_3003: 3003,
  30537. FAILURE_CODE_3004: 3004,
  30538. FAILURE_CODE_3005: 3005,
  30539. FAILURE_CODE_3006: 3006,
  30540. FAILURE_CODE_3007: 3007,
  30541. FAILURE_CODE_3008: 3008,
  30542. FAILURE_CODE_3009: 3009,
  30543. FAILURE_CODE_3010: 3010,
  30544. FAILURE_CODE_3011: 3011,
  30545. FAILURE_CODE_3012: 3012,
  30546. FAILURE_CODE_3013: 3013,
  30547. FAILURE_CODE_3014: 3014,
  30548. FAILURE_CODE_3015: 3015,
  30549. FAILURE_CODE_3016: 3016,
  30550. FAILURE_CODE_3017: 3017,
  30551. FAILURE_CODE_3018: 3018,
  30552. FAILURE_CODE_5010: 5010,
  30553. FAILURE_CODE_5012: 5012,
  30554. FAILURE_CODE_5014: 5014,
  30555. FAILURE_CODE_5005: 5005
  30556. };
  30557. /**
  30558. * 获取Token
  30559. * @function
  30560. */
  30561. function getToken() {
  30562. var urlToken = browser.urlHasValue("token", true);
  30563. if (urlToken) {
  30564. // 设置token共享给用户中心
  30565. localStorage.setItem("token", urlToken);
  30566. }
  30567. return urlToken || localStorage.getItem("token") || "";
  30568. }
  30569. /**
  30570. * 根据状态码的结果处理后续操作
  30571. * @function
  30572. * @param {number} code - 状态码
  30573. * @param {function} callback - 回调
  30574. */
  30575. function statusCodesHandler(code, callback) {
  30576. if (code == statusCode.EXCEPTION) {
  30577. return $alert({
  30578. content: i18n.t("tips.exception")
  30579. });
  30580. }
  30581. if (code == statusCode.FAILURE_CODE_3002 || code == statusCode.FAILURE_CODE_3003 || code == statusCode.FAILURE_CODE_3004) {
  30582. callback(code);
  30583. return showLoginTips();
  30584. }
  30585. if (code == statusCode.FAILURE_CODE_3001) {
  30586. callback(code);
  30587. return $alert({
  30588. content: i18n.t("tips.params_notfound")
  30589. });
  30590. }
  30591. if (code == statusCode.FAILURE_CODE_3017) {
  30592. callback(code);
  30593. return $alert({
  30594. content: i18n.t("tips.file_notfound")
  30595. });
  30596. }
  30597. if (code == statusCode.FAILURE_CODE_5005) {
  30598. /* if (!config.isEdit) {
  30599. return (location.href = config.pages.NotFound)
  30600. } */
  30601. callback(code);
  30602. return $alert({
  30603. content: i18n.t("tips.scene_notfound")
  30604. });
  30605. }
  30606. if (code == statusCode.FAILURE_CODE_5010) {
  30607. callback(code);
  30608. return $alert({
  30609. content: i18n.t("tips.camera_notfound")
  30610. });
  30611. }
  30612. if (code == statusCode.FAILURE_CODE_5012) {
  30613. callback(code);
  30614. return $alert({
  30615. content: i18n.t("tips.data_error")
  30616. });
  30617. }
  30618. if (code == statusCode.FAILURE_CODE_5014) {
  30619. callback(code);
  30620. return $alert({
  30621. content: i18n.t("tips.auth_deny")
  30622. });
  30623. }
  30624. return statusCode.NEXT;
  30625. }
  30626. $.ajaxSetup({
  30627. headers: {},
  30628. beforeSend: function beforeSend(xhr) {
  30629. var token = getToken();
  30630. if (token) {
  30631. xhr.setRequestHeader("token", token);
  30632. } else if (!token && this.url.indexOf("isLogin") != -1) {
  30633. showLoginTips();
  30634. }
  30635. /* if (config.oem == "localshow") {
  30636. // 本地版本兼容当前目录
  30637. if (this.url.indexOf("http") == -1 && this.url.indexOf("/") == 0) {
  30638. this.url = this.url.substr(1)
  30639. }
  30640. } */
  30641. // if(this.url.indexOf('http')==-1 && this.url.indexOf('/') !=0){
  30642. // this.url = '/'+this.url
  30643. // }
  30644. },
  30645. error: function error(xhr, status, _error) {
  30646. // 出错时默认的处理函数
  30647. if (this.url.indexOf("/scene.json") != -1 && xhr.status == 404) {
  30648. return $alert({
  30649. content: i18n.t("tips.scene_notfound")
  30650. });
  30651. } else if (this.type === "POST") {
  30652. return $alert({
  30653. content: i18n.t("tips.network_error")
  30654. });
  30655. }
  30656. },
  30657. success: function success(result) {},
  30658. complete: function complete() {
  30659. // Post类型请求无论成功或失败都关闭等待提示
  30660. if (this.type === "POST") {
  30661. http.__loading && $waiting.hide();
  30662. }
  30663. http.__loading = true;
  30664. }
  30665. });
  30666. /**
  30667. * @namespace http
  30668. * @type {Object}
  30669. */
  30670. var http = {
  30671. statusCode,
  30672. __loading: true,
  30673. __request(xhr, method, url, data, done, fail) {
  30674. if (typeof done != "function") {
  30675. done = noop;
  30676. }
  30677. if (typeof fail != "function") {
  30678. fail = noop;
  30679. }
  30680. xhr.done(result => {
  30681. if (typeof result.code !== "undefined") {
  30682. var flag = statusCodesHandler(result.code, function (code) {
  30683. // 需要登录的状态
  30684. if (code == statusCode.FAILURE_CODE_3001 || code == statusCode.FAILURE_CODE_3002 || code == statusCode.FAILURE_CODE_3003 || code == statusCode.FAILURE_CODE_3004) {
  30685. if (url.indexOf("isLogin") == -1 && url.indexOf("openSceneBykey") == -1) {
  30686. postQueue.push(function () {
  30687. http[method](url, data, done, fail);
  30688. });
  30689. }
  30690. }
  30691. fail();
  30692. });
  30693. if (flag === statusCode.NEXT) {
  30694. done(result, result.code == 0);
  30695. }
  30696. } else {
  30697. done(result);
  30698. }
  30699. });
  30700. xhr.fail(fail);
  30701. xhr.always(() => xhr = null);
  30702. return xhr;
  30703. },
  30704. /**
  30705. * Get请求
  30706. * @param {String} url 请求地址
  30707. * @param {Object?} data 请求参数
  30708. * @param {Function?} done 成功回调
  30709. * @param {Function?} fail 失败回调
  30710. */
  30711. get(url) {
  30712. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30713. var done = arguments.length > 2 ? arguments[2] : undefined;
  30714. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30715. if (/\.json/.test(url)) {
  30716. // json文件格式自动调用getJson方法
  30717. return this.getJson(url, data, done, fail);
  30718. }
  30719. return this.__request($.get(url, data), "get", url, data, done, fail);
  30720. },
  30721. /**
  30722. * Get Blob请求
  30723. * @param {String} url 请求地址
  30724. * @param {Object?} data 请求参数
  30725. * @param {Function?} done 成功回调
  30726. * @param {Function?} fail 失败回调
  30727. */
  30728. getText(url) {
  30729. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30730. var done = arguments.length > 2 ? arguments[2] : undefined;
  30731. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30732. return this.__request($.ajax({
  30733. url: url,
  30734. dataType: "text"
  30735. }), "getText", url, data, done, fail);
  30736. },
  30737. /**
  30738. * GetJson请求 读取json文件数据
  30739. * @param {String} url 请求地址
  30740. * @param {Object?} data 请求参数
  30741. * @param {Function?} done 成功回调
  30742. * @param {Function?} fail 失败回调
  30743. */
  30744. getJson(url) {
  30745. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30746. var done = arguments.length > 2 ? arguments[2] : undefined;
  30747. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30748. return this.__request($.getJSON(url, data), "get", url, data, done, fail);
  30749. },
  30750. /**
  30751. * Get Blob请求
  30752. * @param {String} url 请求地址
  30753. * @param {Object?} data 请求参数
  30754. * @param {Function?} done 成功回调
  30755. * @param {Function?} fail 失败回调
  30756. */
  30757. getBlob(url) {
  30758. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30759. var done = arguments.length > 2 ? arguments[2] : undefined;
  30760. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30761. return this.__request($.ajax({
  30762. url: url,
  30763. dataType: "blob"
  30764. }), "getBlob", url, data, done, fail);
  30765. },
  30766. /**
  30767. * Get Arraybuffer请求
  30768. * @param {String} url 请求地址
  30769. * @param {Object?} data 请求参数
  30770. * @param {Function?} done 成功回调
  30771. * @param {Function?} fail 失败回调
  30772. */
  30773. getArraybuffer(url) {
  30774. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30775. var done = arguments.length > 2 ? arguments[2] : undefined;
  30776. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30777. return this.__request($.ajax({
  30778. url: url,
  30779. dataType: "arraybuffer"
  30780. }), "getArraybuffer", url, data, done, fail);
  30781. },
  30782. /**
  30783. * Post 请求
  30784. * @param {String} url 请求地址
  30785. * @param {Object?} data 请求参数
  30786. * @param {Function?} done 成功回调
  30787. * @param {Function?} fail 失败回调
  30788. */
  30789. post(url) {
  30790. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30791. var done = arguments.length > 2 ? arguments[2] : undefined;
  30792. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30793. if (url.indexOf("isLogin") == -1) {
  30794. http.__loading && $waiting.show();
  30795. }
  30796. return this.__request($.post(url, data), "post", url, data, done, fail);
  30797. },
  30798. /**
  30799. * PostJson 请求
  30800. * @param {String} url 请求地址
  30801. * @param {Object?} data 请求参数
  30802. * @param {Function?} done 成功回调
  30803. * @param {Function?} fail 失败回调
  30804. */
  30805. postJson(url) {
  30806. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30807. var done = arguments.length > 2 ? arguments[2] : undefined;
  30808. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30809. http.__loading && $waiting.show();
  30810. return this.__request($.ajax({
  30811. type: "POST",
  30812. url: url,
  30813. contentType: "application/json",
  30814. data: JSON.stringify(data)
  30815. }), "postJson", url, data, done, fail);
  30816. },
  30817. /**
  30818. * Post 表单 支持文件上传
  30819. * @param {String} url 请求地址
  30820. * @param {FormData?} formData 请求参数
  30821. * @param {Function?} done 成功回调
  30822. * @param {Function?} fail 失败回调
  30823. */
  30824. postForm(url, formData, done, fail, onProgress) {
  30825. if (typeof onProgress === "function") {
  30826. return this.__request($.ajax({
  30827. type: "POST",
  30828. url: url,
  30829. processData: false,
  30830. contentType: false,
  30831. data: formData,
  30832. xhr: function xhr() {
  30833. var xhr = new XMLHttpRequest();
  30834. xhr.upload.addEventListener("progress", function (e) {
  30835. onProgress(e.loaded / e.total * 100 + "%");
  30836. });
  30837. return xhr;
  30838. }
  30839. }), "postForm", url, formData, done, fail);
  30840. } else {
  30841. http.__loading && $waiting.show();
  30842. return this.__request($.ajax({
  30843. type: "POST",
  30844. url: url,
  30845. processData: false,
  30846. contentType: false,
  30847. data: formData
  30848. }), "postForm", url, formData, done, fail);
  30849. }
  30850. },
  30851. /**
  30852. * 加载图片
  30853. * @param {String} url 请求地址
  30854. * @param {Number?} retry 重试次数,默认为3
  30855. */
  30856. loadImage(url) {
  30857. var retry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
  30858. var def = $.Deferred();
  30859. var img = new Image();
  30860. /* if (process.env.VUE_APP_REGION == "AWS" && url.indexOf("x-oss-process=image") != -1) {
  30861. var arr = url.split("?")
  30862. url = arr[0] + encodeURIComponent("?" + arr[1].replace(/\//g, "@"))
  30863. } */
  30864. var load = () => {
  30865. console.warn("Retrying load image: " + url);
  30866. this.loadImage(url, retry - 1).done(def.resolve.bind(def)).progress(def.notify.bind(def)).fail(def.reject.bind(def));
  30867. };
  30868. img.onerror = function () {
  30869. retry > 0 ? setTimeout(() => load(), 1e3) : def.reject("[".concat(url, "]\u52A0\u8F7D\u5931\u8D25"));
  30870. };
  30871. img.onload = function () {
  30872. def.resolve(img);
  30873. };
  30874. img.crossOrigin = "anonymous";
  30875. img.src = url;
  30876. return def;
  30877. },
  30878. /**
  30879. * 上传文件
  30880. * @param {String} url 请求地址
  30881. * @param {Object?} data 请求参数
  30882. * @param {Function?} done 成功回调
  30883. * @param {Function?} fail 失败回调
  30884. */
  30885. uploadFile(url) {
  30886. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30887. var done = arguments.length > 2 ? arguments[2] : undefined;
  30888. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30889. var onProgress = arguments.length > 4 ? arguments[4] : undefined;
  30890. var form = new FormData();
  30891. // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob
  30892. // form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name);
  30893. // } else {
  30894. // form.append("file", file.file, file.name || file.file.name);
  30895. // }
  30896. for (var key in data) {
  30897. if (key == "file") {
  30898. form.append("file", data[key], data.filename || data[key].name);
  30899. } else if (key != "filename") {
  30900. form.append(key, data[key]);
  30901. }
  30902. }
  30903. return this.postForm(url, form, done, fail, onProgress);
  30904. },
  30905. /**
  30906. * 上传文件
  30907. * @param {String} url 请求地址
  30908. * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...}
  30909. * @param {Function?} done 成功回调
  30910. * @param {Function?} fail 失败回调
  30911. */
  30912. uploadBlobFile(url) {
  30913. var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  30914. var done = arguments.length > 2 ? arguments[2] : undefined;
  30915. var fail = arguments.length > 3 ? arguments[3] : undefined;
  30916. var form = new FormData();
  30917. for (var key in data) {
  30918. if (key === "file") {
  30919. form.append("file", base64ToBlob(data.file), data.filename);
  30920. } else if (key != "filename") {
  30921. form.append(key, data[key]);
  30922. }
  30923. }
  30924. return this.postForm(url, form, done, fail);
  30925. }
  30926. };
  30927. var {
  30928. TileDownloaderEvents,
  30929. DownloadStatus: DownloadStatus$1
  30930. } = Potree.defines;
  30931. window.downloaded = {};
  30932. window.startdownloads = [];
  30933. class TileDownloader extends EventDispatcher {
  30934. constructor() {
  30935. super();
  30936. this.panos = null;
  30937. this.retryMinimumTime = 1e4;
  30938. this.panoLoadCallbacks = {};
  30939. this.downloadDescriptors = {};
  30940. this.priorityQueue = [];
  30941. this.forceQueue = [];
  30942. this.activeDownloads = [];
  30943. this.tilePrioritizer = null;
  30944. this.refreshInterval = null;
  30945. this.processPriorityQueue = !1;
  30946. this.concurrentDownloads = 6; //e.concurrentDownloads || 1;
  30947. this.downloadTestResults = {};
  30948. this.freeze = Object.freeze({
  30949. Testing: 1,
  30950. Success: 2,
  30951. Fail: 3
  30952. });
  30953. this.tilesCount = 0; //add 加载好的tile数目
  30954. /* viewer.addEventListener('pageVisible', (e)=>{//不可见时不refreshUpdateInterval
  30955. //console.log('visibilitychange:', state)
  30956. Potree.Utils.updateVisible(this, 'pageVisible', e.v)
  30957. this.judgeStart()
  30958. })
  30959. this.visible = true //add 借用Potree.Utils.updateVisible来判断是否start
  30960. if(Potree.settings.useDepthTex){
  30961. this.judgeStart() //开始下载depthTex
  30962. }else{
  30963. Potree.Utils.updateVisible(this,'showPanos', false ) //默认visible = false
  30964. } */
  30965. }
  30966. setPanoData(e, t /* , i */) {
  30967. this.panos = e, this.imagePanos = t;
  30968. // this.panoGroupId = i
  30969. }
  30970. start() {
  30971. this.downloadCubeTex = true;
  30972. /* if(!Potree.settings.useDepthTex){
  30973. Potree.Utils.updateVisible(this,'showPanos', true )
  30974. this.judgeStart()
  30975. }else{
  30976. //this.refreshInterval || this.judgeStart()
  30977. } */
  30978. }
  30979. stop() {
  30980. this.downloadCubeTex = false;
  30981. /* if(!Potree.settings.useDepthTex){
  30982. Potree.Utils.updateVisible(this,'showPanos', false )
  30983. this.judgeStart()
  30984. } */
  30985. }
  30986. /* judgeStart(){//add
  30987. if(this.visible){
  30988. //console.log('judgeStart true')
  30989. this.started = true
  30990. //this.refreshUpdateInterval(0)
  30991. }else{
  30992. //console.log('judgeStart false')
  30993. this.started = false
  30994. //window.clearTimeout(this.refreshInterval)
  30995. }
  30996. } */
  30997. /* refreshUpdateInterval(e) {
  30998. e || (e = 0),
  30999. this.refreshInterval = window.setTimeout(function() {
  31000. var e = this.update();
  31001. e ? this.refreshUpdateInterval(TileDownloader.ACTIVE_REFRESH_DELAY) : this.refreshUpdateInterval(TileDownloader.IDLE_REFRESH_DELAY)
  31002. }
  31003. .bind(this), e)
  31004. } */
  31005. update() {
  31006. if (!this.panos) return;
  31007. var time = Potree.Common.getBestCountFPS('processPriorityQueue', false, 700, 66);
  31008. if (this.downloadCubeTex) {
  31009. //可以下载贴图
  31010. var e = this.forceQueue.length > 0;
  31011. this.processQueueForDownloading(this.forceQueue);
  31012. if (this.processPriorityQueue) {
  31013. Potree.Common.intervalTool.isWaiting('processPriorityQueue', () => {
  31014. //延时update,防止崩溃 , 未到时间就拦截(第一次直接执行)
  31015. this.downloadCubeTex && this.queuePrioritizedTilesForPanos(this.panos); //这句比较耗时 降四倍时大概1-2毫秒
  31016. }, time);
  31017. this.priorityQueue.length > 0 && (e = !0);
  31018. this.processQueueForDownloading(this.priorityQueue);
  31019. }
  31020. //return e
  31021. } else if (viewer.scene.pointclouds.some(e => e.hasDepthTex)) {
  31022. //不加载贴图也要获得nearPanos
  31023. viewer.lastFrameChanged && Potree.Common.intervalTool.isWaiting('processPriorityQueue2', () => {
  31024. this.tilePrioritizer.getNearPanos(this.panos);
  31025. }, time);
  31026. }
  31027. var time2 = 1000; //Potree.Common.getBestCountFPS('filterDepthTex', false, 5000, 88, 2, 63 )
  31028. Potree.Common.intervalTool.isWaiting('filterDepthTex', () => {
  31029. this.tilePrioritizer.filterDepthTex(this.panos); //下载深度图
  31030. }, time2);
  31031. }
  31032. queuePrioritizedTilesForPanos(e) {
  31033. viewer.addTimeMark('queuePrioritizedTilesForPanos', 'start');
  31034. this.tilePrioritizer && (this.clearQueue(this.priorityQueue), this.tilePrioritizer.filterAndPrioritize(this.priorityQueue, e, this), this.clearFromQueue(this.priorityQueue, DownloadStatus$1.None, !0),
  31035. //去除state为DownloadStatus.None的(可能是去除已经在下载的)
  31036. this.setStatusOrRemoveForAllDescriptors(this.priorityQueue, DownloadStatus$1.Queued));
  31037. viewer.addTimeMark('queuePrioritizedTilesForPanos', 'end');
  31038. }
  31039. clearQueue(e) {
  31040. //停止下载并清空
  31041. this.setStatusForAllDescriptors(e, DownloadStatus$1.None), e.length = 0;
  31042. }
  31043. clearForceQueue() {
  31044. this.clearQueue(this.forceQueue);
  31045. }
  31046. clearFromQueue(e, t, i) {
  31047. for (var n = 0; n < e.length; n++) {
  31048. var r = e[n];
  31049. r && (t === r.status && !i || t !== r.status && i) && (e[n] = null);
  31050. }
  31051. }
  31052. setStatusForAllDescriptors(e, t) {
  31053. for (var i = 0; i < e.length; i++) {
  31054. var n = e[i];
  31055. n && (n.status = t);
  31056. }
  31057. }
  31058. setStatusOrRemoveForAllDescriptors(e, t) {
  31059. for (var i = 0; i < e.length; i++) {
  31060. var n = e[i];
  31061. n && (n.status !== t ? n.status = t : e[i] = null);
  31062. }
  31063. }
  31064. getTileDownloadDescriptors(pano, size) {
  31065. //获取该pano的该size的全部的tile的descriptor
  31066. var i = this.getAllTileDownloadDescriptorsForPano(pano),
  31067. n = i[size];
  31068. return n || (n = this.buildDownloadDescriptorArray(size),
  31069. //创建的全部是空的
  31070. i[size] = n, this.initTileDownloadDescriptors(n, pano, size)),
  31071. //绑定到该pano size
  31072. n;
  31073. }
  31074. getAllTileDownloadDescriptorsForPano(pano) {
  31075. //新建空Descriptors
  31076. var t = this.downloadDescriptors[pano.id];
  31077. return t || (t = {}, this.downloadDescriptors[pano.id] = t), t;
  31078. }
  31079. processQueueForDownloading(e, t) {
  31080. //执行下载任务
  31081. this.cleanupActiveDownloads();
  31082. if (e.length) {
  31083. var concurrentDownloads = Potree.Common.getBestCount('concurrentDownloads', 1, 6, 1.8, 13 /* ,true */);
  31084. if (this.activeDownloads.length < concurrentDownloads || t) {
  31085. var i = t ? e.length : concurrentDownloads - this.activeDownloads.length;
  31086. for (var n = 0, r = 0; n < i && e.length > 0; r++) {
  31087. var o = e.shift();
  31088. if (o) {
  31089. //add 为了防止1024的在512前下载完,这里强行等待512下载完毕再开始下载
  31090. if (o.panoSize > 512 && !this.isPanoDownloaded(o.pano, 512)) {
  31091. //console.log('512的还没下载好呢!')
  31092. e.push(o);
  31093. break; //一般512的都是连续下载的,所以后面就都不是512了直接中断
  31094. }
  31095. this.startDownload(o);
  31096. n++;
  31097. }
  31098. }
  31099. }
  31100. }
  31101. }
  31102. testDownload(panoSize, tileSize, callback) {
  31103. var n = this.downloadTestResults[panoSize];
  31104. if (n) return void (n === this.freeze.Success ? callback(!0) : n === this.freeze.Fail && callback(!1));
  31105. this.downloadTestResults[panoSize] = this.freeze.Testing;
  31106. var r = this.panos[0],
  31107. o = this.getTileUrl({
  31108. pano: r,
  31109. panoSize,
  31110. tileSize,
  31111. tileIndex: 0
  31112. } /* r.id, panoSize, tileSize, 0 */),
  31113. a = function (t) {
  31114. this.downloadTestResults[panoSize] = this.freeze.Success, callback(!0);
  31115. }.bind(this),
  31116. s = function () {
  31117. this.downloadTestResults[panoSize] = this.freeze.Fail, callback(!1);
  31118. }.bind(this);
  31119. this.loadImage(o, 0, a, s);
  31120. }
  31121. startDownload(e) {
  31122. //开始下载啦
  31123. startdownloads.push(e);
  31124. e.local2SrcFailed = this.local2SrcFailed;
  31125. e.status = DownloadStatus$1.Downloading;
  31126. var t = this.getTileUrl(e /* e.pano.id, e.panoSize, e.tileSize, e.tileIndex, e.pano.alignmentType */); //xzw add alignmentType
  31127. if (!t) return;
  31128. this.activeDownloads.push(e);
  31129. this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e));
  31130. }
  31131. downloadFailed(e, t) {
  31132. //add
  31133. if (Potree.settings.isLocal2 && !e.local2SrcFailed) {
  31134. //为了兼容旧的数据src,如果新src没加载成功,就加载旧的
  31135. e.local2SrcFailed = this.local2SrcFailed = true;
  31136. //this.startDownload(e)//重新下载
  31137. var t = this.getTileUrl(e);
  31138. this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e));
  31139. }
  31140. }
  31141. downloadComplete(e, t) {
  31142. //下载成功时
  31143. //if (e.panoGroupId === this.panoGroupId) {
  31144. var i = this.getPanoLoadCallbacks(e.pano, e.panoSize);
  31145. e.status = DownloadStatus$1.Downloaded, i && i.onProgress && i.onProgress(e.pano, e.panoSize);
  31146. var n = {
  31147. panoId: e.pano.id,
  31148. image: t,
  31149. tileSize: e.tileSize,
  31150. panoSize: e.panoSize,
  31151. tileIndex: e.tileIndex,
  31152. faceTileIndex: e.faceTileIndex,
  31153. totalTiles: e.totalTiles,
  31154. face: e.face,
  31155. tileX: e.tileX,
  31156. tileY: e.tileY,
  31157. direction: e.direction
  31158. };
  31159. downloaded[e.pano.id] || (downloaded[e.pano.id] = {
  31160. 512: [],
  31161. 1024: [],
  31162. 2048: []
  31163. });
  31164. downloaded[e.pano.id][e.panoSize] || (downloaded[e.pano.id][e.panoSize] = []);
  31165. downloaded[e.pano.id][e.panoSize].push(e);
  31166. if (e.panoSize != 512 && downloaded[e.pano.id][512].length < 6) {
  31167. console.warn('没下完');
  31168. }
  31169. this.tilesCount++; //add
  31170. e.image = t, this.dispatchEvent({
  31171. type: TileDownloaderEvents.TileDownloadSuccess,
  31172. desc: n
  31173. });
  31174. this.isPanoDownloaded(e.pano, e.panoSize) && (n = {
  31175. panoId: e.pano.id,
  31176. tileSize: e.tileSize,
  31177. panoSize: e.panoSize
  31178. }, this.dispatchEvent({
  31179. type: TileDownloaderEvents.PanoDownloadComplete,
  31180. desc: n
  31181. }), i && i.onLoad && i.onLoad(e.pano, e.panoSize));
  31182. //}
  31183. }
  31184. isPanoDownloaded(e, t) {
  31185. var i = this.getTileDownloadDescriptors(e, t);
  31186. if (i.length <= 0) return !1;
  31187. for (var n = 0; n < i.length; n++) {
  31188. var r = i[n];
  31189. if (r.status !== DownloadStatus$1.Downloaded) return !1;
  31190. }
  31191. return !0;
  31192. }
  31193. setPanoLoadCallbacks(e, t, i, n, r) {
  31194. var o = e.id + ":" + this.qualityManager.getPanoSize(t);
  31195. this.panoLoadCallbacks[o] = {
  31196. onLoad: i,
  31197. onFail: n,
  31198. onProgress: r
  31199. };
  31200. }
  31201. getPanoLoadCallbacks(e, t) {
  31202. var i = e.id + ":" + t;
  31203. return this.panoLoadCallbacks[i];
  31204. }
  31205. buildDownloadDescriptorArray(e) {
  31206. for (var t = TileUtils.getTileCountForSize(e), i = [], n = 0; n < t; n++) {
  31207. var r = this.buildDownloadDescriptor();
  31208. i.push(r);
  31209. }
  31210. return i;
  31211. }
  31212. buildDownloadDescriptor() {
  31213. //Descriptor!
  31214. var e = {
  31215. panoGroupId: null,
  31216. pano: null,
  31217. panoSize: -1,
  31218. tileSize: -1,
  31219. tileIndex: -1,
  31220. totalTiles: -1,
  31221. faceTileIndex: -1,
  31222. status: DownloadStatus$1.None,
  31223. url: null,
  31224. image: null,
  31225. direction: new Vector3(),
  31226. //该tile在cube中的方向
  31227. face: -1,
  31228. cubeFace: -1,
  31229. tileX: -1,
  31230. tileY: -1
  31231. };
  31232. return e;
  31233. }
  31234. initTileDownloadDescriptors(e, t, i) {
  31235. for (var n = 0; n < e.length; n++) {
  31236. var r = e[n];
  31237. this.initTileDownloadDescriptor(r, t, i, n);
  31238. }
  31239. }
  31240. initTileDownloadDescriptor(desc, pano, size, index) {
  31241. var r = size >= TileUtils.TILE_SIZE ? TileUtils.TILE_SIZE : size;
  31242. desc.face = TileUtils.getFaceForTile(size, index); //根据顺序得到的face的index
  31243. desc.cubeFace = TileUtils.mapFaceToCubemapFace(desc.face); //为了贴图而转化的face index
  31244. //desc.panoGroupId = this.panoGroupId;//就是场景号
  31245. desc.pano = pano;
  31246. desc.panoSize = size;
  31247. desc.tileSize = r; //瓦片图size 512
  31248. desc.tileIndex = index;
  31249. desc.totalTiles = TileUtils.getTileCountForSize(size);
  31250. desc.status = DownloadStatus$1.None;
  31251. desc.image = null;
  31252. TileUtils.getTileLocation(desc.panoSize, desc.tileIndex, desc); //得到该tile在这个face中的具体位置(tileX等)
  31253. TileUtils.getTileVector(desc.panoSize, desc.tileSize, desc.cubeFace, desc.tileX, desc.tileY, TileUtils.LocationOnTile.Center, 0, desc.direction);
  31254. }
  31255. getTiles(d, sceneNum, useV4url, pointcloud) {
  31256. var v3OrV4Str = useV4url ? "/scene_view_data/".concat(sceneNum, "/images/") : "/images/images".concat(sceneNum, "/");
  31257. var prefix = Potree.settings.urls.getPrefix(3, pointcloud); //Potree.settings.urls.panoOssRoot || pointcloud.prop?.raw?.panoOssRoot || Potree.settings.urls.prefix3
  31258. if (Potree.settings.isLocal && !this.local2SrcFailed && pointcloud.datasetData.mapping && !Potree.settings.isLocal2) {
  31259. //非离线包的话加mapping
  31260. return "".concat(prefix, "/").concat(pointcloud.datasetData.mapping).concat(v3OrV4Str).concat(d);
  31261. }
  31262. return "".concat(prefix).concat(v3OrV4Str).concat(d);
  31263. /*
  31264. if(Potree.settings.isLocal && !this.local2SrcFailed || useV4url){//新的地址 scene_view_data/场景码/images/tiles
  31265. if(pointcloud.datasetData.mapping && !Potree.settings.isLocal2){//非离线包的话加mapping
  31266. return `${Potree.settings.urls.prefix3}/${pointcloud.datasetData.mapping}/scene_view_data/${sceneNum}/images/${d}`
  31267. }else{
  31268. return `${Potree.settings.urls.prefix3}/scene_view_data/${sceneNum}/images/${d}`
  31269. }
  31270. }
  31271. return `${Potree.settings.urls.prefix3}/images/images${sceneNum}/${d}`
  31272. */
  31273. }
  31274. loadImage(e, t, i, n) {
  31275. //自己修改了ajax,把getImage改成了loadImg
  31276. http.loadImage(e, t).then(function (e) {
  31277. i(e);
  31278. }).fail(n);
  31279. }
  31280. }
  31281. TileDownloader.prototype.forceQueueTilesForPano = function () {
  31282. //根据条件开始加载tile
  31283. var e = [],
  31284. t = [];
  31285. return function (pano, size, dir, hFov, vFov, download) {
  31286. e.length = 0;
  31287. for (var u = this.getTileDownloadDescriptors(pano, size), d = 0; d < u.length; d++) {
  31288. var p = u[d];
  31289. p.status !== DownloadStatus$1.None && p.status !== DownloadStatus$1.Queued || e.push(p);
  31290. } //挑出没下载的开始下载
  31291. if (dir && e.length > 0) {
  31292. TilePrioritizer.sortPanoTiles(e, pano, dir); //按最佳方向排序e
  31293. t.length = 0;
  31294. TileUtils.matchingTilesInDirection(pano, size, dir, hFov, vFov, t); //得到在符合视野标准的集合t
  31295. for (var f = 0, g = function g(e) {
  31296. return e.face === m.face && e.faceTileIndex === m.faceTileIndex;
  31297. }; f < e.length;) {
  31298. //过滤掉不符合角度要求的
  31299. var m = e[f],
  31300. v = t.findIndex(g);
  31301. v < 0 ? e.splice(f, 1) : f++;
  31302. }
  31303. }
  31304. for (var A = 0; A < e.length; A++) {
  31305. this.forceQueue.push(e[A]); //装载
  31306. }
  31307. /* if(e.length){
  31308. console.log(e)
  31309. } */
  31310. this.setStatusForAllDescriptors(this.forceQueue, DownloadStatus$1.ForceQueued);
  31311. this.clearFromQueue(this.priorityQueue, DownloadStatus$1.ForceQueued, !1);
  31312. download && this.processQueueForDownloading(this.forceQueue, !0);
  31313. };
  31314. }();
  31315. TileDownloader.prototype.cleanupActiveDownloads = function () {
  31316. var e = [];
  31317. return function () {
  31318. e.length = 0;
  31319. for (var t = 0; t < this.activeDownloads.length; t++) {
  31320. var i = this.activeDownloads[t];
  31321. i.status !== DownloadStatus$1.Downloaded && i.status !== DownloadStatus$1.Failed && e.push(i);
  31322. }
  31323. this.activeDownloads.length = 0, this.activeDownloads.push.apply(this.activeDownloads, e);
  31324. };
  31325. }();
  31326. TileDownloader.prototype.getTileUrl = function () {
  31327. var e = {
  31328. 256: "256",
  31329. 512: "512",
  31330. 1024: "1k",
  31331. 2048: "2k",
  31332. 4096: "4k"
  31333. },
  31334. t = {
  31335. face: -1,
  31336. faceTileIndex: -1,
  31337. tileX: -1,
  31338. tileY: -1
  31339. };
  31340. return function () {
  31341. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  31342. var id = o.pano.originID,
  31343. ////////
  31344. panoSize = o.panoSize,
  31345. tileSize = o.tileSize,
  31346. tileIndex = o.tileIndex,
  31347. sceneCode = o.pano.pointcloud.sceneCode,
  31348. useV4url = Potree.settings.useV4url && (!o.pano.pointcloud.datasetData || o.pano.pointcloud.datasetData.sceneVersion == 'V4'); //v4的全景图等路径不一样
  31349. var resolution = o.pano.pointcloud.tileRes || '4k';
  31350. var metadata = {
  31351. sceneScheme: 10
  31352. };
  31353. TileUtils.getTileLocation(panoSize, tileIndex, t);
  31354. var s = Math.floor(panoSize / tileSize),
  31355. l = s * s,
  31356. h = Math.floor(tileIndex / l),
  31357. u = "",
  31358. d = '',
  31359. g = '';
  31360. if (Potree.settings.tileOriginUrl) {
  31361. //原始规则
  31362. //1 === config.tiling.customCompression && (u = "_" + config.tiling["q" + e[panoSize]]);
  31363. //1 === o.tiling.customCompression && (u = "_" + o.tiling["q" + e[n]]);
  31364. d = "tiles/" + id + "/" + e[panoSize] + u + "_face" + h + "_" + t.tileX + "_" + t.tileY + ".jpg";
  31365. d = this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud);
  31366. g = "?";
  31367. } else {
  31368. //阿里云oss的规则 if (metadata.sceneScheme == 10)
  31369. d = 'tiles/' + resolution + '/' + id + '_skybox' + h + '.jpg?x-oss-process=';
  31370. if (e[panoSize] == '512') {
  31371. d += 'image/resize,h_512';
  31372. } else {
  31373. //4k的图,移动端是1k,pc端是2k,放大才是4k
  31374. if (e[panoSize] == '1k' || e[panoSize] == '2k') {
  31375. //https://4dkk.4dage.com/images/imagesx4iqYDG3/tiles/4k/122_skybox0.jpg?x-oss-process=image/resize,m_lfit,w_1024/crop,w_512,h_512,x_511,y_0
  31376. d += 'image/resize,m_lfit,w_' + panoSize + '/crop,w_512,h_512,';
  31377. } else {
  31378. d = 'tiles/' + resolution + '/' + id + '_skybox' + h + '.jpg?x-oss-process=image/crop,w_512,h_512,';
  31379. }
  31380. //起始位置
  31381. if (t.tileX == 0) {
  31382. d += 'x_0,';
  31383. } else {
  31384. d += 'x_' + 512 * t.tileX /* - 1 */ + ',';
  31385. }
  31386. if (t.tileY == 0) {
  31387. d += 'y_0';
  31388. } else {
  31389. d += 'y_' + 512 * t.tileY /* - 1 */;
  31390. }
  31391. }
  31392. d = this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud);
  31393. g = "&";
  31394. }
  31395. //Potree.settings.panoVersion = 4
  31396. d += g + (Potree.settings.panoVersion ? 'version=' + Potree.settings.panoVersion : 'time=' + o.pano.pointcloud.timeStamp); //加后缀
  31397. return d;
  31398. /* 4dkk
  31399. getViewImagesURL(url) {
  31400. if (url.indexOf('&_=') !== -1) {
  31401. return url
  31402. }
  31403. let version = url.indexOf('/panorama/') !== -1 ? this.linkVersion : this.imageVersion
  31404. if (url.indexOf('?') !== -1) {
  31405. return this.$app.config.resource + `scene_view_data/${this.num}/images/${url}&_=${version}`
  31406. }
  31407. return this.$app.config.resource + `scene_view_data/${this.num}/images/${url}?_=${version}`
  31408. }
  31409. /**
  31410. */
  31411. };
  31412. }();
  31413. TileDownloader.tilegen = true;
  31414. TileDownloader.IDLE_REFRESH_DELAY = 500;
  31415. TileDownloader.ACTIVE_REFRESH_DELAY = 16;
  31416. TileDownloader.DOWNLOAD_RETRIES = 4;
  31417. function Node$1(e, t) {
  31418. this.tree = e,
  31419. //所属树(TileTree)
  31420. this.parent = t, this.children = [], this.id = ++u$1;
  31421. }
  31422. function o(e, t, i, r, a, s, l, h) {
  31423. if (e) {
  31424. l = l || TileTree.TraversalType.PreOrder;
  31425. var u = r * c + i;
  31426. if (l === TileTree.TraversalType.PreOrder && (a && a(e, t, u, i, r), s && s.push(e)), e.children && 0 !== e.children.length) {
  31427. for (var d = r * c, p = i * c, f = 0; f < c; f++) for (var g = 0; g < c; g++) o(e.children[g * c + f], t + 1, p + f, d + g, a, s, l, h);
  31428. l === TileTree.TraversalType.PostOrder && (a && a(e, t, u, i, r), s && s.push(e));
  31429. }
  31430. }
  31431. }
  31432. function Plant(seed) {
  31433. seed.root = Branch(seed, null, 0);
  31434. }
  31435. function Branch(seed, parent, level) {
  31436. if (level > seed.levels) return null;
  31437. var node = new Node$1(seed, parent);
  31438. seed.allNodes.push(node);
  31439. for (var o = 0; o < h$1; o++) node.children[o] = Branch(seed, node, level + 1);
  31440. return node;
  31441. }
  31442. function l(parent, t, level, n, r) {
  31443. if (!parent) return null;
  31444. if (0 === level) return parent;
  31445. if (!parent.children || 0 === parent.children.length) return null;
  31446. var o = Math.pow(c, level),
  31447. a = o / c,
  31448. s = n % a,
  31449. h = r % a,
  31450. u = Math.floor(r / a),
  31451. d = Math.floor(n / a),
  31452. p = u * c + d,
  31453. f = parent.children[p];
  31454. return l(f, t + 1, level - 1, s, h);
  31455. }
  31456. /* cube每个面都有一个分层树 用于代表瓦片图的细分?
  31457. 树4096的分为三层,每层有4个子节点。(最后一层的四个子节点都是null)
  31458. */
  31459. var c = 2,
  31460. h$1 = c * c; //4个子节点
  31461. var u$1 = 0;
  31462. class TileTree {
  31463. constructor(e, t) {
  31464. this.levels = t, this.tileSize = e, this.root = null, this.allNodes = [], Plant(this);
  31465. }
  31466. getSubNode(e, t, i) {
  31467. (!t || e < this.tileSize) && (t = 0), (!i || e < this.tileSize) && (i = 0), e < this.tileSize && (e = this.tileSize);
  31468. var level = TileTree.getLevelCountForSize(this.tileSize, e),
  31469. o = l(this.root, 0, level, t, i);
  31470. return o;
  31471. }
  31472. breadthFirst(e) {
  31473. //广度优先搜索
  31474. e = e || {};
  31475. var t = !!e.nullLevelEnd,
  31476. i = e.maxLevel,
  31477. n = e.minLevel,
  31478. r = e.callback,
  31479. o = e.saveVisited,
  31480. a = [],
  31481. s = {},
  31482. l = 0,
  31483. c = 0;
  31484. for (a.push(this.root), a.push(s); a.length > 0 && !(i && l > i);) {
  31485. var h = a.shift();
  31486. if (h === s) (!n || l >= n) && (r && t && r(null), o && t && o.push(null)), a.length > 0 && a.push(s), l++, c = 0;else {
  31487. if (h.children) for (var u = 0; u < h.children.length; u++) {
  31488. var d = h.children[u];
  31489. d && a.push(h.children[u]);
  31490. }
  31491. var p = this.getFaceIndexFromNode(h);
  31492. (!n || l >= n) && (r && r(h, l, p), o && o.push(h)), c++;
  31493. }
  31494. }
  31495. }
  31496. getFaceIndexFromNode(e) {
  31497. if (!e) return -1;
  31498. for (var t = 1, i = e, n = 0, r = 0;;) {
  31499. var o = i.parent;
  31500. if (!o) break;
  31501. for (var a = -1, s = 0; s < o.children.length; s++) o.children[s] === i && (a = s);
  31502. var l = a % c,
  31503. h = Math.floor(a / c);
  31504. n = l * t + n, r = h * t + r, t *= c, i = o;
  31505. }
  31506. return r * t + n;
  31507. }
  31508. depthFirst(e, t, i) {
  31509. o(this.root, 0, 0, 0, e, t, i, this.tileSize);
  31510. }
  31511. }
  31512. TileTree.TraversalType = Object.freeze({
  31513. PreOrder: 0,
  31514. PostOrder: 1
  31515. });
  31516. TileTree.getLevelCountForSize = function (tileSize, size) {
  31517. //512->0 2024->1
  31518. var i = 0;
  31519. for (size < tileSize && (size = tileSize);;) {
  31520. if (size /= c, size < tileSize) break;
  31521. i++;
  31522. }
  31523. return i;
  31524. };
  31525. TileTree.getSizeForLevel = function (e, t) {
  31526. return Math.pow(c, t) * e;
  31527. };
  31528. var {
  31529. PanoSizeClass: PanoSizeClass$2,
  31530. PanoRendererEvents: PanoRendererEvents$1,
  31531. Vectors,
  31532. SceneRendererEvents,
  31533. TileDownloaderEvents: TileDownloaderEvents$1,
  31534. GLCubeFaces: GLCubeFaces$2
  31535. } = Potree.defines;
  31536. function createDescriptor() {
  31537. var e = {
  31538. renderTarget: null,
  31539. inUse: !1,
  31540. size: -1,
  31541. pano: null
  31542. };
  31543. return e;
  31544. }
  31545. /* function upload() {
  31546. if (!this.uploadIntervalCancelled) {
  31547. if (this.overlayTilesLoaded || !this.usingTileOverlay) {
  31548. b = !0
  31549. let maxNonBaseUploadsPerFrame = viewer.mainViewport.view.isFlying() ? 1 : this.maxNonBaseUploadsPerFrame //原先2。这是每帧uploadTile非512的瓦片tex的数量。之前的2太卡了,降为1。(检测卡顿方法:在一个pano点旋转至所有2048的tile都加载完,然后之后到这个点看看卡不卡。因为该点tiles都下载完了所以会在飞过来时陆续都加载,所以容易卡)
  31550. this.updateUploadQueue(maxNonBaseUploadsPerFrame, this.maxBaseUploadsPerFrame)
  31551. let time = viewer.mainViewport.view.isFlying() ? 60 : w //add 飞行有时候会卡,增长间隔
  31552. this.peekNextFromUploadQueue() ? this.refreshUploadInterval(time) : this.uploadInterval = null //定时下一次更新
  31553. } else {
  31554. this.refreshUploadInterval(this.uploadIntervalDelay)
  31555. }
  31556. }
  31557. } */
  31558. var b = !1,
  31559. w = config$1.tiling.uploadIntervalDelay,
  31560. _ = config$1.tiling.initialIntervalDelay,
  31561. T = config$1.tiling.maxNonBaseUploadsPerFrame,
  31562. //2 size>512的每次只upload这么多个
  31563. x$1 = config$1.tiling.maxBaseUploadsPerFrame,
  31564. //6
  31565. S = {
  31566. Base: 0,
  31567. Remaining: 1
  31568. }; /* ,
  31569. M = []; */
  31570. class PanoRenderer extends EventDispatcher {
  31571. constructor(viewer, tileDownloader, qualityManager) {
  31572. super();
  31573. this.tileDirectory = {};
  31574. this.activeRenderTargetDescriptors = {};
  31575. this.activePanos = [];
  31576. this.panoLODDescriptors = {};
  31577. this.panoDescriptors = {};
  31578. this.tileTrees = {};
  31579. this.forceQueue = [];
  31580. this.uploadQueues = {};
  31581. this.uploadInterval = null;
  31582. this.uploadIntervalCancelled = true; //!1;
  31583. this.usingTileOverlay = !1;
  31584. this.overlayTilesLoaded = !1;
  31585. this.overlayTileBase = null;
  31586. this.overlayTilesBasic = {};
  31587. this.overlayTilesEnhanced = {};
  31588. this.zoomRenderTarget = null; //用于缩放的rendertarget
  31589. this.zoomPano = null;
  31590. this.zoomingActive = !1;
  31591. this.zoomPanoId = null;
  31592. this.zoomPanoRenderingDisabled = !1;
  31593. this.direction = []; //new THREE.Vector3;
  31594. this.maxBaseUploadsPerFrame = x$1;
  31595. this.maxNonBaseUploadsPerFrame = T;
  31596. this.M = []; //move M to here 似乎列表里会有两个
  31597. this.viewer = viewer;
  31598. this.tileDownloader = tileDownloader;
  31599. this.qualityManager = qualityManager;
  31600. this.initTime = performance.now();
  31601. this.bindEvents();
  31602. }
  31603. getActivePanoTextures(e) {
  31604. e = e || [];
  31605. for (var t = 0; t < M.length; t++) {
  31606. var i = M[t];
  31607. i.renderTarget && i.renderTarget.texture && e.push(i.renderTarget.texture);
  31608. }
  31609. }
  31610. hasQueuedTiles() {
  31611. var e = this.peekNextFromUploadQueue();
  31612. return null !== e && void 0 !== e;
  31613. }
  31614. getActiveRenderTargetDescriptor(e) {
  31615. return this.activeRenderTargetDescriptors[e];
  31616. }
  31617. setActiveRenderTargetDescriptor(e, t) {
  31618. this.activeRenderTargetDescriptors[e] = t;
  31619. }
  31620. bindEvents() {
  31621. this.tileDownloader.addEventListener(TileDownloaderEvents$1.TileDownloadSuccess, this.onTileDownloaded.bind(this));
  31622. }
  31623. enableUltraHighQualityMode(e) {
  31624. if (config$1.tileClass == "2k" || config$1.tileClass == "1k") return this.enableHighQuality(e); //xzw add 濡傛灉鏈€澶氬彧瑕?k鐨勮瘽
  31625. if (!this.qualityManager.ultraHighQualityModeEnabled()) {
  31626. var t = this.qualityManager.getPanoSize(PanoSizeClass$2.ULTRAHIGH);
  31627. this.tileDownloader.testDownload(t, TileUtils.TILE_SIZE, function (t) {
  31628. t && (this.qualityManager.enableUltraHighQualityMode(), this.setupZoomRenderTarget(), e());
  31629. }.bind(this));
  31630. }
  31631. }
  31632. activateTiledPano(pano, size, i) {
  31633. i && this.clearAllQueuedUploads();
  31634. for (var n = 0; n < TileUtils.FACES_PER_PANO; n++) this.initTileTree(pano.id, n, this.qualityManager.getMaxPossiblePanoSize()); //得到this.tileTrees[pano.id],arr[6]
  31635. this.linkAllTilesAndNodes(pano);
  31636. var r = this.getActiveRenderTargetDescriptor(pano.id),
  31637. l = size;
  31638. l > this.qualityManager.getMaxNavPanoSize() && (l = this.qualityManager.getMaxNavPanoSize());
  31639. if (!r || l !== r.size) {
  31640. r && this.deactiveDescripor(r.renderTarget);
  31641. r = this.activeDescripor(l);
  31642. if (!r) {
  31643. var ren = this.initTiledPano(l, Potree.settings.disableAATarget ? false : !browser.isMobile()); //有的老设备如果抗锯齿打开场景时要多花五秒
  31644. r = this.initDescriptor(ren.width);
  31645. r.renderTarget = ren;
  31646. }
  31647. r.pano = pano;
  31648. this.resetPanoDescriptor(pano.id);
  31649. this.resetPanoLODDescriptors(pano.id);
  31650. this.resetRenderStatus(pano.id, !0, !0);
  31651. }
  31652. this.setActiveRenderTargetDescriptor(pano.id, r);
  31653. var h = i ? 0 : 1;
  31654. this.updateActivePanos(pano, h);
  31655. //console.log(`index:${this.viewer.index} ${r.renderTarget.texture.id} ${pano.id}`)
  31656. return r.renderTarget;
  31657. }
  31658. deactivateTiledPano(pano) {
  31659. var t = this.getActiveRenderTargetDescriptor(pano.id);
  31660. if (this.isRenderTargetDescriptorValid(t)) {
  31661. this.deactiveDescripor(t.renderTarget);
  31662. this.setActiveRenderTargetDescriptor(pano.id, null);
  31663. }
  31664. var i = this.getUploadQueueForPano(pano.id);
  31665. this.clearUploadQueue(i);
  31666. this.updateActivePanos();
  31667. viewer.cancelLoad(pano); //add
  31668. }
  31669. getActivePanoCount() {
  31670. return this.activePanos.length;
  31671. }
  31672. resetRenderStatus(e, t, i, n) {
  31673. var r = null;
  31674. n && (r = TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, n) + 1);
  31675. for (var o = function o(e, n, r, _o) {
  31676. i && (n.tile.zoomUploaded = !1), t && (n.tile.uploaded = !1);
  31677. }, a = 0; a < TileUtils.FACES_PER_PANO; a++) {
  31678. var s = this.getTileTree(e, a);
  31679. s.breadthFirst({
  31680. callback: o.bind(this, a),
  31681. minLevel: r
  31682. });
  31683. }
  31684. }
  31685. copyBaseRenderStatusToZoomed(e) {
  31686. for (var t = TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, this.qualityManager.getMaxNavPanoSize()), i = function i(e, t, _i, n) {
  31687. t.tile.zoomUploaded = t.tile.uploaded, t.zoomCovered = t.covered;
  31688. }, n = 0; n < TileUtils.FACES_PER_PANO; n++) {
  31689. var r = this.getTileTree(e, n);
  31690. r.breadthFirst({
  31691. callback: i.bind(this, n),
  31692. maxLevel: t
  31693. });
  31694. }
  31695. }
  31696. isRenderTargetDescriptorValid(e) {
  31697. return e && e.renderTarget;
  31698. }
  31699. isPanoActive(e) {
  31700. var t = this.getActiveRenderTargetDescriptor(e);
  31701. return this.isRenderTargetDescriptorValid(t);
  31702. }
  31703. isPanoZoomed(e) {
  31704. return this.zoomingActive && this.zoomPanoId === e;
  31705. }
  31706. initTileTree(e, t, i) {
  31707. var n = this.tileTrees[e];
  31708. n || (n = [], this.tileTrees[e] = n);
  31709. var r = n[t];
  31710. if (!r) {
  31711. var o = TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, i);
  31712. r = new TileTree(TileUtils.TILE_SIZE, o), n[t] = r;
  31713. }
  31714. }
  31715. getTileTree(e, t) {
  31716. var i = this.tileTrees[e];
  31717. if (!i) console.error("PanoRenderer.getTileTree() -> Tree array not yet initialized!");
  31718. var n = i[t];
  31719. if (!n) console.error("PanoRenderer.getTileTree() -> Tree not yet initialized!");
  31720. return n;
  31721. }
  31722. /*
  31723. * 创建tile的renderTarget, 包括pano.tiledPanoRenderTarget和zoomRenderTarget
  31724. * @param {number} size 当前的panoSize,每个面的分辨率
  31725. */
  31726. initTiledPano(size, ifNormalFilter) {
  31727. //创建 RenderTargetCube
  31728. var renderer = this.viewer.renderer;
  31729. var renderTarget, texture;
  31730. renderTarget = new WebGLCubeRenderTarget(size, {
  31731. //THREE.WebGLRenderTargetCube(size, size, {
  31732. stencilBuffer: !1
  31733. });
  31734. texture = new CubeTexture([]);
  31735. texture.image = [null, null, null, null, null, null];
  31736. texture.flipY = !0, texture.format = RGBAFormat;
  31737. ifNormalFilter ? (texture.generateMipmaps = !0, texture.magFilter = LinearFilter, texture.minFilter = LinearMipMapLinearFilter) : (texture.generateMipmaps = !1, texture.magFilter = LinearFilter,
  31738. //LinearFilter更清晰,但锯齿噪点严重,相当于锐化,其实失真了。对于条纹状的画面移动镜头时锯齿明显 眩晕
  31739. texture.minFilter = LinearFilter);
  31740. //平时还是直接用LinearMipMapLinearFilter,其实并非不清晰,只是没有加锐化,像加了层柔光和抗锯齿,观感更好。放大后使用LinearFilter
  31741. // 如果抗锯齿的话,采用mipmap,会增加一倍的存储消耗。原版本都是不抗锯齿的。但是抗锯齿效果更柔和
  31742. renderTarget.texture = texture; //居然漏了一句,2022.10.9补
  31743. renderer.setRenderTarget(renderTarget);
  31744. renderer.setRenderTarget(null);
  31745. var o = renderer.properties.get(texture);
  31746. o.__image__webglTextureCube = o.__webglTexture;
  31747. //window.tex[r.id] = {texture:r, index:this.viewer.index }
  31748. return renderTarget;
  31749. }
  31750. getUploadQueueForPano(e) {
  31751. var t = this.uploadQueues[e];
  31752. return t || (t = [], this.uploadQueues[e] = t), t;
  31753. }
  31754. isTileUploaded(e) {
  31755. return this.isPanoZoomed(e.panoId) ? e.zoomUploaded : e.uploaded;
  31756. }
  31757. setUploaded(e, t) {
  31758. this.isPanoZoomed(e.panoId) ? e.zoomUploaded = t : e.uploaded = t;
  31759. }
  31760. queueTileUpload(e, t, i) {
  31761. var n = this.getActiveRenderTargetDescriptor(e.panoId);
  31762. if (this.isRenderTargetDescriptorValid(n) && e.downloaded && !this.isTileUploaded(e) && (!e.uploadQueued || i) && (!(e.panoSize > this.qualityManager.getMaxNavPanoSize()) || this.zoomingActive && viewer.images360.getPano(e.panoId).tileRes != '2k')) {
  31763. var r = this.getUploadQueueForPano(e.panoId);
  31764. //console.log(window.sceneName, 'queueTileUpload: ', e.panoId, e.tileIndex, i)
  31765. if (i) {
  31766. //console.log('512下载好了直接uploadTile')
  31767. this.uploadTile(e, !1); //提交后该tile直接loaded了,无需等待
  31768. } else {
  31769. if (this.shoulPushToFrontOfQueue(e)) {
  31770. //如果是512的优先
  31771. this.forceQueue.push(e);
  31772. } else {
  31773. if (t && this.direction) {
  31774. TilePrioritizer.insertSortedPanoTile(r, e, n.pano, this.direction);
  31775. } else r.push(e);
  31776. }
  31777. e.uploadQueued = !0;
  31778. this.uploadInterval || this.uploadIntervalCancelled || this.refreshUploadInterval(0);
  31779. }
  31780. }
  31781. }
  31782. shoulPushToFrontOfQueue(e) {
  31783. return 0 === TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, e.panoSize);
  31784. }
  31785. getTopUploadQueue() {
  31786. for (var e = null, t = null, i = S.Base; i <= S.Remaining; i++) for (var n = 0; n < this.activePanos.length; n++) if (e = this.activePanos[n], t = this.getUploadQueueForPano(e.id), t.length > 0) switch (i) {
  31787. case S.Base:
  31788. if (0 === t[0].level) return t;
  31789. break;
  31790. case S.Remaining:
  31791. return t;
  31792. }
  31793. return null;
  31794. }
  31795. peekNextFromUploadQueue() {
  31796. if (this.forceQueue.length > 0) return this.forceQueue[0];
  31797. var e = this.getTopUploadQueue();
  31798. return e && e.length > 0 ? e[0] : null;
  31799. }
  31800. clearAllQueuedUploads() {
  31801. this.clearAllUploadQueues(null, 0);
  31802. }
  31803. clearAllQueuedUploadsForPano(e) {
  31804. this.clearAllUploadQueues(e, 0);
  31805. }
  31806. clearAllUploadQueues(e, t) {
  31807. if (e) this.clearUploadQueue(this.getUploadQueueForPano(e), t), this.clearUploadQueue(this.forceQueue, t, e);else {
  31808. for (var i = 0; i < this.activePanos.length; i++) {
  31809. var n = this.activePanos[i];
  31810. this.clearUploadQueue(this.getUploadQueueForPano(n.id), t);
  31811. }
  31812. this.clearUploadQueue(this.forceQueue, t);
  31813. }
  31814. }
  31815. clearUploadQueue(e, t, i) {
  31816. void 0 !== t && null !== t || (t = 0);
  31817. for (var n = 0; n < e.length;) {
  31818. var r = e[n];
  31819. (!i || i && i === r.tile.panoId) && r.level >= t ? (r.uploadQueued = !1, e.splice(n, 1)) : n++;
  31820. }
  31821. //若报错, r.tile.panoId改为 r.panoId
  31822. }
  31823. updateUploadQueue(maxNPF, maxPF /* e, t */) {
  31824. //参数是 maxNonBaseUploadsPerFrame and maxBaseUploadsPerFrame, 优先上传512
  31825. //maxNPF || (maxNPF = 1);
  31826. for (var i = 0, n = 0;;) {
  31827. //let old = this.forceQueue.slice(0)
  31828. if (n >= maxPF || i >= maxNPF) break;
  31829. var r = this.getNextFromUploadQueue();
  31830. if (!r) break;
  31831. //r.panoSize <2048 && console.log('panoId', r.panoId, 'panoSize', r.panoSize , old)
  31832. 0 !== r.level ? i++ : n++;
  31833. if (!(r.panoSize > this.qualityManager.getMaxNavPanoSize()) || this.zoomingActive) {
  31834. var o = this.getActiveRenderTargetDescriptor(r.panoId);
  31835. this.isRenderTargetDescriptorValid(o) && this.uploadTile(r, r.forceUpload);
  31836. }
  31837. }
  31838. }
  31839. updateDirection(e) {
  31840. if (e = e || this.direction) {
  31841. this.direction = e;
  31842. for (var t = 0; t < this.activePanos.length; t++) {
  31843. var i = this.activePanos[t],
  31844. n = this.getUploadQueueForPano(i.id);
  31845. TilePrioritizer.sortPanoTiles(n, i, this.direction);
  31846. }
  31847. }
  31848. }
  31849. anyUploaded(e) {
  31850. if (!e) return !1;
  31851. if (e.tile && this.isTileUploaded(e.tile)) return !0;
  31852. if (e.children) for (var t = 0; t < e.children.length; t++) {
  31853. var i = e.children[t];
  31854. if (this.anyUploaded(i)) return !0;
  31855. }
  31856. return !1;
  31857. }
  31858. setNodeCovered(e, t) {
  31859. this.isPanoZoomed(e.tile.panoId) ? e.zoomCovered = t : e.covered = t;
  31860. }
  31861. isNodeCovered(e) {
  31862. return !!e && (this.isPanoZoomed(e.tile.panoId) ? e.zoomCovered : e.covered);
  31863. }
  31864. addCoverageForNode(e) {
  31865. if (this.setNodeCovered(e, !0), e.parent && e.covered) {
  31866. var t = e.parent;
  31867. this.nodeSubcovered(t) && this.addCoverageForNode(t, !0);
  31868. }
  31869. }
  31870. calcFullCoverage(e) {
  31871. var t = !1;
  31872. if (e.children) for (var i = 0; i < e.children.length; i++) {
  31873. var n = e.children[i];
  31874. t = t || this.calcFullCoverage(n);
  31875. }
  31876. e.covered = e.tile.uploaded || t;
  31877. }
  31878. nodeSubcovered(e) {
  31879. if (!e.children) return !1;
  31880. for (var t = 0; t < e.children.length; t++) if (!e.children[t] || !this.isNodeCovered(e.children[t])) return !1;
  31881. return !0;
  31882. }
  31883. resetPanoDescriptor(e) {
  31884. this.getPanoDescriptor(e);
  31885. }
  31886. getPanoDescriptor(e) {
  31887. var t = this.panoDescriptors[e];
  31888. return t || (t = {}, this.panoDescriptors[e] = t), t;
  31889. }
  31890. resetPanoLODDescriptors(e) {
  31891. var t = this.getPanoLODDescriptors(e);
  31892. for (var i in t) if (t.hasOwnProperty(i)) {
  31893. var n = t[i];
  31894. n.uploadCount = 0, n.uploadAttempts = 0;
  31895. n.uploaded = [];
  31896. }
  31897. }
  31898. getPanoLODDescriptor(e, t) {
  31899. var i = this.getPanoLODDescriptors(e),
  31900. n = i[t];
  31901. return n || (n = {
  31902. uploadCount: 0,
  31903. uploadAttempts: 0,
  31904. uploaded: [] //add
  31905. }, i[t] = n), n;
  31906. }
  31907. getPanoLODDescriptors(e) {
  31908. var t = this.panoLODDescriptors[e];
  31909. return t || (t = {}, this.panoLODDescriptors[e] = t), t;
  31910. }
  31911. onTileDownloaded(o) {
  31912. var e = o.desc;
  31913. var t = TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, e.panoSize),
  31914. i = this.getTileDirectoryEntry(e.panoId, e.face, t, e.faceTileIndex);
  31915. i.downloaded = !0;
  31916. i.image = e.image;
  31917. i.panoSize = e.panoSize;
  31918. i.tileX = e.tileX;
  31919. i.tileY = e.tileY;
  31920. i.totalTiles = e.totalTiles;
  31921. i.tileIndex = e.tileIndex;
  31922. i.faceTileIndex = e.faceTileIndex;
  31923. i.face = e.face;
  31924. i.cubeFace = TileUtils.mapFaceToCubemapFace(e.face);
  31925. i.panoId = e.panoId;
  31926. i.tileSize = e.tileSize;
  31927. i.direction = new Vector3().copy(e.direction);
  31928. i.node = null;
  31929. i.level = TileTree.getLevelCountForSize(TileUtils.TILE_SIZE, i.panoSize);
  31930. if (this.isPanoActive(i.panoId)) {
  31931. var n = this.getTileTree(i.panoId, i.face);
  31932. var r = n.getSubNode(i.panoSize, i.tileX, i.tileY);
  31933. this.linkTileAndNode(i, r);
  31934. this.queueTileUpload(i, !0);
  31935. }
  31936. }
  31937. getTileDirectoryEntry(panoId, t, i, n) {
  31938. var r = this.tileDirectory[panoId];
  31939. r || (r = {}, this.tileDirectory[panoId] = r);
  31940. var o = 16384 * t + 1024 * i + n,
  31941. //t:4096级别
  31942. a = r[o];
  31943. return a || (a = {
  31944. downloaded: !1,
  31945. uploaded: !1,
  31946. zoomUploaded: !1
  31947. }, r[o] = a), a._key = panoId + ":" + t + ":" + i + ":" + n,
  31948. //panoId : face : level : faceTileIndex
  31949. a._tileKey = o, a;
  31950. }
  31951. setZoomingActive(active, pano, i) {
  31952. //设置当前正在zoom的pano
  31953. this.zoomPanoRenderingDisabled || active === this.zoomingActive && this.zoomPanoId === pano.id || (this.zoomingActive = active, this.zoomPanoId = pano.id, this.zoomingActive && (this.zoomPanoId !== pano.id || i) && this.updateZoomedPanoFromBase(pano));
  31954. }
  31955. updateZoomedPanoFromBase(pano) {
  31956. //因更换pano所以将pano的rendertarget渲染到panoRenderer的zoomRenderTarget上
  31957. if (!this.zoomPanoRenderingDisabled) {
  31958. var t = this.getActiveRenderTargetDescriptor(pano.id);
  31959. if (t && t.renderTarget) {
  31960. if (this.zoomRenderTarget) {
  31961. var i = Math.min(this.qualityManager.maxRenderTargetSize, this.qualityManager.getMaxZoomPanoSize()),
  31962. //change
  31963. n = t.renderTarget,
  31964. r = t.size;
  31965. this.copyCubeMap(n.texture, this.zoomRenderTarget, r, r, i, i);
  31966. }
  31967. this.copyBaseRenderStatusToZoomed(pano.id);
  31968. }
  31969. }
  31970. }
  31971. add(e) {
  31972. this.M.push(e);
  31973. }
  31974. initDescriptor(size) {
  31975. var t = createDescriptor();
  31976. t.inUse = !0;
  31977. t.size = size;
  31978. this.add(t);
  31979. return t;
  31980. }
  31981. activeDescripor(e) {
  31982. for (var t = 0; t < this.M.length; t++) {
  31983. var i = this.M[t];
  31984. if (!i.inUse && i.size === e) {
  31985. i.inUse = !0;
  31986. return i;
  31987. }
  31988. }
  31989. return null;
  31990. }
  31991. deactiveDescripor(e) {
  31992. for (var t = 0; t < this.M.length; t++) {
  31993. var i = this.M[t];
  31994. if (i.renderTarget === e) {
  31995. i.inUse = !1;
  31996. return !0;
  31997. }
  31998. }
  31999. return !1;
  32000. }
  32001. enableHighQuality(e) {
  32002. //xzw add 如果最多只要2k图的话enableUltraHighQualityMode替换成这个
  32003. if (!this.qualityManager.highQualityModeStarted) {
  32004. this.setupZoomRenderTarget();
  32005. e();
  32006. //this.qualityManager.updateHighResolutionSettings(e)////////?
  32007. this.qualityManager.highQualityModeStarted = true;
  32008. }
  32009. }
  32010. linkTileAndNode(e, t) {
  32011. t.tile = e, e.node = t;
  32012. }
  32013. linkAllTilesAndNodes(e) {
  32014. var t = function t(_t, i, n, r, o) {
  32015. var a = this.getTileDirectoryEntry(e.id, i, r, o);
  32016. this.linkTileAndNode(a, n);
  32017. };
  32018. for (var i = 0; i < TileUtils.FACES_PER_PANO; i++) {
  32019. var n = this.getTileTree(e.id, i);
  32020. n.breadthFirst({
  32021. callback: t.bind(this, n, i)
  32022. });
  32023. }
  32024. }
  32025. //--------------sceneRenderer
  32026. initSizedTexture2D(e, t, i) {
  32027. var renderer = this.viewer.renderer,
  32028. o = renderer.getContext(),
  32029. a = renderer.state,
  32030. s = new Texture(null);
  32031. s.flipY = !1, i !== !0 && (i = !1), s.generateMipmaps = i;
  32032. var l = renderer.paramThreeToGL(s.format),
  32033. c = renderer.paramThreeToGL(s.type),
  32034. h = renderer.properties.get(s),
  32035. u = o.createTexture();
  32036. a.bindTexture(o.TEXTURE_2D, u), o.pixelStorei(o.UNPACK_FLIP_Y_WEBGL, s.flipY), o.texImage2D(o.TEXTURE_2D, 0, l, e, e, 0, l, c, null), s.wrapS = t, s.wrapT = t;
  32037. var d = renderer.paramThreeToGL(t);
  32038. return o.texParameteri(o.TEXTURE_2D, o.TEXTURE_WRAP_S, d), o.texParameteri(o.TEXTURE_2D, o.TEXTURE_WRAP_T, d), i ? (s.magFilter = LinearFilter, s.minFilter = LinearMipMapLinearFilter, o.texParameteri(o.TEXTURE_2D, o.TEXTURE_MAG_FILTER, o.LINEAR), o.texParameteri(o.TEXTURE_2D, o.TEXTURE_MIN_FILTER, o.LINEAR_MIPMAP_NEAREST), o.generateMipmap(o.TEXTURE_2D)) : (s.magFilter = LinearFilter, s.minFilter = LinearFilter, o.texParameteri(o.TEXTURE_2D, o.TEXTURE_MAG_FILTER, o.LINEAR), o.texParameteri(o.TEXTURE_2D, o.TEXTURE_MIN_FILTER, o.LINEAR)), a.bindTexture(o.TEXTURE_2D, null), h.__webglTexture = u, s;
  32039. }
  32040. deallocateCubeTexture(e) {
  32041. var t = this.viewer.renderer,
  32042. i = t.getContext(),
  32043. renderer = t.properties.get(e);
  32044. i.deleteTexture(renderer.__image__webglTextureCube);
  32045. }
  32046. uploadTexture2D(img, tex, startX, startY, width, height) {
  32047. var renderer = this.viewer.renderer,
  32048. gl = renderer.getContext(),
  32049. webglState = renderer.state,
  32050. c = renderer.properties.get(tex);
  32051. webglState.bindTexture(gl.TEXTURE_2D, c.__webglTexture), gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, tex.flipY), gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, tex.premultiplyAlpha), gl.pixelStorei(gl.UNPACK_ALIGNMENT, tex.unpackAlignment), gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, renderer.paramThreeToGL(tex.wrapS)), gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, renderer.paramThreeToGL(tex.wrapT)), gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, renderer.paramThreeToGL(tex.magFilter)), gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, renderer.paramThreeToGL(tex.minFilter)), gl.texSubImage2D(gl.TEXTURE_2D, 0, startX, startY, gl.RGBA, gl.UNSIGNED_BYTE, img), tex.generateMipmaps && gl.generateMipmap(gl.TEXTURE_2D), webglState.bindTexture(gl.TEXTURE_2D, null);
  32052. }
  32053. getCubeOrientationForCubeFace(e, t) {
  32054. switch (e) {
  32055. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  32056. t.set(0, -Math.PI / 2, 0);
  32057. break;
  32058. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  32059. t.set(0, Math.PI / 2, 0);
  32060. break;
  32061. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  32062. t.set(Math.PI / 2, Math.PI, 0);
  32063. break;
  32064. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  32065. t.set(-Math.PI / 2, Math.PI, 0);
  32066. break;
  32067. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  32068. t.set(0, -Math.PI, 0);
  32069. break;
  32070. case GLCubeFaces$2.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  32071. t.set(0, 0, 0);
  32072. }
  32073. }
  32074. //dispose所有cubeRenderTarget
  32075. disposeIdelTargets() {
  32076. var disposeCount = 0;
  32077. for (var t = 0; t < this.M.length; t++) {
  32078. var i = this.M[t];
  32079. if (!i.inUse) {
  32080. disposeCount++;
  32081. i.renderTarget.dispose();
  32082. }
  32083. }
  32084. //console.log('disposeIdelTargets ', disposeCount, 'of', this.M.length)
  32085. }
  32086. }
  32087. PanoRenderer.prototype.setupZoomRenderTarget = function () {
  32088. var targets = {};
  32089. return function () {
  32090. if (this.qualityManager.maxRenderTargetSize == 2048 && this.qualityManager.getMaxNavPanoSize() == 2048) return; //不使用zoomTarget 直接用pano的tiledPanoRenderTarget,防崩溃
  32091. if (this.qualityManager.getMaxZoomPanoSize() >= this.qualityManager.getMaxNavPanoSize()) {
  32092. //部分手机2k时copyCubeMap会重载 , 所以如果没有超出当前分辨率,就不使用zoomRenderTarget。但在微信依旧会重载,只是优化了些,safari几乎不会。
  32093. if (this.zoomRenderTarget && this.zoomRenderTarget.width === this.qualityManager.getMaxZoomPanoSize()) return;
  32094. var e = this.zoomRenderTarget;
  32095. var size = this.qualityManager.getMaxZoomPanoSize();
  32096. if (size > this.qualityManager.maxRenderTargetSize) {
  32097. return;
  32098. }
  32099. if (targets[size]) {
  32100. this.zoomRenderTarget = targets[size];
  32101. } else {
  32102. this.zoomRenderTarget = this.initTiledPano(size, false); //放大后不使用抗锯齿,否则消
  32103. targets[size] = this.zoomRenderTarget;
  32104. }
  32105. if (e) {
  32106. //将旧的zoomRenderTarget渲染到新zoomRenderTarget上
  32107. var t = e.width,
  32108. i = this.zoomRenderTarget.width;
  32109. this.copyCubeMap(e.texture, this.zoomRenderTarget, t, t, i, i), e.texture.dispose(), e.texture.loaded = !1, e.texture.version = 0, this.deallocateCubeTexture(e.texture), e.texture = null;
  32110. }
  32111. this.zoomPanoRenderingDisabled = !1;
  32112. } else this.zoomPanoRenderingDisabled = !0;
  32113. };
  32114. }();
  32115. PanoRenderer.prototype.updateActivePanos = function () {
  32116. var e = [];
  32117. return function (t, i) {
  32118. e.length = 0;
  32119. for (var n = 0; n < this.activePanos.length; n++) {
  32120. t && e.length === i && e.push(t);
  32121. var r = this.activePanos[n],
  32122. o = this.getActiveRenderTargetDescriptor(r.id);
  32123. t && r.id === t.id || !this.isRenderTargetDescriptorValid(o) || e.push(r);
  32124. }
  32125. t && i >= e.length && e.push(t), this.activePanos.length = 0, this.activePanos.push.apply(this.activePanos, e);
  32126. };
  32127. }();
  32128. PanoRenderer.prototype.renderPanoTiles = function () {
  32129. var e = [];
  32130. return function (panoId, i, n, r) {
  32131. this.zoomRenderTarget && this.zoomRenderTarget.width === this.qualityManager.getMaxZoomPanoSize() || this.zoomPanoRenderingDisabled || this.setupZoomRenderTarget(),
  32132. //如果ZoomRenderTarget大小需要变动就重新创建
  32133. i = i || this.direction || Vectors.FORWARD; // [{1:Vectors.FORWARD}]?
  32134. var o = this.getActiveRenderTargetDescriptor(panoId);
  32135. if (!this.isRenderTargetDescriptorValid(o)) console.error("PanoRenderer.renderPanoTiles() -> Cannot render to a pano that is not activated.");
  32136. for (var a = 0; a < TileUtils.FACES_PER_PANO; a++) {
  32137. var s = this.getTileTree(panoId, a);
  32138. e.length = 0;
  32139. s.breadthFirst({
  32140. //获取该面所有node 85个 = 1+4+16+64
  32141. saveVisited: e
  32142. });
  32143. for (var l = 0; l < e.length; l++) {
  32144. var c = e[l];
  32145. this.queueTileUpload(c.tile, !1, r || 0 === l && n); // 第0个是512的,会直接uploadTile
  32146. }
  32147. }
  32148. this.updateDirection(i);
  32149. };
  32150. }();
  32151. PanoRenderer.prototype.getNextFromUploadQueue = function () {
  32152. var e = function e(_e) {
  32153. var t = _e.shift();
  32154. return t.uploadQueued = !1, t;
  32155. };
  32156. return function () {
  32157. if (this.forceQueue.length > 0) return e(this.forceQueue);
  32158. var t = this.getTopUploadQueue();
  32159. return t && t.length > 0 ? e(t) : null;
  32160. };
  32161. }();
  32162. /* PanoRenderer.prototype.refreshUploadInterval = function () {
  32163. var e = null;
  32164. return function (t) {
  32165. this.uploadIntervalCancelled || (e || (e = upload.bind(this)),
  32166. null !== t && void 0 !== t || (t = w),
  32167. b || (t = _),
  32168. this.uploadInterval = window.setTimeout(e, t),
  32169. this.uploadIntervalDelay = t)
  32170. }
  32171. }()
  32172. PanoRenderer.prototype.update = function () {
  32173. var e = performance.now(),
  32174. t = 0;
  32175. return function () {
  32176. this.uploadIntervalCancelled = !0;
  32177. window.clearTimeout(this.uploadInterval);
  32178. this.uploadInterval = null;
  32179. var i = performance.now() - e;
  32180. //!(i > w || 0 === t) || !this.overlayTilesLoaded && this.usingTileOverlay || (this.updateUploadQueue(this.maxNonBaseUploadsPerFrame, this.maxBaseUploadsPerFrame),
  32181. //e = performance.now()),
  32182. if (!(i > w || 0 === t) || !this.overlayTilesLoaded && this.usingTileOverlay) {} else {
  32183. this.updateUploadQueue(this.maxNonBaseUploadsPerFrame, this.maxBaseUploadsPerFrame);
  32184. e = performance.now();
  32185. }
  32186. t++;
  32187. }
  32188. }() */
  32189. PanoRenderer.prototype.update = function () {
  32190. //this.uploadIntervalCancelled = true ; //不使用setTimeout,而是在sceneRenderer每帧都update
  32191. if (viewer.images360.latestRequestMode == 'showPanos') {
  32192. var maxNonBaseUploadsPerFrame = viewer.lastFrameChanged ? Common$1.getBestCount('maxStandard', 0, 2, 1, 10 /* ,true */) : 2; // 这是每帧uploadTile非512的瓦片tex的数量。 手机在前进时可能会总是0,直到到漫游点后为2
  32193. var maxBaseUploadsPerFrame = viewer.lastFrameChanged ? Common$1.getBestCount('maxBase', 1, 6, 1, 14 /* ,true */) : 6; //this.maxBaseUploadsPerFrame //原先6. 但持续前进过程中会请求加载下一个漫游图,一次加6张会卡的。
  32194. this.updateUploadQueue(maxNonBaseUploadsPerFrame, maxBaseUploadsPerFrame);
  32195. //注:静止时看不出卡顿所以全速加载
  32196. }
  32197. };
  32198. /* function upload() {
  32199. if (!this.uploadIntervalCancelled) {
  32200. if (this.overlayTilesLoaded || !this.usingTileOverlay) {
  32201. b = !0
  32202. let maxNonBaseUploadsPerFrame = viewer.mainViewport.view.isFlying() ? 1 : this.maxNonBaseUploadsPerFrame //原先2。这是每帧uploadTile非512的瓦片tex的数量。之前的2太卡了,降为1。(检测卡顿方法:在一个pano点旋转至所有2048的tile都加载完,然后之后到这个点看看卡不卡。因为该点tiles都下载完了所以会在飞过来时陆续都加载,所以容易卡)
  32203. this.updateUploadQueue(maxNonBaseUploadsPerFrame, this.maxBaseUploadsPerFrame)
  32204. let time = viewer.mainViewport.view.isFlying() ? 60 : w //add 飞行有时候会卡,增长间隔
  32205. this.peekNextFromUploadQueue() ? this.refreshUploadInterval(time) : this.uploadInterval = null //定时下一次更新
  32206. } else {
  32207. this.refreshUploadInterval(this.uploadIntervalDelay)
  32208. }
  32209. }
  32210. } */
  32211. PanoRenderer.prototype.uploadTile = function () {
  32212. //重写
  32213. var collection = {},
  32214. overlayStyle = config$1.tiling.overlayStyle;
  32215. var failHistory = {};
  32216. return function (info, n) {
  32217. var id = info.panoId,
  32218. img = info.image,
  32219. tileSize = info.tileSize,
  32220. panoSize = info.panoSize,
  32221. tileIndex = info.tileIndex,
  32222. totalTiles = info.totalTiles,
  32223. tileX = info.tileX,
  32224. tileY = info.tileY,
  32225. p = !0,
  32226. g = !1,
  32227. ignore = false,
  32228. //add
  32229. LodDescripor = (this.getPanoDescriptor(id), this.getPanoLODDescriptor(id, panoSize)),
  32230. activeDescripor = this.getActiveRenderTargetDescriptor(id),
  32231. renderTarget = activeDescripor.renderTarget,
  32232. size = activeDescripor.size; //当前要渲染的面的分辨率,也就是MaxNavPanoSize
  32233. if (this.isPanoZoomed(id) && this.zoomRenderTarget) {
  32234. renderTarget = this.zoomRenderTarget;
  32235. size = this.zoomRenderTarget.width; //this.qualityManager.getMaxZoomPanoSize(); //放大后可能2048或4096
  32236. }
  32237. //console.log(window.sceneName, 'uploadTile ', id, tileIndex)
  32238. var done = () => {
  32239. if (!LodDescripor.uploaded.includes(tileIndex)) {
  32240. //已经upload过(本来这时候直接返回,但发现缩放后这不会归零,导致清晰度不更新,所以还是redraw且emit吧)
  32241. //console.log('try to reupload and return',tileIndex)
  32242. LodDescripor.uploaded.push(tileIndex);
  32243. LodDescripor.uploadCount++;
  32244. }
  32245. this.dispatchEvent({
  32246. type: PanoRendererEvents$1.TileRenderSuccess,
  32247. id,
  32248. panoSize,
  32249. tileIndex,
  32250. totalTiles
  32251. });
  32252. LodDescripor.uploadCount === totalTiles && this.dispatchEvent({
  32253. type: PanoRendererEvents$1.PanoRenderComplete,
  32254. id,
  32255. panoSize,
  32256. totalTiles,
  32257. updateFullComplete: true
  32258. });
  32259. this.setUploaded(info, !0);
  32260. this.addCoverageForNode(info.node);
  32261. };
  32262. {
  32263. //已经uploadTile过了不再uploadTile
  32264. if (!this.isRenderTargetDescriptorValid(activeDescripor)) {
  32265. p = !1;
  32266. g = !1;
  32267. }
  32268. if (!n) {
  32269. this.anyUploaded(info.node) && (p = !1, g = !0, ignore = true); //包括子集也uploadTile了
  32270. this.isTileUploaded(info) && (p = !1, g = !1, ignore = true); //当前tile uploadTile了
  32271. }
  32272. }
  32273. if (p) {
  32274. /*if(failHistory[id+':'+ panoSize+ ':' +tileIndex]){
  32275. console.log('uploadTile retry',id, panoSize, tileIndex)
  32276. }
  32277. console.log('uploadTile 成功', id, panoSize, tileIndex) */
  32278. var C = tileX * tileSize,
  32279. I = tileY * tileSize,
  32280. E = tileSize / panoSize * size,
  32281. // tile在renderTarget上渲染出的宽度
  32282. b = C / panoSize * size,
  32283. // tile在renderTarget上渲染的startX
  32284. w = I / panoSize * size; // tile在renderTarget上渲染的startY
  32285. if (panoSize > this.qualityManager.maxRenderTargetSize) {
  32286. //4096 改
  32287. /* var tex = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping);
  32288. var loaded = this.viewer.images360.isHighMapLoaded(info.cubeFace, tileX,tileY) */
  32289. this.viewer.images360.getHighImage(img, info.cubeFace, tileX, tileY);
  32290. } else {
  32291. collection[tileSize] || (collection[tileSize] = this.initSizedTexture2D(tileSize, ClampToEdgeWrapping));
  32292. var tex = collection[tileSize];
  32293. this.uploadTexture2D(img, tex, 0, 0, tileSize, tileSize); //只替换tex对应的img,不新建
  32294. if (panoSize > this.qualityManager.maxRenderTargetSize) {
  32295. loaded || this.viewer.images360.updateHighMap(tex, info.cubeFace, tileX, tileY);
  32296. } else {
  32297. if (1 === overlayStyle || 2 === overlayStyle) {
  32298. var T = 1 === overlayStyle ? this.overlayTilesBasic : this.overlayTilesEnhanced;
  32299. this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
  32300. this.renderToCubeMap(T[panoSize], renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace, NormalBlending, !0, .5);
  32301. } else {
  32302. this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
  32303. }
  32304. }
  32305. }
  32306. done();
  32307. } else if (ignore) {
  32308. //console.log('finish because anyUploaded',id,panoSize,tileIndex)
  32309. done(); //改: 如果因为这部分更高清的贴图已加载所以才不绘制的话,直接完成
  32310. } else {
  32311. //console.log('uploadTile 失败', id, panoSize, tileIndex)
  32312. if (panoSize == 512) {
  32313. //console.log("!!!!!!!!!!!!!")
  32314. }
  32315. failHistory[id + ':' + panoSize + ':' + tileIndex] = true;
  32316. this.setUploaded(info, !1);
  32317. }
  32318. info.uploadAttempted || (LodDescripor.uploadAttempts++, this.dispatchEvent({
  32319. type: PanoRendererEvents$1.TileUploadAttempted,
  32320. id,
  32321. panoSize,
  32322. tileIndex,
  32323. totalTiles
  32324. })), info.uploadAttempted = !0;
  32325. LodDescripor.uploadAttempts === totalTiles && this.dispatchEvent({
  32326. type: PanoRendererEvents$1.UploadAttemptedForAllTiles,
  32327. id,
  32328. panoSize,
  32329. totalTiles
  32330. });
  32331. return g;
  32332. };
  32333. }();
  32334. /*
  32335. 注:tileY的方向同UV,从下到上
  32336. renderToCubeMap里的画布or镜头的xy范围是-0.5到0.5
  32337. */
  32338. PanoRenderer.prototype.renderToCubeMap = function () {
  32339. var inited = !1,
  32340. scene = null,
  32341. camera = null,
  32342. material = null,
  32343. geo = null,
  32344. plane = null,
  32345. l = 1;
  32346. return function (texture, renderTarget, tileWidth, tileHeight, startXinTile, startYinTile, widthinTile, heightinTile, startX, startY, width, height, cubeFace, E, b, w) {
  32347. var renderer = this.viewer.renderer;
  32348. inited || (camera = new OrthographicCamera(l / -2, l / 2, l / 2, l / -2, -200, 200), camera.position.z = 150, scene = new Scene(), scene.add(camera), material = new BasicMaterial({
  32349. depthWrite: !1,
  32350. depthTest: !1,
  32351. side: 0
  32352. }), geo = new PlaneBufferGeometry(l, l), plane = new Mesh(geo, material), plane.position.z = 0, scene.add(plane), inited = !0);
  32353. var uv = geo.getAttribute("uv");
  32354. uv.setDynamic(!0),
  32355. //setUsage
  32356. uv.needsUpdate = !0;
  32357. var uvArr = uv.array,
  32358. S = startXinTile / tileWidth,
  32359. //uv这几个值基本是固定的startXinTile:0,startYinTile:0,widthinTile:512,widthinTile:512,tileWidth:512,tileHeight:512 也就是说uv不会变、每张tile的有效范围是100%
  32360. M = startYinTile / tileHeight,
  32361. R = widthinTile / tileWidth,
  32362. P = heightinTile / tileHeight;
  32363. uvArr[0] = S, uvArr[1] = M + P, uvArr[2] = S + R, uvArr[3] = M + P, uvArr[4] = S, uvArr[5] = M, uvArr[6] = S + R, uvArr[7] = M;
  32364. //修改posistion,使该plane只占据需要绘制的部分。类似拼图。
  32365. //startX startY width height 都是在画布上的大小,比如画布大小为2048*2048,此tile为16分之一,tileX是1,tileY是1,则startX=2048/4,startY=2048/4
  32366. var pos = geo.getAttribute("position");
  32367. pos.setDynamic(!0), pos.needsUpdate = !0;
  32368. var posArr = pos.array,
  32369. D = startX / renderTarget.width - l / 2 // 起始x
  32370. ,
  32371. N = startY / renderTarget.height - l / 2 // 起始y
  32372. ,
  32373. B = width / renderTarget.width // 宽
  32374. ,
  32375. F = height / renderTarget.height; // 高
  32376. posArr[0] = D, posArr[1] = N + F, posArr[3] = D + B, posArr[4] = N + F, posArr[6] = D, posArr[7] = N, posArr[9] = D + B, posArr[10] = N;
  32377. //renderer.properties.get(scene);
  32378. material.map = texture; //material.uniforms.map.value = texture;
  32379. material.blending = E || NoBlending, material.transparent = !!b;
  32380. void 0 !== w && null !== w || (w = 1), material.uniforms.opacity.value = w,
  32381. // material.needUpdate = !0
  32382. //renderTarget.activeCubeFace = cubeFace, //0-5 应该是指定渲染h中的面 失效
  32383. /* renderer.setScissorTest(!0)
  32384. //指定绘制区域,类似遮罩(相对于屏幕)
  32385. renderer.setScissor(startX,startY,width,height) //加上这个会不会快一些,尤其是spherical
  32386. //指定绘制视口位置和大小(相对于屏幕)
  32387. */
  32388. renderTarget.viewport.set(0, 0, renderTarget.width, renderTarget.height);
  32389. var V = renderer.autoClear;
  32390. var oldTarget = renderer.getRenderTarget();
  32391. renderer.autoClear = !1;
  32392. renderer.setRenderTarget(renderTarget, cubeFace);
  32393. renderer.render(scene, camera /* , renderTarget, !1 */);
  32394. renderer.setRenderTarget(oldTarget);
  32395. renderer.autoClear = V;
  32396. //renderer.setScissorTest(!1)
  32397. /* this.renderer.render(scene, camera, this.planeTargets[cubeFace], !1),//针对有的场景app第一个点图加载不成功的问题
  32398. console.log(`图index ${cubeFace} , ${startX}, ${startY}, ${width}, ${height}`)
  32399. this.targetList[cubeFace] || (this.targetList[cubeFace] = [])
  32400. this.targetList[cubeFace].push([startX,startY,width,height])*/
  32401. };
  32402. }();
  32403. /*
  32404. * 将texture渲染到zoomRenderTarget上(目的是复制贴图到zoomRenderTarget)
  32405. */
  32406. PanoRenderer.prototype.copyCubeMap = function () {
  32407. //将texture渲染到zoomRenderTarget上
  32408. var inited = !1,
  32409. scene = null,
  32410. camera = null,
  32411. material = null,
  32412. geo = null,
  32413. mesh = null,
  32414. testCube = null,
  32415. //add
  32416. c = new Euler();
  32417. return function (texture, renderTarget, tWidth, tHeight, rWidth, rHeight, m, v, A) {
  32418. if (rWidth > this.qualityManager.maxRenderTargetSize) return; //add
  32419. if (!inited) {
  32420. var w = 2;
  32421. camera = new OrthographicCamera(w / -2, w / 2, w / 2, w / -2, 0, 200), camera.position.set(0, 0, 0), scene = new Scene(), scene.add(camera);
  32422. material = new ShaderMaterial({
  32423. uniforms: {
  32424. tDiffuse: {
  32425. type: "t",
  32426. value: null
  32427. },
  32428. alpha: {
  32429. type: "f",
  32430. value: 1
  32431. }
  32432. },
  32433. vertexShader: Shaders['copyCubeMap.vs'],
  32434. fragmentShader: Shaders['copyCubeMap.fs'],
  32435. depthWrite: !1,
  32436. depthTest: !1,
  32437. side: DoubleSide
  32438. });
  32439. geo = new BoxGeometry(w, w, w), mesh = new Mesh(geo, material), scene.add(mesh);
  32440. inited = !0;
  32441. /* testCube = mesh.clone();
  32442. viewer.scene.scene.add(testCube);
  32443. Potree.Utils.setObjectLayers(testCube, 'sceneObjects')
  32444. */
  32445. }
  32446. var autoClear = this.viewer.renderer.autoClear;
  32447. var oldTarget = this.viewer.renderer.getRenderTarget();
  32448. this.viewer.renderer.autoClear = false;
  32449. material.uniforms.tDiffuse.value = texture;
  32450. material.blending = m || NoBlending;
  32451. material.transparent = !!v;
  32452. void 0 !== A && null !== A || (A = 1);
  32453. material.uniforms.alpha.value = A;
  32454. material.needUpdate = !0;
  32455. for (var C = 0; C < 6; C++) {
  32456. this.getCubeOrientationForCubeFace(C, c);
  32457. mesh.rotation.copy(c);
  32458. mesh.matrixWorldNeedsUpdate = !0;
  32459. mesh.updateMatrixWorld();
  32460. renderTarget.viewport.set(0, 0, rWidth, rHeight);
  32461. this.viewer.renderer.setRenderTarget(renderTarget, C); //renderTarget.activeCubeFace = C//失效
  32462. this.viewer.renderer.render(scene, camera);
  32463. }
  32464. //console.warn('copyCubeMap' + rWidth)
  32465. this.viewer.renderer.autoClear = autoClear;
  32466. this.viewer.renderer.setRenderTarget(oldTarget);
  32467. };
  32468. }();
  32469. var imgCount = {};
  32470. window.imgCount = imgCount;
  32471. class DepthImageSampler extends EventDispatcher {
  32472. constructor() {
  32473. super();
  32474. var canvas = document.createElement("canvas");
  32475. this.canvas = canvas;
  32476. this.context = canvas.getContext("2d", {
  32477. willReadFrequently: true
  32478. });
  32479. this.imgDatas = [];
  32480. /* document.getElementsByTagName('body')[0].appendChild(canvas);
  32481. canvas.style.position = 'fixed';
  32482. canvas.style.width = '1024px';
  32483. canvas.style.top = canvas.style.left = 0
  32484. canvas.style['z-index'] = 100
  32485. */
  32486. this.maxDataCount = browser.isMobile() ? 12 : 20; //手机会崩溃. 平均每张图为8M数据量(以200个点的园区为例,加载时间久一些后,总内存=700 + 每张图的8M * maxDataCount)
  32487. this.maxNeighCount = browser.isMobile() ? 9 : 14; //包含在maxDataCount内的nearPanos最大个数.至少比maxDataCount少3个,留出空位给最近更新的pano
  32488. this.nearPanos = [];
  32489. }
  32490. updateNearPanos(panos) {
  32491. this.nearPanos = panos.slice(0, this.maxNeighCount);
  32492. }
  32493. changeImg(img, pano) {
  32494. imgCount[pano.id] = (imgCount[pano.id] || 0) + 1;
  32495. this.pano = pano;
  32496. var item = this.imgDatas.find(p => p.pano == pano);
  32497. if ( /* this.img == img || */item) {
  32498. //最新的在末尾,所以换到末尾
  32499. var index = this.imgDatas.indexOf(item);
  32500. this.imgDatas.splice(index, 1);
  32501. this.imgDatas.push(item);
  32502. //console.log('重复使用',item.pano.id)
  32503. return;
  32504. }
  32505. Potree.timeCollect.depthSamChangeImg.start = true; //不过在刚启动时得到的用时较大
  32506. try {
  32507. viewer.addTimeMark('depthSamChangeImg', 'start');
  32508. this.canvas.width = img.width;
  32509. this.canvas.height = img.height;
  32510. this.context.drawImage(img, 0, 0);
  32511. var o = this.context.getImageData(0, 0, img.width, img.height);
  32512. var data = o && o.data; //getImageData 1px时 : pc chrome 耗时0.01毫秒左右(排除第一次的50) , 但firefox: 4。但换贴图之后就多达5甚至几十
  32513. //console.warn('changeImg', pano.id, !!data )
  32514. //this.img = img
  32515. if (!data) {
  32516. console.error('getImageData 得不到?!why!');
  32517. return false;
  32518. }
  32519. if (this.imgDatas.length >= this.maxDataCount) {
  32520. var old = this.imgDatas.find(e => !this.nearPanos.includes(e.pano));
  32521. //console.log('推出',old.pano.id)
  32522. this.imgDatas.splice(this.imgDatas.indexOf(old), 1); //推出使用时间最早的一个非nearPano
  32523. }
  32524. this.imgDatas.push({
  32525. pano,
  32526. data
  32527. });
  32528. this.dispatchEvent({
  32529. type: 'changeImg',
  32530. pano
  32531. });
  32532. viewer.addTimeMark('depthSamChangeImg', 'end'); //耗时chrome 25ms,firefox: 38ms, iphoneX:33ms
  32533. } catch (e) {
  32534. console.error(e); //内存不足 Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Out of memory at ImageData creation
  32535. return false;
  32536. }
  32537. /* pano.depthData = {}
  32538. for(let h=0; h<img.height; h++){
  32539. for(let w=0; w<img.width; w++){
  32540. let blockIndex = img.width * h + w
  32541. let r = data.slice(blockIndex*4, (blockIndex+1)*4)
  32542. let depth = r[1] + r[0] / 256
  32543. if(depth>0) pano.depthData[h+'|'+w] = depth
  32544. }
  32545. } */
  32546. }
  32547. clearTexData() {
  32548. this.imgDatas.length = 0;
  32549. }
  32550. getDepth(UVx, UVy, useNeighIfZero) {
  32551. //根据图片像素获取深度值
  32552. var x = Math.round(UVx * (this.canvas.width - 1)),
  32553. y = Math.round(UVy * (this.canvas.height - 1));
  32554. var imgData = this.imgDatas.find(p => p.pano == this.pano);
  32555. var get = (x, y) => {
  32556. if (!(x < 0 || y < 0 || x >= this.canvas.width || y >= this.canvas.height)) {
  32557. var blockIndex = this.canvas.width * y + x;
  32558. var color = imgData.data.slice(blockIndex * 4, (blockIndex + 1) * 4);
  32559. return color[1] + color[0] / 256; //为什么不是除以255见聊天记录.(验证过比点云的远一点点)
  32560. }
  32561. };
  32562. /* viewer.addTimeMark('depthSampler','start')
  32563. var r = this.context.getImageData(x, y, 1, 1).data; //pc chrome 耗时0.01毫秒左右(排除第一次的50) , 但firefox: 4。但换贴图之后就多达5甚至几十
  32564. viewer.addTimeMark('depthSampler','end')
  32565. */
  32566. var depth = get(x, y);
  32567. if (!depth && useNeighIfZero) {
  32568. //遇到过有的相隔很远且有阻挡的两个漫游点间居然depth为0,没有阻挡?但是周围点有四个非零。所以为了修正会飞到很远的点加个识别周围像素的depth 。 2024.3.19
  32569. var results = [];
  32570. var d = 0,
  32571. sum = 0,
  32572. count = 0,
  32573. maxResDis = 1,
  32574. padding = 2; //间隔
  32575. while (d++ < maxResDis) {
  32576. for (var i = -d; i <= d; i++) {
  32577. for (var j = -d; j <= d; j++) {
  32578. if (i == -d || i == d || j == -d || j == d) {
  32579. //外围
  32580. var depth1 = get(x + i * padding, y + j * padding);
  32581. if (depth1 != 0) {
  32582. results.push(depth1);
  32583. }
  32584. }
  32585. }
  32586. }
  32587. }
  32588. if (results.length) {
  32589. depth = results.reduce((w, c) => {
  32590. return w + c;
  32591. }, 0) / results.length;
  32592. //console.error('useNeighIfZero', results, depth)
  32593. }
  32594. //console.log('useNeighIfZero', results, depth)
  32595. }
  32596. return {
  32597. depth,
  32598. x,
  32599. y
  32600. };
  32601. }
  32602. sample(intersect, currentPano, onlyPos, useNeighIfZero) {
  32603. //通过和skybox的intersect得到真实的intersect的位置
  32604. if (!intersect) return;
  32605. var location = new Vector3();
  32606. var normal;
  32607. currentPano = currentPano || viewer.images360.currentPano;
  32608. if (currentPano != this.currentPano || !this.imgDatas.find(p => p.pano == currentPano)) {
  32609. if (!currentPano.depthTex /* || !currentPano.depthTex.image */) return; //未加载
  32610. if (this.changeImg(currentPano.depthTex.image, currentPano) === false) {
  32611. console.log('失败', currentPano.id);
  32612. return false; //失败
  32613. }
  32614. this.currentPano = currentPano;
  32615. }
  32616. var origin = currentPano.position;
  32617. var dir = intersect.dir || new Vector3().subVectors(intersect.point, origin).normalize();
  32618. //var uv = intersect.uv
  32619. //let dirInPano = math.getNormalDir(dir, currentPano)//转化为考虑漫游点旋转的方向
  32620. var dirInPano = dir.clone().applyMatrix4(currentPano.panoMatrix2Inverse).normalize(); //转化为考虑漫游点旋转的方向
  32621. var uv = math.getUVfromDir(dirInPano); //转化为uv
  32622. var {
  32623. depth,
  32624. x,
  32625. y
  32626. } = this.getDepth(uv.x, uv.y, useNeighIfZero);
  32627. depth *= currentPano.pointcloud.scale.x;
  32628. //viewer.addTimeMark(markName,'end')
  32629. if (!depth) {
  32630. if (this.ignoreTopAndBtmHole) {
  32631. return null;
  32632. }
  32633. var margin = 0.1;
  32634. if (uv.y > 1 - Potree.config.depthTexUVyLimit) {
  32635. //漫游点底部识别不到的区域,给一个地板高度
  32636. depth = (currentPano.floorPosition.z - origin.z - margin) / dir.z;
  32637. location.copy(dir).multiplyScalar(depth).add(origin);
  32638. var _normal = new Vector3(0, 0, 1);
  32639. return {
  32640. location,
  32641. normal: _normal,
  32642. distance: depth,
  32643. uv
  32644. };
  32645. } else if (uv.y < Potree.config.depthTexUVyLimit) {
  32646. var ceilZ = currentPano.getCeilHeight();
  32647. if (ceilZ == Infinity) return !1;else {
  32648. depth = (ceilZ - origin.z - margin) / dir.z;
  32649. location.copy(dir).multiplyScalar(depth).add(origin);
  32650. var _normal2 = new Vector3(0, 0, -1);
  32651. return {
  32652. location,
  32653. normal: _normal2,
  32654. distance: depth,
  32655. uv
  32656. };
  32657. }
  32658. }
  32659. //console.log('无穷远')
  32660. return !1; //应该是天空或模型外 , 因为很少有漫游点的地方还拍不到地板
  32661. }
  32662. //console.log('depth', depth, dirInPano.clone().multiplyScalar(depth))
  32663. location.copy(dir).multiplyScalar(depth).add(origin);
  32664. if (!onlyPos) {
  32665. var pL = this.getNearbyPoint(origin, uv, -1, 0),
  32666. pR = this.getNearbyPoint(origin, uv, 1, 0),
  32667. pB = this.getNearbyPoint(origin, uv, 0, -1),
  32668. pT = this.getNearbyPoint(origin, uv, 0, 1);
  32669. normal = this.planeFit(dir, location, pL, pR, pB, pT);
  32670. }
  32671. /* if(normal.x != normal.x ){
  32672. console.log('NAN', normal)
  32673. var pL = this.getNearbyPoint(origin, uv, -1, 0)
  32674. , pR = this.getNearbyPoint(origin, uv, 1, 0)
  32675. , pB = this.getNearbyPoint(origin, uv, 0, -1)
  32676. , pT = this.getNearbyPoint(origin, uv, 0, 1);
  32677. } */
  32678. //console.log(location, normal, distance)
  32679. return {
  32680. location,
  32681. normal,
  32682. distance: depth,
  32683. x,
  32684. y,
  32685. uv
  32686. };
  32687. }
  32688. getNearbyPoint(origin, uv, x, y) {
  32689. //获取附近的若干像素距离的点
  32690. var uv2 = uv.clone();
  32691. uv2.x += x / (this.canvas.width - 1);
  32692. uv2.x = this.clampUV(uv2.x);
  32693. uv2.y += y / (this.canvas.height - 1);
  32694. uv2.y = this.clampUV(uv2.y);
  32695. /* if(uv2.x < 0 || uv2.y < 0 || uv2.x > 1 || uv2.y > 1){
  32696. console.log('will nan')
  32697. } */
  32698. var dir = math.getDirFromUV(uv2); //从uv获取到方向
  32699. dir.applyMatrix4(viewer.images360.currentPano.panoMatrix2);
  32700. var {
  32701. depth
  32702. } = this.getDepth(uv2.x, uv2.y);
  32703. /* if(Math.abs(depth - this.mainDepth) > 0.3){
  32704. console.log('Math.abs(depth - this.mainDepth) > 0.3')
  32705. } */
  32706. //let dir = new THREE.Vector3().subVectors(intersect.point, origin).normalize()
  32707. var position = new Vector3().copy(dir).multiplyScalar(depth).add(origin);
  32708. //console.log('getNearbyPoint', uv2, depth, dir, position )
  32709. return position;
  32710. }
  32711. clampUV(v) {
  32712. return (v + 1) % 1; // 使输出在 0-1
  32713. }
  32714. planeFit(dir, position, pL, pR, pB, pT) {
  32715. //求平均法线
  32716. var normal = new Vector3();
  32717. var plane = new Plane();
  32718. function addNormal(p1, p2) {
  32719. //根据临接的四个点,分别求法线,然后法线相加能得到平均法线
  32720. if (!p1 || !p2) return;
  32721. plane.setFromCoplanarPoints(position, p1, p2);
  32722. //console.log('normalSub', plane.normal)
  32723. normal.addScaledVector(plane.normal, dir.dot(plane.normal) < 0 ? 1 : -1); //根据面的朝向判断加还是减
  32724. }
  32725. addNormal(pL, pB);
  32726. addNormal(pL, pT);
  32727. addNormal(pR, pB);
  32728. addNormal(pR, pT);
  32729. if (0 !== normal.x || 0 !== normal.y || 0 !== normal.z) {
  32730. normal.normalize();
  32731. //console.log(normal)
  32732. return normal;
  32733. }
  32734. /* 四个面拼成一个菱形 */
  32735. }
  32736. }
  32737. var {
  32738. PanoSizeClass: PanoSizeClass$3,
  32739. Vectors: Vectors$1,
  32740. GLCubeFaces: GLCubeFaces$3,
  32741. PanoramaEvents: PanoramaEvents$1
  32742. } = Potree.defines;
  32743. var rot90$1 = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2); //使用的是刚好适合全景图的,给cube贴图需要转90°
  32744. var raycaster = new Raycaster();
  32745. //let currentlyHovered = null;
  32746. var texLoader$4 = new TextureLoader();
  32747. var addLine = function addLine(origin, dir, len) {
  32748. var color = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '#fff';
  32749. var line1 = LineDraw.createLine([origin, origin.clone().add(dir.clone().multiplyScalar(len || 1))], {
  32750. color
  32751. });
  32752. //console.log(origin.toArray(), dir.toArray())
  32753. viewer.scene.scene.add(line1);
  32754. return line1;
  32755. };
  32756. var tileArr = [];
  32757. var previousView = {
  32758. controls: null,
  32759. position: null,
  32760. target: null
  32761. };
  32762. var HighMapCubeWidth = 1;
  32763. var directionFactor = 400; //原先10,几乎只往距离近的走了;设置太大容易略过近处漫游点走向下坡,因为鼠标一般在地面,下坡的漫游点更有利
  32764. var getID = function () {
  32765. var id = 0;
  32766. return function () {
  32767. return id++;
  32768. };
  32769. }();
  32770. class Images360 extends EventDispatcher {
  32771. constructor(viewer) {
  32772. super();
  32773. this.viewer = viewer;
  32774. this.panos = [];
  32775. this.neighbourMap = {};
  32776. this.disMap = {};
  32777. this.node = new Object3D();
  32778. this.node.name = 'ImagesNode';
  32779. this.cubePanos = [];
  32780. this.fastTranMaskPass = new FastTranPass(viewer.renderer);
  32781. {
  32782. this.cube = new Mesh(new BoxBufferGeometry(1, 1, 1, 1), new ModelTextureMaterial());
  32783. Potree.Utils.updateVisible(this.cube, 'showSkybox', false);
  32784. this.cube.layers.set(Potree.config.renderLayers.skybox);
  32785. this.cube.name = 'skyboxCube';
  32786. viewer.scene.scene.add(this.cube);
  32787. if (Potree.settings.mergeType2 && Potree.settings.modelSkybox) {
  32788. this.materialInside = new ModelTextureMaterial();
  32789. this.materialInside.dontChangeDepth = true; //chunk本身深度是对的,不用深度图,否则过渡会有很多裂痕
  32790. this.cube.material.defines.depth_background = ''; //skybox的深度改得向后一些, 避免盖住chunk,造成坑坑洼洼
  32791. this.addEventListener('endChangeMode', e => {
  32792. viewer.objs.children.forEach(e => {
  32793. if (e.panos) this.changeModelMat(e);
  32794. }); //干脆全部换,就不容易错
  32795. });
  32796. }
  32797. }
  32798. if (Potree.settings.testCube) {
  32799. this.cubeTest = this.cube.clone();
  32800. this.cubeTest.material = new MeshBasicMaterial({
  32801. wireframe: true,
  32802. color: '#FF3377',
  32803. transparent: true,
  32804. opacity: 0.7,
  32805. depthWrite: false,
  32806. depthTest: false
  32807. });
  32808. viewer.scene.scene.add(this.cubeTest);
  32809. this.cubeTest.visible = true;
  32810. }
  32811. this.flying_ = false;
  32812. this.currentPano = null;
  32813. this.mouseLastMoveTime = Date.now();
  32814. this.scrollZoomSpeed = 0.06;
  32815. this.zoomLevel = 1;
  32816. this.tileDownloader = new TileDownloader();
  32817. this.qualityManager = new QualityManager();
  32818. this.panoRenderer = new PanoRenderer(viewer, this.tileDownloader, this.qualityManager);
  32819. this.basePanoSize = this.qualityManager.getPanoSize(PanoSizeClass$3.BASE);
  32820. this.standardPanoSize = this.qualityManager.getPanoSize(PanoSizeClass$3.STANDARD);
  32821. this.highPanoSize = this.qualityManager.getPanoSize(PanoSizeClass$3.HIGH);
  32822. this.ultraHighPanoSize = this.qualityManager.getPanoSize(PanoSizeClass$3.ULTRAHIGH);
  32823. this.tileDownloader.processPriorityQueue = !1;
  32824. this.tileDownloader.tilePrioritizer = new TilePrioritizer(this.qualityManager, this.basePanoSize, this.standardPanoSize, this.highPanoSize, this.ultraHighPanoSize);
  32825. {
  32826. //高分辨率cube 放大
  32827. this.addHighMapCube();
  32828. viewer.addEventListener(PanoramaEvents$1.Enter, e => {
  32829. this.setHighMap(e.newPano);
  32830. });
  32831. viewer.addEventListener('panoSetZoom', e => {
  32832. if (Potree.settings.displayMode == 'showPanos') {
  32833. e.zoomed ? this.showHighMap() : this.hideHighMap(); //add
  32834. }
  32835. });
  32836. }
  32837. this.depthSampler = new DepthImageSampler();
  32838. viewer.fpControls.addEventListener('dollyStopCauseUnable', e => {
  32839. if ( /* e.hoverViewport != viewer.mainViewport || */!Potree.settings.zoom.enabled) return;
  32840. if (e.scale != void 0) {
  32841. //触屏
  32842. this.zoomBy(e.scale, e.pointer);
  32843. } else {
  32844. //滚轮
  32845. var zoom;
  32846. if (e.delta > 0) {
  32847. zoom = 1 + this.scrollZoomSpeed;
  32848. } else {
  32849. zoom = 1 - this.scrollZoomSpeed;
  32850. }
  32851. e.delta != 0 && this.zoomBy(zoom);
  32852. }
  32853. });
  32854. var click = e => {
  32855. var _e$intersect;
  32856. //不用"mouseup" 是因为 mouseup有drag object时也会触发
  32857. if (e.clickElement || Potree.settings.unableNavigate || this.flying || !e.isTouch && e.button != MOUSE.LEFT || e.drag && e.drag.object //拖拽结束时不算
  32858. /* || Potree.settings.editType == 'pano' && viewer.modules.PanoEditor.entered */
  32859. //|| Potree.settings.editType == 'merge' && !e.intersectPoint || viewer.inputHandler.hoveredElements[0] && viewer.inputHandler.hoveredElements[0].isModel && e.intersectPoint.distance > viewer.inputHandler.hoveredElements[0].distance
  32860. || Potree.settings.editType == 'merge' && !Potree.settings.mergeType2 || Potree.settings.editType == 'merge' && (_e$intersect = e.intersect) !== null && _e$intersect !== void 0 && _e$intersect.object && !e.intersect.object.is4dkkModel //支持全景模式下点击非场景模型
  32861. //|| Potree.settings.mergeType2 && Potree.settings.displayMode == 'showPointCloud'
  32862. ) return;
  32863. if (Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge') {
  32864. if (e.hoverViewport == viewer.mapViewer.viewports[0]) {
  32865. return viewer.mapViewer.dispatchEvent(e /* {type:'global_click',e } */);
  32866. } else if (e.hoverViewport != viewer.mainViewport) {
  32867. //如数据集校准其他viewport
  32868. return;
  32869. }
  32870. }
  32871. if (!Potree.settings.dblToFocusPoint /* && this.currentPano */) {
  32872. //双击不会focus点云 或者 已经focusPano了
  32873. this.flyToPanoClosestToMouse();
  32874. }
  32875. };
  32876. viewer.addEventListener('global_click', click);
  32877. viewer.addEventListener("global_mousemove", e => {
  32878. if (!Potree.settings.unableNavigate && Potree.settings.ifShowMarker && e.hoverViewport == viewer.mainViewport) {
  32879. //如果不显示marker,就在点击时再更新
  32880. this.updateClosestPano(e.intersect);
  32881. }
  32882. });
  32883. this.addEventListener('markerHover', e => {
  32884. this.updateClosestPano(e.pano, e.hovered);
  32885. });
  32886. if (!Potree.settings.isOfficial) {
  32887. this.domRoot = viewer.renderer.domElement.parentElement;
  32888. var elUnfocus = $("<input type='button' value='unfocus'></input>");
  32889. elUnfocus.css({
  32890. position: "absolute",
  32891. right: '25%',
  32892. bottom: '20px',
  32893. zIndex: "10000",
  32894. fontSize: '1em',
  32895. color: "black",
  32896. display: 'none',
  32897. background: 'rgba(255,255,255,0.8)'
  32898. });
  32899. elUnfocus.on("click", () => this.unfocus());
  32900. this.elUnfocus = elUnfocus;
  32901. this.domRoot.appendChild(elUnfocus[0]);
  32902. if (Potree.settings.editType != 'merge') {
  32903. var elHide = $("<input type='button' value='隐藏点云'></input>");
  32904. elHide.css({
  32905. position: "absolute",
  32906. right: '40%',
  32907. bottom: '20px',
  32908. zIndex: "10000",
  32909. fontSize: '1em',
  32910. color: "black",
  32911. width: '100px',
  32912. background: 'rgba(255,255,255,0.8)'
  32913. });
  32914. this.domRoot.appendChild(elHide[0]);
  32915. elHide.on("click", e => {
  32916. var visi = Potree.Utils.getObjVisiByReason(viewer.scene.pointclouds[0], 'force');
  32917. viewer.scene.pointclouds.forEach(e => {
  32918. Potree.Utils.updateVisible(e, 'force', !visi);
  32919. });
  32920. elHide.val(!visi ? "隐藏点云" : "显示点云");
  32921. });
  32922. viewer.addEventListener('allLoaded', () => {
  32923. var interval = setInterval(() => {
  32924. var _viewer$scene$pointcl, _viewer$scene$pointcl2;
  32925. var attrs = ((_viewer$scene$pointcl = viewer.scene.pointclouds[0].root.geometryNode) === null || _viewer$scene$pointcl === void 0 ? void 0 : _viewer$scene$pointcl.geometry.attributes) || ((_viewer$scene$pointcl2 = viewer.scene.pointclouds[0].root.geometry) === null || _viewer$scene$pointcl2 === void 0 ? void 0 : _viewer$scene$pointcl2.attributes);
  32926. if (!attrs) return;
  32927. if (attrs.ir) {
  32928. var btnHot = $('<button id="hot" style="position: fixed;right: 10px;top: 10px;z-index: 10;">打开热成像</button>');
  32929. $('body').append(btnHot);
  32930. var onHot = false;
  32931. btnHot.on('click', () => {
  32932. onHot = !onHot;
  32933. Potree.settings.showHotIr = onHot;
  32934. btnHot.text((onHot ? '关闭' : '打开') + '热成像');
  32935. });
  32936. }
  32937. if (attrs.temp) {
  32938. var btn = $('<button id="hot" style="position: fixed;right: 10px;top: 50px;z-index: 10;">打开火调温度</button>');
  32939. $('body').append(btn);
  32940. var on = false;
  32941. btn.on('click', () => {
  32942. on = !on;
  32943. Potree.settings.showHotTemp = on;
  32944. btn.text((on ? '关闭' : '打开') + '火调温度');
  32945. });
  32946. }
  32947. if (attrs.classification) {
  32948. var btnSeg = $('<button id="hot" style="position: fixed;right: 10px;top: 100px;z-index: 10;">打开分类</button>');
  32949. $('body').append(btnSeg);
  32950. var onSeg = false;
  32951. btnSeg.on('click', () => {
  32952. onSeg = !onSeg;
  32953. Potree.settings.showClass = onSeg;
  32954. btnSeg.text((onSeg ? '关闭' : '打开') + '分类');
  32955. });
  32956. }
  32957. clearInterval(interval);
  32958. }, 100);
  32959. }, {
  32960. once: true
  32961. });
  32962. }
  32963. var elDisplayModel = $("<input type='button' value='>>全景'></input>");
  32964. elDisplayModel.css({
  32965. position: "absolute",
  32966. right: '65%',
  32967. bottom: '20px',
  32968. zIndex: "10000",
  32969. fontSize: '1em',
  32970. color: "black",
  32971. width: '100px',
  32972. background: 'rgba(255,255,255,0.8)'
  32973. });
  32974. this.domRoot.appendChild(elDisplayModel[0]);
  32975. elDisplayModel.on("click", e => {
  32976. if (Potree.settings.displayMode == 'showPointCloud' && this.panos.length == 0) return;
  32977. Potree.settings.displayMode = Potree.settings.displayMode == 'showPointCloud' ? 'showPanos' : 'showPointCloud';
  32978. });
  32979. this.elDisplayModel = elDisplayModel;
  32980. if (viewer.mapViewer) {
  32981. var mapStyleBtn = $("<input type='button' value='普通'></input>");
  32982. mapStyleBtn.css({
  32983. position: "absolute",
  32984. right: '50%',
  32985. bottom: '20px',
  32986. zIndex: "10000",
  32987. fontSize: '1em',
  32988. color: "black",
  32989. width: '100px',
  32990. background: 'rgba(255,255,255,0.8)'
  32991. });
  32992. this.domRoot.appendChild(mapStyleBtn[0]);
  32993. var map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'map');
  32994. mapStyleBtn.on("click", e => {
  32995. map.switchStyle(map.style == 'satellite' ? 'standard' : 'satellite');
  32996. mapStyleBtn.val(map.style == 'satellite' ? '卫星' : '普通');
  32997. });
  32998. }
  32999. }
  33000. {
  33001. //切换模式
  33002. var displayMode = '';
  33003. this.latestRequestMode = ''; //因为可能延迟,所以记录下每次的请求模式,延迟后判断这个
  33004. Object.defineProperty(Potree.settings, "displayMode", {
  33005. get: function get() {
  33006. return displayMode;
  33007. },
  33008. set: mode => {
  33009. this.latestRequestMode = mode;
  33010. console.warn('Request setMode: ' + mode);
  33011. this.dispatchEvent({
  33012. type: 'requestMode',
  33013. mode
  33014. });
  33015. var config2;
  33016. var config = Potree.config.displayMode[mode];
  33017. if (this.isAtPano() && !this.latestToPano) {
  33018. config2 = config.atPano;
  33019. } else {
  33020. config2 = config.transition;
  33021. }
  33022. var pano = this.currentPano;
  33023. var changeTileDownload = () => {
  33024. if (config2.showSkybox || config2.showPoint && config2.pointUsePanoTex) {
  33025. this.tileDownloader.start();
  33026. this.currentPano && this.currentPano.enter();
  33027. } else {
  33028. this.tileDownloader.stop();
  33029. this.currentPano && this.currentPano.exit();
  33030. this.nextPano && viewer.cancelLoad(this.nextPano);
  33031. }
  33032. };
  33033. if (mode != displayMode) {
  33034. var camera = viewer.scene.getActiveCamera();
  33035. if (mode == 'showPanos' && viewer.mainViewport.view.isFlying()) {
  33036. //飞完才能切换全景
  33037. var f = () => {
  33038. if (this.latestRequestMode == mode) {
  33039. //如果ui还是停在这个模式的话
  33040. Potree.settings.displayMode = mode;
  33041. }
  33042. viewer.mainViewport.view.removeEventListener('flyingDone', f);
  33043. viewer.mainViewport.view.removeEventListener('flyCancel', f);
  33044. };
  33045. viewer.mainViewport.view.addEventListener('flyingDone', f); //once
  33046. viewer.mainViewport.view.addEventListener('flyCancel', f);
  33047. return;
  33048. }
  33049. if (this.isAtPano() && !this.latestToPano) {
  33050. config2 = config.atPano;
  33051. } else {
  33052. config2 = config.transition;
  33053. if (mode == 'showPanos') {
  33054. //自动飞入一个pano
  33055. //要改成飞进最近的。。。
  33056. if (this.panos.length == 0) return;
  33057. //this.modeChanging = true //主要是因为到全景图不会立刻成功
  33058. var wait = e => {
  33059. console.log('flyToPanoDone');
  33060. this.removeEventListener('flyToPanoDone', wait);
  33061. setTimeout(() => {
  33062. if (this.latestRequestMode == mode) {
  33063. Potree.settings.displayMode = mode; //被打断,重新执行
  33064. }
  33065. }, e.makeIt ? 1 : 50);
  33066. };
  33067. this.addEventListener('flyToPanoDone', wait); //等待飞行完毕。flyToPano的callback可能不执行所以换这个。但也可能被cancel
  33068. this.flyToPano({
  33069. pano: this.findNearestPano()
  33070. //dealDoneWhenCancel:true,
  33071. /* callback: ()=>{
  33072. setTimeout(()=>{ //防止循环,所以延迟
  33073. if(this.latestRequestMode == mode ){
  33074. Potree.settings.displayMode = mode
  33075. }
  33076. },1)
  33077. } */
  33078. });
  33079. return;
  33080. } else {}
  33081. }
  33082. changeTileDownload();
  33083. if (config2.showSkybox || config2.pointUsePanoTex) {
  33084. var _wait = () => {
  33085. //console.log('waitdone')
  33086. //if(e.pano && e.pano != this.currentPano)return //loadedDepthImg
  33087. setTimeout(() => {
  33088. if (this.latestRequestMode == mode) {
  33089. Potree.settings.displayMode = mode;
  33090. }
  33091. }, 1);
  33092. };
  33093. //this.updateDepthTex()
  33094. if (this.checkAndWaitForPanoLoad(pano, this.basePanoSize, _wait)) {
  33095. //console.log('等待贴图加载2', this.currentPano.id)
  33096. return;
  33097. }
  33098. var types = {
  33099. 'seg': 'showClass',
  33100. 'ir': 'showHotIr',
  33101. 'temp': 'showHotTemp'
  33102. };
  33103. for (var type in types) {
  33104. if (Potree.settings[types[type]] && pano['has_' + type] && !pano[type + 'Tex']) {
  33105. pano.loadTypeImg(type);
  33106. return pano.addEventListener('loaded_' + type, _wait, {
  33107. once: true
  33108. });
  33109. }
  33110. }
  33111. }
  33112. viewer.scene.pointclouds.forEach(e => {
  33113. Potree.Utils.updateVisible(e, 'displayMode', config2.showPoint, 2);
  33114. });
  33115. if (config2.pointUsePanoTex) {
  33116. viewer.scene.pointclouds.forEach(e => {
  33117. e.material.setProjectedPanos(this.currentPano, this.currentPano, 1);
  33118. });
  33119. } else {
  33120. viewer.scene.pointclouds.forEach(e => {
  33121. e.material.stopProjectedPanos();
  33122. });
  33123. }
  33124. Potree.Utils.updateVisible(this.cube, 'showSkybox', config2.showSkybox); // this.cube.visible = config2.showSkybox
  33125. //this.cube.visible = config.atPano.showSkybox
  33126. if (this.cube.visible) {
  33127. //this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
  33128. this.setProjectedPanos({
  33129. progress: 1,
  33130. ifSkybox: true,
  33131. ifPointcloud: false,
  33132. easeInOutRatio: 0,
  33133. pano0: this.currentPano,
  33134. pano1: this.currentPano
  33135. });
  33136. } else {
  33137. this.smoothZoomTo(1);
  33138. this.resetHighMap();
  33139. this.hideHighMap();
  33140. }
  33141. /* viewer.dispatchEvent({
  33142. type: "enableChangePos",
  33143. canLeavePano : config.canLeavePano ,
  33144. viewport:
  33145. }) */
  33146. //viewer.mainViewport.unableChangePos = !config.canLeavePano
  33147. displayMode = mode;
  33148. if (mode == 'showPanos') {
  33149. camera.far = viewer.farWhenShowPano; //修改far
  33150. Potree.settings.pointDensity = 'panorama';
  33151. if (Potree.config.displayMode.showPanos.transition.pointUsePanoTex) {
  33152. viewer.scene.pointclouds.forEach(e => {
  33153. e.material.pointSizeType = 'FIXED';
  33154. });
  33155. }
  33156. this.updateCube(this.currentPano);
  33157. //viewer.setControls(viewer.fpControls)
  33158. } else {
  33159. if (camera.limitFar) camera.far = Potree.settings.cameraFar; //修改far
  33160. Potree.settings.pointDensity = Potree.settings.UserPointDensity;
  33161. //Potree.sdk && Potree.sdk.scene.changePointOpacity()
  33162. if (Potree.config.displayMode.showPanos.transition.pointUsePanoTex) {
  33163. viewer.scene.pointclouds.forEach(e => {
  33164. e.material.pointSizeType = Potree.config.material.pointSizeType;
  33165. });
  33166. }
  33167. //Potree.settings.editType == 'merge' && viewer.setControls(viewer.orbitControls)
  33168. }
  33169. camera.updateProjectionMatrix();
  33170. if (this.elDisplayModel) {
  33171. this.elDisplayModel.val(mode == 'showPointCloud' ? ">>全景" : '>>点云');
  33172. }
  33173. /* this.panos.forEach(e=>{
  33174. Potree.Utils.updateVisible(e, 'modeIsShowPanos', mode == 'showPanos', 1, mode == 'showPanos' ? 'add':'cancel') //
  33175. }) */
  33176. this.dispatchEvent({
  33177. type: 'endChangeMode',
  33178. mode
  33179. });
  33180. console.log('setModeSuccess: ' + mode);
  33181. } else {
  33182. changeTileDownload();
  33183. //this.dispatchEvent({type:'endChangeMode',mode})
  33184. }
  33185. }
  33186. });
  33187. Potree.settings.displayMode = 'showPointCloud';
  33188. } // 切换模式 end
  33189. {
  33190. var showHotTemp = null; //火调温度 /* --目前仅需点云模式 */
  33191. Object.defineProperty(Potree.settings, "showHotTemp", {
  33192. get: function get() {
  33193. return showHotTemp;
  33194. },
  33195. set: show => {
  33196. if (showHotTemp == show) return;
  33197. showHotTemp = show;
  33198. viewer.switchHotType();
  33199. var pano = this.currentPano;
  33200. if (Potree.settings.displayMode == 'showPanos' && pano.has_temp) {
  33201. var change = () => {
  33202. this.cube.material.updateTempEnable();
  33203. };
  33204. if (show && !pano.tempTex) {
  33205. pano.loadTypeImg('temp');
  33206. pano.addEventListener('loaded_temp', change, {
  33207. once: true
  33208. });
  33209. } else {
  33210. change();
  33211. }
  33212. }
  33213. }
  33214. });
  33215. }
  33216. {
  33217. //优先级最低
  33218. var showHotIr = null;
  33219. Object.defineProperty(Potree.settings, "showHotIr", {
  33220. get: function get() {
  33221. return showHotIr;
  33222. },
  33223. set: show => {
  33224. if (showHotIr == show) return;
  33225. showHotIr = show;
  33226. viewer.switchHotType();
  33227. var pano = this.currentPano;
  33228. if (Potree.settings.displayMode == 'showPanos' && pano.has_ir) {
  33229. var change = () => {
  33230. this.cube.material.updateTempEnable();
  33231. };
  33232. if (show && !pano.irTex) {
  33233. pano.loadTypeImg('ir');
  33234. pano.addEventListener('loaded_ir', change, {
  33235. once: true
  33236. });
  33237. } else {
  33238. change();
  33239. }
  33240. }
  33241. }
  33242. });
  33243. }
  33244. {
  33245. //优先级最高
  33246. var showClass = null;
  33247. Object.defineProperty(Potree.settings, "showClass", {
  33248. get: function get() {
  33249. return showClass;
  33250. },
  33251. set: show => {
  33252. if (showClass == show) return;
  33253. showClass = show;
  33254. var pano = this.currentPano;
  33255. viewer.scene.pointclouds.forEach(e => e.updateAttrAuto());
  33256. if (Potree.settings.displayMode == 'showPanos' && pano.has_seg) {
  33257. var change = () => {
  33258. this.cube.material.updateClassEnable();
  33259. };
  33260. if (show && !pano.segTex) {
  33261. pano.loadTypeImg('seg');
  33262. pano.addEventListener('loaded_seg', change, {
  33263. once: true
  33264. });
  33265. } else {
  33266. change();
  33267. }
  33268. }
  33269. }
  33270. });
  33271. }
  33272. {
  33273. //
  33274. var currentPano = null;
  33275. Object.defineProperty(this, "currentPano", {
  33276. get: function get() {
  33277. return currentPano;
  33278. },
  33279. set: function set(e) {
  33280. if (e != currentPano) {
  33281. //console.log('set currentPano ', e.id)
  33282. currentPano && currentPano.exit();
  33283. e && e.enter();
  33284. currentPano = e;
  33285. }
  33286. }
  33287. });
  33288. }
  33289. {
  33290. //是否显示marker
  33291. var ifShowMarker = true;
  33292. Object.defineProperty(Potree.settings, "ifShowMarker", {
  33293. get: function get() {
  33294. return ifShowMarker;
  33295. },
  33296. set: show => {
  33297. show = !!show;
  33298. if (show != ifShowMarker) {
  33299. this.panos.forEach(pano => {
  33300. Potree.Utils.updateVisible(pano, 'ifShowMarker', show, 1);
  33301. });
  33302. //this.emit('markersDisplayChange', show)
  33303. ifShowMarker = show;
  33304. viewer.dispatchEvent('showMarkerChanged');
  33305. viewer.dispatchEvent('content_changed');
  33306. }
  33307. }
  33308. });
  33309. }
  33310. viewer.addEventListener("update", () => {
  33311. this.update(viewer);
  33312. });
  33313. //viewer.inputHandler.addInputListener(this);
  33314. var keys = {
  33315. FORWARD: ['W'.charCodeAt(0), 38],
  33316. BACKWARD: ['S'.charCodeAt(0), 40],
  33317. LEFT: ['A'.charCodeAt(0), 37],
  33318. RIGHT: ['D'.charCodeAt(0), 39]
  33319. };
  33320. viewer.inputHandler.addEventListener('keydown', e => {
  33321. if (Potree.settings.displayMode == 'showPanos') {
  33322. for (var i in keys) {
  33323. if (keys[i].some(a => a == e.keyCode)) {
  33324. switch (i) {
  33325. case 'FORWARD':
  33326. this.flyLocalDirection(Vectors$1.FORWARD.clone());
  33327. break;
  33328. case 'BACKWARD':
  33329. this.flyLocalDirection(Vectors$1.BACK.clone());
  33330. break;
  33331. case 'LEFT':
  33332. this.flyLocalDirection(Vectors$1.LEFT.clone());
  33333. break;
  33334. case 'RIGHT':
  33335. this.flyLocalDirection(Vectors$1.RIGHT.clone());
  33336. break;
  33337. }
  33338. break;
  33339. }
  33340. }
  33341. }
  33342. });
  33343. }
  33344. changeModelMat(model /* , isCurModel */) {
  33345. if (model !== null && model !== void 0 && model.is4dkkModel) {
  33346. if (model.fileType == '3dTiles') {
  33347. viewer.setAllTilesets(model, child => {
  33348. child.runtime.limit2lowestDepth(Potree.settings.displayMode == 'showPanos');
  33349. child.runtime.getTileset().tiles.forEach(e => {
  33350. this.judgeModelMat(e.tileContent /* , isCurModel */);
  33351. });
  33352. });
  33353. } else {
  33354. this.judgeModelMat(model /* , isCurModel */);
  33355. }
  33356. }
  33357. }
  33358. judgeModelMat(object /* , isCurModel */) {
  33359. if (!(Potree.settings.mergeType2 && Potree.settings.modelSkybox)) return;
  33360. object.traverse(mesh => {
  33361. if (mesh.external) return {
  33362. stopContinue: true
  33363. };
  33364. if (mesh.material) {
  33365. if (!mesh.materialOutside) {
  33366. mesh.materialOutside = mesh.material;
  33367. }
  33368. //mesh.material = Potree.settings.displayMode == 'showPanos' && (this.nextPano?.pointcloud == object || this.currentPano.pointcloud == object || isCurModel) ? this.materialInside : mesh.materialOutside
  33369. mesh.material = Potree.settings.displayMode == 'showPanos' ? this.materialInside : mesh.materialOutside;
  33370. Potree.Utils.setObjectLayers(mesh, Potree.settings.displayMode == 'showPanos' ? 'skybox' : 'model'); //为了渲染到rtEDL
  33371. }
  33372. });
  33373. }
  33374. updateDepthTex(pano) {
  33375. if (this.currentPano != pano || !pano.depthTex) return;
  33376. //this.depthSampler.changeImg(pano.depthTex.image); //pick sampler要飞到了才能切换图,而skybox贴图是随着全景图切换而切换的
  33377. this.cube.material.updateDepthTex(pano); //确保一下
  33378. }
  33379. findNearestPano(pos) {
  33380. var panos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.panos;
  33381. pos = pos ? new Vector3().copy(pos) : this.position;
  33382. var result = Common$1.sortByScore(panos, [Images360.filters.isEnabled()], [e => -e.position.distanceTo(pos) / e.pointcloud.scale.x]);
  33383. var pano = result[0] && result[0].item;
  33384. return pano;
  33385. }
  33386. /* set flying(v){//正在飞向pano
  33387. this.flying_ = !!v
  33388. //console.log('this.flying_ ', !!v )
  33389. //this.emit('flying', this.flying_)
  33390. let config = Potree.config.displayMode[Potree.settings.displayMode]
  33391. viewer.mainViewport.unableChangePos = !config.canLeavePano || !!v
  33392. }
  33393. get flying(){
  33394. return this.flying_
  33395. } */
  33396. flyLocalDirection(dir) {
  33397. var direction = this.getDirection(dir),
  33398. option1 = 1 === dir.y ? .4 : .75,
  33399. option2 = 1 === Math.abs(dir.x);
  33400. return this.flyDirection(direction, option1, option2, true);
  33401. }
  33402. getDirection(e) {
  33403. if (!e) {
  33404. return viewer.scene.view.direction;
  33405. } else {
  33406. return e = e ? e : new Vector3().copy(Vectors$1.FORWARD), e.applyQuaternion(viewer.mainViewport.camera.quaternion);
  33407. }
  33408. }
  33409. get position() {
  33410. return this.viewer.scene.view.position.clone();
  33411. }
  33412. isAtPano() {
  33413. var precision = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1e-6;
  33414. //是否在某个漫游点上
  33415. if (precision) {
  33416. return this.currentPano && math.closeTo(viewer.scene.view.position, this.currentPano.position, precision);
  33417. }
  33418. return this.currentPano && viewer.scene.view.position.equals(this.currentPano.position);
  33419. }
  33420. updateProjectedPanos() {
  33421. //更新材质贴图
  33422. //console.warn('updateProjectedPanos')
  33423. this.projectedPano0 && this.projectedPano1 && this.setProjectedPanos({
  33424. pano0: this.projectedPano0,
  33425. pano1: this.projectedPano1
  33426. });
  33427. }
  33428. setProjectedPanos() {
  33429. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  33430. //设置cube和点云的材质贴图
  33431. this.cube.material.setProjectedPanos(o.pano0, o.pano1, o.progress);
  33432. this.materialInside && this.materialInside.setProjectedPanos(o.pano0, o.pano1, o.progress);
  33433. if (o.ifPointcloud) {
  33434. viewer.scene.pointclouds.forEach(e => {
  33435. e.material.setProjectedPanos(o.pano0, o.pano1, o.progress, o.easeInOutRatio);
  33436. });
  33437. }
  33438. //console.warn('setProjectedPanos ', o.pano0.id , o.pano1.id)
  33439. this.projectedPano0 = o.pano0;
  33440. this.projectedPano1 = o.pano1;
  33441. }
  33442. get latestToPano() {
  33443. return this._latestToPano;
  33444. }
  33445. set latestToPano(toPano) {
  33446. this._latestToPano = toPano;
  33447. //console.warn('latestToPano',toPano)
  33448. }
  33449. cancelFlyToPano(toPano) {
  33450. //取消当前已有的飞行准备,前提是相机还未移动 //2024.11.13删除isFlying的判断,因为在done中延时1之后居然isFlying有概率还是true bugID=47743
  33451. if ( /* viewer.mainViewport.view.isFlying() || */toPano && this.latestToPano != toPano) {
  33452. return;
  33453. }
  33454. //Potree.Log('cancelFlyToPano', this.latestToPano && this.latestToPano.pano.id)
  33455. this.nextPano = null;
  33456. this.latestToPano = null;
  33457. }
  33458. flyToPano(toPano) {
  33459. //飞向漫游点
  33460. if (!toPano) return;
  33461. if (typeof toPano == 'number') toPano = this.panos[toPano];
  33462. if (toPano instanceof Panorama) {
  33463. toPano = {
  33464. pano: toPano
  33465. };
  33466. }
  33467. var done = (makeIt, disturb) => {
  33468. //console.log('flyToPano done ', toPano.pano.id, makeIt, disturb )
  33469. if (makeIt || disturb) {
  33470. // disturb已经开始飞行但中途取消
  33471. toPano.callback && toPano.callback(makeIt);
  33472. //this.flying = false
  33473. this.cancelFlyToPano(toPano);
  33474. this.updateClosestPano(this.closestPano, false); //飞行结束后取消点击漫游点时得到的closestPano
  33475. } else {
  33476. if (toPano.retryUntilArrive) {
  33477. //一直试直到可以飞成功
  33478. //console.log('wait for reFly to pano ', toPano.pano.id)
  33479. var retry = e => {
  33480. //重飞
  33481. if (e.makeIt) {
  33482. this.removeEventListener('flyToPanoDone', retry);
  33483. //console.log('reFly to pano ', toPano.pano.id)
  33484. this.flyToPano(toPano);
  33485. }
  33486. };
  33487. this.addEventListener('flyToPanoDone', retry);
  33488. }
  33489. }
  33490. this.dispatchEvent({
  33491. type: 'flyToPanoDone',
  33492. makeIt,
  33493. disturb
  33494. });
  33495. this.fastTranMaskPass.stop();
  33496. toPano.deferred && toPano.deferred.resolve(makeIt); //测量线截图时发现,resolve需要写在flying=false 后才行。
  33497. };
  33498. if (!toPano.pano.enabled) return done(false, true);
  33499. //Potree.Log('hope flyToPano: '+toPano.pano.id/* , toPano.pano.position.toArray() */)
  33500. if (!toPano.canCancelLast && this.latestToPano && this.latestToPano != toPano && (
  33501. //还在飞
  33502. this.latestToPano.pano != this.currentPano || !this.isAtPano())) {
  33503. //如果旧的toPano只在pano旋转镜头,就直接取消旧的,继续执行
  33504. //console.log('还在飞', this.latestToPano.pano.id)
  33505. return done(false);
  33506. }
  33507. if (this.currentPano == toPano.pano && this.isAtPano() && !toPano.target && !toPano.quaternion) {
  33508. //已在该pano
  33509. //console.log('已在该pano', this.currentPano.id)
  33510. this.dispatchEvent({
  33511. type: 'flyToPano',
  33512. toPano
  33513. });
  33514. return done(true);
  33515. }
  33516. //Potree.Log('flyToPano: '+toPano.pano.id /*, toPano.pano.position.toArray() this.latestToPano && this.latestToPano.pano.id */ )
  33517. var target = toPano.target;
  33518. var config = Potree.config.displayMode[Potree.settings.displayMode];
  33519. var pano = toPano.pano;
  33520. var dis = pano.position.distanceTo(this.position);
  33521. this.nextPano = pano;
  33522. this.latestToPano = toPano;
  33523. //this.flying = true //防止新的请求
  33524. //Potree.Log('flyToPano:'+pano.id + ' , duration:'+toPano.duration, null, 12)
  33525. {
  33526. //不飞的话是否不要执行这段?
  33527. var wait = e => {
  33528. //console.log('wait done', pano.id)
  33529. if ( /* e.pano && */this.latestToPano && pano != this.latestToPano.pano) return; //loadedDepthImg
  33530. if (this.latestToPano != toPano) return Potree.Log('已经取消', pano.id); //如果取消了
  33531. setTimeout(() => {
  33532. if (this.latestToPano != toPano) return;
  33533. this.flyToPano(toPano);
  33534. }, 1);
  33535. };
  33536. if (!pano.depthTex && pano.pointcloud.hasDepthTex) {
  33537. //点云模式也要加载depthTex,因获取neighbour需要用到
  33538. console.log('等待加载depthtex', pano.id);
  33539. pano.addEventListener('loadedDepthImg', wait, {
  33540. once: true
  33541. });
  33542. return pano.loadDepthImg();
  33543. }
  33544. if (config.atPano.showSkybox || config.atPano.pointUsePanoTex) {
  33545. var types = {
  33546. 'seg': 'showClass',
  33547. 'ir': 'showHotIr',
  33548. 'temp': 'showHotTemp'
  33549. };
  33550. for (var type in types) {
  33551. if (Potree.settings[types[type]] && pano['has_' + type] && !pano[type + 'Tex']) {
  33552. pano.loadTypeImg(type);
  33553. return pano.addEventListener('loaded_' + type, wait, {
  33554. once: true
  33555. });
  33556. }
  33557. }
  33558. var a = this.updateCube(this.currentPano, toPano.pano);
  33559. if (a == 'useBound') {
  33560. toPano.useBound = true;
  33561. }
  33562. if (this.checkAndWaitForPanoLoad(pano, toPano.basePanoSize || this.basePanoSize, wait)) {
  33563. return;
  33564. }
  33565. }
  33566. }
  33567. config = Potree.config.displayMode[Potree.settings.displayMode]; //可能换了
  33568. var pointcloudVisi = config.atPano.showPoint; //viewer.scene.pointclouds[0].visible
  33569. Potree.Utils.updateVisible(this.cube, 'showSkybox', config.atPano.showSkybox); // this.cube.visible = config.atPano.showSkybox
  33570. //console.log('开始飞1')
  33571. if (config.transition.showPoint) {
  33572. viewer.scene.pointclouds.forEach(e => {
  33573. Potree.Utils.updateVisible(e, 'displayMode', true);
  33574. });
  33575. }
  33576. var endPosition = pano.position.clone();
  33577. var T = Potree.config.transitionsTime;
  33578. var maxDis = 7;
  33579. var duration = toPano.duration == void 0 ? Math.min(dis, maxDis) * T.flytimeDistanceMultiplier + T.flyMinTime : toPano.duration;
  33580. if (config.transition.showSkybox || config.transition.pointUsePanoTex) {
  33581. if (Potree.settings.fastTran) {
  33582. this.fastTranMaskPass.start(); //截图当前画面
  33583. viewer.scene.view.position.copy(endPosition);
  33584. }
  33585. this.setProjectedPanos({
  33586. progress: 0,
  33587. ifSkybox: this.cube.visible,
  33588. ifPointcloud: config.transition.pointUsePanoTex,
  33589. easeInOutRatio: pointcloudVisi ? 0.3 : 0,
  33590. pano0: this.currentPano,
  33591. pano1: pano
  33592. });
  33593. }
  33594. if (toPano.useBound) {
  33595. duration = Math.min(1500, duration);
  33596. toPano.easeName = 'easeInOutQuad';
  33597. } else {
  33598. if (endPosition.equals(this.position)) toPano.easeName = 'easeOutSine';
  33599. }
  33600. {
  33601. toPano.easeName = toPano.easeName || 'linearTween';
  33602. toPano.duration = duration;
  33603. this.beforeFlyToPano(toPano);
  33604. }
  33605. /* let fly = ()=>{
  33606. this.dispatchEvent({type:'flyToPano', toPano})
  33607. viewer.scene.view.setView({position:endPosition, target, quaternion:toPano.quaternion , duration,
  33608. callback:()=>{
  33609. if(!config.atPano.pointUsePanoTex){
  33610. viewer.scene.pointclouds.forEach(e=>{
  33611. e.material.stopProjectedPanos()
  33612. })
  33613. }
  33614. this.currentPano = pano;
  33615. this.nextPano = null;
  33616. if(Potree.settings.displayMode == 'showPanos'){
  33617. viewer.scene.pointclouds.forEach(e=>{
  33618. Potree.Utils.updateVisible(e, 'displayMode',pointcloudVisi)
  33619. })
  33620. }
  33621. done(true);
  33622. this.updateDepthTex(this.currentPano)
  33623. }, onUpdate:(progress)=>{
  33624. //console.log('uniforms progress',progress)
  33625. this.cube.material.uniforms.progress.value = progress
  33626. viewer.scene.pointclouds.forEach(e=>{
  33627. e.material.uniforms.progress.value = progress
  33628. })
  33629. },
  33630. cancelFun:()=>{ done(false, true) },
  33631. Easing:easeName
  33632. })
  33633. //duration > 0 && (this.flying = true) //再写一遍 防止cancel其他项目导致flying为false
  33634. } */
  33635. var _onUpdate = progress => {
  33636. this.cube.material.uniforms.progress.value = progress;
  33637. this.materialInside && (this.materialInside.uniforms.progress.value = progress);
  33638. viewer.scene.pointclouds.forEach(e => {
  33639. e.material.uniforms.progress.value = progress;
  33640. });
  33641. };
  33642. var fly = () => {
  33643. var startProgress = toPano.progress = toPano.progress || 0;
  33644. var loadNextProgress = MathUtils.clamp(1 - 2.5 / dis, 0.3, 0.8);
  33645. //console.log(loadNextProgress, (1-loadNextProgress) * dis )
  33646. this.dispatchEvent({
  33647. type: 'flyToPano',
  33648. toPano
  33649. });
  33650. viewer.scene.view.setView({
  33651. position: endPosition,
  33652. target,
  33653. quaternion: toPano.quaternion,
  33654. duration: toPano.duration,
  33655. onUpdate: (progress_, delta) => {
  33656. var progress = startProgress + progress_ * (1 - startProgress);
  33657. var currentSpeed;
  33658. if (progress_ != 1 && progress_ != 0) {
  33659. // 1的时候不准,往往偏小, 0的时候速度为0,也不记录
  33660. currentSpeed = (progress - toPano.progress) * dis / delta; //记录下当前速度,当变为匀速时可以过渡到flySpeed
  33661. } else {
  33662. currentSpeed = toPano.currentSpeed || 0;
  33663. }
  33664. toPano.currentSpeed = currentSpeed;
  33665. toPano.progress = progress;
  33666. //console.log('progress_', progress_, 'delta',delta , 'progress', progress/*, 'currentSpeed', currentSpeed, */ )
  33667. if (progress > loadNextProgress && toPano.easeName == 'linearTween' && currentSpeed) {
  33668. // 减速. 如果仅旋转就不停止
  33669. //console.log('减速', /* currentSpeed , */progress_ )
  33670. toPano.easeName = 'easeOutSine';
  33671. var restDis = (1 - progress) * dis;
  33672. toPano.duration = Math.PI / 2 * restDis / currentSpeed; // 这样能保证初始速度为currentSpeed
  33673. viewer.scene.view.cancelFlying('all', false); //为了防止执行cancelFun先主动cancel
  33674. toPano.flyCount = 2;
  33675. fly(toPano);
  33676. }
  33677. _onUpdate(progress);
  33678. },
  33679. callback: () => {
  33680. if (!config.atPano.pointUsePanoTex) {
  33681. viewer.scene.pointclouds.forEach(e => {
  33682. e.material.stopProjectedPanos();
  33683. });
  33684. }
  33685. this.lastPano = this.currentPano; //记录,调试
  33686. this.currentPano = pano;
  33687. this.nextPano = null;
  33688. if (Potree.settings.displayMode == 'showPanos') {
  33689. viewer.scene.pointclouds.forEach(e => {
  33690. Potree.Utils.updateVisible(e, 'displayMode', pointcloudVisi);
  33691. });
  33692. }
  33693. done(true);
  33694. this.updateDepthTex(this.currentPano); //删除dispose的depthTex
  33695. },
  33696. cancelFun: () => {
  33697. done(false, true);
  33698. },
  33699. Easing: toPano.easeName,
  33700. ignoreFirstFrame: toPano.flyCount != 2 //变换transition时不停一帧
  33701. });
  33702. };
  33703. if (Potree.settings.displayMode == 'showPanos') {
  33704. setTimeout(fly, 40); //更新geo后缓冲
  33705. } else {
  33706. fly();
  33707. }
  33708. //console.log('flyToPano:', toPano.pano.id)
  33709. }
  33710. beforeFlyToPano(toPano) {
  33711. if (this.currentPano != toPano.pano) {
  33712. if (Potree.settings.displayMode == 'showPanos') {
  33713. this.resetHighMap();
  33714. }
  33715. this.smoothZoomTo(toPano.zoomLevel || 1, toPano.duration / 2);
  33716. }
  33717. }
  33718. /* updateCube(pano0, pano1){
  33719. if(Potree.settings.displayMode != 'showPanos')return
  33720. if(!viewer.scene.pointclouds.some(e=>!e.hasDepthTex)) return this.updateCube2(pano0, pano1) //都hasDepthTex的话
  33721. let useBound = (bound, size)=>{
  33722. size = size || bound.getSize(new THREE.Vector3)
  33723. let center = bound.getCenter(new THREE.Vector3)
  33724. size.max(new THREE.Vector3(HighMapCubeWidth,HighMapCubeWidth,HighMapCubeWidth))
  33725. this.cube.scale.copy(size)
  33726. this.cube.position.copy(center)
  33727. }
  33728. let getPanoBound = (pano)=>{//因漫游点可能在点云外部,如室外平地,所以需要union进漫游点
  33729. let panoBound = new THREE.Box3
  33730. panoBound.expandByPoint(pano.position)
  33731. panoBound.expandByVector(new THREE.Vector3(10,10,10));//give pano a margin
  33732. return pano.pointcloud.bound.clone().union(panoBound)
  33733. }
  33734. let getDis = (bound1, bound2)=>{ //获取bound1边界到bound2边界距离
  33735. if(bound1.intersectsBox(bound2))return 0
  33736. let center1 = bound1.getCenter(new THREE.Vector3)
  33737. let center2 = bound2.getCenter(new THREE.Vector3)
  33738. let dis = center1.distanceTo(center2)
  33739. let dis1 = bound1.distanceToPoint(center2)
  33740. let dis2 = bound2.distanceToPoint(center1)
  33741. return dis1 + dis2 - dis
  33742. }
  33743. if(pano1){//过渡
  33744. if(pano0.pointcloud == pano1.pointcloud){//同一个数据集内的过渡
  33745. useBound(getPanoBound(pano0))
  33746. }else{//非同一个数据集内的过渡
  33747. let bound = getPanoBound(pano0).union(getPanoBound(pano1))
  33748. if(getDis(pano0.pointcloud.bound, pano1.pointcloud.bound) < 100){
  33749. useBound(bound)
  33750. }else{//如果两个数据集boundingbox距离大于这个距离,扩大一下,防止精度问题导致失真//对很远的数据集似乎没有什么用
  33751. let size = bound.getSize(new THREE.Vector3)
  33752. let max = Math.max(size.x, size.y, size.z)
  33753. size.set(max,max,max)
  33754. useBound(pano0.pointcloud.bound.clone().union(pano1.pointcloud.bound), size)
  33755. }
  33756. }
  33757. }else{
  33758. useBound(getPanoBound(pano0)) //假定一个数据集不会太大,否则会造成失真,且bump时移动距离看起来很小。或者可以考虑用固定大小
  33759. }
  33760. } */
  33761. getIntersect(pano, dir, origin) {
  33762. if (pano && pano.pointcloud.hasDepthTex) {
  33763. return this.depthSampler.sample({
  33764. dir
  33765. }, pano, true);
  33766. } else {
  33767. origin = origin || pano.position;
  33768. return viewer.inputHandler.getIntersect({
  33769. viewport: viewer.inputHandler.hoverViewport,
  33770. onlyGetIntersect: true,
  33771. usePointcloud: true,
  33772. point: origin.clone().add(dir),
  33773. cameraPos: origin
  33774. });
  33775. }
  33776. }
  33777. /* updateCube(pano0, pano1){//增加细分的版本,且垂直方向上也分多个
  33778. if(Potree.settings.displayMode != 'showPanos')return
  33779. console.log('updateCube',pano0.id, pano1&&pano1.id)
  33780. let f = (bound, size)=>{
  33781. size = size || bound.getSize(new THREE.Vector3)
  33782. let center = bound.getCenter(new THREE.Vector3)
  33783. size.max(new THREE.Vector3(HighMapCubeWidth,HighMapCubeWidth,HighMapCubeWidth))
  33784. this.cube.scale.copy(size)
  33785. this.cube.position.copy(center)
  33786. }
  33787. this.cube.geometry.dispose();
  33788. if(pano1){//过渡
  33789. let count1, count2;
  33790. let panoIndex = 0
  33791. let add = (pano, dir )=>{
  33792. let getPI = function(index, panoIndex_){
  33793. if(panoIndex_ == void 0) panoIndex_ = panoIndex
  33794. return (count1 * count2 + 2 ) * panoIndex_ + index + 2
  33795. }
  33796. let minZ, maxZ
  33797. minZ = pano.floorPosition.z
  33798. {//天花板高度值
  33799. //用三个间隔120度散开,和中心垂直线成一定夹角的三个向量去求 最高高度 (不求平均的原因:万一是0不好算)
  33800. let rotMat = new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(40))// 角度不能小于天花板中空的半径,大概就是0.2*Math.PI=36度
  33801. let dir1 = new THREE.Vector3(0,0,1).applyMatrix4(rotMat)
  33802. let rotMat1 = new THREE.Matrix4().makeRotationZ(Math.PI*2 / 3);
  33803. let rotMat2 = new THREE.Matrix4().makeRotationZ(-Math.PI*2 / 3);
  33804. let dir2 = dir1.clone().applyMatrix4(rotMat1)
  33805. let dir3 = dir1.clone().applyMatrix4(rotMat2)
  33806. let zs = [dir1,dir2,dir3].map(dir_=>{
  33807. let intersect = this.depthSampler.sample( {dir: dir_}, pano, true )
  33808. let z = intersect ? intersect.location.z : pano.position.z
  33809. return z
  33810. })
  33811. zs.sort((a,b)=>{return b-a});//得最大值
  33812. maxZ = zs[0]
  33813. let min = pano.position.z + 1
  33814. if(maxZ < pano.position.z + 0.04){//户外
  33815. maxZ = pano.position.z + 50
  33816. }
  33817. maxZ = Math.max(min,maxZ)
  33818. console.log(pano.id, 'maxZ:',maxZ )
  33819. console.log(pano.id, 'minZ:',minZ )
  33820. }
  33821. [maxZ, minZ ].forEach(z=>{
  33822. posArr.push(pano.position.clone().setZ(z))
  33823. })
  33824. const angle = Math.PI/8
  33825. let getDir = (angle_)=>{
  33826. let rotMat = new THREE.Matrix4().makeRotationZ(angle_)
  33827. return dir.clone().applyMatrix4(rotMat)
  33828. }
  33829. let dirs = [ getDir(angle*4), getDir(angle*3), getDir(angle*2), getDir(angle), dir.clone(), getDir(-angle) , getDir(-angle*2), getDir(-angle*3), getDir(-angle*4) ]; // 夹角总和180度
  33830. count1 = dirs.length
  33831. dirs.forEach((dir, index)=>{//获取在这个方向上和墙体intersect的最远距离,使用中、上、下三个方向
  33832. let dirs_ = [
  33833. dir.clone().setZ(Math.tan(THREE.Math.degToRad(30))).normalize(),
  33834. dir.clone().setZ(Math.tan(THREE.Math.degToRad(15))).normalize(),
  33835. dir.clone(), // 水平方向
  33836. dir.clone().setZ(-Math.tan(THREE.Math.degToRad(15))).normalize(),
  33837. dir.clone().setZ(-Math.tan(THREE.Math.degToRad(30))).normalize(),
  33838. ];
  33839. count2 = dirs_.length
  33840. dirs_.forEach((dir_, i) =>{
  33841. let intersect = this.depthSampler.sample( {dir: dir_}, pano, true )
  33842. let location
  33843. if(!intersect){ //超级远
  33844. let distance = 100
  33845. location = dir_.clone().multiplyScalar(distance).add(pano.position)
  33846. intersect = {distance,location}
  33847. }
  33848. //intersect.distance
  33849. location = intersect.location.clone()
  33850. let shouldZ// = THREE.Math.clamp(intersect.location.z, minZ, maxZ);
  33851. let needShrink = false
  33852. if(i == 0){//最上方的点高度直接等于天花板
  33853. shouldZ = maxZ
  33854. if(location.z<maxZ)location.z = maxZ
  33855. else needShrink = true
  33856. }else if(i == count2-1){//最下方的点高度直接等于地板
  33857. shouldZ = minZ
  33858. if(location.z>minZ)location.z = minZ
  33859. else needShrink = true
  33860. }
  33861. if(needShrink ){//需要在保持dir_不变的情况下修改z
  33862. let len = (shouldZ - pano.position.z) / (intersect.location.z - pano.position.z) * intersect.distance
  33863. location = dir_.clone().multiplyScalar(len).add(pano.position)
  33864. }
  33865. posArr.push(location)
  33866. if(index!=0 && i!=0){//加入一块四方面
  33867. let curIndex = getPI(count2 * index + i);
  33868. faceArr.push([curIndex-1, curIndex-count2-1, curIndex-count2],
  33869. [curIndex-1, curIndex, curIndex-count2])
  33870. }
  33871. })
  33872. if(index!=0){
  33873. let top = -2;
  33874. let btm = -1
  33875. faceArr.push([getPI(count2*(index-1) ), getPI(count2*index ), getPI(top) ])//天花板扇形
  33876. faceArr.push([getPI(count2*index-1), getPI(count2*(index+1)-1), getPI(btm) ] )//地板扇形
  33877. }else{
  33878. //加入和另一个pano连接的其中一个侧边
  33879. let panoIndex2 = (panoIndex + 1) % 2;
  33880. for(let i=1;i<count2;i++){
  33881. faceArr.push([getPI(i-1), getPI(i), getPI((count1-1)*count2 +i, panoIndex2)],
  33882. [getPI(i-1), getPI((count1-1)*count2+i , panoIndex2) , getPI((count1-1)*count2+i-1 ,panoIndex2)])
  33883. }
  33884. faceArr.push([getPI(0), getPI((count1-1)*count2), getPI(0, panoIndex2)])//加入顶部的一半
  33885. faceArr.push([getPI(count2-1), getPI(count1*count2-1), getPI(count2-1, panoIndex2)])//加入底部的一半
  33886. }
  33887. });
  33888. panoIndex ++
  33889. }
  33890. let posArr = [];
  33891. let faceArr = []
  33892. //两点连线的水平向量
  33893. let vec = new THREE.Vector3().subVectors(pano0.position, pano1.position).setZ(0).normalize()
  33894. add(pano0, vec)
  33895. add(pano1, vec.negate())
  33896. let geo = MeshDraw.createGeometry(posArr, faceArr)
  33897. this.cube.geometry = geo
  33898. this.cube.scale.set(1,1,1);
  33899. this.cube.position.set(0,0,0)
  33900. }else{
  33901. this.cube.geometry = new THREE.BoxBufferGeometry(1,1,1,1)
  33902. f(pano0.pointcloud.bound)
  33903. }
  33904. } */
  33905. isNeighbour(pano0, pano1) {
  33906. var {
  33907. dontCompute,
  33908. onlyUseTex,
  33909. computeDirFirst,
  33910. computeTwoDir
  33911. } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  33912. //是否之间没有遮挡(在加载visibles之前,自己算) 最好pano0是currentPano
  33913. if (!pano0 || !pano1) return;
  33914. if (!Potree.settings.editType && !viewer.scene.pointclouds.some(e => e.hasDepthTex) || Potree.settings.editType == 'pano') return true; //点云编辑页设置exist true但不恢复的话,得不到depthTex。 则Neighbours很难算。所以现在先全部可走。
  33915. if (Potree.settings.editType == 'merge' && pano0.pointcloud != pano1.pointcloud) return true;
  33916. var margin = 0.1;
  33917. var map0 = this.neighbourMap[pano0.id]; //主
  33918. var map1 = this.neighbourMap[pano1.id]; //副
  33919. /* if(map0[pano1.id] != void 0){
  33920. ifNeighbour = map0[pano1.id]
  33921. }
  33922. if(!ifNeighbour && map1[pano0.id] != void 0){
  33923. ifNeighbour = map1[pano0.id]
  33924. } */
  33925. var ifNeighbour = map1[pano0.id] == void 0 ? map0[pano1.id] : map0[pano1.id] && map1[pano0.id]; //如果map1没计算就只要返回map0
  33926. var dis = pano0.position.distanceTo(pano1.position);
  33927. if (math.closeTo(dis, 0)) {
  33928. //两个点相同
  33929. ifNeighbour = map1[pano0.id] = map0[pano1.id] = true;
  33930. return true;
  33931. }
  33932. if (dontCompute) return ifNeighbour;
  33933. var logSids = [/* '1566756240057044992|4','1566756240057044992|5' */];
  33934. var ifLog = pano0.sid == logSids[0] && pano1.sid == logSids[1] || pano0.sid == logSids[1] && pano1.sid == logSids[0];
  33935. if (ifLog) {
  33936. console.log(2);
  33937. }
  33938. var ifSheltered = (mainPano, subPano) => {
  33939. //该点前方近处是否都被遮挡 。 为了防止杂点干扰,多个方向探测
  33940. var vec = new Vector3().subVectors(subPano.position, mainPano.position).normalize();
  33941. var getDir = (angle_, upDown) => {
  33942. //基于vec的方向 向左向右旋转
  33943. //if(upDown) vec.clone().applyAxisAngle(new THREE.Vector3(1, 0, 0), upDown);
  33944. return vec.clone().applyAxisAngle(new Vector3(0, 0, 1), angle_);
  33945. };
  33946. var minScore = 0.25;
  33947. var angles = [20, 16, 12.5, 10, 8, 6, 4.5, 3, 1, -1, -3, -4.5, -6, -8, -10, -12.5, -16, -20]; //水平方向角度 3之间有较大概率杂点, 3以外一部分有较大概率有空隙所以紧凑点
  33948. var wellCount = 0;
  33949. var seccess = [];
  33950. for (var i = 0; i < angles.length; i++) {
  33951. var rad = MathUtils.degToRad(angles[i]);
  33952. var dir = getDir(rad);
  33953. var color = void 0;
  33954. var intersectPoint = viewer.images360.depthSampler.sample({
  33955. dir
  33956. }, mainPano, true);
  33957. if (!intersectPoint || intersectPoint.distance * Math.cos(Math.abs(rad)) /* + margin */ > dis) {
  33958. //投影在vec方向的长度不超过漫游点间距
  33959. wellCount++;
  33960. seccess.push(angles[i]);
  33961. color = new Color('#0f8');
  33962. }
  33963. ifLog && addLine(mainPano.position, dir, dis, color);
  33964. }
  33965. //console.log('ifSheltered')
  33966. if (ifLog) {
  33967. console.log('ifSheltered seccess', seccess, 'id:', mainPano.originID, subPano.originID);
  33968. }
  33969. var score = wellCount / angles.length;
  33970. if (score >= minScore) {
  33971. //合格个数
  33972. return score;
  33973. }
  33974. };
  33975. /*
  33976. 识别一定角度范围内是否有遮挡时
  33977. 几种奇葩的情况:
  33978. 1 在墙的两边的但是墙是倾斜的漫游点:
  33979. A /
  33980. /
  33981. / B
  33982. 从B出发和BA成20度的射线和墙面的交点会远于A,导致识别为无遮挡。
  33983. 所以还是改为识别范围内多个深度图像素, 合格像素个数占比 至少要大于50%,因为半边墙壁是50%
  33984. 如SG-9UsbysDufBw&formal&test 的 6、9点。 而SS-GTmFBp1JN8k&formal&test的 2、3两点是人物遮挡
  33985. 2 可以通行,但是右边是墙,右边的都检测失败,左侧的又有一些杂点,导致成功dir个数很低。
  33986. 所以minRatio 要降低于0.5
  33987. */
  33988. //三个方向 : position0到position1, position0到floorPosition1, position1到floorPosition0。 只要有一个满足ifNeighbour就为true。 不过为了不使sampler总换图,先只考虑从主pano到副pano的方向
  33989. var getNeighbour = (mainPano, subPano) => {
  33990. var dirPoints = [[subPano.position, mainPano.position]]; //注: 点A能到B不代表点B能到A,因为拍摄时物体会移动,或点位相对位置不对,无论是否是意外遮挡都且记下来,反正最后只要有一方可行就算相邻。
  33991. if (new Vector2().subVectors(subPano.position, mainPano.position).length() > 1e-4) {
  33992. //xy都不同
  33993. if (dis < 25) {
  33994. //在远处去掉对floorPosition的判断
  33995. dirPoints.push([subPano.floorPosition.clone().add(new Vector3(0, 0, 0.1)), mainPano.position]);
  33996. }
  33997. if (dis < 15) {
  33998. //为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
  33999. dirPoints.push([subPano.position.clone().add(new Vector3(0, 0, 0.8)), mainPano.position]);
  34000. var normal = math.getNormal2d({
  34001. p1: subPano.position,
  34002. p2: mainPano.position
  34003. }).multiplyScalar(0.3); //左右方向
  34004. dirPoints.push([subPano.position.clone().add(new Vector3(normal.x, normal.y, 0.1)), mainPano.position]);
  34005. dirPoints.push([subPano.position.clone().add(new Vector3(-normal.x, -normal.y, 0.1)), mainPano.position]);
  34006. }
  34007. } else {
  34008. console.warn('两个点位的xy几乎相同', mainPano.id, subPano.id);
  34009. }
  34010. //console.warn('getNeighbour', mainPano.id,subPano.id)
  34011. for (var i = 0; i < dirPoints.length; i++) {
  34012. var dir = new Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
  34013. var intersectPoint = viewer.images360.depthSampler.sample({
  34014. dir
  34015. }, mainPano, true, true);
  34016. if (!intersectPoint || intersectPoint.distance + margin > dirPoints[i][0].distanceTo(dirPoints[i][1])) {
  34017. //if(i>2)console.log('haha',i,'id:',mainPano.id,subPano.id)
  34018. return true;
  34019. }
  34020. }
  34021. };
  34022. //if(!ifNeighbour && (map0[pano1.id] == void 0 || computeTwoDir && !map0[pano1.id] && map1[pano0.id] == void 0 )) {//主方向为空且不为邻居
  34023. if (pano0.pointcloud.hasDepthTex || pano1.pointcloud.hasDepthTex) {
  34024. if (computeTwoDir ? map0[pano1.id] == void 0 || map1[pano0.id] == void 0 : map0[pano1.id] == void 0 && map1[pano0.id] !== false) {
  34025. //2024.3.20改为必须两个方向都为true才行。 因为如果两个点分别在两个数据集相距很远,A确定有墙无法到B,B朝A看 没有B所在的数据集点云遮挡,因深度图不会包含别的数据集的点,故深度图探测到A处为无遮挡,就会导致会飞到遥远的A。 即使在同一个数据集,因为点云可以编辑位置,导致AB相对位置错误,也要避免这种情况可以互相乱走。 缺点是更容易被杂点阻挡,所以需要ifShelter降低阈值。
  34026. if (map0[pano1.id] == void 0 && pano0.depthTex) {
  34027. var is = getNeighbour(pano0, pano1);
  34028. map0[pano1.id] = !!is;
  34029. }
  34030. if (computeTwoDir && map0[pano1.id] && pano1.depthTex && map1[pano0.id] == void 0) {
  34031. //computeTwoDir : 允许反向计算,即可以读取另一张的深度图 。 如果map0为false,map1就不用计算,只需要等待计算ifShelter
  34032. var _is = getNeighbour(pano1, pano0);
  34033. map1[pano0.id] = !!_is;
  34034. }
  34035. if (map0[pano1.id] === false || map1[pano0.id] === false) {
  34036. if (dis < 25) {
  34037. //再检查下 只要两方都没有被完全遮挡就算可通行 针对杂点较多的情况
  34038. if (pano0.depthTex && pano1.depthTex) {
  34039. ifNeighbour = false;
  34040. var a = ifSheltered(pano0, pano1);
  34041. if (a) {
  34042. var b = ifSheltered(pano1, pano0);
  34043. if (b && a + b >= 0.6) {
  34044. ifNeighbour = true;
  34045. }
  34046. }
  34047. map0[pano1.id] = map1[pano0.id] = ifNeighbour;
  34048. }
  34049. } else {
  34050. //标记为无需再计算, 因已经失败。 当map0和map1都不为void 0后就无法再计算了。
  34051. if (map0[pano1.id] === void 0) map0[pano1.id] = false;
  34052. if (map1[pano0.id] === void 0) map1[pano0.id] = false;
  34053. }
  34054. }
  34055. ifNeighbour = map1[pano0.id] == void 0 ? map0[pano1.id] : map0[pano1.id] && map1[pano0.id]; //如果map1没计算就只要返回map0
  34056. if (ifLog) {
  34057. console.log('isNeighbour', pano0.id + "(" + pano0.originID + ")", pano1.id + "(" + pano1.originID + ")", map0[pano1.id], map1[pano0.id]);
  34058. }
  34059. }
  34060. } else if (!onlyUseTex && !ifNeighbour) {
  34061. //使用点云判断(有深度贴图时不会执行到这)
  34062. /* let inDirection = ()=>{
  34063. let dir = new THREE.Vector3().subVectors(pano1.position,pano0.position).normalize()
  34064. let dis = pano1.position.distanceTo(pano0.position)
  34065. let fov = THREE.Math.degToRad(viewer.mainViewport.camera.fov)
  34066. let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera , true );
  34067. let hov = Math.min(fov, hfov)
  34068. let max = Math.cos(THREE.Math.degToRad(10))
  34069. let min = Math.cos(THREE.Math.degToRad(40))
  34070. if(this.getDirection().dot(dir) > THREE.Math.clamp(Math.cos(hov/2 ) * dis / 10, min, max )){//距离越远要求和视线角度越接近
  34071. return true
  34072. }
  34073. }
  34074. if(computeDirFirst){//先计算方向,防止重复计算ifBlockedByIntersect
  34075. if(inDirection()){
  34076. ifNeighbour = !viewer.inputHandler.ifBlockedByIntersect({point:pano1.position, margin, cameraPos:pano0.position})
  34077. }
  34078. }else{
  34079. ifNeighbour = !viewer.inputHandler.ifBlockedByIntersect({point:pano1.position, margin, cameraPos:pano0.position})
  34080. if(ifNeighbour && !inDirection()){
  34081. ifNeighbour = undefined //不确定
  34082. }
  34083. }
  34084. map0[pano1.id] = map1[pano0.id] = ifNeighbour ? 'byCloud' : ifNeighbour//写简单点
  34085. */
  34086. map0[pano1.id] = map1[pano0.id] = true; //全部可通行
  34087. }
  34088. if (map0[pano1.id] && map1[pano0.id]) {
  34089. //要获得双向需要depthTex都加载好,可能要很久时间
  34090. pano0.neighbours.includes(pano1) || pano0.neighbours.push(pano1);
  34091. pano1.neighbours.includes(pano0) || pano1.neighbours.push(pano0);
  34092. }
  34093. return ifNeighbour;
  34094. }
  34095. bump(direction) {
  34096. //撞墙弹回效果
  34097. if (!this.bumping && !this.latestToPano) {
  34098. var _this$currentPano;
  34099. var distance = (Potree.settings.displayMode == 'showPanos' ? 0.15 : 0.12) * (((_this$currentPano = this.currentPano) === null || _this$currentPano === void 0 ? void 0 : _this$currentPano.pointcloud.scale.x) || 1); //感觉点云模式比全景模式更明显,所以降低
  34100. var currentPos = this.position.clone();
  34101. var endPosition = new Vector3().addVectors(this.position, direction.clone().multiplyScalar(distance));
  34102. var duration = 150;
  34103. viewer.scene.view.setView({
  34104. position: endPosition,
  34105. duration,
  34106. callback: () => {
  34107. viewer.scene.view.setView({
  34108. position: currentPos,
  34109. duration: duration * 5,
  34110. callback: () => {
  34111. this.bumping = false;
  34112. //this.dispatchEvent('cameraMoveDone')
  34113. },
  34114. Easing: 'easeInOutSine',
  34115. cancelFun: () => {
  34116. this.bumping = false;
  34117. }
  34118. });
  34119. this.bumping = true;
  34120. },
  34121. cancelFun: () => {
  34122. this.bumping = false;
  34123. },
  34124. Easing: 'easeInOutSine'
  34125. });
  34126. this.bumping = true;
  34127. }
  34128. //备注:将4dkk中的‘前后方向变化fov、左右方向移动镜头’ 都改为移动镜头。 因为这里无法判断左右离壁距离。
  34129. }
  34130. flyToPanoClosestToMouse() {
  34131. /* if (Date.now() - this.mouseLastMoveTime > 50) {
  34132. //this.intersect = this.getMouseIntersect();
  34133. this.intersect && this.updateClosestPano(this.intersect);
  34134. } */
  34135. if (!Potree.settings.ifShowMarker) {
  34136. //不显示marker的时候mousemove没更新鼠标最近点所以更新
  34137. this.updateClosestPano(viewer.inputHandler.intersect);
  34138. }
  34139. //console.log('flyToPanoClosestToMouse',this.closestPano)
  34140. if (this.closestPano) {
  34141. var pano = this.closestPano;
  34142. return this.flyToPano({
  34143. pano,
  34144. easeName: this.isAtPano() ? 'linearTween' : 'easeInOutQuad'
  34145. });
  34146. }
  34147. var direction = this.viewer.inputHandler.getMouseDirection().direction;
  34148. this.flyDirection(direction);
  34149. }
  34150. flyDirection(direction, option1, option2, byKey) {
  34151. if (viewer.mainViewport.view.isFlying()) {
  34152. // closestPanoInDirection函数耗时长,飞行时运行会卡顿(如果以后加无缝过渡再说)
  34153. return;
  34154. }
  34155. var deferred = $.Deferred();
  34156. //this.history.invalidate();
  34157. var panoSet = this.closestPanoInDirection(direction, option1, option2, byKey);
  34158. if (panoSet) {
  34159. this.flyToPano({
  34160. pano: panoSet,
  34161. callback: deferred.resolve.bind(deferred, !0)
  34162. });
  34163. } else {
  34164. //如果离数据集较远,转动也很难找到点云,就飞到就近点:
  34165. if (Potree.settings.displayMode == 'showPointcloud') {
  34166. var po = viewer.scene.pointclouds.find(e => e.visibleNodes.some(a => a.getLevel() > Math.ceil(e.maxLevel * 0.15))); //虽然当点云在前方很远的地方也可能符合
  34167. if (!po) {
  34168. //无可见点云
  34169. //console.log('no visi cloud')
  34170. if (!this.panos.length) {
  34171. //如果场景中没有漫游点,如SG-t-XPf1k9pv3Zg 点击后回到可见区域
  34172. if (viewer.scene.pointclouds.length == 0) return;
  34173. var map = new Map();
  34174. var clouds = viewer.scene.pointclouds.filter(e => e.root.geometryNode);
  34175. clouds.forEach(e => map.set(e, e.bound.distanceToPoint(this.position)));
  34176. clouds.sort((a, b) => map.get(a) - map.get(b));
  34177. viewer.flyToDataset({
  34178. focusOnPoint: true,
  34179. pointcloud: clouds[0],
  34180. duration: 500
  34181. }); //飞最近的一个点云
  34182. return deferred.promise();
  34183. }
  34184. this.flyToPano({
  34185. pano: this.findNearestPano(),
  34186. duration: 500,
  34187. callback: deferred.resolve.bind(deferred, !0)
  34188. });
  34189. return deferred.promise();
  34190. }
  34191. }
  34192. this.bump(direction);
  34193. deferred.resolve(!1);
  34194. }
  34195. return deferred.promise();
  34196. }
  34197. closestPanoInDirection(direction, option1, option2, byKey) {
  34198. return this.rankedPanoInDirection(0, direction, option1, option2, byKey);
  34199. }
  34200. rankedPanoInDirection(t, direction, option1, option2, byKey) {
  34201. var _this$currentPano2;
  34202. //此direction为mouseDirection,是否需要加上相机角度的权重
  34203. var startTime = Date.now();
  34204. var panoSet = {
  34205. pano: null,
  34206. candidates: [] //缓存顺序--如果需要打印的话
  34207. };
  34208. t || (t = 0);
  34209. option1 = void 0 !== option1 ? option1 : 0.6; //.75; 2024.3.22改小,也就是可以走的角度范围增加,主要针对像山野那种很大的场景,不知道可以走哪,容易因角度范围内无近点而飞到远处的情况。但不能太小,总是横着走路
  34210. var o = option2 ? "angle" : "direction";
  34211. var floor = viewer.modules.SiteModel.currentFloor;
  34212. var entity = viewer.modules.SiteModel.inEntity;
  34213. var scaleFactor = Math.pow(((_this$currentPano2 = this.currentPano) === null || _this$currentPano2 === void 0 ? void 0 : _this$currentPano2.pointcloud.scale.x) || 1, 2);
  34214. var changeTexCount = 0,
  34215. maxWaitDur = 300;
  34216. //maxSamplerChangeTex = THREE.Math.clamp( maxWaitDur / Potree.timeCollect.depthSampler.median, 2, 10) //计算换贴图最大数目
  34217. var request = [
  34218. //必要条件
  34219. Images360.filters.not(this.currentPano), Images360.filters.isEnabled(),
  34220. //Images360.filters.inFloorDirection( this.position, direction, option1 ), //原先用inPanoDirection,但容易穿楼层,当mouse较低或较高 //因不束缚纵向所以可能往相反反向
  34221. pano => {
  34222. // 不会再changeTex了
  34223. var isNeighbour = this.isNeighbour(this.currentPano, pano, {
  34224. onlyUseTex: true
  34225. });
  34226. if (isNeighbour || pano.noNeighbour && Images360.scoreFunctions.distanceSquaredNew(this.currentPano)(pano) > -200 /* disSquareMap.get(pano) < 200 */) {
  34227. //在靠近孤立点时可以通行。但是不好把握这个距离,太远的话很多地方都会不小心到孤立点,太近的话可能永远到不了。
  34228. return true;
  34229. }
  34230. }];
  34231. if (byKey) {
  34232. request.push(Images360.filters.inPanoDirection(this.position, direction, option1));
  34233. } else {
  34234. request.push(Images360.filters.inPanoDirection(this.position, this.getDirection(), option1 /* , true */)); //垂直方向上再稍微限制一下, 要接近视线方向,避免点击前方时因无路而到下一楼。但不能太高,否则楼梯上稍微朝下点击都到不了上方。之所以使用视线方向是因为镜头方向比鼠标方向目的性更强。
  34235. }
  34236. var list = [
  34237. //决胜项目
  34238. /* (pano)=>{
  34239. return -disSquareMap.get(pano)
  34240. }, */
  34241. Images360.scoreFunctions.distanceSquaredNew(this.currentPano), Images360.scoreFunctions[o](this.position, direction, true), pano => {
  34242. var neighbour = this.isNeighbour(this.currentPano, pano, {
  34243. dontCompute: true,
  34244. isNeighbour: true
  34245. }); //不计算的
  34246. return neighbour ? directionFactor : 0;
  34247. }
  34248. /* (pano)=>{//尽量不穿越地板到下一层
  34249. let dis = getHeightDis(pano)
  34250. return -dis * directionFactor * 0.1;
  34251. }, */
  34252. /* (pano)=>{ //尽量在一个建筑内行走,这样不易穿墙
  34253. let score = 0
  34254. if(entity ){
  34255. if(!entity.panos.includes(pano) ) score -= directionFactor * 0.01; //不能设置太高,否则会走不进大房间的小房间中,因为容易穿过小房间的一个门到另一个门外
  34256. if(!floor.panos.includes(pano)) {//避免穿楼层
  34257. let heightDiff = Math.abs(pano.position.z - this.position.z);
  34258. if(heightDiff > 2){
  34259. score -= directionFactor * 0.1 * heightDiff;
  34260. }
  34261. }
  34262. }
  34263. return score
  34264. } */];
  34265. if (!byKey && viewer.inputHandler.intersect && this.currentPano) {
  34266. //方便上下楼, 考虑panos之间的角度差
  34267. var pos1 = this.currentPano.floorPosition;
  34268. var vec1 = new Vector3().subVectors(viewer.inputHandler.intersect.location, pos1).normalize(); //应该只有atPano时才会执行到这吧?
  34269. list.push(function (pano) {
  34270. var pos2 = pano.floorPosition;
  34271. var vec2 = pos2.clone().sub(pos1).normalize();
  34272. return vec2.dot(vec1) * directionFactor * 4;
  34273. });
  34274. }
  34275. this.findRankedByScore(t, request, list, panoSet);
  34276. //console.log( 'costTime:',Date.now() - startTime)
  34277. return panoSet.pano;
  34278. }
  34279. findRankedByScore(e, t, i, n) {
  34280. n && (n.candidates = null,
  34281. //candidates 缓存顺序--如果需要打印的话
  34282. n.pano = null), e || (e = 0);
  34283. var r = Common$1.sortByScore(this.panos, t, i);
  34284. //console.log('findRankedByScore', r && r.map(u=>u.item.id + '| ' + math.toPrecision(u.score,4) + " | " + math.toPrecision(u.scores,4)))
  34285. return !r || 0 === r.length || e >= r.length ? null : (n && (n.candidates = r, n.pano = r[e].item), r[e].item);
  34286. }
  34287. updateClosestPano(intersect, state) {
  34288. //hover到的pano 大多数时候是null
  34289. var pano;
  34290. if (intersect instanceof Panorama) {
  34291. //漫游模式
  34292. pano = state ? intersect : null;
  34293. } else {
  34294. if (this.isAtPano() || this.bumping) {
  34295. return;
  34296. } else {
  34297. var filterFuncs = [];
  34298. intersect = intersect && intersect.location;
  34299. if (!intersect) return;
  34300. var sortFuncs = Potree.settings.editType != 'pano' ? [Images360.sortFunctions.floorDisSquaredToPoint(intersect)] : [Images360.sortFunctions.disSquaredToPoint(intersect)];
  34301. pano = Common$1.find(this.panos, filterFuncs, sortFuncs);
  34302. }
  34303. }
  34304. if (pano != this.closestPano) {
  34305. pano && (this.isPanoHover = !0);
  34306. this.closestPanoChanging(this.closestPano, pano); // 高亮marker
  34307. //console.log('closestPano '+ (pano ? pano.id : 'null' ))
  34308. this.closestPano = pano;
  34309. } else {
  34310. this.isPanoHover = !1;
  34311. }
  34312. }
  34313. closestPanoChanging(oldPano, newPano) {
  34314. if (!Potree.settings.ifShowMarker) return;
  34315. oldPano && oldPano.hoverOff({
  34316. byImages360: true
  34317. });
  34318. newPano && newPano.hoverOn({
  34319. byImages360: true
  34320. });
  34321. }
  34322. getTileDirection() {
  34323. //根据不同dataset的来存储
  34324. var vectorForward = viewer.scene.view.direction.clone();
  34325. var vectorForwards = viewer.scene.pointclouds.concat(viewer.objs.children.filter(e => e.panos)).map(e => {
  34326. var inv = new Matrix4().copy(e.rotateMatrix).invert(); //乘上dataset的旋转的反转
  34327. var direction = vectorForward.clone().applyMatrix4(inv);
  34328. return {
  34329. datasetId: e.dataset_id,
  34330. direction: math.convertVector.ZupToYup(direction)
  34331. };
  34332. });
  34333. //return vectorForwards[0].direction
  34334. return {
  34335. datasetsLocal: vectorForwards,
  34336. vectorForward
  34337. };
  34338. }
  34339. update() {
  34340. //if(this.tileDownloader.started){
  34341. var vectorForwards = this.getTileDirection();
  34342. //vectorForwards = vectorForwards[0].direction
  34343. this.updateTileDownloader(tileArr, vectorForwards);
  34344. this.updatePanoRenderer(vectorForwards);
  34345. //}
  34346. this.updateZoomPano();
  34347. }
  34348. updateTileDownloader(t, vectorForward) {
  34349. var i = this.nextPano || this.currentPano;
  34350. if (i) {
  34351. this.tileDownloader.tilePrioritizer.updateCriteria(i, viewer.scene.view.position.clone(), vectorForward, t.length > 0 ? t : null), this.tileDownloader.processPriorityQueue = !0;
  34352. }
  34353. }
  34354. updatePanoRenderer(vectorForward) {
  34355. var i = this.nextPano || this.currentPano;
  34356. if (i) {
  34357. if (this.panoRenderer.hasQueuedTiles() && i) {
  34358. this.panoRenderer.updateDirection(vectorForward);
  34359. }
  34360. }
  34361. }
  34362. //等待部分加载完
  34363. checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, l) {
  34364. //console.log('checkAndWaitForTiledPanoLoad',pano.id)
  34365. if (!pano) {
  34366. console.error("Player.checkAndWaitForTiledPanoLoad() -> Cannot load texture for null pano.");
  34367. }
  34368. var vectorForward = this.getTileDirection();
  34369. if (!pano.isLoaded(basePanoSize)) {
  34370. iswait && viewer.waitForLoad(pano, function () {
  34371. //发送loading
  34372. return pano.isLoaded(basePanoSize);
  34373. });
  34374. /* var fov = {//test for direction 预加载的边缘有一丢丢不准确,尤其在相机倾斜时(4dkk也是)。
  34375. hFov: cameraLight.getHFOVForCamera(viewer.scene.getActiveCamera() ),
  34376. vFov: viewer.scene.getActiveCamera().fov
  34377. }//原先是null,不要求方向 */
  34378. var fov = null; //若不为null的话,因为可能可见范围的tile下载过了从而无法触发下载,然后得不到下载成功的消息,怎么办
  34379. pano.loadTiledPano( /* 1024 */basePanoSize, vectorForward, fov, isclear, l, null).done(function (e, t) {
  34380. callback1 && callback1(e, t);
  34381. }.bind(this)).fail(function (msg) {
  34382. callback2 && callback2(msg);
  34383. }.bind(this)).progress(function (e, t, i) {
  34384. progressCallback && progressCallback(e, t, i);
  34385. }.bind(this));
  34386. return !0;
  34387. }
  34388. }
  34389. fitPanoTowardPoint(o) {
  34390. //寻找最适合的点位
  34391. var point = o.point,
  34392. //相机最佳位置
  34393. target = o.target || o.point,
  34394. //实际要看的位置
  34395. require = o.require || [],
  34396. rank = o.rank || [],
  34397. force = o.force,
  34398. getAll = o.getAll,
  34399. bestDistance = o.bestDistance || 0,
  34400. sameFloor = o.sameFloor,
  34401. maxDis = o.maxDis,
  34402. dir = o.dir;
  34403. var camera = viewer.scene.getActiveCamera();
  34404. if (target && !dir) {
  34405. dir = new Vector3().subVectors(target, point).normalize();
  34406. }
  34407. var atFloor = sameFloor && viewer.modules.SiteModel.pointInWhichEntity(point, 'floor');
  34408. //if(o.floor)require.push(Panorama.filters.atFloor(o.floor))
  34409. var checkIntersect = o.checkIntersect;
  34410. var base = Math.max(300, viewer.bound.boundSize.length() * 3);
  34411. if (o.boundSphere) {
  34412. //只接受boundSphere
  34413. var aspect = 1; //size.x / size.y
  34414. var dis;
  34415. if (camera.aspect > aspect) {
  34416. //视野更宽则用bound的纵向来决定
  34417. dis = /* size.y */o.boundSphere.radius /* / 2 */ / MathUtils.degToRad(camera.fov / 2);
  34418. } else {
  34419. var hfov = cameraLight.getHFOVForCamera(camera, true);
  34420. dis = /* size.x */o.boundSphere.radius /* / 2 */ / (hfov / 2);
  34421. }
  34422. bestDistance = dis; //*0.8
  34423. }
  34424. var disSquareMap = new Map();
  34425. var bestDisSquared = bestDistance * bestDistance;
  34426. var maxDisSquared = maxDis && maxDis * maxDis;
  34427. this.panos.forEach(pano => {
  34428. var dis2 = pano.position.distanceToSquared(target); //距离目标点
  34429. disSquareMap.set(pano, dis2);
  34430. });
  34431. var panos = this.panos.sort((p1, p2) => {
  34432. return disSquareMap.get(p1) - disSquareMap.get(p2);
  34433. });
  34434. if (maxDisSquared) {
  34435. //热点超过最大距离不可见的
  34436. var panos2 = [],
  34437. _pano,
  34438. i = 0;
  34439. while (_pano = panos[i], disSquareMap.get(_pano) < maxDisSquared) {
  34440. panos2.push(_pano);
  34441. i++;
  34442. }
  34443. if (panos2.length == 0) return {
  34444. pano: _pano,
  34445. msg: 'tooFar'
  34446. }; //全部都大于maxDis, 就返回最近的
  34447. panos = panos2;
  34448. }
  34449. rank.push(pano => {
  34450. var dis1 = Math.abs(pano.position.distanceToSquared(point) - bestDisSquared); //距离最佳位置
  34451. disSquareMap.set(pano, dis1);
  34452. if (!target) {
  34453. return -dis1;
  34454. } else {
  34455. var dis2 = disSquareMap.get(pano);
  34456. if (o.gotoBestView) {
  34457. //忽略和当前视线的角度
  34458. return -(dis1 + dis2 * 0.3);
  34459. }
  34460. var vec2 = new Vector3().subVectors(target, pano.position).normalize();
  34461. var cos = dir.dot(vec2);
  34462. //let result = (- dis1 - Math.pow(dis2 , 1.5)) / (cos + 2) // cos+2是为了调整到1-3,
  34463. var result = (dis1 + dis2 * 0.3) * (-1 + cos * 0.4); //尽量贴近最佳位置的角度, 或贴近相机原来的角度 。尽量靠近最佳观测点,并且优先选择靠近目标点的位置.(注意cos的乘数不能太接近1,否则容易只考虑角度)
  34464. //Potree.Log(pano.id, dis1, dis2, cos, result,{font:{toFixed:2,fontSize:10}})
  34465. return result;
  34466. }
  34467. //注:热点最好加上法线信息,这样可以多加一个限制,尽量顺着热点像展示的方向。
  34468. }
  34469. /* (pano)=>{
  34470. let score = 0
  34471. if(pano.depthTex && checkIntersect){
  34472. let intersect = !!viewer.ifPointBlockedByIntersect(target, pano.id, true) //viewer.inputHandler.ifBlockedByIntersect({point:target, margin:0.1, cameraPos:pano})
  34473. if(intersect){
  34474. score = 0
  34475. }else {
  34476. score = base * 2
  34477. }
  34478. }else{
  34479. score = base * 1.5 //没加载好的话,不管了 , 几乎当做无遮挡,否则容易到不了最近点
  34480. }
  34481. return score
  34482. } */);
  34483. var g = Common$1.sortByScore(panos, require, rank);
  34484. // console.log(g)
  34485. var pano = g && g.length > 0 && g[0].item;
  34486. if (pano && checkIntersect) {
  34487. var intersect = !!viewer.ifPointBlockedByIntersect(target, pano.id, true);
  34488. if (intersect) {
  34489. return {
  34490. pano,
  34491. msg: 'sheltered'
  34492. };
  34493. }
  34494. }
  34495. //if(getAll)return g;
  34496. return pano;
  34497. //注:深度图有的位置会不准确,以至于会算出错误的遮挡、选择错误的pano,解决办法只能是移动下热点到更好的位置
  34498. }
  34499. //---------------scroll zoom ------------------------------------------
  34500. /* zoomIn = function() { //放大
  34501. this.zoomBy(1 + this.zoomSpeed);
  34502. }
  34503. zoomOut = function() {//缩小
  34504. this.zoomBy(1 - this.zoomSpeed);
  34505. } */
  34506. zoomBy(e, pointer) {
  34507. //以倍数
  34508. this.zoomTo(this.zoomLevel * e, pointer);
  34509. }
  34510. zoomTo(zoomLevel, pointer) {
  34511. //缩放到某绝对zoomLevel
  34512. var zoom = Potree.settings.zoom;
  34513. if (zoom.enabled) {
  34514. zoomLevel = MathUtils.clamp(zoomLevel, zoom.min, zoom.max);
  34515. //console.log(zoomLevel)
  34516. if (zoomLevel == this.zoomLevel) return;
  34517. this.zoomLevel = zoomLevel;
  34518. if (Potree.settings.panoZoomByPointer) {
  34519. //定点缩放:使当前鼠标所在的位置缩放后不变
  34520. var view = viewer.scene.view;
  34521. var originDir = viewer.scene.view.direction;
  34522. var oldPointerDir = viewer.inputHandler.getMouseDirection(pointer).direction;
  34523. viewer.setFOV(Potree.config.view.fov * (1 / this.zoomLevel));
  34524. var newPointerDir = viewer.inputHandler.getMouseDirection(pointer).direction;
  34525. view.direction = oldPointerDir; //获取一下鼠标所在位置的yaw 和 pitch
  34526. var oldPitch = view.pitch,
  34527. oldYaw = view.yaw;
  34528. view.direction = newPointerDir;
  34529. var newPitch = view.pitch,
  34530. newYaw = view.yaw;
  34531. view.direction = originDir; //还原
  34532. viewer.scene.view.pitch -= newPitch - oldPitch;
  34533. viewer.scene.view.yaw -= newYaw - oldYaw;
  34534. } else {
  34535. viewer.setFOV(Potree.config.view.fov * (1 / this.zoomLevel));
  34536. }
  34537. }
  34538. }
  34539. zoomFovTo(fov) {
  34540. //通过fov来算zoomLevel
  34541. var zoomLevel = Potree.config.view.fov /* this.baseFov */ / fov;
  34542. this.zoomTo(zoomLevel);
  34543. }
  34544. smoothZoomTo(aimLevel) {
  34545. var dur = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  34546. var currentLevel = this.zoomLevel;
  34547. if (currentLevel == aimLevel) return;
  34548. var fun = progress => {
  34549. //progress > 1 && (progress = 1)
  34550. var level = currentLevel * (1 - progress) + aimLevel * progress;
  34551. this.zoomTo(level, !0);
  34552. };
  34553. transitions.start(fun, dur, null, null, 0, easing['easeInOutQuad']);
  34554. }
  34555. updateZoomPano() {
  34556. if (!this.panoRenderer.zoomPanoRenderingDisabled && Potree.settings.displayMode == 'showPanos') {
  34557. var currentPano = this.currentPano;
  34558. if (currentPano) {
  34559. var levelThreshold1 = Potree.settings.navTileClass == '1k' ? 1.3 : 1.7,
  34560. levelThreshold2 = 2;
  34561. var t = this.zoomLevel > levelThreshold1,
  34562. n = !(this.flying && this.nextPano && this.nextPano !== this.currentPano),
  34563. r = t && n;
  34564. this.tileDownloader.tilePrioritizer.setZoomingActive(r);
  34565. this.panoRenderer.setZoomingActive(r, currentPano, !0);
  34566. var o = (pano, ifZoom) => {
  34567. this.panoRenderer.resetRenderStatus(pano.id, !1, !0, this.qualityManager.getMaxNavPanoSize());
  34568. this.panoRenderer.clearAllQueuedUploadsForPano(pano.id);
  34569. this.panoRenderer.renderPanoTiles(pano.id, null, !1, !1);
  34570. pano.setZoomed(ifZoom);
  34571. };
  34572. if (currentPano.pointcloud.tileRes == '2k') {
  34573. //融合页面
  34574. return currentPano.zoomed && o(currentPano, !1);
  34575. }
  34576. if (r && (!currentPano.zoomed || this.qualityManager.zoomLevelResolution && this.qualityManager.zoomLevelResolution != '4k')) {
  34577. //needZoom
  34578. currentPano.zoomed || o(currentPano, !0);
  34579. if (Potree.settings.navTileClass == '1k' && Potree.settings.tileClass != '1k' && this.zoomLevel < levelThreshold2) {
  34580. this.panoRenderer.enableHighQuality(function () {
  34581. //开启2k
  34582. if (Potree.settings.tileClass != '4k') o(currentPano, !0);
  34583. }.bind(this));
  34584. } else {
  34585. this.panoRenderer.enableUltraHighQualityMode(function () {
  34586. //开启4k getMaxZoomPanoSize
  34587. this.qualityManager.useUltraHighResolutionPanos && (Potree.settings.zoom.max = Potree.config.ultraHighQualityMaxZoom);
  34588. o(currentPano, !0);
  34589. }.bind(this));
  34590. }
  34591. } else {
  34592. !t && currentPano.zoomed && o(currentPano, !1);
  34593. }
  34594. if (r && Potree.settings.navTileClass == '1k' && Potree.settings.tileClass == '4k') {
  34595. //目前只有手机端navTileClass == '1k' (分三个梯度)
  34596. var change = zoomedFlag => {
  34597. this.qualityManager.updateMaximums(); //更新maxZoomPanoSize
  34598. this.panoRenderer.setupZoomRenderTarget(); //更新renderTarget
  34599. //currentPano.setZoomed(t);//更新uniforms贴图
  34600. };
  34601. this.qualityManager.zoomLevelResolution = this.zoomLevel >= levelThreshold2 ? '4k' : this.zoomLevel > levelThreshold1 ? '2k' : '1k';
  34602. if (this.oldZoomLevel < levelThreshold2 && this.zoomLevel >= levelThreshold2) {
  34603. //1k/2k-4k
  34604. change();
  34605. o(currentPano, t);
  34606. } else if (this.oldZoomLevel <= levelThreshold1 && this.zoomLevel > levelThreshold1) {
  34607. //1k-2k
  34608. change();
  34609. } else if (this.oldZoomLevel > levelThreshold2 && this.zoomLevel <= levelThreshold2) {
  34610. //4k-2k/1k
  34611. change();
  34612. o(currentPano, t);
  34613. } else if (this.oldZoomLevel > levelThreshold1 && this.zoomLevel <= levelThreshold1) {
  34614. //2k-1k
  34615. change();
  34616. }
  34617. this.oldZoomLevel = this.zoomLevel;
  34618. }
  34619. }
  34620. }
  34621. }
  34622. //--------------------
  34623. addHighMapCube() {
  34624. //创建8*8的tile cube 主要因手机版崩溃 要在电脑端测试得设置maxRenderTargetSize
  34625. if (Potree.settings.tileClass == '4k' && this.qualityManager.maxRenderTargetSize == 2048) {
  34626. var geo = new PlaneGeometry(1, 1, 1, 1);
  34627. var cube = new Object3D();
  34628. cube.tiles = [];
  34629. for (var cubeIndex = 0; cubeIndex < 6; cubeIndex++) {
  34630. var face = new Object3D();
  34631. for (var i = 0; i < 8; i++) {
  34632. for (var j = 0; j < 8; j++) {
  34633. var tile = new Mesh(geo, new MeshBasicMaterial({
  34634. //之后有必要的话像4dkk一样换成ModelTextureMaterial,加深度图
  34635. //side:THREE.DoubleSide
  34636. transparent: true,
  34637. opacity: 0.4,
  34638. depthTest: false
  34639. }));
  34640. tile.position.set(i - 3.5, j - 3.5, -4);
  34641. if (Potree.settings.isTest) {
  34642. var colorHue = Math.random();
  34643. tile.material.color = new Color().setHSL(colorHue, 0.6, 0.7);
  34644. /* tile.scoreLabel = new TextSprite( {
  34645. backgroundColor: { r: 0, g: 0, b: 0, a: 0 },
  34646. textColor: { r: 0, g: 0, b: 0, a: 1 },
  34647. borderRadius: 15,
  34648. renderOrder: 50, fontsize : 13,
  34649. text: '' ,
  34650. dontFixOrient:true
  34651. })
  34652. tile.scoreLabel.sprite.material.side = 2;
  34653. tile.scoreLabel.rotation.x = Math.PI
  34654. tile.add(tile.scoreLabel) */
  34655. }
  34656. Potree.Utils.updateVisible(tile, 'show', false);
  34657. tile.tileX = i;
  34658. tile.tileY = j;
  34659. tile.cubeFace = cubeIndex;
  34660. //tile.renderOrder = RenderOrder.highTileCube
  34661. cube.tiles.push(tile);
  34662. face.add(tile);
  34663. }
  34664. }
  34665. switch (cubeIndex) {
  34666. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  34667. face.rotation.set(0, Math.PI / 2, 0);
  34668. break;
  34669. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  34670. face.rotation.set(0, -Math.PI / 2, 0);
  34671. break;
  34672. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  34673. var rot1 = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
  34674. var rot2 = new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2);
  34675. face.quaternion.copy(rot1).multiply(rot2);
  34676. //face.rotation.set(Math.PI/2,0,0);
  34677. break;
  34678. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  34679. //face.rotation.set(-Math.PI/2,0,0);
  34680. var rot1 = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
  34681. var rot2 = new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
  34682. face.quaternion.copy(rot1).multiply(rot2);
  34683. break;
  34684. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  34685. face.rotation.set(0, Math.PI, 0);
  34686. break;
  34687. case GLCubeFaces$3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  34688. face.rotation.set(0, 0, 0);
  34689. }
  34690. face.scale.set(1, -1, 1);
  34691. face.cubeFace = cubeIndex;
  34692. cube.add(face);
  34693. }
  34694. cube.name = 'highMapCube';
  34695. this.highMapCube = cube;
  34696. viewer.scene.scene.add(cube);
  34697. {
  34698. var s = 0.1;
  34699. cube.scale.set(s, s, s);
  34700. } //注:由于原本的mesh上加了深度贴图,可能距离镜头比这里的近。凡是在cube以内的部分都会挡住cube导致模糊。但是应该不常见吧(另外到天空的边缘也是很近)。姑且depthTest=false
  34701. this.highMapCube.visible = false;
  34702. Potree.Utils.setObjectLayers(this.highMapCube, 'sceneObjects' /* 'skybox' */); //因它的深度是错误的,故不在skybox层渲染,影响edlRT, 而在renderOverlay时渲染覆盖。
  34703. //console.warn('addHighMapCube')
  34704. viewer.addEventListener('update', () => {
  34705. if (this.highMapCube.visibleTiles) {
  34706. this.updateTiles(); //逐步将visibleTiles加载完
  34707. }
  34708. });
  34709. viewer.addEventListener('camera_changed', e => {
  34710. if (e.viewport == viewer.mainViewport) {
  34711. //重新获取visibleTiles
  34712. Common$1.intervalTool.isWaiting('update4kTiles', () => {
  34713. var vectorForward = this.getDirection();
  34714. this.updateTiles(vectorForward);
  34715. }, 500);
  34716. }
  34717. });
  34718. }
  34719. }
  34720. isHighMapLoaded(cubeFace, tileX, tileY) {
  34721. var tile = this.highMapCube.children[cubeFace].children[tileX * 8 + tileY];
  34722. return !!tile.material.map;
  34723. }
  34724. updateTiles(direction) {
  34725. if (!this.highMapCube || !this.highMapCube.visible) return;
  34726. if (this.highMapCube.tiles.filter(e => e.image).length <= 10) return; //加载的太少了
  34727. //performance.mark('updateTiles-start')
  34728. if (direction) {
  34729. var camera = viewer.mainViewport.camera;
  34730. var hfov = cameraLight.getHFOVForCamera(camera, true) / 2;
  34731. var vfov = MathUtils.degToRad(camera.fov) / 2;
  34732. /* let hcos = Math.cos(hfov / 2)
  34733. let vcos = Math.cos(vfov / 2) */
  34734. var list = this.highMapCube.tiles;
  34735. list.forEach(e => {
  34736. //屏幕外的不显示
  34737. var pos = e.getWorldPosition(new Vector3());
  34738. var dir = new Vector3().subVectors(pos, this.highMapCube.position).normalize();
  34739. var hcos_ = dir.clone().setZ(direction.z).normalize().dot(direction); //在direction的斜面上水平角度差
  34740. var hRad = Math.acos(hcos_);
  34741. var vRad = -200;
  34742. if ( /* hRad > hfov + 0.08 */hRad / hfov > 1.5) {
  34743. e.score = -100;
  34744. } else {
  34745. vRad = Math.abs(Math.acos(dir.z) - Math.acos(direction.z));
  34746. if ( /* vRad > vfov + 0.08 */vRad / vfov > 1.5) {
  34747. e.score = -100;
  34748. } else {
  34749. e.score = -(hRad / hfov + vRad / vfov);
  34750. }
  34751. }
  34752. e.scores = hRad.toFixed(3) + ', ' + vRad.toFixed(3);
  34753. if (e.score == -100) {
  34754. this.resetTile(e);
  34755. }
  34756. });
  34757. this.highMapCube.visibleTiles = list.filter(e => e.score > -100);
  34758. //list.forEach(e=>e.scoreLabel.setText(e.scores))
  34759. }
  34760. var needRecover = this.highMapCube.visibleTiles.filter(e => !e.material.map);
  34761. if (needRecover.length) {
  34762. var maxCount = Common$1.getBestCount('4kmaxTileRecover', 0, 2, 1.5, 6, false, 2);
  34763. var count = 0;
  34764. //console.log(maxCount)
  34765. needRecover.forEach((e, i) => {
  34766. //只更新若干个,因为太耗时了, 其余的等下帧更新
  34767. if (count >= maxCount) return;
  34768. var r = this.recoverTile(e);
  34769. if (r) count++;
  34770. });
  34771. }
  34772. }
  34773. getHighImage(image, cubeFace, tileX, tileY) {
  34774. var tile = this.highMapCube.children[cubeFace].children[tileX * 8 + tileY];
  34775. tile.image = image; //先记录下来
  34776. }
  34777. updateHighMap(image, cubeFace, tileX, tileY) {
  34778. //console.warn('updateHighMap')
  34779. var tile = this.highMapCube.children[cubeFace].children[tileX * 8 + tileY];
  34780. if (image) tile.image = image; //先记录下来
  34781. if (tile.material.map) return;
  34782. if (this.highMapCube.visibleTiles && !this.highMapCube.visibleTiles.includes(tile) /* this.highMapCube.texLoadedCount >= this.getMaxTileCount() */) {
  34783. return;
  34784. }
  34785. //简易创建贴图
  34786. /* var tex = this.$app.core.get('SceneRenderer').initSizedTexture2D(512, THREE.ClampToEdgeWrapping)
  34787. //var loaded = this.$app.core.get('Player').model.isHighMapLoaded(tile.cubeFace, tile.tileX, tile.tileY)
  34788. this.$app.core.get('SceneRenderer').uploadTexture2D(image, tex, 0, 0, 512, 512) //只替换tex对应的img,不新建
  34789. */
  34790. var tex = new Texture();
  34791. tex.image = image;
  34792. tex.flipY = false;
  34793. tex.wrapS = tex.wrapT = ClampToEdgeWrapping;
  34794. tex.generateMipmaps = false;
  34795. tex.minFilter = LinearFilter;
  34796. tex.needsUpdate = true;
  34797. tile.material.map = tex;
  34798. tile.material.opacity = 1;
  34799. tile.material.transparent = false;
  34800. Potree.Utils.updateVisible(tile, 'show', true);
  34801. tile.material.needsUpdate = true; //发现每次开始放大但还未放大到4k时也会把之前加载过的4k加载
  34802. }
  34803. recoverTile(tile) {
  34804. if (tile.material.map) return;
  34805. if (tile.image) {
  34806. this.updateHighMap(tile.image, tile.cubeFace, tile.tileX, tile.tileY);
  34807. return true;
  34808. } else {
  34809. //console.log('no image')
  34810. }
  34811. }
  34812. resetTile(tile, kill) {
  34813. if (kill) {
  34814. //完全消灭
  34815. tile.image = null;
  34816. }
  34817. var map = tile.material.map;
  34818. if (map) {
  34819. map.dispose(); //这句执行了以后,h.__webglTexture一直就是undefined
  34820. map.loaded = !1;
  34821. map.version = 0;
  34822. //保底再执行一下这个,类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
  34823. var h = viewer.renderer.properties.get(map);
  34824. //console.log('__webglTexture',!!h.__webglTexture)
  34825. viewer.renderer.getContext().deleteTexture(h.__webglTexture);
  34826. tile.material.map = null;
  34827. tile.material.needsUpdate = true;
  34828. Potree.Utils.updateVisible(tile, 'show', false);
  34829. //this.highMapCube.texLoadedCount --
  34830. //console.log('resetTile'/* , tile.cubeFace, tile.tileX, tile.tileY */)
  34831. }
  34832. }
  34833. resetHighMap() {
  34834. if (!this.highMapCube) return;
  34835. this.highMapCube.children.forEach(e => e.children.forEach(tile => {
  34836. this.resetTile(tile, true);
  34837. }));
  34838. //this.highMapCube.texLoadedCount = 0
  34839. this.highMapCube.visibleTiles = null;
  34840. this.hideHighMap();
  34841. //console.log('resetHighMap')
  34842. }
  34843. setHighMap(pano) {
  34844. if (!this.highMapCube) return;
  34845. this.highMapCube.position.copy(pano.position);
  34846. //可以利用第0个pano查看,其 rotation4dkk是(_x: 0, _y: -1.5707963267948966, _z: 0 )而手动旋转至(_x:1.5707963, _y: -1.57079, _z: 0)时才正确,说明要在4dkk的旋转基础上,绕x轴转90度,(也就是转成navvis坐标系), 然后得到YupToZup的函数写法的
  34847. this.highMapCube.quaternion.copy(math.convertQuaternion.YupToZup(pano.quaternion4dkk));
  34848. //乘上数据集整体的旋转:
  34849. var modelRotQua = new Quaternion().setFromRotationMatrix(pano.pointcloud.rotateMatrix);
  34850. this.highMapCube.quaternion.premultiply(modelRotQua);
  34851. }
  34852. showHighMap() {
  34853. if (!this.highMapCube) return;
  34854. //console.warn('showHighMap')
  34855. this.highMapCube.visible = true;
  34856. }
  34857. hideHighMap() {
  34858. if (!this.highMapCube) return;
  34859. //console.warn('hideHighMap')
  34860. this.highMapCube.visible = false;
  34861. }
  34862. //缩小后继续显示cube呢还是不显示? 不显示的话,就要把cube上的复制到renderTarget上……会不会又崩溃,or没加载的显示???
  34863. addPanoData(data, pointcloud) {
  34864. //加载漫游点
  34865. //data[0].file_id = '00019'
  34866. if (data.data) data = data.data;
  34867. //if(data.length == 0)console.error(pointcloud.dataset_id + ' 没有漫游点')
  34868. //data = data.sort(function(a,b){return a.id-b.id})
  34869. data.forEach(info => {
  34870. //if(Potree.fileServer){
  34871. info.id = getID(); //把info的id的一长串数字改简单点
  34872. info.pointcloud = pointcloud;
  34873. //}
  34874. var pano = new Panorama(info, this);
  34875. pano.addEventListener('dispose', e => {
  34876. if (this.closestPano == pano) this.closestPano = null;
  34877. if (this.currentPano == pano && Potree.settings.displayMode == 'showPanos') {
  34878. Potree.settings.displayMode = 'showPointCloud';
  34879. }
  34880. });
  34881. this.panos.push(pano);
  34882. this.neighbourMap[info.id] = {};
  34883. pano.label && Potree.Utils.setObjectLayers(pano.label, 'bothMapAndScene');
  34884. pano.label2 && Potree.Utils.setObjectLayers(pano.label2, 'bothMapAndScene');
  34885. if (Potree.settings.editType == 'pano') {
  34886. Potree.settings.datasetsPanos[pointcloud.dataset_id].panos.push(pano);
  34887. }
  34888. });
  34889. }
  34890. loadDone() {
  34891. this.tileDownloader.setPanoData(this.panos, []);
  34892. this.updatePanoBound();
  34893. if (viewer.scene.pointclouds.some(e => e.panos.length == 0)) {
  34894. //console.warn('存在数据集没有pano');
  34895. viewer.hasNoPanoDataset = true;
  34896. }
  34897. }
  34898. updatePanoBound() {
  34899. var minSize = new Vector3(1, 1, 1);
  34900. this.bound = math.getBoundByPoints(this.panos.map(e => e.position), minSize);
  34901. Potree.settings.editType == 'pano' || viewer.scene.pointclouds.forEach(pointcloud => pointcloud.getPanosBound());
  34902. }
  34903. getPano(value) {
  34904. var typeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'id';
  34905. //默认找的是id,也可以是sid、uuid
  34906. return this.panos.find(p => p[typeName] == value);
  34907. }
  34908. }
  34909. ;
  34910. //判断当前点是否加载了全景图
  34911. Images360.prototype.checkAndWaitForPanoLoad = function () {
  34912. var loadingPanos = {},
  34913. LoadedTimePanos = {},
  34914. loadedCallback = {},
  34915. //add
  34916. maxTime = 5e3;
  34917. /* var withinTime = function() {
  34918. for (var panoId in loadingPanos)
  34919. if (loadingPanos.hasOwnProperty(panoId) && loadingPanos[panoId]) {
  34920. var differTime = performance.now() - LoadedTimePanos[panoId];
  34921. if (differTime < maxTime)
  34922. return !0
  34923. }
  34924. return !1
  34925. } */
  34926. // withinTime 改为只判断当前请求的点。原始代码的callback是针对任意pano的,所以遍历所有漫游点,只要有在加载的就返回,但已不满足需求(4dkk)。2024:9 发现bim分屏有问题,然后发现4dkk已经改过这,遂搬过来
  34927. var withinTime = function withinTime(pano) {
  34928. //5秒之内还在加载的话,直接返回仍在加载状态,否则重新判断
  34929. if (loadingPanos.hasOwnProperty(pano.id) && loadingPanos[pano.id]) {
  34930. //还在加载
  34931. var differTime = performance.now() - LoadedTimePanos[pano.id];
  34932. if (differTime < maxTime) return !0;
  34933. }
  34934. };
  34935. return function (pano, basePanoSize, doneFun1, doneFun2, progressCallback, iswait, isclear, p) {
  34936. loadedCallback[pano.id] = doneFun1; //add 因为有可能之前请求的没加doneFun1, 如果加载好就执行最新的doneFun1
  34937. if (withinTime(pano)) {
  34938. //距离上次请求时间很近
  34939. //console.log('withinTime',window.name)
  34940. return !0; //这里感觉应该是!1
  34941. }
  34942. var changeMode = e => {
  34943. if (e.mode == 'showPointCloud') {
  34944. //console.warn('切到点云模式了,就删除loadedCallback记录',pano.id)//否则再次转为showPanos会被withinTime阻拦
  34945. delete loadingPanos[pano.id];
  34946. viewer.cancelLoad(pano);
  34947. loadedCallback[pano.id] && loadedCallback[pano.id](); //可以飞行了
  34948. doneFun2 && doneFun2();
  34949. this.removeEventListener('requestMode', changeMode);
  34950. }
  34951. };
  34952. this.addEventListener('requestMode', changeMode);
  34953. var callback1 = (param1, param2) => {
  34954. setTimeout(() => {
  34955. loadingPanos[pano.id] = !1;
  34956. loadedCallback[pano.id] && loadedCallback[pano.id](param1, param2);
  34957. this.removeEventListener('requestMode', changeMode);
  34958. }, 1);
  34959. };
  34960. var callback2 = param => {
  34961. //没有看到有传doneFun2的
  34962. setTimeout(() => {
  34963. loadingPanos[pano.id] = !1;
  34964. doneFun2 && doneFun2(param);
  34965. }, 1);
  34966. };
  34967. try {
  34968. null !== iswait && void 0 !== iswait || (iswait = !0);
  34969. loadingPanos[pano.id] = this.checkAndWaitForTiledPanoLoad(pano, basePanoSize, callback1, callback2, progressCallback, iswait, isclear, p);
  34970. //true代表没加载好
  34971. if (loadingPanos[pano.id]) {
  34972. LoadedTimePanos[pano.id] = performance.now();
  34973. }
  34974. return loadingPanos[pano.id];
  34975. } catch (msg) {
  34976. loadingPanos[pano.id] = !1;
  34977. LoadedTimePanos[pano.id] = performance.now() - maxTime;
  34978. throw msg;
  34979. }
  34980. };
  34981. }(); //加载全景图的流程:请求下载当前点的最低分辨率图(不过有可能已经下载了),并且请求uploadTile渲染当前漫游点,若tile都upload完(先6个)会发送消息,LoadComplete 从而回调成功。
  34982. Images360.prototype.getNeighbours = function () {
  34983. //逐渐自动获取neighbours。 200个点差不多在半分钟内算完
  34984. var lastIndex, inited; //标记上次查询到哪,防止重新sortByScore
  34985. var startTime = 0,
  34986. lastTime = 0;
  34987. return function (interacted) {
  34988. var _this = this;
  34989. if (Potree.settings.editType == 'pano') return;
  34990. if (!this.currentPano || viewer.mainViewport.view.isFlying() || viewer.lastFrameChanged || viewer.inputHandler.drag //拖拽时不更新,否则移动端卡
  34991. || !viewer.scene.pointclouds.some(e => e.hasDepthTex) //目前无深度图的话不判断可行,全部可通行
  34992. ) {
  34993. return lastIndex = 0;
  34994. }
  34995. var nearPanos = this.tileDownloader.tilePrioritizer.nearPanos;
  34996. if (!nearPanos) return;
  34997. if (Date.now() - lastTime < 50) return; //不要每帧都算
  34998. startTime = lastTime = Date.now();
  34999. var panos = [this.currentPano, ...nearPanos];
  35000. this.depthSampler.updateNearPanos(panos);
  35001. var maxWaitDur = browser.isMobile() ? 2 : 4;
  35002. var changeCount = 0,
  35003. getCount = 0,
  35004. maxChangeTex = 1;
  35005. var changeTexCount = () => {
  35006. changeCount++;
  35007. };
  35008. var median = Potree.timeCollect.depthSamChangeImg.median;
  35009. var loopOutCount = 0;
  35010. var ifOverTime = () => {
  35011. var is = changeCount >= maxChangeTex || changeCount * median + getCount * 0.01 + 0.0004 * panos.length * loopOutCount > maxWaitDur; //不换贴图也要一丢丢计算时间
  35012. /* if(is){
  35013. console.log('OverTime, changeCount', changeCount)
  35014. } */
  35015. return is;
  35016. };
  35017. this.depthSampler.addEventListener('changeImg', changeTexCount);
  35018. var maxChangePanoCount = Math.min(panos.length, this.depthSampler.maxDataCount); //在lastIndex清空前最多可以有的mainPano的数量。 限制数量,否则一直changeTex很卡
  35019. outer: for (var i = lastIndex, j = panos.length; i < maxChangePanoCount /* j */; i++) {
  35020. var pano = panos[i];
  35021. var others = panos.slice(i + 1, j);
  35022. lastIndex = i;
  35023. if (!pano.pointcloud.hasDepthTex && i > 0) break; //点云的情况下最好不改相机位置,因为其他位置点云还没加载完,所以不判断当前点以外的漫游点
  35024. viewer.addTimeMark('sortByScore', 'start');
  35025. var g = Common$1.sortByScore(others, [], [Images360.scoreFunctions.distanceSquaredNew(pano) //900个点时至少耗时0.3
  35026. ]);
  35027. loopOutCount++;
  35028. viewer.addTimeMark('sortByScore', 'end');
  35029. var _loop = function _loop() {
  35030. var item = g[a];
  35031. if (item.item == pano) return 0; // continue
  35032. if (_this.neighbourMap[pano.id][item.item.id] != void 0 && _this.neighbourMap[item.item.id][pano.id] != void 0 /* this.isNeighbour(pano,item.item,{dontCompute:true}) != void 0 */) return 0; // continue
  35033. //确定结果了就不需要算
  35034. //console.log('check isNeighbour', pano.id, item.item.id)
  35035. var byCloud = !pano.pointcloud.hasDepthTex;
  35036. //const computeTwoDir = <maxChangePanoCount
  35037. var computeTwoDir = _this.depthSampler.nearPanos.includes(item.item) || _this.depthSampler.imgDatas.some(e => e.pano == item.item);
  35038. //一定数量内允许双向计算,也就是允许changeTex. 这样一来,每到一个新的pano最多只有开头一秒卡一点,不然一直changeTex很卡
  35039. var result = _this.isNeighbour(pano, item.item, {
  35040. onlyUseTex: !byCloud,
  35041. computeDirFirst: true,
  35042. computeTwoDir
  35043. }); //计算
  35044. if (result != void 0) {
  35045. //计算了 (byTex时其实并不一定)
  35046. //console.log('提前计算neighbor', pano.id, item.item.id)
  35047. _this.dispatchEvent({
  35048. type: 'getNeighbourAuto',
  35049. panos: [pano, item.item]
  35050. });
  35051. if (byCloud) {
  35052. //只计算一次
  35053. //console.log('提前计算neighbor byCloud', result, pano.id, item.item.id)
  35054. return 1; // break outer
  35055. }
  35056. getCount++;
  35057. if (ifOverTime()) {
  35058. return 1; // break outer
  35059. }
  35060. }
  35061. },
  35062. _ret;
  35063. for (var a = 0, b = g.length; a < b; a++) {
  35064. _ret = _loop();
  35065. if (_ret === 0) continue;
  35066. if (_ret === 1) break outer;
  35067. }
  35068. lastIndex = i + 1; //这轮结束
  35069. if (ifOverTime()) {
  35070. break outer;
  35071. }
  35072. }
  35073. /* if(changeCount){
  35074. console.log( 'changeCount', changeCount)
  35075. } */
  35076. this.depthSampler.removeEventListener('changeImg', changeTexCount);
  35077. if (!inited) {
  35078. inited = true;
  35079. this.addEventListener('loadedDepthImg', e => {
  35080. //console.log('loadedDepthImg',e.pano)
  35081. var computeTwoDir = this.depthSampler.nearPanos.includes(e.pano) || this.depthSampler.imgDatas.some(a => e.pano == a.pano);
  35082. if (computeTwoDir) {
  35083. lastIndex = 0; //主要针对刚打开场景第一个点有杂点时单向不成功,要立即进一步双向计算ifShelter
  35084. }
  35085. });
  35086. }
  35087. var costTime = Date.now() - startTime; //控制好时间,否则转动时卡(主要是开始拖拽时延迟). 尽量在转完一圈使附近disMap都算完后costTime和maxWaitDur接近
  35088. //costTime > maxWaitDur && changeCount == 0 && console.log( 'costTime:',costTime)
  35089. //console.log('getCount',getCount)
  35090. };
  35091. }();
  35092. Images360.filters = {
  35093. inPanoDirection: function inPanoDirection(pos, dir, i, log) {
  35094. //pano在mouse的方向上
  35095. return function (pano) {
  35096. var o = pano.position.clone().sub(pos).normalize();
  35097. if (o.dot(dir) > i) return true;
  35098. var r = pano.floorPosition.clone().sub(pos).normalize();
  35099. if (r.dot(dir) > i) return true;
  35100. };
  35101. },
  35102. inFloorDirection: function inFloorDirection(pos, dir, min, log) {
  35103. //pano在mouse的水平方向上
  35104. return function (pano) {
  35105. var vec = new Vector2().subVectors(pano.floorPosition, pos).normalize();
  35106. var dir_ = new Vector2().copy(dir).normalize();
  35107. log && console.log('dire', pano.id, vec.dot(dir_));
  35108. return vec.dot(dir_) > min;
  35109. /* var i = pano.floorPosition.clone().sub(pos).setZ(0).normalize();//改成在xz方向上,否则点击墙面不会移动
  35110. return i.dot(dir.clone().setZ(0)) > min */
  35111. };
  35112. },
  35113. isNotBehindNormal: function isNotBehindNormal(e, t) {
  35114. var i = new Vector3();
  35115. return t = t.clone(), function (n) {
  35116. var r = i.copy(n.position).sub(e).normalize();
  35117. return r.dot(t) > 0;
  35118. };
  35119. },
  35120. isCloseEnoughTo: function isCloseEnoughTo(e, t) {
  35121. return function (i) {
  35122. //因为marker可能比地面高,所以识别范围要比marker看起来更近一些。(因为投影到地板的位置比marker更近)
  35123. return e.distanceTo(i.floorPosition) < t; //许钟文
  35124. };
  35125. },
  35126. not: function not(e) {
  35127. return function (t) {
  35128. return t !== e;
  35129. };
  35130. },
  35131. isEnabled: function isEnabled() {
  35132. return function (t) {
  35133. return t.enabled;
  35134. };
  35135. },
  35136. isVisible: function isVisible() {
  35137. return function (t) {
  35138. return t.visible;
  35139. };
  35140. }
  35141. };
  35142. Images360.scoreFunctions = {
  35143. direction: function direction(curPos, dir, ifLog) {
  35144. return function (pano) {
  35145. var pos1 = /* pano.floorPosition */pano.position; //旧:改为权重放在marker上,这样对有斜坡的更准确,如上楼, 但这样近距离的pano角度就会向下了,以致于走不到
  35146. var n = pos1.clone().sub(curPos).normalize();
  35147. //ifLog && console.log('direction', pano.id, n.dot(dir) * directionFactor )
  35148. return n.dot(dir) * directionFactor;
  35149. };
  35150. },
  35151. distance: function distance(pos1) {
  35152. var r = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  35153. var ifLog = arguments.length > 2 ? arguments[2] : undefined;
  35154. if (pos1.position) pos1 = pos1.position;
  35155. return function (pano) {
  35156. //许钟文 改
  35157. var pos2 = pano.position.clone();
  35158. //ifLog && console.log('distance', pano.id, pos1.distance(pos2) * -1 )
  35159. return pos1.distanceTo(pos2) * -1 * r;
  35160. };
  35161. },
  35162. distanceSquared: function distanceSquared(pos1) {
  35163. var r = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  35164. if (pos1.position) pos1 = pos1.position;
  35165. return function (pano) {
  35166. //许钟文 改
  35167. var pos2 = pano.position.clone();
  35168. return pos1.distanceToSquared(pos2) * -1 * r;
  35169. };
  35170. },
  35171. distanceSquaredNew: function distanceSquaredNew(mainPano) {
  35172. var r = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  35173. var disMap = viewer.images360.disMap;
  35174. return function (pano) {
  35175. //许钟文 改
  35176. if (!disMap[mainPano.id]) disMap[mainPano.id] = {};
  35177. if (!disMap[pano.id]) disMap[pano.id] = {};
  35178. var dis;
  35179. if (disMap[mainPano.id][pano.id] != void 0) dis = disMap[mainPano.id][pano.id];else if (disMap[pano.id][mainPano.id]) dis = disMap[pano.id][mainPano.id];else {
  35180. dis = Images360.scoreFunctions.distanceSquared(mainPano, 1)(pano);
  35181. disMap[mainPano.id][pano.id] = dis;
  35182. }
  35183. return dis * r;
  35184. };
  35185. },
  35186. angle: function angle(e, t) {
  35187. return function (i) {
  35188. var n = i.position.clone().sub(e).normalize();
  35189. return n.angleTo(t) * Potree.config.navigation.angleFactor;
  35190. };
  35191. }
  35192. };
  35193. Images360.sortFunctions = {
  35194. //排序函数,涉及到两个item相减
  35195. floorDisSquaredToPoint: function floorDisSquaredToPoint(e) {
  35196. return function (t, i) {
  35197. return t.floorPosition.distanceToSquared(e) - i.floorPosition.distanceToSquared(e);
  35198. };
  35199. },
  35200. disSquaredToPoint: function disSquaredToPoint(e) {
  35201. return function (t, i) {
  35202. return t.position.distanceToSquared(e) - i.position.distanceToSquared(e);
  35203. };
  35204. }
  35205. };
  35206. Images360.prototype.updateCube = function () {
  35207. //增加细分的版本,且垂直方向上取中位数 侧边多条
  35208. var minDis = 0.2; //pano和墙距离不能小于相机的near
  35209. var height = 1; //准确计算的话要分别计算两个pano的地面、天花板之间的俯仰角,和pano之间的还不一样。这里统一假设一个比较小的高度,因高度越大 maxSinAlpha 越大
  35210. var minTanBeta = minDis / height; /* (pano0.position.z - pano0.floorPosition.z) */
  35211. var minBeta = Math.atan(minTanBeta);
  35212. var maxSinAlpha = Math.cos(minBeta); // 注:beta = Math/2 - alpha
  35213. var skyHeight = 50;
  35214. return function (pano0, pano1) {
  35215. if (Potree.settings.displayMode != 'showPanos' || pano0 == pano1 || this.cubePanos.some(e => e.pano == pano0 && e.matrix.equals(pano0.pointcloud.matrix)) && (!pano1 || this.cubePanos.some(e => e.pano == pano1 && e.matrix.equals(pano1.pointcloud.matrix)))) return;
  35216. this.cubePanos = [{
  35217. pano: pano0,
  35218. matrix: pano0.pointcloud.matrix.clone()
  35219. }, {
  35220. pano: pano1,
  35221. matrix: pano1 && pano1.pointcloud.matrix.clone()
  35222. }];
  35223. viewer.addTimeMark('updateCube', 'start');
  35224. //console.log('updateCube',pano0.id, pano1&&pano1.id)
  35225. var useBound = (bound, size) => {
  35226. size = size || bound.getSize(new Vector3());
  35227. var center = bound.getCenter(new Vector3());
  35228. size.max(new Vector3(HighMapCubeWidth, HighMapCubeWidth, HighMapCubeWidth));
  35229. this.cube.geometry = new BoxBufferGeometry(1, 1, 1, 1);
  35230. this.cube.scale.copy(size);
  35231. this.cube.position.copy(center);
  35232. if (Potree.settings.testCube) {
  35233. this.cubeTest.geometry = this.cube.geometry;
  35234. this.cubeTest.scale.copy(size);
  35235. this.cubeTest.position.copy(center);
  35236. }
  35237. return 'useBound';
  35238. };
  35239. var getPanoBound = (pano, dis) => {
  35240. //因漫游点可能在点云外部,如室外平地,所以需要union进漫游点
  35241. var panoBound = new Box3();
  35242. panoBound.expandByPoint(pano.position);
  35243. var margin = dis ? Math.max(dis * 0.1, 10) : 10;
  35244. panoBound.expandByVector(new Vector3(margin, margin, margin)); //give pano a margin 。 随着bound扩大,margin要相应扩大,否则当距离很远时看起来就像没有
  35245. return pano.pointcloud.bound.clone().union(panoBound);
  35246. };
  35247. this.cube.geometry.dispose();
  35248. if (pano1) {
  35249. //过渡
  35250. var dontAddSides;
  35251. var dis = pano0.position.distanceTo(pano1.position);
  35252. if (dis == 0) return;
  35253. var sinAlpha = Math.abs(pano0.position.z - pano1.position.z) / dis; //俯仰角的sin,随角度增大而增大 0-1
  35254. var score = (1 + sinAlpha * 20) * dis; //score越大创建的mesh越不适合
  35255. var isNeighbour = this.isNeighbour(pano0, pano1);
  35256. //console.log(pano0.id, pano1.id, maxSinAlpha.toFixed(2), sinAlpha.toFixed(2), score.toFixed(2), isNeighbour)
  35257. if (sinAlpha > maxSinAlpha || !pano0.pointcloud.hasDepthTex || !pano1.pointcloud.hasDepthTex || (isNeighbour ? score > 100 : score > 50)) {
  35258. var bound = getPanoBound(pano0, dis).union(getPanoBound(pano1, dis));
  35259. var size = bound.getSize(new Vector3());
  35260. var max = Math.max(size.x, size.y, size.z);
  35261. size.set(max, max, max); //距离太远的数据集,过渡会畸变。所以扩大skybox,且为立方体
  35262. return useBound(bound, size);
  35263. } else if (isNeighbour ? score > 70 : score > 15) {
  35264. dontAddSides = true; //pano间有阻挡时得到的side点可能使通道变窄,所以去掉。
  35265. }
  35266. //俯仰角增大时可能不在同一楼层,算出来的mesh不太好,所以更倾向直接使用cube,或去除side。
  35267. var half = browser.isMobile() ? 4 : 8; //自行输入 (点云计算的慢,还不准)
  35268. var count1 = 2 * half; //偶数个 每个pano向 外dir 个数
  35269. //奇数个的好处:在窄空间内能探测到最远距离,坏处是前方有尖角。偶数个的坏处就是可能检测距离太近。
  35270. var getDir = (angle_, vec) => {
  35271. //旋转获得水平向量
  35272. var rotMat = new Matrix4().makeRotationZ(angle_);
  35273. return vec.clone().applyMatrix4(rotMat);
  35274. };
  35275. var getFar = (dir, pano, origin, height) => {
  35276. //获取在这个方向上和墙体intersect的距离
  35277. //在垂直方向上分出多个方向,取一个最可能的接近真实的距离
  35278. var maxH = 40,
  35279. minH = 2,
  35280. minR = 0.5,
  35281. maxR = 2;
  35282. height = height == void 0 ? Math.min(skyHeight, pano.ceilZ - pano.floorPosition.z) : height;
  35283. //let r = height (maxH - minH)* 0.14 // 高度越小,角度越小
  35284. //let r = minR + ( maxR - minR) * THREE.Math.clamp((height - minH) / (maxH - minH),0,1) //THREE.Math.smoothstep(currentDis, op.nearBound, op.farBound);
  35285. var r = math.linearClamp(height, [minH, maxH], [minR, maxR]);
  35286. var getZ = deg => {
  35287. deg *= r;
  35288. deg = MathUtils.clamp(deg, 1, 80);
  35289. return Math.tan(MathUtils.degToRad(deg));
  35290. };
  35291. var dirs_; //注意:角度太大会碰到天花板或地板,越远越容易碰到, 在地下停车场就会伸展不开。 更多取接近0度的,否则围墙矮一点就会取到远处。
  35292. dirs_ = [15, 8, 3, -1, -5];
  35293. dirs_ = dirs_.map(deg => dir.clone().setZ(getZ(deg)).normalize());
  35294. var max = 50;
  35295. var count2 = dirs_.length;
  35296. var disArr = dirs_.map((dir_, i) => {
  35297. var intersect = this.getIntersect(pano, dir_, origin);
  35298. var projectLen = intersect && intersect.distance ? dir_.dot(dir) * intersect.distance : max; //得到project在dir的长度
  35299. return projectLen; //得水平距离
  35300. });
  35301. //console.log(pano ? pano.id : 'side','disArr', disArr.slice(0))
  35302. disArr.sort((a, b) => {
  35303. return b - a;
  35304. }); //从大到小
  35305. //console.log(pano ? pano.id : 'side','disArr', disArr)
  35306. var dis = disArr[Math.floor(count2 / 2 - 0.5)]; //对半、取前(中位数)
  35307. return dis;
  35308. };
  35309. var sideCount = [0, 0];
  35310. var addPos = (pano, vec) => {
  35311. //添加这个pano这一侧向外半圆的顶点
  35312. //添加pano位置对应的最高点最低点:
  35313. var minZ, maxZ;
  35314. minZ = pano.floorPosition.z;
  35315. maxZ = pano.getCeilHeight();
  35316. if (maxZ == Infinity) maxZ = skyHeight + pano.position.z; //maxZ = Math.max(skyHeight, maxZ)
  35317. [maxZ, minZ].forEach(z => {
  35318. posArr.push(pano.position.clone().setZ(z));
  35319. });
  35320. //在画面上线条从左往右数
  35321. var angle = Math.PI / (count1 - 1);
  35322. var dirs = []; //平分这半边180度
  35323. for (var i = 0; i < count1; i++) {
  35324. dirs.push(getDir(Math.PI / 2 - i * angle, vec)); //正的在左边
  35325. }
  35326. var dirs2 = dirs.map(dir => {
  35327. return {
  35328. dir,
  35329. dis: getFar(dir, pano)
  35330. };
  35331. });
  35332. //剔除那些突然间离相机很近的dir。有可能是拍摄的人、或者杆子、树
  35333. /* dirs2.forEach((e,i)=>{
  35334. console.log(i, e.dis)
  35335. let smallThanBefore = ()=>{
  35336. return dirs2[i-1].dis / e.dis > maxRatio
  35337. }
  35338. let smallThanAfter = ()=>{
  35339. return dirs2[i+1].dis / e.dis > maxRatio
  35340. }
  35341. if(i>0 && i<count1-1 && smallThanBefore() && smallThanAfter()){//比左右两边都小很多
  35342. e.disB = (dirs2[i-1].dis + dirs2[i+1].dis) / 2 //平均数
  35343. console.log('两者之间',i,e.disB)
  35344. }else if(i==count1-1 && smallThanBefore() ) {//比前者小很多
  35345. e.disB = dirs2[i-1].dis * 0.8
  35346. console.log('smallThanBefore', i, e.disB)
  35347. }else if(i==0 && smallThanAfter() ){//比后者小很多
  35348. e.disB = dirs2[i+1].dis * 0.8
  35349. console.log('smallThanAftere', i, e.disB)
  35350. }
  35351. }) */
  35352. var maxRatio1 = 3,
  35353. maxRatio2 = 8; //超过maxRatio1就要加入判断,而最终结果的设限其实是maxRatio2
  35354. var minWidth = 0.5;
  35355. var computeWidth = (start, end) => {
  35356. start += 1; //不包含start和end
  35357. var count = end - start;
  35358. var dis = 0;
  35359. for (var m = start; m < end; m++) {
  35360. //得平均数
  35361. dis += dirs2[m].dis;
  35362. }
  35363. dis /= count;
  35364. var angle = Math.PI / (count1 - 1) * count / 2;
  35365. var width = dis * Math.tan(angle); //得到block的半宽度
  35366. return width;
  35367. };
  35368. var changeDis = (start, end) => {
  35369. //不包含start
  35370. start += 1; //不包含start和end
  35371. for (var m = start; m < end; m++) {
  35372. dirs2[m].disB = dirs2[end].dis * 0.8;
  35373. //console.log('changeDis', m, dirs2[m].disB)
  35374. }
  35375. };
  35376. var start = -1;
  35377. for (var _i = 0; _i < count1; _i++) {
  35378. //遍历时将左边dis比之小很多且宽度较小的改大
  35379. //console.log(i, dirs2[i].dis)
  35380. var j = _i - 1;
  35381. var ratios = 0;
  35382. while (j > start && dirs2[_i].dis / dirs2[j].dis > maxRatio1) {
  35383. ratios += dirs2[_i].dis / dirs2[j].dis;
  35384. j--;
  35385. }
  35386. var count = _i - j - 1;
  35387. ratios /= count;
  35388. if (count > 0 && computeWidth(j, _i) < minWidth * ratios / maxRatio2) {
  35389. //怎么感觉好像改成了视觉宽度小于某个值即可,那直接用count好了?
  35390. changeDis(j, _i);
  35391. start = _i; //在此之前的修改过,之后不用再判断
  35392. }
  35393. /* if(count > 0 && (count == 1 || computeWidth(j,i)<minWidth)){//若只有一个不用判断宽度直接修改
  35394. changeDis(j,i)
  35395. start = i //在此之前的修改过,之后不用再判断
  35396. } */
  35397. }
  35398. dirs2.forEach((e, index) => {
  35399. var dir = e.dir.clone().multiplyScalar(e.disB || e.dis);
  35400. [maxZ, minZ].forEach(z => {
  35401. posArr.push(pano.position.clone().setZ(z).add(dir)); //获取到外墙点
  35402. });
  35403. });
  35404. };
  35405. var addSide = () => {
  35406. //两个漫游点间两边各加一些侧线
  35407. //中点处的
  35408. var top0 = pano0.ceilZ == Infinity ? pano0.position.z + skyHeight : pano0.ceilZ;
  35409. var top1 = pano1.ceilZ == Infinity ? pano1.position.z + skyHeight : pano1.ceilZ;
  35410. var midMaxZ = (top0 + top1) / 2;
  35411. var midMinZ = (pano0.floorPosition.z + pano1.floorPosition.z) / 2;
  35412. var mid = new Vector3().addVectors(pano0.position, pano1.position).multiplyScalar(0.5);
  35413. if (!dontAddSides) {
  35414. if (pano0.pointcloud.hasDepthTex && pano0.pointcloud.hasDepthTex) {
  35415. var panos = [pano0, pano1];
  35416. var vecs = [vec.clone().negate(), vec];
  35417. var axis = [[-1, 1], [1, -1]];
  35418. var dis2d = new Vector2().subVectors(pano0.position, pano1.position).length(); //水平上的距离
  35419. var maxDis = 50,
  35420. _minDis = 0.5,
  35421. minR = 0.2,
  35422. maxR = 1.2;
  35423. //let r = maxR - ( maxR - minR) * THREE.Math.clamp((dis2d - minDis) / (maxDis - minDis),0,1) //dis2d越大,角度要越小 //THREE.Math.smoothstep(currentDis, op.nearBound, op.farBound);
  35424. var r = math.linearClamp(dis2d, [_minDis, maxDis], [maxR, minR]);
  35425. //console.log('dis2d',dis2d,'r',r)
  35426. var angles = (browser.isMobile() /* || dis2d<4 */ ? [60] : [50, 70] /* [35,65] */).map(deg => {
  35427. //正的在左边 尽量能够平分中间这段墙体。 (角度为从中心向外)
  35428. var angle = MathUtils.clamp(deg * r, 5, 80);
  35429. //console.log('angle',angle)
  35430. return MathUtils.degToRad(angle);
  35431. });
  35432. axis.forEach((axis_, index0) => {
  35433. var disToSides = [];
  35434. var accordingPano = index0 == 0 ? pano0 : pano1; //根据离该点在vec方向上的距离顺序来存顶点
  35435. panos.forEach((pano, index) => {
  35436. var dirs = angles.map(angle => getDir(axis_[index] * angle, vecs[index])); //一侧的若干角度
  35437. dirs.forEach((dir_, i) => {
  35438. var dis1 = getFar(dir_, pano);
  35439. var disToPano2d = dis1 * Math.cos(angles[i]);
  35440. if (disToPano2d < dis2d) {
  35441. //超过的话都到另一半pano的半圆了,不计入。(角度越小越容易超过)
  35442. var disToSide = dis1 * Math.sin(angles[i]);
  35443. if (pano != accordingPano) {
  35444. disToPano2d = dis2d - disToPano2d; //反一下
  35445. }
  35446. dir_.multiplyScalar(dis1);
  35447. disToSides.push({
  35448. disToSide,
  35449. disToPano2d,
  35450. pano,
  35451. dir_
  35452. });
  35453. } else {
  35454. //console.log('超过',index0,index,i)
  35455. }
  35456. });
  35457. });
  35458. if (disToSides.length) {
  35459. //disToSides.sort((a,b)=>{return b-a});//从大到小
  35460. //由距离accordingPano的近到远:
  35461. disToSides.sort((a, b) => {
  35462. return a.disToPano2d - b.disToPano2d;
  35463. });
  35464. //console.log('disToSides', index0, disToSides)
  35465. if (disToSides.length == 1 && disToSides[0].disToSide < 0.5) {
  35466. disToSides = []; //如果太近直接去除
  35467. }
  35468. disToSides.forEach(e => {
  35469. //求z
  35470. var ratio = e.disToPano2d / dis2d;
  35471. var r = accordingPano == pano0 ? 1 - ratio : ratio;
  35472. var sideMaxZ_ = top0 * r + top1 * (1 - r);
  35473. var sideMinZ_ = pano0.floorPosition.z * r + pano1.floorPosition.z * (1 - r);
  35474. [sideMaxZ_, sideMinZ_].forEach(z => {
  35475. posArr.push(e.pano.position.clone().setZ(z).add(e.dir_)); //是直接使用最长dis的那个intersect点好还是mid
  35476. });
  35477. });
  35478. }
  35479. sideCount[index0] = disToSides.length; //记录侧边个数
  35480. });
  35481. } else {
  35482. //这段针对点云时,仅测试才会执行到
  35483. sideCount = [1, 1];
  35484. var sideDirs = [getDir(Math.PI / 2, vec), getDir(-Math.PI / 2, vec)];
  35485. sideDirs.forEach((dir_, index) => {
  35486. var dis = getFar(dir_, null, mid, midMaxZ - midMinZ); //直接从中点求两侧的距离
  35487. dir_.multiplyScalar( /* Math.max( */dis /* , sideDis[index]) */);
  35488. [midMaxZ, midMinZ].forEach(z => {
  35489. posArr.push(mid.clone().setZ(z).add(dir_));
  35490. });
  35491. });
  35492. }
  35493. }
  35494. //中心:
  35495. [midMaxZ, midMinZ].forEach(z => {
  35496. posArr.push(mid.clone().setZ(z));
  35497. });
  35498. };
  35499. //positions存放顺序:pano的每边的 zMax和zMin 、count1个dir的点 ;侧边的点 ;连接处顶底的中点
  35500. var addFaces = () => {
  35501. var getPI = function getPI(index, posType, panoIndex) {
  35502. //获取顶点序号
  35503. return 2 + (count1 * 2 + 2) * panoIndex + index * 2 + (posType == 'top' ? 0 : 1);
  35504. };
  35505. var getSidePI = function getSidePI(index, posType, panoIndex) {
  35506. //获取侧边顶点序号
  35507. if (panoIndex == 1) index += sideCount[0];
  35508. return getPI(index, posType, 2) - 2;
  35509. };
  35510. var getPanoPI = function getPanoPI(posType, panoIndex) {
  35511. //获取pano处对应的点序号
  35512. return getPI(-1, posType, panoIndex);
  35513. };
  35514. var topCenter = posArr.length - 2; //最后添加的两个中心点
  35515. var btmCenter = posArr.length - 1;
  35516. for (var i = 0; i < 2; i++) {
  35517. for (var index = 1; index < count1; index++) {
  35518. //pano外侧半圆围墙
  35519. faceArr.push([getPI(index, 'top', i), getPI(index - 1, 'btm', i), getPI(index - 1, 'top', i)],
  35520. //加入一块四方面
  35521. [getPI(index, 'top', i), getPI(index, 'btm', i), getPI(index - 1, 'btm', i)]);
  35522. faceArr.push([getPI(index, 'top', i), getPI(index - 1, 'top', i), getPanoPI('top', i)]); //天花板扇形
  35523. faceArr.push([getPI(index, 'btm', i), getPI(index - 1, 'btm', i), getPanoPI('btm', i)]); //地板扇形
  35524. }
  35525. var j = (i + 1) % 2; //另一个pano
  35526. //侧边
  35527. for (var u = 0; u <= sideCount[i]; u++) {
  35528. //侧边每个四方的左上右上左下右下四个点
  35529. var pLT = u == 0 ? getPI(0, 'top', i) : getSidePI(u - 1, 'top', i);
  35530. var pRT = u == sideCount[i] ? getPI(count1 - 1, 'top', j) : getSidePI(u, 'top', i);
  35531. var pLB = u == 0 ? getPI(0, 'btm', i) : getSidePI(u - 1, 'btm', i);
  35532. var pRB = u == sideCount[i] ? getPI(count1 - 1, 'btm', j) : getSidePI(u, 'btm', i);
  35533. faceArr.push([pLT, pLB, pRB], [pLT, pRB, pRT]); //外侧四方面
  35534. faceArr.push([pLT, topCenter, pRT], [pLB, btmCenter, pRB]); //顶部和底部到整体中心的扇形(由于点的顺序是根据和两个pano的距离,因此到中心的夹角并没按顺序排列,所以可能会重叠)
  35535. if (i == 0) {
  35536. //只需要算一次
  35537. //顶部和底部中心与两个pano边构成的三角形
  35538. if (u == 0) {
  35539. faceArr.push([pLT, getPI(count1 - 1, 'top', i), topCenter], [pLB, getPI(count1 - 1, 'btm', i), btmCenter]);
  35540. }
  35541. //不能用else 因为当length==0时u==0也==sideCount[i],此时就是要两个面
  35542. if (u == sideCount[i]) {
  35543. faceArr.push([pRT, getPI(0, 'top', j), topCenter], [pRB, getPI(0, 'btm', j), btmCenter]);
  35544. }
  35545. }
  35546. }
  35547. }
  35548. };
  35549. var posArr = [];
  35550. var faceArr = [];
  35551. //两点连线的水平向量
  35552. var vec = new Vector3().subVectors(pano0.position, pano1.position).setZ(0).normalize();
  35553. /* let sideDis0 = */
  35554. addPos(pano0, vec);
  35555. /* let sideDis1 = */
  35556. addPos(pano1, vec.clone().negate());
  35557. addSide();
  35558. addFaces();
  35559. //MeshDraw.updateGeometry(this.cube.geometry, posArr, faceArr)
  35560. var geo = MeshDraw.createGeometry(posArr, faceArr);
  35561. this.cube.geometry = geo;
  35562. this.cube.scale.set(1, 1, 1);
  35563. this.cube.position.set(0, 0, 0);
  35564. if (Potree.settings.testCube) {
  35565. this.cubeTest.geometry = geo;
  35566. this.cubeTest.scale.set(1, 1, 1);
  35567. this.cubeTest.position.set(0, 0, 0);
  35568. }
  35569. } else {
  35570. useBound(getPanoBound(pano0));
  35571. }
  35572. viewer.addTimeMark('updateCube', 'end');
  35573. return true;
  35574. /*
  35575. 关于卡顿:
  35576. 即使使用cube,若scale设置为只容纳两个pano,也会卡顿。但也是有的卡有的不卡。
  35577. 若按照原先的复杂geo,一般在平直的街道上行走流畅,经过拐弯或者复杂区域较卡。减小geo复杂度没有什么作用。
  35578. 注: 修改skybox,若不准的话,会遮住其他mesh,比如marker。尤其在没有深度贴图时。
  35579. 耗时: chrome: 20+ ,但是firefox:500+ 咋回事 ? iphonex safari: 40+
  35580. */
  35581. };
  35582. }();
  35583. /*
  35584. viewer.images360.flyToPano(viewer.images360.getPano('1765955963253690368|70','sid'))
  35585. viewer.images360.flyToPano(viewer.images360.lastPano)
  35586. */
  35587. /**
  35588. * @author alteredq / http://alteredqualia.com/
  35589. *
  35590. * Full-screen textured quad shader
  35591. */
  35592. var CopyShader = {
  35593. uniforms: {
  35594. "tDiffuse": {
  35595. value: null
  35596. },
  35597. "opacity": {
  35598. value: 1.0
  35599. }
  35600. },
  35601. vertexShader: ["varying vec2 vUv;", "void main() {", "vUv = uv;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}"].join("\n"),
  35602. fragmentShader: ["uniform float opacity;", "uniform sampler2D tDiffuse;", "varying vec2 vUv;", "void main() {", "vec4 texel = texture2D( tDiffuse, vUv );",
  35603. //如果开启premultipliedAlpha用这个,否则用注释的
  35604. "gl_FragColor = opacity * texel;",
  35605. //"gl_FragColor = texture2D( tDiffuse, vUv );",
  35606. //"gl_FragColor.a *= opacity;",
  35607. "}"].join("\n")
  35608. };
  35609. /**
  35610. * @author alteredq / http://alteredqualia.com/
  35611. */
  35612. var Pass = function Pass() {
  35613. // if set to true, the pass is processed by the composer
  35614. this.enabled = true;
  35615. // if set to true, the pass indicates to swap read and write buffer after rendering
  35616. this.needsSwap = true;
  35617. // if set to true, the pass clears its buffer before rendering
  35618. this.clear = false;
  35619. // if set to true, the result of the pass is rendered to screen
  35620. this.renderToScreen = false;
  35621. };
  35622. Object.assign(Pass.prototype, {
  35623. setSize: function setSize(width, height) {},
  35624. render: function render(renderer, writeBuffer, readBuffer, delta, maskActive) {
  35625. console.error('THREE.Pass: .render() must be implemented in derived pass.');
  35626. }
  35627. });
  35628. var ShaderPass = function ShaderPass(shader, textureID) {
  35629. Pass.call(this);
  35630. this.textureID = textureID !== undefined ? textureID : "tDiffuse";
  35631. if (shader instanceof ShaderMaterial) {
  35632. this.uniforms = shader.uniforms;
  35633. this.material = shader;
  35634. } else if (shader) {
  35635. this.uniforms = UniformsUtils.clone(shader.uniforms);
  35636. this.material = new ShaderMaterial({
  35637. defines: Object.assign({}, shader.defines),
  35638. uniforms: this.uniforms,
  35639. vertexShader: shader.vertexShader,
  35640. fragmentShader: shader.fragmentShader,
  35641. transparent: true //add
  35642. });
  35643. }
  35644. this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
  35645. this.scene = new Scene();
  35646. this.quad = new Mesh(new PlaneBufferGeometry(2, 2), null);
  35647. this.quad.frustumCulled = false; // Avoid getting clipped
  35648. this.scene.add(this.quad);
  35649. };
  35650. ShaderPass.prototype = Object.assign(Object.create(Pass.prototype), {
  35651. constructor: ShaderPass,
  35652. render: function render(scene, camera, viewports, renderer, writeBuffer, readBuffer, delta, maskActive) {
  35653. var oldTarget = renderer.getRenderTarget();
  35654. /* if(this.readTarget){ //add
  35655. readBuffer = oldTarget
  35656. } */
  35657. if (this.uniforms[this.textureID]) {
  35658. this.uniforms[this.textureID].value = readBuffer.texture;
  35659. }
  35660. this.quad.material = this.material;
  35661. if (this.renderToScreen) {
  35662. renderer.render(this.scene, this.camera);
  35663. } else {
  35664. renderer.setRenderTarget(writeBuffer);
  35665. if (this.clear) renderer.clear();
  35666. renderer.render(this.scene, this.camera);
  35667. renderer.setRenderTarget(oldTarget);
  35668. }
  35669. }
  35670. });
  35671. // Copied from three.js: WebGLRenderer.js
  35672. function paramThreeToGL$1(_gl, p) {
  35673. var extension;
  35674. if (p === RepeatWrapping) return _gl.REPEAT;
  35675. if (p === ClampToEdgeWrapping) return _gl.CLAMP_TO_EDGE;
  35676. if (p === MirroredRepeatWrapping) return _gl.MIRRORED_REPEAT;
  35677. if (p === NearestFilter) return _gl.NEAREST;
  35678. if (p === NearestMipMapNearestFilter) return _gl.NEAREST_MIPMAP_NEAREST;
  35679. if (p === NearestMipMapLinearFilter) return _gl.NEAREST_MIPMAP_LINEAR;
  35680. if (p === LinearFilter) return _gl.LINEAR;
  35681. if (p === LinearMipMapNearestFilter) return _gl.LINEAR_MIPMAP_NEAREST;
  35682. if (p === LinearMipMapLinearFilter) return _gl.LINEAR_MIPMAP_LINEAR;
  35683. if (p === UnsignedByteType) return _gl.UNSIGNED_BYTE;
  35684. if (p === UnsignedShort4444Type) return _gl.UNSIGNED_SHORT_4_4_4_4;
  35685. if (p === UnsignedShort5551Type) return _gl.UNSIGNED_SHORT_5_5_5_1;
  35686. if (p === UnsignedShort565Type) return _gl.UNSIGNED_SHORT_5_6_5;
  35687. if (p === ByteType) return _gl.BYTE;
  35688. if (p === ShortType) return _gl.SHORT;
  35689. if (p === UnsignedShortType) return _gl.UNSIGNED_SHORT;
  35690. if (p === IntType) return _gl.INT;
  35691. if (p === UnsignedIntType) return _gl.UNSIGNED_INT;
  35692. if (p === FloatType) return _gl.FLOAT;
  35693. if (p === HalfFloatType) {
  35694. extension = extensions.get('OES_texture_half_float');
  35695. if (extension !== null) return extension.HALF_FLOAT_OES;
  35696. }
  35697. if (p === AlphaFormat) return _gl.ALPHA;
  35698. if (p === RGBFormat) return _gl.RGB;
  35699. if (p === RGBAFormat) return _gl.RGBA;
  35700. if (p === LuminanceFormat) return _gl.LUMINANCE;
  35701. if (p === LuminanceAlphaFormat) return _gl.LUMINANCE_ALPHA;
  35702. if (p === DepthFormat) return _gl.DEPTH_COMPONENT;
  35703. if (p === DepthStencilFormat) return _gl.DEPTH_STENCIL;
  35704. if (p === AddEquation) return _gl.FUNC_ADD;
  35705. if (p === SubtractEquation) return _gl.FUNC_SUBTRACT;
  35706. if (p === ReverseSubtractEquation) return _gl.FUNC_REVERSE_SUBTRACT;
  35707. if (p === ZeroFactor) return _gl.ZERO;
  35708. if (p === OneFactor) return _gl.ONE;
  35709. if (p === SrcColorFactor) return _gl.SRC_COLOR;
  35710. if (p === OneMinusSrcColorFactor) return _gl.ONE_MINUS_SRC_COLOR;
  35711. if (p === SrcAlphaFactor) return _gl.SRC_ALPHA;
  35712. if (p === OneMinusSrcAlphaFactor) return _gl.ONE_MINUS_SRC_ALPHA;
  35713. if (p === DstAlphaFactor) return _gl.DST_ALPHA;
  35714. if (p === OneMinusDstAlphaFactor) return _gl.ONE_MINUS_DST_ALPHA;
  35715. if (p === DstColorFactor) return _gl.DST_COLOR;
  35716. if (p === OneMinusDstColorFactor) return _gl.ONE_MINUS_DST_COLOR;
  35717. if (p === SrcAlphaSaturateFactor) return _gl.SRC_ALPHA_SATURATE;
  35718. if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
  35719. extension = extensions.get('WEBGL_compressed_texture_s3tc');
  35720. if (extension !== null) {
  35721. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
  35722. if (p === RGBA_S3TC_DXT1_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
  35723. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
  35724. if (p === RGBA_S3TC_DXT5_Format$1) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
  35725. }
  35726. }
  35727. if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
  35728. extension = extensions.get('WEBGL_compressed_texture_pvrtc');
  35729. if (extension !== null) {
  35730. if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  35731. if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  35732. if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
  35733. if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
  35734. }
  35735. }
  35736. if (p === RGB_ETC1_Format) {
  35737. extension = extensions.get('WEBGL_compressed_texture_etc1');
  35738. if (extension !== null) return extension.COMPRESSED_RGB_ETC1_WEBGL;
  35739. }
  35740. if (p === MinEquation || p === MaxEquation) {
  35741. extension = extensions.get('EXT_blend_minmax');
  35742. if (extension !== null) {
  35743. if (p === MinEquation) return extension.MIN_EXT;
  35744. if (p === MaxEquation) return extension.MAX_EXT;
  35745. }
  35746. }
  35747. if (p === UnsignedInt248Type) {
  35748. extension = extensions.get('WEBGL_depth_texture');
  35749. if (extension !== null) return extension.UNSIGNED_INT_24_8_WEBGL;
  35750. }
  35751. return 0;
  35752. }
  35753. ;
  35754. var attributeLocations$1 = {
  35755. "position": {
  35756. name: "position",
  35757. location: 0
  35758. },
  35759. "color": {
  35760. name: "color",
  35761. location: 1
  35762. },
  35763. "rgba": {
  35764. name: "color",
  35765. location: 1
  35766. },
  35767. "intensity": {
  35768. name: "intensity",
  35769. location: 2
  35770. },
  35771. "classification": {
  35772. name: "classification",
  35773. location: 3
  35774. },
  35775. "returnNumber": {
  35776. name: "returnNumber",
  35777. location: 4
  35778. },
  35779. "return number": {
  35780. name: "returnNumber",
  35781. location: 4
  35782. },
  35783. "returns": {
  35784. name: "returnNumber",
  35785. location: 4
  35786. },
  35787. "numberOfReturns": {
  35788. name: "numberOfReturns",
  35789. location: 5
  35790. },
  35791. "number of returns": {
  35792. name: "numberOfReturns",
  35793. location: 5
  35794. },
  35795. "pointSourceID": {
  35796. name: "pointSourceID",
  35797. location: 6
  35798. },
  35799. "source id": {
  35800. name: "pointSourceID",
  35801. location: 6
  35802. },
  35803. "point source id": {
  35804. name: "pointSourceID",
  35805. location: 6
  35806. },
  35807. "indices": {
  35808. name: "indices",
  35809. location: 7
  35810. },
  35811. "normal": {
  35812. name: "normal",
  35813. location: 8
  35814. },
  35815. "spacing": {
  35816. name: "spacing",
  35817. location: 9
  35818. },
  35819. "gps-time": {
  35820. name: "gpsTime",
  35821. location: 10
  35822. },
  35823. "aExtra": {
  35824. name: "aExtra",
  35825. location: 11
  35826. },
  35827. //add:
  35828. ir: {
  35829. name: "ir",
  35830. location: 12
  35831. },
  35832. temp: {
  35833. name: "temp",
  35834. location: 13
  35835. }
  35836. };
  35837. class Shader$1 {
  35838. constructor(gl, name, vsSource, fsSource) {
  35839. this.gl = gl;
  35840. this.name = name;
  35841. this.vsSource = vsSource;
  35842. this.fsSource = fsSource;
  35843. this.cache = new Map();
  35844. this.vs = null;
  35845. this.fs = null;
  35846. this.program = null;
  35847. this.uniformLocations = {};
  35848. this.attributeLocations = {};
  35849. this.uniformBlockIndices = {};
  35850. this.uniformBlocks = {};
  35851. this.uniforms = {};
  35852. this.update(vsSource, fsSource);
  35853. }
  35854. update(vsSource, fsSource) {
  35855. this.vsSource = vsSource;
  35856. this.fsSource = fsSource;
  35857. this.linkProgram();
  35858. }
  35859. compileShader(shader, source) {
  35860. var gl = this.gl;
  35861. gl.shaderSource(shader, source);
  35862. gl.compileShader(shader);
  35863. var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  35864. if (!success) {
  35865. var info = gl.getShaderInfoLog(shader);
  35866. var numberedSource = source.split("\n").map((a, i) => "".concat(i + 1).padEnd(5) + a).join("\n");
  35867. throw "could not compile shader ".concat(this.name, ": ").concat(info, ", \n").concat(numberedSource);
  35868. }
  35869. }
  35870. linkProgram() {
  35871. var tStart = performance.now();
  35872. var gl = this.gl;
  35873. this.uniformLocations = {};
  35874. this.attributeLocations = {};
  35875. this.uniforms = {};
  35876. gl.useProgram(null);
  35877. var cached = this.cache.get("".concat(this.vsSource, ", ").concat(this.fsSource));
  35878. if (cached) {
  35879. this.program = cached.program;
  35880. this.vs = cached.vs;
  35881. this.fs = cached.fs;
  35882. this.attributeLocations = cached.attributeLocations;
  35883. this.uniformLocations = cached.uniformLocations;
  35884. this.uniformBlocks = cached.uniformBlocks;
  35885. this.uniforms = cached.uniforms;
  35886. return;
  35887. } else {
  35888. this.vs = gl.createShader(gl.VERTEX_SHADER);
  35889. this.fs = gl.createShader(gl.FRAGMENT_SHADER);
  35890. this.program = gl.createProgram();
  35891. if (!gl.isProgram(this.program)) {
  35892. //创建失败 开启多个页面可能会,原因是webglcontextlost
  35893. //console.error('创建program失败');
  35894. viewer.dispatchEvent('webglError', {
  35895. msg: 'potreeRenderer创建program失败'
  35896. });
  35897. console.log(this.vs);
  35898. console.log(this.fs);
  35899. return;
  35900. }
  35901. for (var name of Object.keys(attributeLocations$1)) {
  35902. var location = attributeLocations$1[name].location;
  35903. var glslName = attributeLocations$1[name].name;
  35904. gl.bindAttribLocation(this.program, location, glslName);
  35905. }
  35906. this.compileShader(this.vs, this.vsSource);
  35907. this.compileShader(this.fs, this.fsSource);
  35908. var program = this.program;
  35909. gl.attachShader(program, this.vs);
  35910. gl.attachShader(program, this.fs);
  35911. gl.linkProgram(program);
  35912. gl.detachShader(program, this.vs);
  35913. gl.detachShader(program, this.fs);
  35914. // 检测当前程序链接状态
  35915. var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  35916. if (!success) {
  35917. var info = gl.getProgramInfoLog(program);
  35918. throw "could not link program ".concat(this.name, ": ").concat(info);
  35919. }
  35920. {
  35921. // attribute locations
  35922. var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
  35923. for (var i = 0; i < numAttributes; i++) {
  35924. var attribute = gl.getActiveAttrib(program, i);
  35925. var _location = gl.getAttribLocation(program, attribute.name);
  35926. this.attributeLocations[attribute.name] = _location;
  35927. }
  35928. }
  35929. {
  35930. // uniform locations
  35931. var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  35932. for (var _i = 0; _i < numUniforms; _i++) {
  35933. var uniform = gl.getActiveUniform(program, _i);
  35934. var _location2 = gl.getUniformLocation(program, uniform.name);
  35935. this.uniformLocations[uniform.name] = _location2;
  35936. this.uniforms[uniform.name] = {
  35937. location: _location2,
  35938. value: null
  35939. };
  35940. }
  35941. }
  35942. // uniform blocks
  35943. if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
  35944. //WebGL2RenderingContext在mac的safari14以下是没有定义的
  35945. var numBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  35946. for (var _i2 = 0; _i2 < numBlocks; _i2++) {
  35947. var blockName = gl.getActiveUniformBlockName(program, _i2);
  35948. var blockIndex = gl.getUniformBlockIndex(program, blockName);
  35949. this.uniformBlockIndices[blockName] = blockIndex;
  35950. gl.uniformBlockBinding(program, blockIndex, blockIndex);
  35951. var dataSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
  35952. var uBuffer = gl.createBuffer();
  35953. gl.bindBuffer(gl.UNIFORM_BUFFER, uBuffer);
  35954. gl.bufferData(gl.UNIFORM_BUFFER, dataSize, gl.DYNAMIC_READ);
  35955. gl.bindBufferBase(gl.UNIFORM_BUFFER, blockIndex, uBuffer);
  35956. gl.bindBuffer(gl.UNIFORM_BUFFER, null);
  35957. this.uniformBlocks[blockName] = {
  35958. name: blockName,
  35959. index: blockIndex,
  35960. dataSize: dataSize,
  35961. buffer: uBuffer
  35962. };
  35963. }
  35964. }
  35965. var _cached = {
  35966. program: this.program,
  35967. vs: this.vs,
  35968. fs: this.fs,
  35969. attributeLocations: this.attributeLocations,
  35970. uniformLocations: this.uniformLocations,
  35971. uniforms: this.uniforms,
  35972. uniformBlocks: this.uniformBlocks
  35973. };
  35974. this.cache.set("".concat(this.vsSource, ", ").concat(this.fsSource), _cached);
  35975. }
  35976. var tEnd = performance.now();
  35977. var duration = tEnd - tStart;
  35978. //console.log(`shader compile duration: ${duration.toFixed(3)}`);
  35979. }
  35980. setUniformMatrix4(name, value) {
  35981. var gl = this.gl;
  35982. var location = this.uniformLocations[name];
  35983. if (location == null) {
  35984. return;
  35985. }
  35986. var tmp = new Float32Array(value.elements);
  35987. gl.uniformMatrix4fv(location, false, tmp);
  35988. }
  35989. setUniform1f(name, value) {
  35990. var gl = this.gl;
  35991. var uniform = this.uniforms[name];
  35992. if (uniform === undefined) {
  35993. return;
  35994. }
  35995. if (uniform.value === value) {
  35996. return;
  35997. }
  35998. uniform.value = value;
  35999. gl.uniform1f(uniform.location, value);
  36000. }
  36001. setUniformBoolean(name, value) {
  36002. var gl = this.gl;
  36003. var uniform = this.uniforms[name];
  36004. if (uniform === undefined) {
  36005. return;
  36006. }
  36007. if (uniform.value === value) {
  36008. return;
  36009. }
  36010. uniform.value = value;
  36011. gl.uniform1i(uniform.location, value);
  36012. }
  36013. setUniformTexture(name, value) {
  36014. var gl = this.gl;
  36015. var location = this.uniformLocations[name];
  36016. if (location == null) {
  36017. return;
  36018. }
  36019. gl.uniform1i(location, value);
  36020. }
  36021. setUniform2f(name, value) {
  36022. var gl = this.gl;
  36023. var location = this.uniformLocations[name];
  36024. if (location == null) {
  36025. return;
  36026. }
  36027. gl.uniform2f(location, value[0], value[1]);
  36028. }
  36029. setUniform3f(name, value) {
  36030. var gl = this.gl;
  36031. var location = this.uniformLocations[name];
  36032. if (location == null) {
  36033. return;
  36034. }
  36035. gl.uniform3f(location, value[0], value[1], value[2]);
  36036. }
  36037. setUniform(name, value) {
  36038. if (value.constructor === Matrix4) {
  36039. this.setUniformMatrix4(name, value);
  36040. } else if (typeof value === "number") {
  36041. this.setUniform1f(name, value);
  36042. } else if (typeof value === "boolean") {
  36043. this.setUniformBoolean(name, value);
  36044. } else if (value instanceof WebGLTexture$1) {
  36045. this.setUniformTexture(name, value);
  36046. } else if (value instanceof Array) {
  36047. if (value.length === 2) {
  36048. this.setUniform2f(name, value);
  36049. } else if (value.length === 3) {
  36050. this.setUniform3f(name, value);
  36051. }
  36052. } else {
  36053. console.error("unhandled uniform type: ", name, value);
  36054. }
  36055. }
  36056. setUniform1i(name, value) {
  36057. var gl = this.gl;
  36058. var location = this.uniformLocations[name];
  36059. if (location == null) {
  36060. return;
  36061. }
  36062. gl.uniform1i(location, value);
  36063. }
  36064. }
  36065. ;
  36066. class WebGLTexture$1 {
  36067. constructor(gl, texture, threeRenderer) {
  36068. this.gl = gl;
  36069. this.texture = texture;
  36070. if (texture.image && !(texture.image instanceof Image) && !texture.isCanvasTexture && !texture.isDataTexture) {
  36071. //renderTarget的texture在创建renderTarget时已经初始化过 见setupRenderTarget
  36072. this.id = threeRenderer.properties.get(texture).__webglTexture || gl.createTexture();
  36073. this.isFromRenderTarget = true;
  36074. } else {
  36075. this.id = gl.createTexture();
  36076. }
  36077. this.target = gl.TEXTURE_2D;
  36078. this.version = -1;
  36079. this.update(texture);
  36080. }
  36081. update() {
  36082. if (!this.texture.image) {
  36083. this.version = this.texture.version;
  36084. return;
  36085. }
  36086. //if(this.isFromRenderTarget)return //没找到怎么update。 在three.js里的uploadTexture没找到。 这里会报错,可能是 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ),类似depthTex的写法
  36087. var gl = this.gl;
  36088. var texture = this.texture;
  36089. if (this.version === texture.version) {
  36090. return;
  36091. }
  36092. this.target = gl.TEXTURE_2D;
  36093. gl.bindTexture(this.target, this.id);
  36094. var level = 0;
  36095. var internalFormat = paramThreeToGL$1(gl, texture.format);
  36096. var width = texture.image.width;
  36097. var height = texture.image.height;
  36098. var border = 0;
  36099. var srcFormat = internalFormat;
  36100. var srcType = paramThreeToGL$1(gl, texture.type);
  36101. var data;
  36102. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
  36103. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
  36104. gl.pixelStorei(gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
  36105. if (texture instanceof DataTexture) {
  36106. data = texture.image.data;
  36107. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  36108. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  36109. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL$1(gl, texture.magFilter));
  36110. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL$1(gl, texture.minFilter));
  36111. gl.texImage2D(this.target, level, internalFormat, width, height, border, srcFormat, srcType, data);
  36112. } else if (texture instanceof CanvasTexture || texture instanceof Texture) {
  36113. data = texture.image;
  36114. gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, paramThreeToGL$1(gl, texture.wrapS));
  36115. gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, paramThreeToGL$1(gl, texture.wrapT));
  36116. gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, paramThreeToGL$1(gl, texture.magFilter));
  36117. gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, paramThreeToGL$1(gl, texture.minFilter));
  36118. if (this.isFromRenderTarget) {
  36119. //咋写?
  36120. //gl.texImage2D( 3553, 0, internalFormat, width, height, 0, srcFormat, srcType, null )
  36121. //console.log('isFromRenderTarget')
  36122. } else {
  36123. gl.texImage2D(this.target, level, internalFormat, internalFormat, srcType, data); //这个参数怎么跟我查的不一样呢
  36124. }
  36125. if (texture instanceof Texture) {
  36126. gl.generateMipmap(gl.TEXTURE_2D);
  36127. }
  36128. }
  36129. gl.bindTexture(this.target, null);
  36130. this.version = texture.version;
  36131. }
  36132. }
  36133. ;
  36134. class WebGLBuffer$1 {
  36135. constructor() {
  36136. this.numElements = 0;
  36137. this.vao = null;
  36138. this.vbos = new Map();
  36139. }
  36140. }
  36141. ;
  36142. class Renderer$1 {
  36143. constructor(threeRenderer) {
  36144. this.threeRenderer = threeRenderer;
  36145. this.gl = this.threeRenderer.getContext();
  36146. this.buffers = new Map();
  36147. this.shaders = new Map();
  36148. this.textures = new Map();
  36149. this.glTypeMapping = new Map();
  36150. this.glTypeMapping.set(Float32Array, this.gl.FLOAT);
  36151. this.glTypeMapping.set(Uint8Array, this.gl.UNSIGNED_BYTE);
  36152. this.glTypeMapping.set(Uint16Array, this.gl.UNSIGNED_SHORT); //貌似不能用,uint只能是Uint32Array
  36153. this.toggle = 0;
  36154. }
  36155. deleteBuffer(geometry) {
  36156. var gl = this.gl;
  36157. var webglBuffer = this.buffers.get(geometry);
  36158. if (webglBuffer != null) {
  36159. for (var attributeName in geometry.attributes) {
  36160. gl.deleteBuffer(webglBuffer.vbos.get(attributeName).handle);
  36161. }
  36162. this.buffers.delete(geometry);
  36163. }
  36164. }
  36165. createBuffer(geometry) {
  36166. var gl = this.gl;
  36167. var webglBuffer = new WebGLBuffer$1();
  36168. webglBuffer.vao = gl.createVertexArray();
  36169. webglBuffer.numElements = geometry.attributes.position.count;
  36170. gl.bindVertexArray(webglBuffer.vao);
  36171. for (var attributeName in geometry.attributes) {
  36172. var bufferAttribute = geometry.attributes[attributeName];
  36173. var vbo = gl.createBuffer();
  36174. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  36175. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  36176. var normalized = bufferAttribute.normalized;
  36177. var type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  36178. if (attributeLocations$1[attributeName] === undefined) {
  36179. //attributeLocation = attributeLocations["aExtra"];
  36180. } else {
  36181. var attributeLocation = attributeLocations$1[attributeName].location;
  36182. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  36183. gl.enableVertexAttribArray(attributeLocation);
  36184. }
  36185. webglBuffer.vbos.set(attributeName, {
  36186. handle: vbo,
  36187. name: attributeName,
  36188. count: bufferAttribute.count,
  36189. itemSize: bufferAttribute.itemSize,
  36190. type: geometry.attributes.position.array.constructor,
  36191. version: 0
  36192. });
  36193. }
  36194. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  36195. gl.bindVertexArray(null);
  36196. var disposeHandler = event => {
  36197. this.deleteBuffer(geometry);
  36198. geometry.removeEventListener("dispose", disposeHandler);
  36199. };
  36200. geometry.addEventListener("dispose", disposeHandler);
  36201. return webglBuffer;
  36202. }
  36203. updateBuffer(geometry) {
  36204. var gl = this.gl;
  36205. var webglBuffer = this.buffers.get(geometry);
  36206. gl.bindVertexArray(webglBuffer.vao);
  36207. for (var attributeName in geometry.attributes) {
  36208. var bufferAttribute = geometry.attributes[attributeName];
  36209. var normalized = bufferAttribute.normalized;
  36210. var type = this.glTypeMapping.get(bufferAttribute.array.constructor);
  36211. var vbo = null;
  36212. if (!webglBuffer.vbos.has(attributeName)) {
  36213. vbo = gl.createBuffer();
  36214. webglBuffer.vbos.set(attributeName, {
  36215. handle: vbo,
  36216. name: attributeName,
  36217. count: bufferAttribute.count,
  36218. itemSize: bufferAttribute.itemSize,
  36219. type: geometry.attributes.position.array.constructor,
  36220. version: bufferAttribute.version
  36221. });
  36222. } else {
  36223. vbo = webglBuffer.vbos.get(attributeName).handle;
  36224. webglBuffer.vbos.get(attributeName).version = bufferAttribute.version;
  36225. }
  36226. gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  36227. gl.bufferData(gl.ARRAY_BUFFER, bufferAttribute.array, gl.STATIC_DRAW);
  36228. if (attributeLocations$1[attributeName] === undefined) {
  36229. //attributeLocation = attributeLocations["aExtra"];
  36230. } else {
  36231. var attributeLocation = attributeLocations$1[attributeName].location;
  36232. gl.vertexAttribPointer(attributeLocation, bufferAttribute.itemSize, type, normalized, 0, 0);
  36233. gl.enableVertexAttribArray(attributeLocation);
  36234. }
  36235. }
  36236. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  36237. gl.bindVertexArray(null);
  36238. }
  36239. traverse(scene) {
  36240. var octrees = [];
  36241. var stack = [scene];
  36242. while (stack.length > 0) {
  36243. var node = stack.pop();
  36244. if (node instanceof PointCloudTree) {
  36245. octrees.push(node);
  36246. continue;
  36247. }
  36248. var visibleChildren = node.children.filter(c => c.visible);
  36249. stack.push(...visibleChildren);
  36250. }
  36251. var result = {
  36252. octrees: octrees
  36253. };
  36254. return result;
  36255. }
  36256. renderNodes(octree, nodes, visibilityTextureData, camera, target, shader, params) {
  36257. var _this = this;
  36258. viewer.addTimeMark('renderNodes', 'start');
  36259. var gl = this.gl;
  36260. var material = params.material ? params.material : octree.material;
  36261. var shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  36262. var view = camera.matrixWorldInverse;
  36263. if (params.viewOverride) {
  36264. view = params.viewOverride;
  36265. }
  36266. var worldView = new Matrix4();
  36267. var mat4holder = new Float32Array(16);
  36268. var i = 0;
  36269. //---------从renderOctree搬到这----
  36270. shader.setUniform1f("size", material.usePanoMap ? Potree.config.material.absolutePanoramaSize * Math.min(window.devicePixelRatio, 2) : material.size); //usePanoMap时控制在不大不小的范围内感觉较好,考虑到有的点云稀疏,用大一点的点
  36271. shader.setUniform1f("uOpacity", material.usePanoMap ? 1 : material.opacity);
  36272. shader.setUniform3f("uColor", material.color.toArray());
  36273. shader.setUniform2f("temperRange", material.uniforms.temperRange.value.toArray());
  36274. var currentTextureBindingPoint = params.currentTextureBindingPoint;
  36275. if (material.pointSizeType >= 0 /* && window.needvisibilityTexture */) {
  36276. if (material.pointSizeType === PointSizeType.ADAPTIVE || material.activeAttributeName === "level of detail") {
  36277. var vnNodes = params.vnTextureNodes != null ? params.vnTextureNodes : nodes;
  36278. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  36279. var vnt = material.visibleNodesTexture;
  36280. var data = vnt.image.data;
  36281. data.set(visibilityTextureData.data);
  36282. vnt.needsUpdate = true;
  36283. var webGLTexture = this.textures.get(vnt);
  36284. webGLTexture.update(); //不加这个会闪烁
  36285. var vnWebGLTexture = this.textures.get(material.visibleNodesTexture); //不知道为什么这段从renderOctree中移过来,会崩溃。暂时不移动了
  36286. if (vnWebGLTexture) {
  36287. shader.setUniform1i("visibleNodes", currentTextureBindingPoint);
  36288. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36289. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  36290. currentTextureBindingPoint++;
  36291. }
  36292. }
  36293. }
  36294. /* if (material.pointSizeType >= 0) {
  36295. if (material.pointSizeType === PointSizeType.ADAPTIVE ||
  36296. material.activeAttributeName === "level of detail") {
  36297. let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
  36298. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  36299. const vnt = material.visibleNodesTexture;
  36300. const data = vnt.image.data;
  36301. data.set(visibilityTextureData.data);
  36302. vnt.needsUpdate = true;
  36303. }
  36304. } */
  36305. var transparent = false;
  36306. if (params.transparent !== undefined) {
  36307. transparent = params.transparent && material.opacity < 1;
  36308. } else {
  36309. transparent = material.usePanoMap ? false : material.useFilterByNormal || material.opacity < 1; //add useFilterByNormal
  36310. }
  36311. if (transparent) {
  36312. gl.enable(gl.BLEND);
  36313. if (params.notAdditiveBlending) {
  36314. gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); //NormalBlending
  36315. //gl.disable(gl.DEPTH_TEST); gl.depthMask(true); //old
  36316. gl.enable(gl.DEPTH_TEST);
  36317. gl.depthMask(false);
  36318. //gl.enable(gl.DEPTH_TEST); gl.depthMask(true);
  36319. //gl.disable(gl.DEPTH_TEST);
  36320. /* 几种选择:
  36321. 1 都开启: 当opacity很小时发黑且遮住其他透明物体
  36322. 2 关闭depthTest开启depthWrite 自己深度错乱,前排挡不住后排, 自己将后排的晚渲染可以改善,见disSqToCamZ_。 但前排不透明遮不住它!之前没发现
  36323. 3 开启depthTest关闭depthWrite 除了2的缺点,还挡不住后排的半透明物体(因为后渲染),或被先渲染的前排透明物体完全遮住。(写入深度值就会遮住后方。总之透明的要后渲染而且按距离排序,但mesh和点云排序是不可能了) 采用这项
  36324. 4 关闭depthTest关闭depthWrite 连不透明物都遮不住它,后排透明物能遮住它
  36325. */
  36326. } else {
  36327. gl.blendFunc(gl.SRC_ALPHA, gl.ONE); //AdditiveBlending 原本
  36328. gl.disable(gl.DEPTH_TEST);
  36329. gl.depthMask(false);
  36330. }
  36331. } else {
  36332. gl.disable(gl.BLEND);
  36333. gl.depthMask(true);
  36334. gl.enable(gl.DEPTH_TEST);
  36335. }
  36336. if (params.blendFunc !== undefined) {
  36337. gl.enable(gl.BLEND);
  36338. gl.blendFunc(...params.blendFunc);
  36339. }
  36340. if (params.depthTest !== undefined) {
  36341. if (params.depthTest === true) {
  36342. gl.enable(gl.DEPTH_TEST);
  36343. } else {
  36344. gl.disable(gl.DEPTH_TEST);
  36345. }
  36346. }
  36347. if (params.depthWrite !== undefined) {
  36348. if (params.depthWrite === true) {
  36349. gl.depthMask(true);
  36350. } else {
  36351. gl.depthMask(false);
  36352. }
  36353. }
  36354. //---------------------------------
  36355. var _loop = function _loop() {
  36356. if (exports.debug.allowedNodes !== undefined) {
  36357. if (!exports.debug.allowedNodes.includes(node.name)) {
  36358. return 1; // continue
  36359. }
  36360. }
  36361. var world = node.sceneNode.matrixWorld;
  36362. worldView.multiplyMatrices(view, world);
  36363. if (visibilityTextureData) {
  36364. var vnStart = visibilityTextureData.offsets.get(node);
  36365. //console.log('vnStart',vnStart)
  36366. shader.setUniform1f("uVNStart", vnStart);
  36367. }
  36368. var level = node.getLevel();
  36369. if (node.debug) {
  36370. shader.setUniform("uDebug", true);
  36371. } else {
  36372. shader.setUniform("uDebug", false);
  36373. }
  36374. // let isLeaf = false;
  36375. // if(node instanceof PointCloudOctreeNode){
  36376. // isLeaf = Object.keys(node.children).length === 0;
  36377. // }else if(node instanceof PointCloudArena4DNode){
  36378. // isLeaf = node.geometryNode.isLeaf;
  36379. // }
  36380. // shader.setUniform("uIsLeafNode", isLeaf);
  36381. // let isLeaf = node.children.filter(n => n != null).length === 0;
  36382. // if(!isLeaf){
  36383. // continue;
  36384. // }
  36385. // TODO consider passing matrices in an array to avoid uniformMatrix4fv overhead
  36386. var lModel = shader.uniformLocations["modelMatrix"];
  36387. if (lModel) {
  36388. mat4holder.set(world.elements);
  36389. gl.uniformMatrix4fv(lModel, false, mat4holder);
  36390. }
  36391. var lModelView = shader.uniformLocations["modelViewMatrix"];
  36392. //mat4holder.set(worldView.elements);
  36393. // faster then set in chrome 63
  36394. for (var j = 0; j < 16; j++) {
  36395. mat4holder[j] = worldView.elements[j];
  36396. }
  36397. gl.uniformMatrix4fv(lModelView, false, mat4holder);
  36398. {
  36399. // Clip Polygons
  36400. if (material.clipPolygons && material.clipPolygons.length > 0) {
  36401. var clipPolygonVCount = [];
  36402. var worldViewProjMatrices = [];
  36403. for (var clipPolygon of material.clipPolygons) {
  36404. var _view = clipPolygon.viewMatrix;
  36405. var proj = clipPolygon.projMatrix;
  36406. var worldViewProj = proj.clone().multiply(_view).multiply(world);
  36407. clipPolygonVCount.push(clipPolygon.markers.length);
  36408. worldViewProjMatrices.push(worldViewProj);
  36409. }
  36410. var flattenedMatrices = [].concat(...worldViewProjMatrices.map(m => m.elements));
  36411. var flattenedVertices = new Array(8 * 3 * material.clipPolygons.length);
  36412. for (var _i3 = 0; _i3 < material.clipPolygons.length; _i3++) {
  36413. var _clipPolygon = material.clipPolygons[_i3];
  36414. for (var _j = 0; _j < _clipPolygon.markers.length; _j++) {
  36415. flattenedVertices[_i3 * 24 + (_j * 3 + 0)] = _clipPolygon.markers[_j].position.x;
  36416. flattenedVertices[_i3 * 24 + (_j * 3 + 1)] = _clipPolygon.markers[_j].position.y;
  36417. flattenedVertices[_i3 * 24 + (_j * 3 + 2)] = _clipPolygon.markers[_j].position.z;
  36418. }
  36419. }
  36420. var lClipPolygonVCount = shader.uniformLocations["uClipPolygonVCount[0]"];
  36421. gl.uniform1iv(lClipPolygonVCount, clipPolygonVCount);
  36422. var lClipPolygonVP = shader.uniformLocations["uClipPolygonWVP[0]"];
  36423. gl.uniformMatrix4fv(lClipPolygonVP, false, flattenedMatrices);
  36424. var lClipPolygons = shader.uniformLocations["uClipPolygonVertices[0]"];
  36425. gl.uniform3fv(lClipPolygons, flattenedVertices);
  36426. }
  36427. }
  36428. //shader.setUniformMatrix4("modelMatrix", world);
  36429. //shader.setUniformMatrix4("modelViewMatrix", worldView);
  36430. shader.setUniform1f("uLevel", level);
  36431. shader.setUniform1f("levelPercent", octree.nodeMaxLevel ? level / octree.nodeMaxLevel : 0.5); //xzw add
  36432. shader.setUniform1f("uNodeSpacing", node.geometryNode.estimatedSpacing);
  36433. shader.setUniform1f("uPCIndex", i);
  36434. // uBBSize
  36435. if (shadowMaps.length > 0) {
  36436. var lShadowMap = shader.uniformLocations["uShadowMap[0]"];
  36437. shader.setUniform3f("uShadowColor", material.uniforms.uShadowColor.value);
  36438. var bindingStart = 5;
  36439. var bindingPoints = new Array(shadowMaps.length).fill(bindingStart).map((a, i) => a + i);
  36440. gl.uniform1iv(lShadowMap, bindingPoints);
  36441. for (var _i4 = 0; _i4 < shadowMaps.length; _i4++) {
  36442. var shadowMap = shadowMaps[_i4];
  36443. var bindingPoint = bindingPoints[_i4];
  36444. var glTexture = _this.threeRenderer.properties.get(shadowMap.target.texture).__webglTexture;
  36445. gl.activeTexture(gl["TEXTURE".concat(bindingPoint)]);
  36446. gl.bindTexture(gl.TEXTURE_2D, glTexture);
  36447. }
  36448. {
  36449. var worldViewMatrices = shadowMaps.map(sm => sm.camera.matrixWorldInverse).map(view => new Matrix4().multiplyMatrices(view, world));
  36450. var _flattenedMatrices = [].concat(...worldViewMatrices.map(c => c.elements));
  36451. var lWorldView = shader.uniformLocations["uShadowWorldView[0]"];
  36452. gl.uniformMatrix4fv(lWorldView, false, _flattenedMatrices);
  36453. }
  36454. {
  36455. var _flattenedMatrices2 = [].concat(...shadowMaps.map(sm => sm.camera.projectionMatrix.elements));
  36456. var lProj = shader.uniformLocations["uShadowProj[0]"];
  36457. gl.uniformMatrix4fv(lProj, false, _flattenedMatrices2);
  36458. }
  36459. }
  36460. var geometry = node.geometryNode.geometry;
  36461. if (geometry.attributes["gps-time"]) {
  36462. var bufferAttribute = geometry.attributes["gps-time"];
  36463. var attGPS = octree.getAttribute("gps-time");
  36464. var initialRange = attGPS.initialRange;
  36465. var initialRangeSize = initialRange[1] - initialRange[0];
  36466. var globalRange = attGPS.range;
  36467. var globalRangeSize = globalRange[1] - globalRange[0];
  36468. var scale = initialRangeSize / globalRangeSize;
  36469. var offset = -(globalRange[0] - initialRange[0]) / initialRangeSize;
  36470. scale = Number.isNaN(scale) ? 1 : scale;
  36471. offset = Number.isNaN(offset) ? 0 : offset;
  36472. shader.setUniform1f("uGpsScale", scale);
  36473. shader.setUniform1f("uGpsOffset", offset);
  36474. //shader.setUniform2f("uFilterGPSTimeClipRange", [-Infinity, Infinity]);
  36475. var uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  36476. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  36477. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  36478. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  36479. var normalizedClipRange = [(uFilterGPSTimeClipRange[0] - globalRange[0]) / globalRangeSize, (uFilterGPSTimeClipRange[1] - globalRange[0]) / globalRangeSize];
  36480. shader.setUniform2f("uFilterGPSTimeClipRange", normalizedClipRange);
  36481. // // ranges in full gps coordinate system
  36482. // const globalRange = attGPS.range;
  36483. // const bufferRange = bufferAttribute.potree.range;
  36484. // // ranges in [0, 1]
  36485. // // normalizedGlobalRange = [0, 1]
  36486. // // normalizedBufferRange: norm buffer within norm global range e.g. [0.2, 0.8]
  36487. // const globalWidth = globalRange[1] - globalRange[0];
  36488. // const normalizedBufferRange = [
  36489. // (bufferRange[0] - globalRange[0]) / globalWidth,
  36490. // (bufferRange[1] - globalRange[0]) / globalWidth,
  36491. // ];
  36492. // shader.setUniform2f("uNormalizedGpsBufferRange", normalizedBufferRange);
  36493. // let uFilterGPSTimeClipRange = material.uniforms.uFilterGPSTimeClipRange.value;
  36494. // let gpsCliPRangeMin = uFilterGPSTimeClipRange[0]
  36495. // let gpsCliPRangeMax = uFilterGPSTimeClipRange[1]
  36496. // shader.setUniform2f("uFilterGPSTimeClipRange", [gpsCliPRangeMin, gpsCliPRangeMax]);
  36497. // shader.setUniform1f("uGpsScale", bufferAttribute.potree.scale);
  36498. // shader.setUniform1f("uGpsOffset", bufferAttribute.potree.offset);
  36499. }
  36500. {
  36501. var uFilterReturnNumberRange = material.uniforms.uFilterReturnNumberRange.value;
  36502. var uFilterNumberOfReturnsRange = material.uniforms.uFilterNumberOfReturnsRange.value;
  36503. var uFilterPointSourceIDClipRange = material.uniforms.uFilterPointSourceIDClipRange.value;
  36504. shader.setUniform2f("uFilterReturnNumberRange", uFilterReturnNumberRange);
  36505. shader.setUniform2f("uFilterNumberOfReturnsRange", uFilterNumberOfReturnsRange);
  36506. shader.setUniform2f("uFilterPointSourceIDClipRange", uFilterPointSourceIDClipRange);
  36507. }
  36508. var webglBuffer = null;
  36509. if (!_this.buffers.has(geometry)) {
  36510. webglBuffer = _this.createBuffer(geometry);
  36511. _this.buffers.set(geometry, webglBuffer);
  36512. } else {
  36513. webglBuffer = _this.buffers.get(geometry);
  36514. for (var attributeName in geometry.attributes) {
  36515. var attribute = geometry.attributes[attributeName];
  36516. if (attribute.version > webglBuffer.vbos.get(attributeName).version) {
  36517. _this.updateBuffer(geometry);
  36518. }
  36519. }
  36520. }
  36521. gl.bindVertexArray(webglBuffer.vao);
  36522. var isExtraAttribute = attributeLocations$1[material.activeAttributeName] === undefined && Object.keys(geometry.attributes).includes(material.activeAttributeName);
  36523. if (isExtraAttribute) {
  36524. var attributeLocation = attributeLocations$1["aExtra"].location;
  36525. for (var _attributeName in geometry.attributes) {
  36526. var _bufferAttribute = geometry.attributes[_attributeName];
  36527. var _vbo = webglBuffer.vbos.get(_attributeName);
  36528. gl.bindBuffer(gl.ARRAY_BUFFER, _vbo.handle);
  36529. gl.disableVertexAttribArray(attributeLocation);
  36530. }
  36531. var attName = material.activeAttributeName;
  36532. var _bufferAttribute2 = geometry.attributes[attName];
  36533. var vbo = webglBuffer.vbos.get(attName);
  36534. if (_bufferAttribute2 !== undefined && vbo !== undefined) {
  36535. var type = _this.glTypeMapping.get(_bufferAttribute2.array.constructor);
  36536. var normalized = _bufferAttribute2.normalized;
  36537. gl.bindBuffer(gl.ARRAY_BUFFER, vbo.handle);
  36538. gl.vertexAttribPointer(attributeLocation, _bufferAttribute2.itemSize, type, normalized, 0, 0);
  36539. gl.enableVertexAttribArray(attributeLocation);
  36540. }
  36541. {
  36542. var attExtra = octree.pcoGeometry.pointAttributes.attributes.find(a => a.name === attName);
  36543. var range = material.getRange(attName);
  36544. if (!range) {
  36545. range = attExtra.range;
  36546. }
  36547. if (!range) {
  36548. range = [0, 1];
  36549. }
  36550. var _initialRange = attExtra.initialRange;
  36551. var _initialRangeSize = _initialRange[1] - _initialRange[0];
  36552. var _globalRange = range;
  36553. var _globalRangeSize = _globalRange[1] - _globalRange[0];
  36554. var _scale = _initialRangeSize / _globalRangeSize;
  36555. var _offset = -(_globalRange[0] - _initialRange[0]) / _initialRangeSize;
  36556. _scale = Number.isNaN(_scale) ? 1 : _scale;
  36557. _offset = Number.isNaN(_offset) ? 0 : _offset;
  36558. shader.setUniform1f("uExtraScale", _scale);
  36559. shader.setUniform1f("uExtraOffset", _offset);
  36560. }
  36561. } else {
  36562. for (var _attributeName2 in geometry.attributes) {
  36563. var _bufferAttribute3 = geometry.attributes[_attributeName2];
  36564. var _vbo2 = webglBuffer.vbos.get(_attributeName2);
  36565. if (attributeLocations$1[_attributeName2] !== undefined) {
  36566. var _attributeLocation = attributeLocations$1[_attributeName2].location;
  36567. var _type = _this.glTypeMapping.get(_bufferAttribute3.array.constructor);
  36568. var _normalized = _bufferAttribute3.normalized;
  36569. gl.bindBuffer(gl.ARRAY_BUFFER, _vbo2.handle);
  36570. gl.vertexAttribPointer(_attributeLocation, _bufferAttribute3.itemSize, _type, _normalized, 0, 0);
  36571. gl.enableVertexAttribArray(_attributeLocation);
  36572. }
  36573. }
  36574. }
  36575. var numPoints = webglBuffer.numElements;
  36576. gl.drawArrays(gl.POINTS, 0, numPoints);
  36577. //gl.drawArrays(gl.TRIANGLES, 0, numPoints);
  36578. i++;
  36579. };
  36580. for (var node of nodes) {
  36581. if (_loop()) continue;
  36582. }
  36583. gl.bindVertexArray(null);
  36584. viewer.addTimeMark('renderNodes', 'end');
  36585. }
  36586. renderOctree(octrees, nodes, camera, target) {
  36587. var params = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  36588. viewer.addTimeMark('renderOctree', 'start');
  36589. var octree;
  36590. if (octrees instanceof Array) {
  36591. octree = octrees[0];
  36592. } else {
  36593. octree = octrees;
  36594. octrees = [octree];
  36595. }
  36596. var gl = this.gl;
  36597. var material = params.material ? params.material : octree.material;
  36598. var shadowMaps = params.shadowMaps == null ? [] : params.shadowMaps;
  36599. var view = camera.matrixWorldInverse;
  36600. var viewInv = camera.matrixWorld;
  36601. if (params.viewOverride) {
  36602. view = params.viewOverride;
  36603. viewInv = view.clone().invert();
  36604. }
  36605. var proj = camera.projectionMatrix;
  36606. var projInv = proj.clone().invert();
  36607. //let worldView = new THREE.Matrix4();
  36608. var shader = null;
  36609. var visibilityTextureData = null;
  36610. var currentTextureBindingPoint = 0;
  36611. /* if (material.pointSizeType >= 0) {//最好搬到renderNodes
  36612. if (material.pointSizeType === PointSizeType.ADAPTIVE ||
  36613. material.activeAttributeName === "level of detail") {
  36614. let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
  36615. visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
  36616. const vnt = material.visibleNodesTexture;
  36617. const data = vnt.image.data;
  36618. data.set(visibilityTextureData.data);
  36619. vnt.needsUpdate = true;
  36620. }
  36621. }
  36622. */
  36623. {
  36624. // UPDATE SHADER AND TEXTURES
  36625. if (!this.shaders.has(material)) {
  36626. var [vs, fs] = [material.vertexShader, material.fragmentShader];
  36627. var _shader = new Shader$1(gl, "pointcloud", vs, fs);
  36628. this.shaders.set(material, _shader);
  36629. }
  36630. shader = this.shaders.get(material);
  36631. if (material.shaderNeedsUpdate) {
  36632. var [_vs, _fs] = [material.vertexShader, material.fragmentShader];
  36633. var numSnapshots = material.snapEnabled ? material.numSnapshots : 0;
  36634. var num_in_clipboxes = material.clipBoxes_in && material.clipBoxes_in.length ? material.clipBoxes_in.length : 0;
  36635. var num_out_clipboxes = material.clipBoxes_out && material.clipBoxes_out.length ? material.clipBoxes_out.length : 0;
  36636. var num_highlightBox = material.highlightBoxes && material.highlightBoxes.length ? material.highlightBoxes.length : 0;
  36637. var numClipSpheres = params.clipSpheres && params.clipSpheres.length ? params.clipSpheres.length : 0;
  36638. var numClipPolygons = material.clipPolygons && material.clipPolygons.length ? material.clipPolygons.length : 0;
  36639. var defines = ["#define num_shadowmaps ".concat(shadowMaps.length), "#define num_snapshots ".concat(numSnapshots), "#define num_in_clipboxes ".concat(num_in_clipboxes), //改
  36640. "#define num_out_clipboxes ".concat(num_out_clipboxes), //改
  36641. "#define num_highlightBox ".concat(num_highlightBox), //改
  36642. "#define num_clipspheres ".concat(numClipSpheres), "#define num_prism ".concat(material.prisms.pointsCount ? material.prisms.length : 0), //土方量数 如果num_prism>0,prismPointCountSum为0 会报错 :array size must be greater than zero
  36643. "#define prismPointCountSum ".concat(material.prisms.pointsCount), //点总个数
  36644. "#define prism_maxPointsCount ".concat(material.prisms.maxPointsCount) //单个prism最大点个数 (如果define也能传递个数数组,就不用再uniform里传了,呜 )
  36645. ];
  36646. //add:-----------
  36647. if (material.bigClipInBox) {
  36648. //裁剪下载
  36649. defines.push('#define bigClipInBox');
  36650. }
  36651. if (material.usePanoMap) {
  36652. defines.push("#define usePanoMap");
  36653. }
  36654. if (material.useFilterByNormal) {
  36655. defines.push("#define use_filter_by_normal");
  36656. //Potree.settings.editType == 'pano' ? defines.push("#define attenuated_opacity2") : defines.push("#define attenuated_opacity");
  36657. }
  36658. if (material.uniforms.baseHeightAreaMap.value) {
  36659. //根据模型高亮土方
  36660. defines.push('#define showBaseHeight');
  36661. }
  36662. //---------------
  36663. if (octree.pcoGeometry.root.isLoaded()) {
  36664. var attributes = octree.pcoGeometry.root.geometry.attributes;
  36665. if (attributes["gps-time"]) {
  36666. defines.push("#define clip_gps_enabled");
  36667. }
  36668. if (attributes["return number"]) {
  36669. defines.push("#define clip_return_number_enabled");
  36670. }
  36671. if (attributes["number of returns"]) {
  36672. defines.push("#define clip_number_of_returns_enabled");
  36673. }
  36674. if (attributes["source id"] || attributes["point source id"]) {
  36675. defines.push("#define clip_point_source_id_enabled");
  36676. }
  36677. }
  36678. var definesString = defines.join("\n");
  36679. var vsVersionIndex = _vs.indexOf("#version ");
  36680. var fsVersionIndex = _fs.indexOf("#version ");
  36681. if (vsVersionIndex >= 0) {
  36682. _vs = _vs.replace(/(#version .*)/, "$1\n".concat(definesString));
  36683. } else {
  36684. _vs = "".concat(definesString, "\n").concat(_vs);
  36685. }
  36686. if (fsVersionIndex >= 0) {
  36687. _fs = _fs.replace(/(#version .*)/, "$1\n".concat(definesString));
  36688. } else {
  36689. _fs = "".concat(definesString, "\n").concat(_fs);
  36690. }
  36691. shader.update(_vs, _fs);
  36692. material.shaderNeedsUpdate = false;
  36693. }
  36694. for (var uniformName of Object.keys(material.uniforms)) {
  36695. var uniform = material.uniforms[uniformName];
  36696. if (uniform.type == "t") {
  36697. var texture = uniform.value;
  36698. if (!texture) {
  36699. continue;
  36700. }
  36701. //add
  36702. if (uniformName == 'pano0Map' || uniformName == 'pano1Map') {
  36703. //属于cubeTex,另外设置
  36704. continue;
  36705. }
  36706. /* if(texture.image && !(texture.image instanceof Image) && !(texture instanceof THREE.CanvasTexture)){
  36707. //renderTarget的texture在创建renderTarget时已经初始化过 见setupRenderTarget
  36708. continue
  36709. } */
  36710. if (!this.textures.has(texture) || texture.needsRebuild) {
  36711. var webglTexture = new WebGLTexture$1(gl, texture, this.threeRenderer);
  36712. this.textures.set(texture, webglTexture);
  36713. delete texture.needsRebuild; //renderTarget在resize后会触发dispose, 然后 _gl.deleteTexture( textureProperties.__webglTexture )所以需要重新建立
  36714. }
  36715. var webGLTexture = this.textures.get(texture);
  36716. webGLTexture.update();
  36717. }
  36718. }
  36719. }
  36720. gl.useProgram(shader.program);
  36721. /* let transparent = false;
  36722. if(params.transparent !== undefined){
  36723. transparent = params.transparent && material.opacity < 1;
  36724. }else{
  36725. transparent = material.usePanoMap ? false : (material.useFilterByNormal || material.opacity < 1); //add useFilterByNormal
  36726. }
  36727. if (transparent){
  36728. gl.enable(gl.BLEND);
  36729. if(params.notAdditiveBlending){
  36730. gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); //NormalBlending
  36731. gl.enable(gl.DEPTH_TEST);
  36732. gl.depthMask(true); //如果不开启depthWrite,深度会错乱。
  36733. }else{
  36734. gl.blendFunc(gl.SRC_ALPHA, gl.ONE); //AdditiveBlending 原本
  36735. gl.disable(gl.DEPTH_TEST);
  36736. gl.depthMask(false);
  36737. }
  36738. } else {
  36739. gl.disable(gl.BLEND);
  36740. gl.depthMask(true);
  36741. gl.enable(gl.DEPTH_TEST);
  36742. }
  36743. if(params.blendFunc !== undefined){
  36744. gl.enable(gl.BLEND);
  36745. gl.blendFunc(...params.blendFunc);
  36746. }
  36747. if(params.depthTest !== undefined){
  36748. if(params.depthTest === true){
  36749. gl.enable(gl.DEPTH_TEST);
  36750. }else{
  36751. gl.disable(gl.DEPTH_TEST);
  36752. }
  36753. }
  36754. if(params.depthWrite !== undefined){
  36755. if(params.depthWrite === true){
  36756. gl.depthMask(true);
  36757. }else{
  36758. gl.depthMask(false);
  36759. }
  36760. } */
  36761. {
  36762. // UPDATE UNIFORMS
  36763. shader.setUniformMatrix4("projectionMatrix", proj);
  36764. shader.setUniformMatrix4("viewMatrix", view);
  36765. shader.setUniformMatrix4("uViewInv", viewInv);
  36766. shader.setUniformMatrix4("uProjInv", projInv);
  36767. /* let screenWidth = target ? target.width : material.screenWidth;
  36768. let screenHeight = target ? target.height : material.screenHeight;
  36769. shader.setUniform1f("uScreenWidth", screenWidth);
  36770. shader.setUniform1f("uScreenHeight", screenHeight); */
  36771. shader.setUniform2f('resolution', material.resolution.toArray());
  36772. shader.setUniform1f("fov", Math.PI * camera.fov / 180);
  36773. shader.setUniform1f("near", camera.near);
  36774. shader.setUniform1f("far", camera.far);
  36775. if (camera instanceof OrthographicCamera) {
  36776. shader.setUniform("uUseOrthographicCamera", true);
  36777. shader.setUniform("uOrthoWidth", (camera.right - camera.left) / camera.zoom); //改
  36778. shader.setUniform("uOrthoHeight", camera.top - camera.bottom);
  36779. } else {
  36780. shader.setUniform("uUseOrthographicCamera", false);
  36781. }
  36782. /* if(material.clipBoxes.length + material.clipPolygons.length === 0){//改
  36783. shader.setUniform1i("clipTask", ClipTask.NONE);
  36784. }else{
  36785. shader.setUniform1i("clipTask", material.clipTask);
  36786. }
  36787. shader.setUniform1i("clipMethod", material.clipMethod);*/
  36788. //改
  36789. if (material.clipBoxes_in && material.clipBoxes_in.length > 0) {
  36790. //let flattenedMatrices = [].concat(...material.clipBoxes.map(c => c.inverse.elements));
  36791. var lClipBoxes = shader.uniformLocations["clipBoxes_in[0]"];
  36792. gl.uniformMatrix4fv(lClipBoxes, false, material.uniforms.clipBoxes_in.value);
  36793. }
  36794. if (material.clipBoxes_out && material.clipBoxes_out.length > 0) {
  36795. //add
  36796. var lClipBoxes2 = shader.uniformLocations["clipBoxes_out[0]"];
  36797. gl.uniformMatrix4fv(lClipBoxes2, false, material.uniforms.clipBoxes_out.value);
  36798. }
  36799. if (material.highlightBoxes && material.highlightBoxes.length > 0) {
  36800. //add
  36801. var boxes_highlight = shader.uniformLocations["boxes_highlight[0]"];
  36802. gl.uniformMatrix4fv(boxes_highlight, false, material.uniforms.boxes_highlight.value);
  36803. }
  36804. if (material.bigClipInBox) {
  36805. //add
  36806. shader.setUniformMatrix4("clipBoxBig_in", material.uniforms.clipBoxBig_in.value);
  36807. }
  36808. if (material.uniforms.baseHeightAreaMap.value) {
  36809. //根据模型高亮土方
  36810. var baseHeightBoundZ = shader.uniformLocations["baseHeightBoundZ"];
  36811. gl.uniform2f(baseHeightBoundZ, ...material.uniforms.baseHeightBoundZ.value.toArray());
  36812. var baseHeightBoundXY = shader.uniformLocations["baseHeightBoundXY"];
  36813. gl.uniform4f(baseHeightBoundXY, ...material.uniforms.baseHeightBoundXY.value.toArray());
  36814. }
  36815. if (material.prisms.length) {
  36816. var prismList = shader.uniformLocations["prismList[0]"];
  36817. gl.uniformMatrix3fv(prismList, false, material.uniforms.prismList.value);
  36818. var prismPoints = shader.uniformLocations["prismPoints[0]"];
  36819. gl.uniform2fv(prismPoints, material.uniforms.prismPoints.value);
  36820. }
  36821. // TODO CLIPSPHERES
  36822. if (params.clipSpheres && params.clipSpheres.length > 0) {
  36823. var clipSpheres = params.clipSpheres;
  36824. var matrices = [];
  36825. for (var clipSphere of clipSpheres) {
  36826. //let mScale = new THREE.Matrix4().makeScale(...clipSphere.scale.toArray());
  36827. //let mTranslate = new THREE.Matrix4().makeTranslation(...clipSphere.position.toArray());
  36828. //let clipToWorld = new THREE.Matrix4().multiplyMatrices(mTranslate, mScale);
  36829. var clipToWorld = clipSphere.matrixWorld;
  36830. var viewToWorld = camera.matrixWorld;
  36831. var worldToClip = clipToWorld.clone().invert();
  36832. var viewToClip = new Matrix4().multiplyMatrices(worldToClip, viewToWorld);
  36833. matrices.push(viewToClip);
  36834. }
  36835. var flattenedMatrices = [].concat(...matrices.map(matrix => matrix.elements));
  36836. var lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  36837. gl.uniformMatrix4fv(lClipSpheres, false, flattenedMatrices);
  36838. //const lClipSpheres = shader.uniformLocations["uClipSpheres[0]"];
  36839. //gl.uniformMatrix4fv(lClipSpheres, false, material.uniforms.clipSpheres.value);
  36840. }
  36841. shader.setUniform1f("orthoMaxSize", material.uniforms.orthoMaxSize.value);
  36842. shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
  36843. shader.setUniform1f("minSize", material.uniforms.minSize.value);
  36844. // uniform float uPCIndex
  36845. shader.setUniform1f("uOctreeSpacing", material.spacing);
  36846. shader.setUniform("uOctreeSize", material.uniforms.octreeSize.value);
  36847. shader.setUniform2f("elevationRange", material.elevationRange);
  36848. shader.setUniform2f("intensityRange", material.intensityRange);
  36849. shader.setUniform3f("uIntensity_gbc", [material.intensityGamma, material.intensityBrightness, material.intensityContrast]);
  36850. shader.setUniform3f("uRGB_gbc", [material.rgbGamma, material.rgbBrightness, material.rgbContrast]);
  36851. shader.setUniform1f("uTransition", material.transition);
  36852. shader.setUniform1f("wRGB", material.weightRGB);
  36853. shader.setUniform1f("wIntensity", material.weightIntensity);
  36854. shader.setUniform1f("wElevation", material.weightElevation);
  36855. shader.setUniform1f("wClassification", material.weightClassification);
  36856. shader.setUniform1f("wReturnNumber", material.weightReturnNumber);
  36857. shader.setUniform1f("wSourceID", material.weightSourceID);
  36858. shader.setUniform("backfaceCulling", material.uniforms.backfaceCulling.value);
  36859. //==========================
  36860. //gl.TEXTURE_CUBE_MAP: 34067
  36861. //gl.TEXTURE0=33984 , vnWebGLTexture.target=gl.TEXTURE_2D = 3353
  36862. /* let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);//最好搬到renderNodes
  36863. if(vnWebGLTexture){
  36864. shader.setUniform1i("visibleNodes", currentTextureBindingPoint); //为何之前写的是"visibleNodesTexture",但和"visibleNodes"效果相同?可shader里只有"visibleNodes"
  36865. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36866. gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
  36867. currentTextureBindingPoint++;
  36868. } */
  36869. var gradientTexture = this.textures.get(material.gradientTexture);
  36870. shader.setUniform1i("gradient", currentTextureBindingPoint);
  36871. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36872. gl.bindTexture(gradientTexture.target, gradientTexture.id);
  36873. currentTextureBindingPoint++;
  36874. var repeat = material.elevationGradientRepeat;
  36875. if (repeat === ElevationGradientRepeat.REPEAT) {
  36876. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.REPEAT);
  36877. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.REPEAT);
  36878. } else if (repeat === ElevationGradientRepeat.MIRRORED_REPEAT) {
  36879. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
  36880. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
  36881. } else {
  36882. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  36883. gl.texParameteri(gradientTexture.target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  36884. }
  36885. currentTextureBindingPoint++;
  36886. var classificationTexture = this.textures.get(material.classificationTexture);
  36887. shader.setUniform1i("classificationLUT", currentTextureBindingPoint);
  36888. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36889. gl.bindTexture(classificationTexture.target, classificationTexture.id);
  36890. currentTextureBindingPoint++;
  36891. /* let matcapTexture = this.textures.get(material.matcapTexture);
  36892. shader.setUniform1i("matcapTextureUniform", currentTextureBindingPoint);
  36893. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36894. gl.bindTexture(matcapTexture.target, matcapTexture.id);
  36895. currentTextureBindingPoint++; */
  36896. var baseHeightAreaMap = material.uniforms.baseHeightAreaMap.value;
  36897. if (baseHeightAreaMap) {
  36898. //根据模型高亮土方
  36899. var map = this.textures.get(baseHeightAreaMap);
  36900. shader.setUniform1i("baseHeightAreaMap", currentTextureBindingPoint);
  36901. gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
  36902. gl.bindTexture(map.target, map.id);
  36903. currentTextureBindingPoint++;
  36904. }
  36905. if (material.snapEnabled === true) {
  36906. {
  36907. var lSnapshot = shader.uniformLocations["uSnapshot[0]"];
  36908. var lSnapshotDepth = shader.uniformLocations["uSnapshotDepth[0]"];
  36909. var bindingStart = currentTextureBindingPoint;
  36910. var lSnapshotBindingPoints = new Array(5).fill(bindingStart).map((a, i) => a + i);
  36911. var lSnapshotDepthBindingPoints = new Array(5).fill(1 + Math.max(...lSnapshotBindingPoints)).map((a, i) => a + i);
  36912. currentTextureBindingPoint = 1 + Math.max(...lSnapshotDepthBindingPoints);
  36913. gl.uniform1iv(lSnapshot, lSnapshotBindingPoints);
  36914. gl.uniform1iv(lSnapshotDepth, lSnapshotDepthBindingPoints);
  36915. for (var i = 0; i < 5; i++) {
  36916. var _texture = material.uniforms["uSnapshot"].value[i];
  36917. var textureDepth = material.uniforms["uSnapshotDepth"].value[i];
  36918. if (!_texture) {
  36919. break;
  36920. }
  36921. var snapTexture = this.threeRenderer.properties.get(_texture).__webglTexture;
  36922. var snapTextureDepth = this.threeRenderer.properties.get(textureDepth).__webglTexture;
  36923. var bindingPoint = lSnapshotBindingPoints[i];
  36924. var depthBindingPoint = lSnapshotDepthBindingPoints[i];
  36925. gl.activeTexture(gl["TEXTURE".concat(bindingPoint)]);
  36926. gl.bindTexture(gl.TEXTURE_2D, snapTexture);
  36927. gl.activeTexture(gl["TEXTURE".concat(depthBindingPoint)]);
  36928. gl.bindTexture(gl.TEXTURE_2D, snapTextureDepth);
  36929. }
  36930. }
  36931. {
  36932. var _flattenedMatrices3 = [].concat(...material.uniforms.uSnapView.value.map(c => c.elements));
  36933. var lSnapView = shader.uniformLocations["uSnapView[0]"];
  36934. gl.uniformMatrix4fv(lSnapView, false, _flattenedMatrices3);
  36935. }
  36936. {
  36937. var _flattenedMatrices4 = [].concat(...material.uniforms.uSnapProj.value.map(c => c.elements));
  36938. var lSnapProj = shader.uniformLocations["uSnapProj[0]"];
  36939. gl.uniformMatrix4fv(lSnapProj, false, _flattenedMatrices4);
  36940. }
  36941. {
  36942. var _flattenedMatrices5 = [].concat(...material.uniforms.uSnapProjInv.value.map(c => c.elements));
  36943. var lSnapProjInv = shader.uniformLocations["uSnapProjInv[0]"];
  36944. gl.uniformMatrix4fv(lSnapProjInv, false, _flattenedMatrices5);
  36945. }
  36946. {
  36947. var _flattenedMatrices6 = [].concat(...material.uniforms.uSnapViewInv.value.map(c => c.elements));
  36948. var lSnapViewInv = shader.uniformLocations["uSnapViewInv[0]"];
  36949. gl.uniformMatrix4fv(lSnapViewInv, false, _flattenedMatrices6);
  36950. }
  36951. }
  36952. //=============add===========
  36953. if (material.usePanoMap) {
  36954. //为什么pointsize失效
  36955. shader.setUniform1f("progress", material.uniforms.progress.value);
  36956. shader.setUniform1f("easeInOutRatio", material.uniforms.easeInOutRatio.value);
  36957. shader.setUniform3f("pano0Position", material.uniforms.pano0Position.value.toArray());
  36958. shader.setUniform3f("pano1Position", material.uniforms.pano1Position.value.toArray());
  36959. shader.setUniform('pano0Matrix', material.uniforms.pano0Matrix.value);
  36960. shader.setUniform('pano1Matrix', material.uniforms.pano1Matrix.value);
  36961. var pano0Map = material.uniforms.pano0Map.value;
  36962. if (pano0Map) {
  36963. this.threeRenderer._textures.safeSetTextureCube(pano0Map, ++currentTextureBindingPoint);
  36964. shader.setUniform1i('pano0Map', currentTextureBindingPoint);
  36965. }
  36966. var pano1Map = material.uniforms.pano1Map.value;
  36967. if (pano1Map) {
  36968. this.threeRenderer._textures.safeSetTextureCube(pano1Map, ++currentTextureBindingPoint);
  36969. shader.setUniform1i('pano1Map', currentTextureBindingPoint);
  36970. }
  36971. //注: three.js我添加了个 _textures, safeSetTextureCube里主要就是activeTexture和bindTexture
  36972. }
  36973. }
  36974. viewer.addTimeMark('renderOctree', 'end');
  36975. params.currentTextureBindingPoint = ++currentTextureBindingPoint;
  36976. octrees.forEach(octree => {
  36977. this.renderNodes(octree, nodes || octree.visibleNodes, visibilityTextureData, camera, target, shader, params);
  36978. });
  36979. gl.activeTexture(gl.TEXTURE2);
  36980. gl.bindTexture(gl.TEXTURE_2D, null);
  36981. gl.activeTexture(gl.TEXTURE0);
  36982. //gl.bindTexture(gl.TEXTURE_2D, null); //add
  36983. //add 恢复为不透明(否则renderToCubeMap时的贴图会被渲染成高亮的颜色)
  36984. gl.disable(gl.BLEND);
  36985. gl.depthMask(true);
  36986. gl.enable(gl.DEPTH_TEST);
  36987. //DEPTH_TEST等需要恢复吗
  36988. }
  36989. render(scene, camera) {
  36990. var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
  36991. var params = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  36992. var gl = this.gl;
  36993. // PREPARE
  36994. if (target != null) {
  36995. this.threeRenderer.setRenderTarget(target);
  36996. }
  36997. //camera.updateProjectionMatrix();
  36998. // camera.matrixWorldInverse.invert(camera.matrixWorld);
  36999. var traversalResult = this.traverse(scene);
  37000. //排序
  37001. if (params.notAdditiveBlending) {
  37002. //add
  37003. traversalResult.octrees.forEach(tree => {
  37004. if (tree.material.opacity == 1) {
  37005. tree._z = Infinity; //不透明的先渲染 //2024.10发现没用,会透过不透明的看到后面透明的orz
  37006. } else {
  37007. var center = tree.boundCenter ? tree.boundCenter.clone() : tree.boundingBox.getCenter(tree.boundCenter).applyMatrix4(tree.matrixWorld);
  37008. center.project(camera);
  37009. tree._z = center.z;
  37010. }
  37011. });
  37012. traversalResult.octrees.sort((tree1, tree2) => {
  37013. return tree2._z - tree1._z; //降序 (-1 朝外)。 离屏幕近的后渲染
  37014. });
  37015. }
  37016. // RENDER
  37017. var mat = params.material || traversalResult.octrees[0].material;
  37018. var cloudSameMat = Potree.settings.cloudSameMat && !traversalResult.octrees.some(e => e.material.activeAttributeName != mat.activeAttributeName); //activeAttributeName都一样才行
  37019. if (cloudSameMat && viewer.scene.volumes.length == 0 && mat.pointSizeType != PointSizeType.ADAPTIVE && mat.activeAttributeName != "level of detail") {
  37020. this.renderOctree(traversalResult.octrees, null, camera, target, params); //所有点云除了个别属性需要在shader中更新,其他都使用第一个点云的材质
  37021. } else for (var octree of traversalResult.octrees) {
  37022. for (var _octree of traversalResult.octrees) {
  37023. this.renderOctree(_octree, _octree.visibleNodes, camera, target, params);
  37024. }
  37025. }
  37026. //if (octree material.pointSizeType === PointSizeType.ADAPTIVE || material.activeAttributeName === "level of detail") {
  37027. // CLEANUP
  37028. gl.activeTexture(gl.TEXTURE1);
  37029. gl.bindTexture(gl.TEXTURE_2D, null);
  37030. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  37031. gl.bindVertexArray(null);
  37032. this.threeRenderer.resetState();
  37033. }
  37034. }
  37035. ;
  37036. /*
  37037. 中东的链接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
  37038. geometry: 有的attributes: 属性是:
  37039. classification:
  37040. color:
  37041. indices:
  37042. normal:
  37043. position:
  37044. 最好有个spacing
  37045. */
  37046. /* const mapHeight = -1000;//要比点云低。最低
  37047. const cameraHeight = 1000; //最高 */
  37048. var panosHeight = config$1.map.mapHeight + 100; //要比点云低 (marker)
  37049. var cursorHeight = 0; //比地图高就行
  37050. var routeLayerHeight = config$1.map.mapHeight + 105;
  37051. var texLoader$5 = new TextureLoader();
  37052. var planeGeo$1 = new PlaneBufferGeometry(1, 1);
  37053. var markerSize = 1;
  37054. var initCameraFeildWidth = 50;
  37055. var panoMarkerMats;
  37056. class MapViewer extends ViewerBase {
  37057. constructor(dom) {
  37058. super(dom, {
  37059. clearColor: Potree.config.mapBG,
  37060. name: 'mapViewer',
  37061. antialias: true
  37062. });
  37063. this.visible = true;
  37064. this.initScene();
  37065. this.needRender_ = false;
  37066. this.mapLayer = new MapLayer(this, this.viewports[0]);
  37067. this.scene.add(this.mapLayer.sceneGroup);
  37068. this.mapLayer.sceneGroup.position.setZ(Potree.config.map.mapHeight);
  37069. this.mapRatio = 0.5;
  37070. this.splitDir = 'leftRight';
  37071. this.renderMeasure = false;
  37072. //因context的preserveDrawingBuffer为false之后,canvas渲染多个viewport时会自动clear,所以若不渲染就会是空的。所以没有变化时就直接拷贝buffer好了。
  37073. this.copyPass = new ShaderPass(CopyShader);
  37074. this.copyBuffer = new WebGLRenderTarget(100, 100, {
  37075. minFilter: LinearFilter,
  37076. magFilter: LinearFilter,
  37077. format: RGBAFormat,
  37078. stencilBuffer: false
  37079. });
  37080. viewer.addEventListener("camera_changed", e => {
  37081. var needUpdateCursor;
  37082. if (e.viewport == viewer.mainViewport) {
  37083. needUpdateCursor = true;
  37084. } else if (e.viewport == this.viewports[0]) {
  37085. //attachedToViewer
  37086. needUpdateCursor = true;
  37087. this.mapChanged = true;
  37088. this.updateWhenAtViewer();
  37089. e.changeInfo.projectionChanged && this.setViewLimit();
  37090. }
  37091. needUpdateCursor && this.updateCursor();
  37092. });
  37093. this.addEventListener("camera_changed", e => {
  37094. e.changeInfo.projectionChanged && this.setViewLimit();
  37095. });
  37096. //viewer.addEventListener("global_mousemove", this.updateWhenAtViewer.bind(this)) //鼠标移动时reticule也动,所以直接就needRender
  37097. /* viewer.reticule.addEventListener('update',(e)=>{
  37098. if(this.attachedToViewer)this.needRender = true
  37099. }) */
  37100. viewer.scene.addEventListener("360_images_added", this.addPanos.bind(this));
  37101. viewer.addEventListener("loadPointCloudDone", this.initProjection.bind(this));
  37102. this.addEventListener('global_click', e => {
  37103. if (!e.isTouch && e.button != MOUSE.LEFT) return;
  37104. this.updateClosestPano(e.intersect);
  37105. });
  37106. this.addEventListener('add', e => {
  37107. //添加其他mesh
  37108. this.scene.add(e.object);
  37109. if (e.name == 'route') {
  37110. e.object.position.z = routeLayerHeight;
  37111. }
  37112. Potree.Utils.setObjectLayers(e.object, 'mapObjects');
  37113. });
  37114. viewer.addEventListener('allLoaded', () => {
  37115. this.setViewLimit('standard');
  37116. });
  37117. if (!Potree.settings.isOfficial) {
  37118. var domRoot = viewer.renderer.domElement.parentElement;
  37119. var elAttach = $("<input type='button' value='map绑定'></input>");
  37120. elAttach.css({
  37121. position: "absolute",
  37122. right: '80%',
  37123. bottom: '20px',
  37124. zIndex: "10000",
  37125. fontSize: '1em',
  37126. color: "black",
  37127. background: 'rgba(255,255,255,0.8)'
  37128. });
  37129. var state = false;
  37130. elAttach.on("click", () => {
  37131. state = !state;
  37132. this.attachToMainViewer(state, 'measure');
  37133. elAttach.val(state ? 'map分离' : 'map绑定');
  37134. });
  37135. domRoot.appendChild(elAttach[0]);
  37136. }
  37137. }
  37138. get needRender() {
  37139. return this.needRender_;
  37140. }
  37141. set needRender(n) {
  37142. this.needRender_ = n;
  37143. n && (this.viewports[0].needRender = true); //使attachedToViewer时在renderDefault中可渲染
  37144. }
  37145. get mapChanged() {
  37146. return this.mapChanged_;
  37147. }
  37148. set mapChanged(c) {
  37149. //镜头移动、地图内容改变都会为true
  37150. this.mapChanged_ = c;
  37151. c && (this.needRender = true);
  37152. }
  37153. waitLoadDone(callback) {
  37154. //确保加载完后执行
  37155. var timer; //等待一段时间看有没有新加载的tile,如果超过这个时间没有就不等了,算加载结束
  37156. var pauseCountDown = () => {
  37157. //重新等待加载结束,中断倒计时
  37158. clearTimeout(timer);
  37159. //console.log('pauseCountDown')
  37160. };
  37161. var freshCountDown = () => {
  37162. //刷新倒计时
  37163. //console.log('freshCountDown')
  37164. clearTimeout(timer);
  37165. timer = setTimeout(() => {
  37166. this.mapLayer.removeEventListener('loadDone', freshCountDown);
  37167. this.mapLayer.removeEventListener('startLoad', pauseCountDown);
  37168. callback();
  37169. }, document.hidden ? 5000 : 500);
  37170. };
  37171. this.mapLayer.addEventListener('loadDone', freshCountDown);
  37172. this.mapLayer.addEventListener('startLoad', pauseCountDown);
  37173. if (this.mapLayer.loadingInProgress == 0) {
  37174. freshCountDown();
  37175. }
  37176. }
  37177. addListener(images360) {
  37178. images360.addEventListener('flyToPano', e => {
  37179. var toPano = e.toPano;
  37180. if (toPano.dontMoveMap) return;
  37181. /* transitions.start(lerp.vector(this.view.position, toPano.pano.position.clone().setZ(cameraHeight),
  37182. (pos, progress)=>{
  37183. }), toPano.duration, null, 0, easing[toPano.easeName] ); */
  37184. var boundSize; // = new THREE.Vector2(10,10)
  37185. this.moveTo(toPano.pano.position.clone().setZ(Potree.config.map.cameraHeight), boundSize, toPano.duration, null, toPano.easeName);
  37186. });
  37187. }
  37188. initProjection() {
  37189. this.started = true;
  37190. this.mapLayer.initProjection();
  37191. }
  37192. initScene() {
  37193. var w = initCameraFeildWidth;
  37194. var width = this.renderArea.clientWidth;
  37195. var height = this.renderArea.clientHeight;
  37196. //let aspect = width / height
  37197. this.camera = new OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2 /* -w/2, w/2, w/2/aspect, -w/2/aspect */, 0.01, 10000);
  37198. this.camera.zoom = width / w; //zoom越大视野越小
  37199. //this.camera.position.set(0,0,10);
  37200. this.camera.up.set(0, 0, 1);
  37201. //this.camera.lookAt(new THREE.Vector3())
  37202. //this.camera.updateMatrixWorld()
  37203. this.view = new ExtendView();
  37204. this.view.position.set(0, 0, Potree.config.map.cameraHeight);
  37205. this.view.lookAt(0, 0, 0);
  37206. var viewport = new Viewport(this.view, this.camera, {
  37207. left: 0,
  37208. bottom: 0,
  37209. width: 1,
  37210. height: 1,
  37211. name: 'mapViewport'
  37212. });
  37213. viewport.axis = ["x", "y"];
  37214. viewport.axisSign = [1, 1];
  37215. viewport.noPointcloud = true; //不要渲染点云
  37216. viewport.render = this.render.bind(this); //标志给mainView渲染
  37217. //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
  37218. viewport.addEventListener('resize', () => {
  37219. this.copyBuffer.setSize(viewport.resolution2.x, viewport.resolution2.y);
  37220. //this.cloudBuffer && this.cloudBuffer.setSize(viewport.resolution2.x, viewport.resolution2.y)
  37221. });
  37222. this.viewports = [viewport];
  37223. this.controls = new FirstPersonControls(this, this.viewports[0]);
  37224. this.controls.setEnable(true);
  37225. this.scene = new Scene();
  37226. this.inputHandler = new InputHandler(this, this.scene);
  37227. this.inputHandler.name = 'mapInputHandler';
  37228. //this.inputHandler.addInputListener(this.controls);
  37229. this.inputHandler.registerInteractiveScene(this.scene); //interactiveScenes
  37230. this.viewports[0].interactiveScenes = this.inputHandler.interactiveScenes; //供viewer的inputHandler使用
  37231. var cursor = new Mesh(planeGeo$1, new MeshBasicMaterial({
  37232. transparent: true,
  37233. opacity: 0.9,
  37234. depthTest: false,
  37235. //防止透明冲突
  37236. map: texLoader$5.load(Potree.resourcePath + '/textures/pic_location128.png')
  37237. }));
  37238. cursor.position.set(0, 0, cursorHeight);
  37239. this.cursor = cursor;
  37240. this.scene.add(cursor);
  37241. Potree.Utils.setObjectLayers(this.scene, 'mapObjects');
  37242. }
  37243. setViewLimit(state) {
  37244. //设置边界,当编辑空间模型等时要解禁
  37245. if (!state) state = this.limitBoundState;
  37246. if (!state) return;
  37247. this.limitBoundState = state;
  37248. var setting = Potree.config.OrthoCameraLimit[state];
  37249. if (setting) {
  37250. this.camera.zoomLimit = $.extend({}, setting.zoom);
  37251. var lonlatCenter = viewer.transform.lonlatToLocal.inverse([0, 0]);
  37252. var minY = viewer.transform.lonlatToLocal.forward([lonlatCenter[0], -90 + setting.latPad])[1]; //屏幕边界的bound
  37253. var maxY = viewer.transform.lonlatToLocal.forward([lonlatCenter[0], 90 - setting.latPad])[1];
  37254. /*this.view.limitBound = new THREE.Box3(
  37255. new THREE.Vector3(setting.xBound[0], minY, Potree.config.map.cameraHeight),
  37256. new THREE.Vector3(setting.xBound[1], maxY, 1 / 0)
  37257. ) */
  37258. var halfHeight = this.viewports[0].resolution.y / 2 / this.camera.zoom; //屏幕所占高度的一半
  37259. var halfWidth = this.viewports[0].resolution.x / 2 / this.camera.zoom;
  37260. this.view.limitBound = new Box3(new Vector3(setting.xBound[0] + halfWidth, minY + halfHeight, Potree.config.map.cameraHeight), new Vector3(setting.xBound[1] - halfWidth, maxY - halfHeight, 1 / 0));
  37261. } else {
  37262. this.view.limitBound = null;
  37263. this.camera.zoomLimit = null;
  37264. }
  37265. }
  37266. updateCursor() {
  37267. //console.log('pos', viewer.mainViewport.camera.position.toArray() )
  37268. var scale = math.getScaleForConstantSize({
  37269. //规定下最小最大像素
  37270. minSize: 80,
  37271. maxSize: 200,
  37272. nearBound: initCameraFeildWidth * 0.1,
  37273. farBound: initCameraFeildWidth * 2,
  37274. camera: this.camera,
  37275. position: this.cursor.getWorldPosition(new Vector3()),
  37276. resolution: this.viewports[0].resolution //2
  37277. });
  37278. this.cursor.scale.set(scale, scale, scale); //当地图缩放时
  37279. this.cursor.position.copy(viewer.mainViewport.camera.position).setZ(cursorHeight); //当场景镜头旋转移动时
  37280. this.cursor.rotation.z = viewer.mainViewport.view.yaw;
  37281. this.needRender = true;
  37282. }
  37283. addPanos(e) {
  37284. var panosGroup = new Object3D();
  37285. panosGroup.name = 'markers';
  37286. panoMarkerMats = {
  37287. default: new MeshBasicMaterial({
  37288. transparent: true,
  37289. opacity: 0.5,
  37290. map: texLoader$5.load(Potree.resourcePath + '/textures/map_marker.png')
  37291. }),
  37292. selected: new MeshBasicMaterial({
  37293. transparent: true,
  37294. opacity: 1,
  37295. map: texLoader$5.load(Potree.resourcePath + '/textures/map_marker.png')
  37296. })
  37297. };
  37298. e.images.panos.forEach(pano => {
  37299. pano.mapMarker = new Mesh(planeGeo$1, panoMarkerMats.default);
  37300. pano.mapMarker.position.copy(pano.position).setZ(0);
  37301. pano.mapMarker.scale.set(markerSize, markerSize, markerSize);
  37302. pano.mapMarker.name = 'mapMarker';
  37303. panosGroup.add(pano.mapMarker);
  37304. var mouseover = e => {
  37305. if (!e.byMap) {
  37306. pano.mapMarker.material = panoMarkerMats.selected;
  37307. if (!e.byMainView) pano.dispatchEvent({
  37308. type: "hoverOn",
  37309. byMap: true
  37310. });
  37311. this.needRender = true;
  37312. }
  37313. };
  37314. var mouseleave = e => {
  37315. if (!e.byMap) {
  37316. pano.mapMarker.material = panoMarkerMats.default;
  37317. if (!e.byMainView) pano.dispatchEvent({
  37318. type: "hoverOff",
  37319. byMap: true
  37320. });
  37321. this.needRender = true;
  37322. }
  37323. };
  37324. pano.mapMarker.addEventListener('mouseover', mouseover);
  37325. pano.mapMarker.addEventListener('mouseleave', mouseleave);
  37326. pano.addEventListener('hoverOn', mouseover);
  37327. pano.addEventListener('hoverOff', mouseleave);
  37328. var onclick = e => {
  37329. viewer.images360.flyToPano(pano);
  37330. };
  37331. pano.mapMarker.addEventListener('click', onclick);
  37332. pano.addEventListener('isVisible', e => {
  37333. //是否显示该点的mesh(不显示也能走)
  37334. //console.log('panoMarker isVisible', pano.id, e.visible)
  37335. Potree.Utils.updateVisible(pano.mapMarker, 'panoVisible', e.visible);
  37336. this.needRender = true;
  37337. });
  37338. pano.addEventListener('rePos', e => {
  37339. pano.mapMarker.position.copy(pano.position).setZ(0);
  37340. });
  37341. });
  37342. this.scene.add(panosGroup);
  37343. panosGroup.position.z = panosHeight;
  37344. this.panosGroup = panosGroup;
  37345. Potree.Utils.setObjectLayers(panosGroup, 'mapObjects');
  37346. /* e.images.on('markersDisplayChange', (show)=>{
  37347. panosGroup.visible = show
  37348. this.needRender = true
  37349. }) */
  37350. //-------
  37351. //this.fitPanosToViewport()
  37352. this.initFitView();
  37353. }
  37354. updateClosestPano(intersect) {
  37355. if (viewer.images360.flying) return;
  37356. intersect = intersect && intersect.orthoIntersect;
  37357. if (!intersect) return;
  37358. intersect = intersect.clone().setZ(0);
  37359. var minDis = 20; //距离鼠标不能太远
  37360. var filterFuncs = [Images360.filters.isEnabled(), Images360.filters.isVisible(),
  37361. //只走显示的点,否则会走到别的层
  37362. pano => {
  37363. return pano.position.clone().setZ(0).distanceTo(intersect) < minDis;
  37364. }];
  37365. var pano = Common$1.find(viewer.images360.panos, filterFuncs, [Images360.sortFunctions.floorDisSquaredToPoint(intersect)]);
  37366. if (pano && pano != viewer.images360.currentPano) {
  37367. viewer.images360.flyToPano(pano);
  37368. }
  37369. }
  37370. fitPanosToViewport() {
  37371. //使所有漫游点占满viewport
  37372. //var w = viewer.bound.boundSize.x;
  37373. var boundSize = viewer.images360.bound.size.clone().multiplyScalar(1.1);
  37374. boundSize.max(new Vector3(4, 4, 4));
  37375. var endPosition = viewer.images360.bound.center.clone();
  37376. this.moveTo(endPosition, boundSize, 0);
  37377. }
  37378. fitToPointcloud(pointcloud) {
  37379. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 400;
  37380. var boundSize = pointcloud.bound.getSize(new Vector3()); /* .multiplyScalar(1.1); */
  37381. boundSize.max(new Vector3(4, 4, 4));
  37382. var endPosition = pointcloud.bound.getCenter(new Vector3());
  37383. this.moveTo(endPosition, boundSize, duration); //给点duration去变化 否则地图放大后所占的还是很小
  37384. }
  37385. initFitView() {
  37386. var dis = 5,
  37387. px = 70; //地图上px像素长度代表的距离为dis //px是手动缩放到5m后发现是这个长度
  37388. var zoom = px / dis;
  37389. this.camera.zoom = zoom;
  37390. this.moveTo(viewer.images360.position /* viewer.images360.bound.center */);
  37391. this.camera.updateProjectionMatrix();
  37392. }
  37393. fitToDatasets(datasets) {
  37394. var bound = new Box3();
  37395. datasets.forEach(e => bound.union(e.bound));
  37396. var center = bound.getCenter(new Vector3());
  37397. var size = bound.getSize(new Vector3());
  37398. this.moveTo(center, size, 200); //给duration是为了顺应视口大小改变,缓冲
  37399. }
  37400. moveTo(endPosition, boundSize) {
  37401. var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  37402. var margin = arguments.length > 3 ? arguments[3] : undefined;
  37403. var easeName = arguments.length > 4 ? arguments[4] : undefined;
  37404. var callback = arguments.length > 5 ? arguments[5] : undefined;
  37405. //前两个参数有xy即可
  37406. var z = Math.max(Potree.config.map.cameraHeight, (endPosition.z || 0) + ((boundSize === null || boundSize === void 0 ? void 0 : boundSize.z) || 0) / 2 + 1);
  37407. endPosition = new Vector3(endPosition.x, endPosition.y, z);
  37408. this.view.moveOrthoCamera(this.viewports[0], {
  37409. endPosition,
  37410. boundSize,
  37411. margin,
  37412. callback
  37413. }, duration, easeName);
  37414. /* let endZoom, startZoom = this.camera.zoom
  37415. //修改相机为bound中心,这样能看到全部(宽度范围内)
  37416. this.view.setView({ position:endPosition, duration,
  37417. callback:()=>{//done
  37418. },
  37419. onUpdate:(progress)=>{
  37420. if(boundSize){
  37421. let aspect = boundSize.x / boundSize.y
  37422. let w, h;
  37423. if(this.camera.aspect > aspect){//视野更宽则用bound的纵向来决定
  37424. h = boundSize.y
  37425. //w = h * this.camera.aspect
  37426. endZoom = this.viewports[0].resolution.y / h
  37427. }else{
  37428. w = boundSize.x;
  37429. //h = w / this.camera.aspect
  37430. endZoom = this.viewports[0].resolution.x / w
  37431. }
  37432. //onUpdate时更新endzoom是因为画布大小可能更改
  37433. this.camera.zoom = endZoom * progress + startZoom * (1 - progress)
  37434. this.camera.updateProjectionMatrix()
  37435. }
  37436. },
  37437. Easing:easeName
  37438. }) */
  37439. }
  37440. updateWhenAtViewer(e) {
  37441. //两个触发来源: 1 camera_changed时 2 mapLayer.needUpdate时。 render在viewer中执行
  37442. if (this.attachedToViewer) {
  37443. if (this.started) this.mapLayer.update();
  37444. this.needRender = true;
  37445. }
  37446. }
  37447. update(delta, areaSize) {
  37448. if (!this.visible && !this.attachedToViewer) return;
  37449. if (this.attachedToViewer) {
  37450. if (this.mapLayer.needUpdate) {
  37451. this.updateWhenAtViewer();
  37452. }
  37453. return;
  37454. }
  37455. this.updateScreenSize();
  37456. this.controls.update(delta);
  37457. this.view.applyToCamera(this.camera);
  37458. var changed = this.cameraChanged();
  37459. if (this.started && (changed || this.mapLayer.needUpdate)) this.mapLayer.update();
  37460. if (changed /*|| || this.needRender */) {
  37461. /* this.dispatchEvent({
  37462. type: "camera_changed",
  37463. camera: this.camera,
  37464. viewport : this.viewports[0]
  37465. }) */
  37466. this.mapChanged = true;
  37467. this.needRender = true;
  37468. this.updateCursor(); //更改大小
  37469. }
  37470. this.render();
  37471. }
  37472. attachToMainViewer(state, desc) {
  37473. var mapRatio = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.5;
  37474. var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  37475. //转移到viewer中。测量时展示or截图需要
  37476. if (!Potree.settings.isOfficial) this.renderArea.style.display = state ? 'none' : 'block';
  37477. if (state) {
  37478. this.enabledOld = this.enabled;
  37479. this.enabled = true;
  37480. if (mapRatio != 'dontSet') {
  37481. this.changeSplitScreenDir(options.dir, mapRatio);
  37482. if (this.attachedToViewer) {
  37483. //this.fitPanosToViewport()
  37484. viewer.updateScreenSize({
  37485. forceUpdateSize: true
  37486. });
  37487. return;
  37488. }
  37489. viewer.viewports = [viewer.mainViewport, viewer.mapViewer.viewports[0]]; //因为mainViewer的相机变化会触发map的变化,所以先渲染mainViewer
  37490. }
  37491. if (desc == 'measure') this.inputHandler.registerInteractiveScene(viewer.scene.overlayScene /* viewer.measuringTool.scene */); //虽然用的是viewer的inputHandler,但借用了this.inputHandler的interactiveScenes
  37492. else if (desc == 'split4Screens') {
  37493. this.inputHandler.registerInteractiveScene(viewer.scene.scene);
  37494. }
  37495. } else {
  37496. if (!this.attachedToViewer) return;
  37497. viewer.mainViewport.left = 0;
  37498. viewer.mainViewport.bottom = 0;
  37499. viewer.mainViewport.width = 1;
  37500. viewer.mainViewport.height = 1;
  37501. this.viewports[0].width = 1;
  37502. this.viewports[0].bottom = 0;
  37503. this.viewports[0].height = 1;
  37504. this.viewports[0].left = 0;
  37505. this.renderMeasure || this.inputHandler.unregisterInteractiveScene(viewer.scene.overlayScene /* viewer.measuringTool.scene */);
  37506. this.inputHandler.unregisterInteractiveScene(viewer.scene.scene);
  37507. viewer.viewports = [viewer.mainViewport];
  37508. this.updateScreenSize({
  37509. forceUpdateSize: true
  37510. }); //更新相机projectionMatrix
  37511. }
  37512. //if(desc == 'measure')this.renderMeasure = state
  37513. this.attachedToViewer = state;
  37514. viewer.updateScreenSize({
  37515. forceUpdateSize: true
  37516. });
  37517. //mapRatio != 'dontSet' && !options.dontFit && this.moveTo(...)//要写在updateScreenSize后面,因为要根据视图大小来fit
  37518. if (options.moveToCurrentPos) {
  37519. var boundSize = new Vector2(10, 10);
  37520. var duration = 1000;
  37521. this.moveTo(viewer.images360.position.clone(), boundSize, duration);
  37522. }
  37523. this.needRender = true;
  37524. }
  37525. setDrawMeasure(draw) {
  37526. this.renderMeasure = !!draw;
  37527. if (draw) {
  37528. this.inputHandler.registerInteractiveScene(viewer.scene.overlayScene /* viewer.measuringTool.scene */);
  37529. } else {
  37530. this.inputHandler.unregisterInteractiveScene(viewer.scene.overlayScene /* viewer.measuringTool.scene */);
  37531. }
  37532. }
  37533. changeSplitScreenDir(dir, mapRatio) {
  37534. //左右 | 上下
  37535. //if(!dir || dir == this.dir)return
  37536. if (dir) this.splitDir = dir;
  37537. this.updateSplitSize(mapRatio);
  37538. /* if(this.attachedToViewer){ //如果已经分屏了,中途修改方向的话……
  37539. this.updateSplitSize()
  37540. } */
  37541. }
  37542. updateSplitSize(mapRatio) {
  37543. if (mapRatio != void 0) this.mapRatio = mapRatio;
  37544. //console.log(this.mapRatio)
  37545. if (this.splitDir == 'leftRight') {
  37546. //地图在左方
  37547. viewer.mainViewport.left = this.mapRatio;
  37548. viewer.mainViewport.width = 1 - this.mapRatio;
  37549. this.viewports[0].width = this.mapRatio;
  37550. viewer.mainViewport.bottom = this.viewports[0].bottom = 0;
  37551. viewer.mainViewport.height = this.viewports[0].height = 1;
  37552. } else if (this.splitDir == 'upDown') {
  37553. //地图在下方
  37554. viewer.mainViewport.bottom = this.mapRatio;
  37555. viewer.mainViewport.height = 1 - this.mapRatio;
  37556. this.viewports[0].height = this.mapRatio;
  37557. viewer.mainViewport.left = this.viewports[0].left = 0;
  37558. viewer.mainViewport.width = this.viewports[0].width = 1;
  37559. }
  37560. if (this.attachedToViewer) {
  37561. viewer.updateScreenSize({
  37562. forceUpdateSize: true
  37563. });
  37564. }
  37565. }
  37566. render1() {
  37567. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  37568. //viewer的preserveDrawingBuffer为false时的版本
  37569. var needCopy, waitCopy;
  37570. if (!this.visible && !this.attachedToViewer || !this.needRender && !params.force) {
  37571. if (this.attachedToViewer) {
  37572. needCopy = true;
  37573. } else {
  37574. return;
  37575. }
  37576. }
  37577. waitCopy = this.attachedToViewer && this.needRender && !params.force; //是否写入到copyBuffer。双屏时,若needRender就拷贝到copyBuffer中,双屏时就直接使用copyBuffer。 四屏时因渲染点云会每帧都渲染,所以不需要缓存。
  37578. var renderer = params.renderer || this.renderer;
  37579. if (waitCopy) {
  37580. this.copyBuffer.setSize(params.viewport.resolution2.x, params.viewport.resolution2.y);
  37581. renderer.setRenderTarget(this.copyBuffer);
  37582. } else if (params.target) {
  37583. renderer.setRenderTarget(params.target);
  37584. }
  37585. /* if(params.resize){
  37586. this.emitResizeMsg(new THREE.Vector2(params.width,params.height, viewport:params.viewport))
  37587. } */
  37588. params.clear ? params.clear() : renderer.clear();
  37589. if (!needCopy || waitCopy) {
  37590. //重绘
  37591. viewer.dispatchEvent({
  37592. type: "render.begin",
  37593. viewer: this,
  37594. viewport: this.viewports[0],
  37595. params
  37596. });
  37597. Potree.Utils.setCameraLayers(this.camera, ['map', 'mapObjects', 'bothMapAndScene']);
  37598. if (this.mapGradientBG) {
  37599. //渲染背景
  37600. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  37601. renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  37602. }
  37603. renderer.render(this.scene, this.camera);
  37604. renderer.render(viewer.scene.scene, this.camera);
  37605. //测量线等
  37606. //params.renderOverlay && params.renderOverlay( $.extend({}, params, { isMap:true }))
  37607. renderer.setRenderTarget(params.target || null);
  37608. }
  37609. if (needCopy || waitCopy) {
  37610. //使用缓存 ----当viewer的preserveDrawingBuffer为false的话,使用buffer
  37611. this.copyPass.render(null, null, null, renderer, params.target || null, this.copyBuffer);
  37612. }
  37613. this.needRender = false;
  37614. return true;
  37615. }
  37616. clear(params) {
  37617. if (this.transparentBG) {
  37618. this.renderer.setClearColor(0x000000, 0);
  37619. } else {
  37620. this.renderer.setClearColor(Potree.config.mapBG, 1);
  37621. }
  37622. (params.renderer || this.renderer).clear();
  37623. }
  37624. //拆成两次渲染,一个地图一个其他物体,且地图渲染后保存在buffer中,只有当地图变化后才重渲染。
  37625. render() {
  37626. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  37627. if (!this.visible && !this.attachedToViewer || !this.needRender && !params.force) {
  37628. //注意:mapViewer.needRender的权重高于它的viewport的needRender,也就是说,当attachedToViewer时,viewer即使needRender, mapViewer也不一定会渲染。
  37629. return;
  37630. }
  37631. viewer.addTimeMark('mapRender', 'start');
  37632. var renderer = params.renderer || this.renderer;
  37633. if (this.mapChanged) {
  37634. //渲染地图背景
  37635. renderer.setRenderTarget(this.copyBuffer);
  37636. params.clear ? params.clear(params) : this.clear(params);
  37637. if (this.mapGradientBG) {
  37638. //渲染背景
  37639. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  37640. renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  37641. }
  37642. Potree.Utils.setCameraLayers(this.camera, ['map']);
  37643. renderer.render(this.scene, this.camera);
  37644. params.renderBG && params.renderBG(this.viewports[0]);
  37645. this.mapChanged = false;
  37646. renderer.setRenderTarget(params.target || null);
  37647. }
  37648. params.clear ? params.clear(params) : this.clear(params);
  37649. this.copyPass.render(null, null, null, renderer, params.target || null, this.copyBuffer); //拷贝地图背景
  37650. renderer.clearDepth(); //防止地图遮挡其他物体
  37651. //绘制其他物体
  37652. var layers = ['mapObjects', 'bothMapAndScene', 'light'];
  37653. Potree.settings.showObjectsOnMap && layers.push('model');
  37654. Potree.Utils.setCameraLayers(this.camera, layers);
  37655. viewer.dispatchEvent({
  37656. type: "render.begin",
  37657. viewer: this,
  37658. viewport: this.viewports[0],
  37659. params
  37660. });
  37661. this.attachedToViewer || this.renderCloud || renderer.render(viewer.scene.scene, this.camera); //类同renderOverlay
  37662. renderer.render(this.scene, this.camera);
  37663. if (!this.attachedToViewer && this.renderMeasure) {
  37664. //在未attach到主页面时也要渲染测量线
  37665. viewer.dispatchEvent({
  37666. type: "render.pass.perspective_overlay",
  37667. camera: this.camera,
  37668. viewport: this.viewports[0],
  37669. renderer
  37670. });
  37671. }
  37672. renderer.setRenderTarget(null);
  37673. this.needRender = false;
  37674. viewer.addTimeMark('mapRender', 'end');
  37675. return true;
  37676. }
  37677. renderOverlay() {
  37678. //偶尔需要绘制测量线
  37679. viewer.renderOverlay({
  37680. camera: this.camera,
  37681. viewport: this.viewports[0],
  37682. renderer: this.renderer
  37683. });
  37684. }
  37685. setRenderCloud() {
  37686. var _this = this;
  37687. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  37688. //使利用viewer的渲染来渲染点云 (如果点云不旋转其实也可以贴floorplan……)
  37689. this.renderPointcloud = true;
  37690. this.viewports[0].noPointcloud = false;
  37691. this.viewports[0].background = 'none'; //防止renderBG绘制skybox
  37692. var oldMapRender = this.render,
  37693. oldMapClear = this.clear;
  37694. var pRenderer = new Renderer$1(this.renderer); //必须重新创建一个点云渲染器,否则和旧的webgl冲突
  37695. this.render = function () {
  37696. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  37697. if (!_this.visible && !_this.attachedToViewer || !_this.needRender && !params.force) {
  37698. //注意:mapViewer.needRender的权重高于它的viewport的needRender,也就是说,当attachedToViewer时,viewer即使needRender, mapViewer也不一定会渲染。
  37699. return;
  37700. }
  37701. if (!options.renderMeasure) {
  37702. viewer.scene.measurements.forEach(e => Potree.Utils.updateVisible(e, 'renderCloudAtMap', false));
  37703. }
  37704. viewer.renderDefault({
  37705. viewports: _this.viewports,
  37706. camera: _this.camera,
  37707. renderer: _this.renderer,
  37708. render: oldMapRender,
  37709. clear: oldMapClear,
  37710. pRenderer
  37711. });
  37712. viewer.scene.measurements.forEach(e => Potree.Utils.updateVisible(e, 'renderCloudAtMap', true));
  37713. };
  37714. }
  37715. //本来想用mainViewer渲染点云在target上再贴过来的,但是失败了,可能因为不同的renderer不能互通。
  37716. /* setRenderCloud(){
  37717. this.renderCloud = true
  37718. this.cloudBuffer = new THREE.WebGLRenderTarget( 300, 200 , {
  37719. minFilter: THREE.LinearFilter,
  37720. magFilter: THREE.LinearFilter,
  37721. format: THREE.RGBAFormat,
  37722. //stencilBuffer: false,
  37723. });
  37724. } */
  37725. }
  37726. /*
  37727. 渲染顺序:
  37728. 地图
  37729. 背景Overlay
  37730. 地图scene的物体,如cursor、 marker
  37731. 点云(如果有)
  37732. overlay,两层:第一层:viewer的scene中bothMapAndScene的如reticule. 第二层:如测量线(attachToMainViewer时才渲染)
  37733. */
  37734. //本地调试地图白屏是因为代码自动更新了 但没刷新
  37735. class U {
  37736. static toVector3(v, offset) {
  37737. return new Vector3().fromArray(v, offset || 0);
  37738. }
  37739. static toBox3(b) {
  37740. return new Box3(U.toVector3(b), U.toVector3(b, 3));
  37741. }
  37742. static findDim(schema, name) {
  37743. var dim = schema.find(dim => dim.name == name);
  37744. if (!dim) throw new Error('Failed to find ' + name + ' in schema');
  37745. return dim;
  37746. }
  37747. static sphereFrom(b) {
  37748. return b.getBoundingSphere(new Sphere());
  37749. }
  37750. }
  37751. ;
  37752. class PointCloudEptGeometry {
  37753. constructor(url, info) {
  37754. var version = info.version;
  37755. var schema = info.schema;
  37756. var bounds = info.bounds;
  37757. var boundsConforming = info.boundsConforming;
  37758. var xyz = [U.findDim(schema, 'X'), U.findDim(schema, 'Y'), U.findDim(schema, 'Z')];
  37759. var scale = xyz.map(d => d.scale || 1);
  37760. var offset = xyz.map(d => d.offset || 0);
  37761. this.eptScale = U.toVector3(scale);
  37762. this.eptOffset = U.toVector3(offset);
  37763. this.url = url;
  37764. this.info = info;
  37765. this.type = 'ept';
  37766. this.schema = schema;
  37767. this.span = info.span || info.ticks;
  37768. this.boundingBox = U.toBox3(bounds);
  37769. this.tightBoundingBox = U.toBox3(boundsConforming);
  37770. this.offset = U.toVector3([0, 0, 0]);
  37771. this.boundingSphere = U.sphereFrom(this.boundingBox);
  37772. this.tightBoundingSphere = U.sphereFrom(this.tightBoundingBox);
  37773. this.version = new Potree.Version('1.7');
  37774. this.projection = null;
  37775. this.fallbackProjection = null;
  37776. if (info.srs && info.srs.horizontal) {
  37777. this.projection = info.srs.authority + ':' + info.srs.horizontal;
  37778. }
  37779. if (info.srs.wkt) {
  37780. if (!this.projection) this.projection = info.srs.wkt;else this.fallbackProjection = info.srs.wkt;
  37781. }
  37782. {
  37783. // TODO [mschuetz]: named projections that proj4 can't handle seem to cause problems.
  37784. // remove them for now
  37785. try {
  37786. proj4(this.projection);
  37787. } catch (e) {
  37788. this.projection = null;
  37789. }
  37790. }
  37791. {
  37792. var attributes = new PointAttributes();
  37793. attributes.add(PointAttribute.POSITION_CARTESIAN);
  37794. attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
  37795. attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  37796. attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  37797. attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
  37798. attributes.add(new PointAttribute("returnNumber", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  37799. attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  37800. attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  37801. attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  37802. this.pointAttributes = attributes;
  37803. }
  37804. this.spacing = (this.boundingBox.max.x - this.boundingBox.min.x) / this.span;
  37805. var hierarchyType = info.hierarchyType || 'json';
  37806. var dataType = info.dataType;
  37807. if (dataType == 'laszip') {
  37808. this.loader = new Potree.EptLaszipLoader();
  37809. } else if (dataType == 'binary') {
  37810. this.loader = new Potree.EptBinaryLoader();
  37811. } else if (dataType == 'zstandard') {
  37812. this.loader = new Potree.EptZstandardLoader();
  37813. } else {
  37814. throw new Error('Could not read data type: ' + dataType);
  37815. }
  37816. }
  37817. }
  37818. ;
  37819. class EptKey {
  37820. constructor(ept, b, d, x, y, z) {
  37821. this.ept = ept;
  37822. this.b = b;
  37823. this.d = d;
  37824. this.x = x || 0;
  37825. this.y = y || 0;
  37826. this.z = z || 0;
  37827. }
  37828. name() {
  37829. return this.d + '-' + this.x + '-' + this.y + '-' + this.z;
  37830. }
  37831. step(a, b, c) {
  37832. var min = this.b.min.clone();
  37833. var max = this.b.max.clone();
  37834. var dst = new Vector3().subVectors(max, min);
  37835. if (a) min.x += dst.x / 2;else max.x -= dst.x / 2;
  37836. if (b) min.y += dst.y / 2;else max.y -= dst.y / 2;
  37837. if (c) min.z += dst.z / 2;else max.z -= dst.z / 2;
  37838. return new Potree.EptKey(this.ept, new Box3(min, max), this.d + 1, this.x * 2 + a, this.y * 2 + b, this.z * 2 + c);
  37839. }
  37840. children() {
  37841. var result = [];
  37842. for (var a = 0; a < 2; ++a) {
  37843. for (var b = 0; b < 2; ++b) {
  37844. for (var c = 0; c < 2; ++c) {
  37845. var add = this.step(a, b, c).name();
  37846. if (!result.includes(add)) result = result.concat(add);
  37847. }
  37848. }
  37849. }
  37850. return result;
  37851. }
  37852. }
  37853. class PointCloudEptGeometryNode extends PointCloudTreeNode {
  37854. constructor(ept, b, d, x, y, z) {
  37855. super();
  37856. this.ept = ept;
  37857. this.key = new Potree.EptKey(this.ept, b || this.ept.boundingBox, d || 0, x, y, z);
  37858. this.id = PointCloudEptGeometryNode.IDCount++;
  37859. this.geometry = null;
  37860. this.boundingBox = this.key.b;
  37861. this.tightBoundingBox = this.boundingBox;
  37862. this.spacing = this.ept.spacing / Math.pow(2, this.key.d);
  37863. this.boundingSphere = U.sphereFrom(this.boundingBox);
  37864. // These are set during hierarchy loading.
  37865. this.hasChildren = false;
  37866. this.children = {};
  37867. this.numPoints = -1;
  37868. this.level = this.key.d;
  37869. this.loaded = false;
  37870. this.loading = false;
  37871. this.oneTimeDisposeHandlers = [];
  37872. var k = this.key;
  37873. this.name = this.toPotreeName(k.d, k.x, k.y, k.z);
  37874. this.index = parseInt(this.name.charAt(this.name.length - 1));
  37875. }
  37876. isGeometryNode() {
  37877. return true;
  37878. }
  37879. getLevel() {
  37880. return this.level;
  37881. }
  37882. isTreeNode() {
  37883. return false;
  37884. }
  37885. isLoaded() {
  37886. return this.loaded;
  37887. }
  37888. getBoundingSphere() {
  37889. return this.boundingSphere;
  37890. }
  37891. getBoundingBox() {
  37892. return this.boundingBox;
  37893. }
  37894. url() {
  37895. return this.ept.url + 'ept-data/' + this.filename();
  37896. }
  37897. getNumPoints() {
  37898. return this.numPoints;
  37899. }
  37900. filename() {
  37901. return this.key.name();
  37902. }
  37903. getChildren() {
  37904. var children = [];
  37905. for (var i = 0; i < 8; i++) {
  37906. if (this.children[i]) {
  37907. children.push(this.children[i]);
  37908. }
  37909. }
  37910. return children;
  37911. }
  37912. addChild(child) {
  37913. this.children[child.index] = child;
  37914. child.parent = this;
  37915. }
  37916. load() {
  37917. if (this.loaded || this.loading) return;
  37918. if (Potree.numNodesLoading >= Potree.maxNodesLoading) return;
  37919. this.loading = true;
  37920. ++Potree.numNodesLoading;
  37921. if (this.numPoints == -1) this.loadHierarchy();
  37922. this.loadPoints();
  37923. }
  37924. loadPoints() {
  37925. this.ept.loader.load(this);
  37926. }
  37927. async loadHierarchy() {
  37928. var nodes = {};
  37929. nodes[this.filename()] = this;
  37930. this.hasChildren = false;
  37931. var eptHierarchyFile = "".concat(this.ept.url, "ept-hierarchy/").concat(this.filename(), ".json");
  37932. var response = await fetch(eptHierarchyFile);
  37933. var hier = await response.json();
  37934. // Since we want to traverse top-down, and 10 comes
  37935. // lexicographically before 9 (for example), do a deep sort.
  37936. var keys = Object.keys(hier).sort((a, b) => {
  37937. var [da, xa, ya, za] = a.split('-').map(n => parseInt(n, 10));
  37938. var [db, xb, yb, zb] = b.split('-').map(n => parseInt(n, 10));
  37939. if (da < db) return -1;
  37940. if (da > db) return 1;
  37941. if (xa < xb) return -1;
  37942. if (xa > xb) return 1;
  37943. if (ya < yb) return -1;
  37944. if (ya > yb) return 1;
  37945. if (za < zb) return -1;
  37946. if (za > zb) return 1;
  37947. return 0;
  37948. });
  37949. keys.forEach(v => {
  37950. var [d, x, y, z] = v.split('-').map(n => parseInt(n, 10));
  37951. var a = x & 1,
  37952. b = y & 1,
  37953. c = z & 1;
  37954. var parentName = d - 1 + '-' + (x >> 1) + '-' + (y >> 1) + '-' + (z >> 1);
  37955. var parentNode = nodes[parentName];
  37956. if (!parentNode) return;
  37957. parentNode.hasChildren = true;
  37958. var key = parentNode.key.step(a, b, c);
  37959. var node = new Potree.PointCloudEptGeometryNode(this.ept, key.b, key.d, key.x, key.y, key.z);
  37960. node.level = d;
  37961. node.numPoints = hier[v];
  37962. parentNode.addChild(node);
  37963. nodes[key.name()] = node;
  37964. });
  37965. }
  37966. doneLoading(bufferGeometry, tightBoundingBox, np, mean) {
  37967. bufferGeometry.boundingBox = this.boundingBox;
  37968. this.geometry = bufferGeometry;
  37969. this.tightBoundingBox = tightBoundingBox;
  37970. this.numPoints = np;
  37971. this.mean = mean;
  37972. this.loaded = true;
  37973. this.loading = false;
  37974. --Potree.numNodesLoading;
  37975. }
  37976. toPotreeName(d, x, y, z) {
  37977. var name = 'r';
  37978. for (var i = 0; i < d; ++i) {
  37979. var shift = d - i - 1;
  37980. var mask = 1 << shift;
  37981. var step = 0;
  37982. if (x & mask) step += 4;
  37983. if (y & mask) step += 2;
  37984. if (z & mask) step += 1;
  37985. name += step;
  37986. }
  37987. return name;
  37988. }
  37989. dispose() {
  37990. if (this.geometry && this.parent != null) {
  37991. this.geometry.dispose();
  37992. this.geometry = null;
  37993. this.loaded = false;
  37994. // this.dispatchEvent( { type: 'dispose' } );
  37995. for (var i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  37996. var handler = this.oneTimeDisposeHandlers[i];
  37997. handler();
  37998. }
  37999. this.oneTimeDisposeHandlers = [];
  38000. }
  38001. }
  38002. }
  38003. PointCloudEptGeometryNode.IDCount = 0;
  38004. class ExtendPointCloudOctree extends PointCloudOctree {
  38005. constructor(geometry, material) {
  38006. material = material || new ExtendPointCloudMaterial();
  38007. super(geometry, material);
  38008. //xzw move from material 。 adaptive_point_size才使用
  38009. /* this.visibleNodesTexture = Utils.generateDataTexture(2048, 1, new THREE.Color(0xffffff));
  38010. this.visibleNodesTexture.minFilter = THREE.NearestFilter;
  38011. this.visibleNodesTexture.magFilter = THREE.NearestFilter; */
  38012. this.boundingBox = this.pcoGeometry.tightBoundingBox; //this.pcoGeometry.boundingBox; //boundingBox是正方体,所以换掉
  38013. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  38014. this.nodeMaxLevel = 0; //add
  38015. if (!this.pcoGeometry.loader.version.equalOrHigher('1.5')) {
  38016. //las 一级一级增长的,但是testNodeMaxLevel时需要大于0
  38017. this.nodeMaxLevel = 1; //add
  38018. }
  38019. this.maxLevel = Infinity;
  38020. this.temp = {
  38021. sizeFitToLevel: {},
  38022. opacity: {}
  38023. }; //add
  38024. //add
  38025. this.panos = [];
  38026. this.matrixAutoUpdate = false; //最好禁止updateMatrix 直接使用matrixWorld
  38027. this.orientationUser = 0;
  38028. this.translateUser = new Vector3();
  38029. this.rotateMatrix = new Matrix4();
  38030. this.transformMatrix = new Matrix4(); // 数据集的变化矩阵
  38031. this.transformInvMatrix = new Matrix4();
  38032. /* this.transformMatrix2 = new THREE.Matrix4;// 数据集的变化矩阵
  38033. this.transformInvMatrix2 = new THREE.Matrix4; */
  38034. this.rotateInvMatrix = new Matrix4();
  38035. this.material.spacing = this.pcoGeometry.spacing; //初始化一下 以便于设置pointsize
  38036. this.nodeMaxLevelPredict = this.predictNodeMaxLevel(); //预测maxNodeLevel
  38037. this.testMaxNodeCount = this.testMaxNodeCount2 = 0;
  38038. this._visible = true;
  38039. this.pcoGeometry.addEventListener('updateNodeMaxLevel', this.updateNodeMaxLevel.bind(this));
  38040. this.isPointcloud = true; //add
  38041. }
  38042. /*
  38043. 注释:node的level从最大的box 0开始。
  38044. 且加载任意一个node必定也会加载它的所有祖先。(如visibleNodes中有一个level为4,则一定有3,2,1,0)
  38045. visibleNodes就是所有可见的node,比如:
  38046. 如果相机在0这个位置朝下,这时候的visibleNodes中只有一个level为0的node;
  38047. 而如果朝上看,上方的几个node如果在视野中占据足够大的位置的话,就会加载。
  38048. 如果相机在2这个位置朝上,这时候的visibleNodes中所包含的level为: 0,1,2
  38049. ________________
  38050. | | | |
  38051. |__2| | |
  38052. | 1 | 1 |
  38053. |_______|_______|
  38054. | |
  38055. | |
  38056. | 0 |
  38057. |_______________|
  38058. 查看box可在potree中开启
  38059. */
  38060. updateNodeMaxLevel(e) {
  38061. //目前点云包含node的最高level
  38062. var level = Math.max(e.level, this.nodeMaxLevel);
  38063. if (level != this.nodeMaxLevel) {
  38064. this.nodeMaxLevel = level;
  38065. //viewer.dispatchEvent({type:'updateNodeMaxLevel', pointcloud: this, nodeMaxLevel:level})
  38066. Potree.settings.isOfficial || console.log('updateNodeMaxLevel ' + this.dataset_id + " : " + this.nodeMaxLevel);
  38067. setTimeout(() => {
  38068. this.setPointLevel(); //重新计算 延迟是因为testNodeMax会变回旧的
  38069. }, 1);
  38070. if (!Potree.settings.sizeFitToLevel) {
  38071. this.changePointSize();
  38072. }
  38073. }
  38074. } //注:在没有加载到真实的 nodeMaxLevel之前,点云会显示得偏大
  38075. //panoEdit时比预测值小很多?
  38076. testMaxNodeLevel(camera) {
  38077. //手动使maxLevel达到最高,从而迫使updateNodeMaxLevel。 因为Potree.settings.pointDensity 不为 'high'时,maxLevel不是所加载的最高,就很容易加载不出下一个层级,导致无法知道nodeMaxLevel
  38078. if (this.testMaxNodeLevelDone) return;
  38079. //if(this.nodeMaxLevel > this.nodeMaxLevelPredict.min )return
  38080. if (this.nodeMaxLevel == 0) return true;
  38081. if (camera.type == "OrthographicCamera" || this.testMaxNodeCount < 50) {
  38082. if (!Potree.Utils.isInsideFrustum(this.bound, camera)) {
  38083. return true;
  38084. }
  38085. } else if (!viewer.atDatasets.includes(this)) return true; //否则老远就count++
  38086. var levels = this.visibleNodes.map(e => e.getLevel());
  38087. var actMaxLevel = Math.max.apply(null, levels); //实际加载到的最高的node level
  38088. if (actMaxLevel < this.maxLevel) return true; // 还没加载到能加载到的最高。 但在细节设置较低时,排除作用微弱。
  38089. //尝试加载出更高级的level
  38090. var old = this.maxLevel;
  38091. this.maxLevel = 12;
  38092. //var visibleNodes1 = this.visibleNodes.map(e=>e.getLevel())
  38093. //console.log('visibleNodes1',visibleNodes1)
  38094. Potree.updatePointClouds([this], viewer.scene.getActiveCamera(), viewer.mainViewport.resolution);
  38095. //不在camera可视范围内还是加载不出来。即使临时修改位置
  38096. var visibleNodes2 = this.visibleNodes.map(e => e.getLevel());
  38097. //console.log('visibleNodes2',visibleNodes2)
  38098. this.maxLevel = old;
  38099. this.testMaxNodeCount++;
  38100. viewer.testMaxNodeCount++;
  38101. //console.log('testMaxNodeCount', this.dataset_id, this.testMaxNodeCount, 'nodeMaxLevel', this.nodeMaxLevel )
  38102. if (this.testMaxNodeCount == Potree.config.testNodeCount1) {
  38103. //差不多等当前所在数据集nodeMaxLevel加载出来
  38104. this.changePointSize(); //重新更新一下大小。因之前用的是nodeMaxLevelPredict (防止刚开始因nodeMaxLevel没涨完,导致过大的点云突然出现
  38105. }
  38106. if (this.testMaxNodeCount > 100) {
  38107. console.log('testMaxNodeLevel次数超出,强制结束:', this.dataset_id, this.nodeMaxLevel, this.nodeMaxLevelPredict.min);
  38108. this.testMaxNodeLevelDone = 'moreThanMaxCount';
  38109. return; //在可以看见点云的情况下,超时,有可能是预测的max是错的
  38110. }
  38111. if (this.nodeMaxLevel < this.nodeMaxLevelPredict.min) return true; //仍需要继续testMaxNodeLevel
  38112. this.testMaxNodeCount2++; // 已经> this.nodeMaxLevelPredict.min 后,开始计数。因为min可能低于真实nodeMaxLevel所以要再试几次
  38113. if (this.testMaxNodeCount2 < 50) return true; //再试几次 ( 主要是细节调得低时需要多测几次才加载到
  38114. this.testMaxNodeLevelDone = true;
  38115. }
  38116. updateMatrixWorld(force) {
  38117. //add
  38118. super.updateMatrixWorld(force);
  38119. this.matrixWorldInverse = this.matrixWorld.clone().invert();
  38120. }
  38121. setPointLevel() {
  38122. var pointDensity = Potree.settings.pointDensity;
  38123. var config = Potree.config.pointDensity[pointDensity];
  38124. if (!config) return;
  38125. /* if(this.testingMaxLevel){
  38126. this.maxLevel = 12;//先加载到最大的直到测试完毕。由于5个level为一组来加载,所以如果写4最高能加载到5,如果写5最高能加载到下一个级别的最高也就是10
  38127. //console.log('maxLevel: '+e.maxLevel + ' testingMaxLevel中 ' )
  38128. }else{ */
  38129. var percent = config.percentByUser && Potree.settings.UserDensityPercent != void 0 ? Potree.settings.UserDensityPercent : config.maxLevelPercent;
  38130. this.maxLevel = Math.round(percent * this.nodeMaxLevel);
  38131. //console.log('maxLevel: '+e.maxLevel + ', density : '+Potree.settings.pointDensity, ", percent :"+percent);
  38132. if (Potree.settings.sizeFitToLevel) {
  38133. this.changePointSize();
  38134. }
  38135. this.changePointOpacity();
  38136. //}
  38137. viewer.dealBeforeRender || viewer.dispatchEvent('content_changed');
  38138. }
  38139. //预测可能的nodeMaxLevel:
  38140. predictNodeMaxLevel() {
  38141. //预测maxNodeLevel。 可能只适用于我们相机拍的点云
  38142. var spacing = {
  38143. min: 0.005,
  38144. max: 0.014
  38145. }; //最小节的两点间的距离 ,获得方法:spacing / Math.pow(2, nodeMaxLevel)。 目前观测的我们自己拍的这个数值的范围大概是这样
  38146. var min = Math.log2(this.material.spacing / spacing.max); //有见过最大是0.01368
  38147. var max = Math.log2(this.material.spacing / spacing.min); //大部分是 0.006
  38148. //console.log('predictNodeMaxLevel:', this.name , min, max )
  38149. //只对深时相机,其他相机不准
  38150. return {
  38151. min,
  38152. max
  38153. };
  38154. }
  38155. getHighestNodeSpacing() {
  38156. return this.material.spacing / Math.pow(2, this.nodeMaxLevel); //前提是这个nodeMaxLevel是准确的
  38157. }
  38158. updateMaterial(material, visibleNodes, camera, renderer, resolution) {
  38159. //改
  38160. material.fov = camera.fov * (Math.PI / 180);
  38161. /* material.screenWidth = renderer.domElement.clientWidth;
  38162. material.screenHeight = renderer.domElement.clientHeight; */
  38163. material.resolution = resolution;
  38164. material.spacing = this.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  38165. material.near = camera.near;
  38166. material.far = camera.far;
  38167. material.uniforms.octreeSize.value = this.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  38168. }
  38169. pick(viewer, viewport, camera, ray) {
  38170. var params = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  38171. //改
  38172. var renderer = viewer.renderer;
  38173. var pRenderer = viewer.pRenderer;
  38174. viewer.addTimeMark('pick', 'start');
  38175. var getVal = (a, b) => a != void 0 ? a : b;
  38176. var pickWindowSize = params.pickWindowSize; //拾取像素边长,越小越精准,但点云稀疏的话可能容易出现识别不到的情况。 另外左下侧会有缝隙无法识别到,缝隙大小和这个值有关//突然发现pickWindowSize在一百以内的变化对pick费时影响甚微,1和100差1毫秒不到,但400时会多4毫秒
  38177. if (pickWindowSize == void 0) {
  38178. if (Potree.settings.displayMode == 'showPanos') {
  38179. pickWindowSize = 50;
  38180. } else {
  38181. var r0 = this.nodeMaxLevel > 0 ? this.maxLevel / this.nodeMaxLevel : 0.5;
  38182. pickWindowSize = MathUtils.clamp(Math.round((1.1 - r0) * 80), 15, 100);
  38183. }
  38184. }
  38185. if (camera.type == 'OrthographicCamera') {
  38186. var cameraDir = new Vector3(0, 0, -1).applyQuaternion(camera.quaternion);
  38187. pickWindowSize *= 4; //pointsize比较大时截取太小会没多少点可以选
  38188. }
  38189. var pickOutsideClipRegion = getVal(params.pickOutsideClipRegion, false);
  38190. var size = params.resolution || (viewport ? viewport.resolution : renderer.getSize(new Vector2()));
  38191. var width = Math.ceil(getVal(params.width, size.width)); //renderTarget大小。影响识别精度
  38192. var height = Math.ceil(getVal(params.height, size.height));
  38193. var screenshot = () => {
  38194. if (window.testScreen) {
  38195. pickMaterial.activeAttributeName = "rgba";
  38196. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget);
  38197. var dataUrl = Potree.Utils.renderTargetToDataUrl(pickState.renderTarget, width, height, renderer);
  38198. Potree.Common.downloadFile(dataUrl, 'screenshot.png');
  38199. window.testScreen = 0;
  38200. pickMaterial.activeAttributeName = "indices"; //indices
  38201. renderer.clear(true, true, true);
  38202. }
  38203. };
  38204. var pointSizeType = getVal(params.pointSizeType, this.material.pointSizeType);
  38205. var pointSize = getVal(params.pointSize, this.material.size);
  38206. var nodes = this.nodesOnRay(this.visibleNodes, ray);
  38207. if (window.testScreen) {
  38208. console.log('nodes.length', this.visibleNodes.length, nodes);
  38209. }
  38210. if (nodes.length === 0) {
  38211. //console.log('nodes.length === 0')
  38212. return null;
  38213. }
  38214. //console.log('nodes.length != 0', this.name)
  38215. if (!this.pickState) {
  38216. var scene = new Scene();
  38217. var material = new ExtendPointCloudMaterial();
  38218. material.activeAttributeName = "indices"; //indices
  38219. var renderTarget = new WebGLRenderTarget(1, 1, {
  38220. minFilter: LinearFilter,
  38221. magFilter: NearestFilter,
  38222. format: RGBAFormat
  38223. });
  38224. this.pickState = {
  38225. renderTarget: renderTarget,
  38226. material: material,
  38227. scene: scene
  38228. };
  38229. }
  38230. ;
  38231. var pickState = this.pickState;
  38232. var pickMaterial = pickState.material;
  38233. {
  38234. // update pick material
  38235. pickMaterial.pointSizeType = pointSizeType;
  38236. //pickMaterial.shape = this.material.shape;
  38237. pickMaterial.shape = Potree.PointShape.PARABOLOID;
  38238. pickMaterial.uniforms.uFilterReturnNumberRange.value = this.material.uniforms.uFilterReturnNumberRange.value;
  38239. pickMaterial.uniforms.uFilterNumberOfReturnsRange.value = this.material.uniforms.uFilterNumberOfReturnsRange.value;
  38240. pickMaterial.uniforms.uFilterGPSTimeClipRange.value = this.material.uniforms.uFilterGPSTimeClipRange.value;
  38241. pickMaterial.uniforms.uFilterPointSourceIDClipRange.value = this.material.uniforms.uFilterPointSourceIDClipRange.value;
  38242. pickMaterial.size = pointSize;
  38243. pickMaterial.uniforms.minSize.value = this.material.uniforms.minSize.value;
  38244. pickMaterial.uniforms.maxSize.value = this.material.uniforms.maxSize.value;
  38245. pickMaterial.classification = this.material.classification;
  38246. pickMaterial.recomputeClassification();
  38247. //pickClipped判断转移到上一层函数
  38248. var {
  38249. bigClipInBox,
  38250. clipBoxes_in,
  38251. clipBoxes_out
  38252. } = this.material;
  38253. pickMaterial.setClipBoxes(bigClipInBox, clipBoxes_in, clipBoxes_out, []);
  38254. this.updateMaterial(pickMaterial, nodes, camera, renderer, new Vector2(width, height));
  38255. }
  38256. pickState.renderTarget.setSize(width, height); //仅绘制屏幕大小的,而不乘以devicePixelRatio
  38257. var pixelPos = new Vector2(params.x, params.y);
  38258. var gl = renderer.getContext();
  38259. //规定渲染范围,只渲染一小块
  38260. /* renderer.setScissorTest(true);
  38261. gl.enable(gl.SCISSOR_TEST);
  38262. gl.scissor(
  38263. parseInt(pixelPos.x - (pickWindowSize - 1) / 2),
  38264. parseInt(pixelPos.y - (pickWindowSize - 1) / 2),
  38265. parseInt(pickWindowSize), parseInt(pickWindowSize));
  38266. */ //---这段没用
  38267. pickState.renderTarget.scissor.set(parseInt(pixelPos.x - (pickWindowSize - 1) / 2), parseInt(pixelPos.y - (pickWindowSize - 1) / 2), parseInt(pickWindowSize), parseInt(pickWindowSize));
  38268. pickState.renderTarget.scissorTest = true;
  38269. renderer.state.buffers.depth.setTest(pickMaterial.depthTest);
  38270. renderer.state.buffers.depth.setMask(pickMaterial.depthWrite);
  38271. renderer.state.setBlending(NoBlending);
  38272. {
  38273. // RENDER
  38274. renderer.setRenderTarget(pickState.renderTarget);
  38275. //gl.clearColor(0, 0, 0, 0);
  38276. renderer.setClearColor(0x000000, 0);
  38277. var tmp = this.material;
  38278. this.material = pickMaterial;
  38279. screenshot();
  38280. pRenderer.renderOctree(this, nodes, camera, pickState.renderTarget); //只绘制ray pick到的部分nodes
  38281. this.material = tmp;
  38282. }
  38283. var clamp = (number, min, max) => Math.min(Math.max(min, number), max);
  38284. var x = parseInt(clamp(pixelPos.x - (pickWindowSize - 1) / 2, 0, width));
  38285. var y = parseInt(clamp(pixelPos.y - (pickWindowSize - 1) / 2, 0, height));
  38286. /* let w = parseInt(Math.min(x + pickWindowSize, width) - x);
  38287. let h = parseInt(Math.min(y + pickWindowSize, height) - y); */
  38288. var pixelCount = pickWindowSize * pickWindowSize; //w * h;
  38289. var buffer = new Uint8Array(4 * pixelCount);
  38290. //w<pickWindowSize会报错
  38291. gl.readPixels(x, y, pickWindowSize, pickWindowSize, gl.RGBA, gl.UNSIGNED_BYTE, buffer); //这句花费最多时间 pc:2-4, 即使只有1*1像素
  38292. renderer.clear(true, true, true); //绘制完就clear否则download的图会有上次的轨迹
  38293. renderer.setRenderTarget(null);
  38294. renderer.state.reset();
  38295. renderer.setScissorTest(false);
  38296. gl.disable(gl.SCISSOR_TEST);
  38297. var pixels = buffer;
  38298. var ibuffer = new Uint32Array(buffer.buffer); //四个数整合成一个
  38299. // find closest hit inside pixelWindow boundaries
  38300. var min = Number.MAX_VALUE;
  38301. var hits = [],
  38302. hits2 = [],
  38303. rSquare;
  38304. if (!params.all) {
  38305. var r = MathUtils.clamp(Math.floor(pickWindowSize / 2), 1, 40);
  38306. rSquare = r * r;
  38307. }
  38308. for (var u = 0; u < pickWindowSize; u++) {
  38309. for (var v = 0; v < pickWindowSize; v++) {
  38310. var offset = u + v * pickWindowSize;
  38311. var distance = Math.pow(u - (pickWindowSize - 1) / 2, 2) + Math.pow(v - (pickWindowSize - 1) / 2, 2);
  38312. var pcIndex = pixels[4 * offset + 3]; //nodes index(第四位)
  38313. pixels[4 * offset + 3] = 0; //去除nodes index后剩下的是index(前三位)
  38314. var pIndex = ibuffer[offset]; //index
  38315. if (!(pcIndex === 0 && pIndex === 0) && pcIndex !== undefined && pIndex !== undefined) {
  38316. var hit = {
  38317. pIndex: pIndex,
  38318. pcIndex: pcIndex,
  38319. distanceToCenter: distance
  38320. };
  38321. if (params.all) {
  38322. hits.push(hit);
  38323. } else {
  38324. if (hits.length > 0) {
  38325. //最后选取的是最靠近鼠标的那个pick
  38326. if (distance < hits[0].distanceToCenter) {
  38327. hits[0] = hit;
  38328. }
  38329. } else {
  38330. hits.push(hit);
  38331. }
  38332. if (distance < rSquare) hits2.push(hit); //add
  38333. }
  38334. }
  38335. }
  38336. }
  38337. if (!params.all && Potree.settings.pickFrontPointRatio) {
  38338. if (hits2.length) {
  38339. //add
  38340. hits = hits2;
  38341. }
  38342. }
  38343. // { // DEBUG: show panel with pick image
  38344. // let img = Utils.pixelsArrayToImage(buffer, w, h);
  38345. // let screenshot = img.src;
  38346. // if(!this.debugDIV){
  38347. // this.debugDIV = $(`
  38348. // <div id="pickDebug"
  38349. // style="position: absolute;
  38350. // right: 400px; width: 300px;
  38351. // bottom: 44px; width: 300px;
  38352. // z-index: 1000;
  38353. // "></div>`);
  38354. // $(document.body).append(this.debugDIV);
  38355. // }
  38356. // this.debugDIV.empty();
  38357. // this.debugDIV.append($(`<img src="${screenshot}"
  38358. // style="transform: scaleY(-1); width: 300px"/>`));
  38359. // //$(this.debugWindow.document).append($(`<img src="${screenshot}"/>`));
  38360. // //this.debugWindow.document.write('<img src="'+screenshot+'"/>');
  38361. // }
  38362. for (var _hit of hits) {
  38363. var point = {};
  38364. if (!nodes[_hit.pcIndex]) {
  38365. return null;
  38366. }
  38367. var node = nodes[_hit.pcIndex];
  38368. var pc = node.sceneNode;
  38369. var geometry = node.geometryNode.geometry;
  38370. var _loop = function _loop() {
  38371. var attribute = geometry.attributes[attributeName];
  38372. if (attributeName === 'position') {
  38373. var _x = attribute.array[3 * _hit.pIndex + 0];
  38374. var _y = attribute.array[3 * _hit.pIndex + 1];
  38375. var z = attribute.array[3 * _hit.pIndex + 2];
  38376. var position = new Vector3(_x, _y, z);
  38377. position.applyMatrix4(pc.matrixWorld);
  38378. point[attributeName] = position;
  38379. //add
  38380. if (!params.all && Potree.settings.pickFrontPointRatio) {
  38381. if (camera.type == 'OrthographicCamera') {
  38382. var vec = new Vector3().subVectors(position, camera.position);
  38383. _hit.disSquare = vec.projectOnVector(cameraDir).length(); //只考虑到相机的垂直距离
  38384. } else {
  38385. _hit.disSquare = camera.position.distanceTo(position);
  38386. }
  38387. }
  38388. } else if (attributeName === 'indices') {} else {
  38389. var values = attribute.array.slice(attribute.itemSize * _hit.pIndex, attribute.itemSize * (_hit.pIndex + 1));
  38390. if (attribute.potree) {
  38391. var {
  38392. scale,
  38393. offset: _offset
  38394. } = attribute.potree;
  38395. values = values.map(v => v / scale + _offset);
  38396. }
  38397. point[attributeName] = values;
  38398. //debugger;
  38399. //if (values.itemSize === 1) {
  38400. // point[attribute.name] = values.array[hit.pIndex];
  38401. //} else {
  38402. // let value = [];
  38403. // for (let j = 0; j < values.itemSize; j++) {
  38404. // value.push(values.array[values.itemSize * hit.pIndex + j]);
  38405. // }
  38406. // point[attribute.name] = value;
  38407. //}
  38408. }
  38409. };
  38410. for (var attributeName in geometry.attributes) {
  38411. _loop();
  38412. }
  38413. _hit.point = point;
  38414. }
  38415. viewer.addTimeMark('pick', 'end');
  38416. if (params.all) {
  38417. return hits.map(hit => hit.point);
  38418. } else {
  38419. if (hits.length === 0) {
  38420. return null;
  38421. } else {
  38422. if (Potree.settings.pickFrontPointRatio == 0) {
  38423. //如果不需要选偏离镜头近的,就要离中心近的即可
  38424. //console.log(hits[0], hits2, pixelPos)
  38425. return hits[0].point;
  38426. }
  38427. //为了防止透过点云缝隙,选到后排的点云,将选取的位置离相机的距离考虑进去。倾向选择离相机近、且离鼠标位置近的点。(否则按照原方案只选离鼠标位置最近的,可能从高楼不小心走到下层,导航选点也是)
  38428. var sorted1 = hits.sort((a, b) => a.disSquare - b.disSquare).slice();
  38429. var nearest = sorted1[0]; //return nearest.point; //直接用最近点 在点云稀疏时不太跟手,如地面上,最近点往往在鼠标下方
  38430. hits.forEach(hit => {
  38431. var disDiff = hit.disSquare - nearest.disSquare; //和最近点的偏差
  38432. hit.disDiff = disDiff;
  38433. hit.score = -hit.distanceToCenter - disDiff * Potree.settings.pickFrontPointRatio;
  38434. });
  38435. var sorted2 = hits.sort((a, b) => b.score - a.score);
  38436. //console.log(sorted2[0].point.position.z )
  38437. return sorted2[0].point;
  38438. }
  38439. }
  38440. }
  38441. // 设置点大小
  38442. changePointSize(num, sizeFitToLevel) {
  38443. var size, nodeMaxLevel;
  38444. //console.error('changePointSize',num)
  38445. var dontRender = viewer.dealBeforeRender;
  38446. if (this.material.pointSizeType != PointSizeType.ATTENUATED) {
  38447. num && (size = num / Potree.config.material.realPointSize / 1.3);
  38448. } else {
  38449. var num_ = num;
  38450. if (num_ == void 0) {
  38451. num_ = this.temp.pointSize;
  38452. } else {
  38453. this.temp.pointSize = num_;
  38454. }
  38455. num_ = num_ / (Potree.config.material.realPointSize / Potree.config.material.pointSize); //兼容
  38456. num_ *= this.scale.x; //for mergeEditor
  38457. //num_ = Math.pow(num_, 1.05) * 5
  38458. nodeMaxLevel = this.testMaxNodeCount >= Potree.config.testNodeCount1 ? this.nodeMaxLevel : Math.max(this.nodeMaxLevel, this.nodeMaxLevelPredict.max); //防止刚开始因nodeMaxLevel没涨完,导致过大的点云突然出现
  38459. if (sizeFitToLevel || Potree.settings.sizeFitToLevel) {
  38460. //按照点云质量来调整的版本: 近似将pointSizeType换成ADAPTIVE
  38461. var str = this.temp.pointSize + ':' + this.maxLevel + ':' + nodeMaxLevel;
  38462. var value = this.temp.sizeFitToLevel[str]; //储存。防止每次渲染(反复切换density)都要算。
  38463. if (value) {
  38464. size = value *= this.scale.x;
  38465. } else {
  38466. if (this.maxLevel == Infinity) return;
  38467. var base = this.material.spacing / Math.pow(2, this.maxLevel); //点云大小在level为0时设置为spacing,每长一级,大小就除以2. (不同场景还是会有偏差)
  38468. var r = nodeMaxLevel > 0 ? this.maxLevel / nodeMaxLevel : 0.5; //越大,越精细,需要越缩小
  38469. base *= nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(r, 3 * r + 0.3)) : 0.1; //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙(但是ortho是不用缩小的,如果能分开判断就好了)
  38470. //base *= nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(this.maxLevel / nodeMaxLevel, 1.1)) : 0.1 //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙(但是ortho是不用缩小的,如果能分开判断就好了)
  38471. size = base * 20 * num_; /* * window.devicePixelRatio */
  38472. //在t-8BCqxQAr93 会议室 和 t-e2Kb2iU 隧道 两个场景里调节,因为它们的spacing相差较大,观察会议室墙壁的龟裂程度
  38473. this.temp.sizeFitToLevel[str] = size;
  38474. }
  38475. } else {
  38476. var _base = 0.015; //2024.8.21 又要求需要不同场景点云大小相同,所以只能固定值了 (正式环境这两个场景 SG-5yxFuWhEMlg SG-XZNyvCDk0jz)
  38477. //let base = this.material.spacing / Math.pow(2, nodeMaxLevel) //在保证最高级别大小刚好的情况下,不改变level降低后的大小
  38478. //base的数值理论上应该是右侧算出来的,但发现有的场景nodeMaxLevel和nodeMaxLevelPredict差别较大的点云显示也过大,而直接换成固定值反而可以适应所有场景。该固定值来源于 getHighestNodeSpacing 最小值,修改了下。(会不会是我们的相机其实该值是固定的,根据该值算出的spacing才是有误差的? 如果换了相机是否要改值?)
  38479. //2022-12-21又换回非固定值。因为有的场景如SS-t-t01myDqnfE的两个数据集密集程度差别很大,应该将稀疏点云的大小设置的大些。 但是这样的缺点是两个数据集因相接处有大有小无法融合。
  38480. size = _base * 20 * num_;
  38481. }
  38482. //不同数据集点云最高级别时的间距不同,但不知道如何计算, 级别越高点云越密,spacing越大初始级别越密。 但实际并非2的level次方,底数可能1-2之间
  38483. }
  38484. //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 */)
  38485. if (size) {
  38486. if (Potree.settings.sortCloudMat) {
  38487. //被废弃,不给material分组了
  38488. this.size = size;
  38489. this.material.size = size;
  38490. } else {
  38491. this.material.size = size;
  38492. }
  38493. }
  38494. dontRender || viewer.dispatchEvent('content_changed');
  38495. }
  38496. // 设置点透明度
  38497. changePointOpacity(num, canMoreThanOne) {
  38498. //num:0-1 navvis用的是亮度
  38499. if (num == void 0) {
  38500. num = this.temp.pointOpacity;
  38501. } else {
  38502. this.temp.pointOpacity = num;
  38503. }
  38504. var dontRender = viewer.dealBeforeRender; //在执行beforeRender时更改的话不要发送content_changed 尤其分屏
  38505. if (Potree.settings.notAdditiveBlending) {
  38506. return this.material.opacity = num;
  38507. }
  38508. var opacity;
  38509. if (num == 1) {
  38510. opacity = 1;
  38511. } else {
  38512. var str = (Potree.settings.sizeFitToLevel ? 'sizeFit:' : '') + (canMoreThanOne ? 'canMoreThanOne:' : '') + this.temp.pointOpacity + ':' + this.maxLevel + ':' + this.nodeMaxLevel;
  38513. var value = this.temp.opacity[str]; //储存。防止每次渲染(反复切换density)都要算。
  38514. if (value) {
  38515. opacity = value;
  38516. } else {
  38517. if (Potree.settings.sizeFitToLevel) {
  38518. //按照点云质量来调整的版本:
  38519. var base = this.material.spacing / Math.pow(1.7, this.maxLevel); //随着level提高,点云重叠几率增多
  38520. var minBase = this.material.spacing / Math.pow(1.7, this.nodeMaxLevel);
  38521. var ratio = Math.min(1 / base, 1 / minBase / 3); //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
  38522. opacity = base * ratio * num;
  38523. if (!canMoreThanOne) {
  38524. opacity = MathUtils.clamp(opacity, 0, 0.999); //到1就不透明了(可能出现一段一样)
  38525. }
  38526. } else {
  38527. var _base2 = this.material.spacing / Math.pow(2, this.maxLevel);
  38528. var _minBase = this.material.spacing / Math.pow(2, this.nodeMaxLevel);
  38529. //console.log(1 / base, 1 / minBase / 6)
  38530. var _ratio = Math.min(1 / _base2, 1 / _minBase / 3); //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
  38531. opacity = _base2 * _ratio * num;
  38532. if (!canMoreThanOne) {
  38533. opacity = MathUtils.clamp(opacity, 0, 0.999); //到1就不透明了(可能出现一段一样)
  38534. }
  38535. }
  38536. this.temp.opacity[str] = opacity;
  38537. }
  38538. //缺点:防止颜色过亮主要是相机离远时,当在漫游点处由于离点云太近,可能会导致高质量点云看起来很暗。
  38539. }
  38540. //console.log('changePointOpacity ' + this.dataset_id + ', num : ' + num + ' , opacity : ' + this.material.opacity) //检查是否做到了低质量时num==opacity,中质量opacity稍小于num,高质量更小
  38541. if (Potree.settings.sortCloudMat) {
  38542. this.opacity = opacity;
  38543. this.material.opacity = opacity;
  38544. } else {
  38545. this.material.opacity = opacity;
  38546. }
  38547. dontRender || viewer.dispatchEvent('content_changed');
  38548. }
  38549. updateBound() {
  38550. var boundingBox_ = this.pcoGeometry.tightBoundingBox.clone().applyMatrix4(this.matrixWorld); //tightBoundingBox是点云原始的bound,但经过(绕z)旋转后bound有所改变,比之前体积更大。
  38551. this.bound = boundingBox_;
  38552. this.bound2 = this.getBoundWithPanos();
  38553. }
  38554. getBoundWithPanos() {
  38555. //确保panoBound在内的bound
  38556. var bound = this.bound.clone();
  38557. this.panos.forEach(pano => {
  38558. var panoBound = new Box3();
  38559. panoBound.expandByPoint(pano.position);
  38560. panoBound.expandByVector(new Vector3(1, 1, 1)); //give pano a margin
  38561. bound.union(panoBound);
  38562. });
  38563. return bound;
  38564. }
  38565. getPanosBound() {
  38566. //仅由所有pano构成的bound
  38567. if (this.panos.length > 0) {
  38568. var minSize = new Vector3(1, 1, 1);
  38569. this.panosBound = math.getBoundByPoints(this.panos.map(e => e.position), minSize);
  38570. } else {
  38571. this.panosBound = null;
  38572. }
  38573. }
  38574. getUnrotBoundPoint(type) {
  38575. //获取没有旋转的tightBounding的水平四个点
  38576. //如果alighment支持任意轴旋转,水平面上看到的可能就是六边形了,失去意义,到时候不能用这个。也可以若只绕z旋转, 使用tightBoundingBox,否则bound
  38577. var bound = this.pcoGeometry.tightBoundingBox;
  38578. if (type == 'all') {
  38579. return [new Vector3(bound.min.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.min.y, bound.min.z), new Vector3(bound.max.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.max.y, bound.min.z), new Vector3(bound.min.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.min.y, bound.max.z), new Vector3(bound.max.x, bound.max.y, bound.max.z), new Vector3(bound.min.x, bound.max.y, bound.max.z)].map(e => e.applyMatrix4(this.matrixWorld));
  38580. } else return [new Vector3(bound.min.x, bound.min.y, 0), new Vector3(bound.max.x, bound.min.y, 0), new Vector3(bound.max.x, bound.max.y, 0), new Vector3(bound.min.x, bound.max.y, 0)].map(e => e.applyMatrix4(this.matrixWorld));
  38581. }
  38582. getVolume() {
  38583. /* var points = this.getUnrotBoundPoint() -----在只绕z轴旋转时这么写也行
  38584. var area = Math.abs(math.getArea(points))
  38585. return area * (this.bound.max.z - this.bound.min.z) */
  38586. var bound = this.pcoGeometry.tightBoundingBox.clone();
  38587. var size = bound.getSize(new Vector3());
  38588. return size.x * size.y * size.z;
  38589. }
  38590. ifContainsPoint(pos) {
  38591. //pos是否坐落于tightBound内
  38592. /* if(!this.bound || !this.bound.containsPoint(pos))return ---这样写也行
  38593. var points = this.getUnrotBoundPoint()
  38594. return math.isPointInArea(points, null, pos) */
  38595. //要把tightBoundingBox想象成一个volumeBox
  38596. var box = this.pcoGeometry.tightBoundingBox;
  38597. var center = box.getCenter(new Vector3());
  38598. var size = box.getSize(new Vector3());
  38599. var boxMatrix = new Matrix4().setPosition(center.x, center.y, center.z);
  38600. boxMatrix.scale(size);
  38601. boxMatrix.premultiply(this.matrixWorld);
  38602. return Potree.Utils.isIntersectBox(pos, boxMatrix);
  38603. }
  38604. intersectBox(boxWorldMatrix) {
  38605. var boxM = boxWorldMatrix.clone().premultiply(this.matrixWorld.clone().invert()); //box乘上点云逆矩阵 (因为点云的忽略掉其matrixWorld, 为了保持相对位置不变,box要左乘matrixWorld的逆)(因第一个参数bound不好变形,第二个参数box可以)
  38606. return Potree.Utils.isIntersectBox(this.pcoGeometry.tightBoundingBox, boxM);
  38607. }
  38608. updateAttrAuto() {
  38609. var _this$root$geometryNo, _this$root$geometry;
  38610. //add
  38611. var attributes = ((_this$root$geometryNo = this.root.geometryNode) === null || _this$root$geometryNo === void 0 ? void 0 : _this$root$geometryNo.geometry.attributes) || ((_this$root$geometry = this.root.geometry) === null || _this$root$geometry === void 0 ? void 0 : _this$root$geometry.attributes);
  38612. if (!attributes) {
  38613. console.log('updateAttrAuto unready, delay');
  38614. return setTimeout(() => {
  38615. this.updateAttrAuto();
  38616. }, 300);
  38617. }
  38618. this.material.activeAttributeName = Potree.settings.showClass && attributes.classification ? 'classification' : Potree.settings.showHotTemp && attributes.temp ? 'temp' : Potree.settings.showHotIr && attributes.ir ? 'ir' : Potree.settings.cloudAttributeName || 'rgba';
  38619. }
  38620. deepestNodeAt(position) {
  38621. //改
  38622. var startTime = performance.now();
  38623. var toObjectSpace = this.matrixWorld.clone().invert();
  38624. var objPos = position.clone().applyMatrix4(toObjectSpace);
  38625. var current = this.root;
  38626. while (true) {
  38627. var containingChild = null;
  38628. for (var child of current.children) {
  38629. if (child !== undefined && !containingChild) {
  38630. //
  38631. if (child.getBoundingBox().containsPoint(objPos)) {
  38632. containingChild = child;
  38633. }
  38634. }
  38635. }
  38636. if (containingChild !== null && containingChild instanceof PointCloudOctreeNode) {
  38637. //如果是PointCloudOctreeGeometryNode可能geometry还没加载
  38638. current = containingChild;
  38639. } else {
  38640. break;
  38641. }
  38642. }
  38643. var deepest = current;
  38644. console.log('deepestNodeAt', performance.now() - startTime);
  38645. return deepest;
  38646. }
  38647. getNearestPoint(position, onlySearchLeaves) {
  38648. //add 输入一个世界坐标,查找该点云中和它最近的点
  38649. var startTime = performance.now();
  38650. var inNode = this.deepestNodeAt(position);
  38651. var toObjectSpace = this.matrixWorld.clone().invert();
  38652. var objPos = position.clone().applyMatrix4(toObjectSpace); //该值记录一下,以后不改两点云相对位置直接用
  38653. var firstNode = inNode || this.root; //第一个搜寻点的node为所在node,初步找出最近点
  38654. var nearest = firstNode.searchNearestPoint(position, {
  38655. point: null,
  38656. disSquare: Infinity
  38657. });
  38658. nearest.inNode = inNode === null || inNode === void 0 ? void 0 : inNode.name;
  38659. //重新回到根结点向下找邻近node
  38660. var traverse = current => {
  38661. if (current == firstNode || current.getBoundingBox().distanceToPoint(objPos) < nearest.dis) {
  38662. onlySearchLeaves || current.searchNearestPoint(position, nearest); //搜寻当前节点
  38663. var children = current.children.filter(e => e && e instanceof PointCloudOctreeNode);
  38664. if (children.length) {
  38665. for (var child of children) {
  38666. if (child != firstNode) {
  38667. traverse(child);
  38668. }
  38669. }
  38670. } else {
  38671. onlySearchLeaves && current.searchNearestPoint(position, nearest); //搜寻叶子节点
  38672. }
  38673. }
  38674. };
  38675. traverse(this.root);
  38676. console.log('getNearestPoint', nearest, performance.now() - startTime);
  38677. }
  38678. }
  38679. PointCloudOctreeNode.prototype.searchNearestPoint = function (pos) {
  38680. var nearest = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
  38681. point: null,
  38682. disSquare: Infinity
  38683. };
  38684. var positions = this.geometryNode.geometry.attributes.position;
  38685. var tempPos = new Vector3();
  38686. var toObjectSpace = this.sceneNode.matrixWorld.clone().invert();
  38687. var objPos = pos.clone().applyMatrix4(toObjectSpace);
  38688. var startTime = performance.now(),
  38689. finded;
  38690. for (var i = 0; i < positions.count; i++) {
  38691. tempPos.fromArray(positions.array.slice(i * 3, i * 3 + 3));
  38692. //let diff = new THREE.Vector3().subVectors(tempPos,objPos)
  38693. if (nearest.dis != void 0 && !Potree.math.closeTo(tempPos, objPos, nearest.dis)) {
  38694. //先筛除在xyz方向上的距离
  38695. continue;
  38696. }
  38697. var d = tempPos.distanceToSquared(objPos);
  38698. if (d < nearest.disSquare) {
  38699. finded = true, nearest.point = tempPos, nearest.disSquare = d;
  38700. nearest.dis == void 0 && (nearest.dis = Math.sqrt(nearest.disSquare)); //update
  38701. }
  38702. }
  38703. if (finded) {
  38704. nearest.dis = Math.sqrt(nearest.disSquare); //update
  38705. nearest.point = tempPos.applyMatrix4(this.sceneNode.matrixWorld); //global pos
  38706. nearest.nodeName = this.name;
  38707. }
  38708. console.log('node searchNearestPoint', this.name, performance.now() - startTime);
  38709. //onlySearchLeaves开启后减少了10倍时间,但小概率不准,误差: 点云上的坐标 0.05m , 非点云上的0.1m
  38710. return nearest;
  38711. };
  38712. /*
  38713. 搜索方A pointLoaded
  38714. let tempPos = new THREE.Vector3
  38715. let newAttri = ...
  38716. for(let i=0;i<positions.count;i++){
  38717. tempPos.set(positions[i*3], positions[i*3+1],positions[i*3+2])
  38718. tempPos.applyMatrix4(this.matrixWorld)
  38719. cloudB.getNearestPoint(tempPos)
  38720. }
  38721. */
  38722. class ProfileData {
  38723. constructor(profile) {
  38724. this.profile = profile;
  38725. this.segments = [];
  38726. this.boundingBox = new Box3();
  38727. for (var i = 0; i < profile.points.length - 1; i++) {
  38728. var start = profile.points[i];
  38729. var end = profile.points[i + 1];
  38730. var startGround = new Vector3(start.x, start.y, 0);
  38731. var endGround = new Vector3(end.x, end.y, 0);
  38732. var center = new Vector3().addVectors(endGround, startGround).multiplyScalar(0.5);
  38733. var length = startGround.distanceTo(endGround);
  38734. var side = new Vector3().subVectors(endGround, startGround).normalize();
  38735. var up = new Vector3(0, 0, 1);
  38736. var forward = new Vector3().crossVectors(side, up).normalize();
  38737. var N = forward;
  38738. var cutPlane = new Plane().setFromNormalAndCoplanarPoint(N, startGround);
  38739. var halfPlane = new Plane().setFromNormalAndCoplanarPoint(side, center);
  38740. var segment = {
  38741. start: start,
  38742. end: end,
  38743. cutPlane: cutPlane,
  38744. halfPlane: halfPlane,
  38745. length: length,
  38746. points: new Points$1()
  38747. };
  38748. this.segments.push(segment);
  38749. }
  38750. }
  38751. size() {
  38752. var size = 0;
  38753. for (var segment of this.segments) {
  38754. size += segment.points.numPoints;
  38755. }
  38756. return size;
  38757. }
  38758. }
  38759. ;
  38760. class ProfileRequest {
  38761. constructor(pointcloud, profile, maxDepth, callback) {
  38762. this.pointcloud = pointcloud;
  38763. this.profile = profile;
  38764. this.maxDepth = maxDepth || Number.MAX_VALUE;
  38765. this.callback = callback;
  38766. this.temporaryResult = new ProfileData(this.profile);
  38767. this.pointsServed = 0;
  38768. this.highestLevelServed = 0;
  38769. this.priorityQueue = new BinaryHeap(function (x) {
  38770. return 1 / x.weight;
  38771. });
  38772. this.initialize();
  38773. }
  38774. initialize() {
  38775. this.priorityQueue.push({
  38776. node: this.pointcloud.pcoGeometry.root,
  38777. weight: Infinity
  38778. });
  38779. }
  38780. // traverse the node and add intersecting descendants to queue
  38781. traverse(node) {
  38782. var stack = [];
  38783. for (var i = 0; i < 8; i++) {
  38784. var child = node.children[i];
  38785. if (child && this.pointcloud.nodeIntersectsProfile(child, this.profile)) {
  38786. stack.push(child);
  38787. }
  38788. }
  38789. while (stack.length > 0) {
  38790. var _node = stack.pop();
  38791. var weight = _node.boundingSphere.radius;
  38792. this.priorityQueue.push({
  38793. node: _node,
  38794. weight: weight
  38795. });
  38796. // add children that intersect the cutting plane
  38797. if (_node.level < this.maxDepth) {
  38798. for (var _i = 0; _i < 8; _i++) {
  38799. var _child = _node.children[_i];
  38800. if (_child && this.pointcloud.nodeIntersectsProfile(_child, this.profile)) {
  38801. stack.push(_child);
  38802. }
  38803. }
  38804. }
  38805. }
  38806. }
  38807. update() {
  38808. if (!this.updateGeneratorInstance) {
  38809. this.updateGeneratorInstance = this.updateGenerator();
  38810. }
  38811. var result = this.updateGeneratorInstance.next();
  38812. if (result.done) {
  38813. this.updateGeneratorInstance = null;
  38814. }
  38815. }
  38816. *updateGenerator() {
  38817. // load nodes in queue
  38818. // if hierarchy expands, also load nodes from expanded hierarchy
  38819. // once loaded, add data to this.points and remove node from queue
  38820. // only evaluate 1-50 nodes per frame to maintain responsiveness
  38821. var start = performance.now();
  38822. var maxNodesPerUpdate = 1;
  38823. var intersectedNodes = [];
  38824. for (var i = 0; i < Math.min(maxNodesPerUpdate, this.priorityQueue.size()); i++) {
  38825. var element = this.priorityQueue.pop();
  38826. var node = element.node;
  38827. if (node.level > this.maxDepth) {
  38828. continue;
  38829. }
  38830. if (node.loaded) {
  38831. // add points to result
  38832. intersectedNodes.push(node);
  38833. exports.lru.touch(node);
  38834. this.highestLevelServed = Math.max(node.getLevel(), this.highestLevelServed);
  38835. var geom = node.pcoGeometry;
  38836. var hierarchyStepSize = geom ? geom.hierarchyStepSize : 1;
  38837. var doTraverse = node.getLevel() === 0 || node.level % hierarchyStepSize === 0 && node.hasChildren;
  38838. if (doTraverse) {
  38839. this.traverse(node);
  38840. }
  38841. } else {
  38842. node.load();
  38843. this.priorityQueue.push(element);
  38844. }
  38845. }
  38846. if (intersectedNodes.length > 0) {
  38847. for (var done of this.getPointsInsideProfile(intersectedNodes, this.temporaryResult)) {
  38848. if (!done) {
  38849. //console.log("updateGenerator yields");
  38850. yield false;
  38851. }
  38852. }
  38853. if (this.temporaryResult.size() > 100) {
  38854. this.pointsServed += this.temporaryResult.size();
  38855. this.callback.onProgress({
  38856. request: this,
  38857. points: this.temporaryResult
  38858. });
  38859. this.temporaryResult = new ProfileData(this.profile);
  38860. }
  38861. }
  38862. if (this.priorityQueue.size() === 0) {
  38863. // we're done! inform callback and remove from pending requests
  38864. if (this.temporaryResult.size() > 0) {
  38865. this.pointsServed += this.temporaryResult.size();
  38866. this.callback.onProgress({
  38867. request: this,
  38868. points: this.temporaryResult
  38869. });
  38870. this.temporaryResult = new ProfileData(this.profile);
  38871. }
  38872. this.callback.onFinish({
  38873. request: this
  38874. });
  38875. var index = this.pointcloud.profileRequests.indexOf(this);
  38876. if (index >= 0) {
  38877. this.pointcloud.profileRequests.splice(index, 1);
  38878. }
  38879. }
  38880. yield true;
  38881. }
  38882. *getAccepted(numPoints, node, matrix, segment, segmentDir, points, totalMileage) {
  38883. var checkpoint = performance.now();
  38884. var accepted = new Uint32Array(numPoints);
  38885. var mileage = new Float64Array(numPoints);
  38886. var acceptedPositions = new Float32Array(numPoints * 3);
  38887. var numAccepted = 0;
  38888. var pos = new Vector3();
  38889. var svp = new Vector3();
  38890. var view = new Float32Array(node.geometry.attributes.position.array);
  38891. for (var i = 0; i < numPoints; i++) {
  38892. pos.set(view[i * 3 + 0], view[i * 3 + 1], view[i * 3 + 2]);
  38893. pos.applyMatrix4(matrix);
  38894. var distance = Math.abs(segment.cutPlane.distanceToPoint(pos));
  38895. var centerDistance = Math.abs(segment.halfPlane.distanceToPoint(pos));
  38896. if (distance < this.profile.width / 2 && centerDistance < segment.length / 2) {
  38897. svp.subVectors(pos, segment.start);
  38898. var localMileage = segmentDir.dot(svp);
  38899. accepted[numAccepted] = i;
  38900. mileage[numAccepted] = localMileage + totalMileage;
  38901. points.boundingBox.expandByPoint(pos);
  38902. pos.sub(this.pointcloud.position);
  38903. acceptedPositions[3 * numAccepted + 0] = pos.x;
  38904. acceptedPositions[3 * numAccepted + 1] = pos.y;
  38905. acceptedPositions[3 * numAccepted + 2] = pos.z;
  38906. numAccepted++;
  38907. }
  38908. if (i % 1000 === 0) {
  38909. var duration = performance.now() - checkpoint;
  38910. if (duration > 4) {
  38911. //console.log(`getAccepted yield after ${duration}ms`);
  38912. yield false;
  38913. checkpoint = performance.now();
  38914. }
  38915. }
  38916. }
  38917. accepted = accepted.subarray(0, numAccepted);
  38918. mileage = mileage.subarray(0, numAccepted);
  38919. acceptedPositions = acceptedPositions.subarray(0, numAccepted * 3);
  38920. //let end = performance.now();
  38921. //let duration = end - start;
  38922. //console.log("accepted duration ", duration)
  38923. //console.log(`getAccepted finished`);
  38924. yield [accepted, mileage, acceptedPositions];
  38925. }
  38926. *getPointsInsideProfile(nodes, target) {
  38927. var checkpoint = performance.now();
  38928. var totalMileage = 0;
  38929. var pointsProcessed = 0;
  38930. for (var segment of target.segments) {
  38931. for (var node of nodes) {
  38932. var numPoints = node.numPoints;
  38933. var geometry = node.geometry;
  38934. if (!numPoints) {
  38935. continue;
  38936. }
  38937. {
  38938. // skip if current node doesn't intersect current segment
  38939. var bbWorld = node.boundingBox.clone().applyMatrix4(this.pointcloud.matrixWorld);
  38940. var bsWorld = bbWorld.getBoundingSphere(new Sphere());
  38941. var start = new Vector3(segment.start.x, segment.start.y, bsWorld.center.z);
  38942. var end = new Vector3(segment.end.x, segment.end.y, bsWorld.center.z);
  38943. var closest = new Line3(start, end).closestPointToPoint(bsWorld.center, true, new Vector3());
  38944. var distance = closest.distanceTo(bsWorld.center);
  38945. var intersects = distance < bsWorld.radius + target.profile.width;
  38946. if (!intersects) {
  38947. continue;
  38948. }
  38949. }
  38950. //{// DEBUG
  38951. // console.log(node.name);
  38952. // let boxHelper = new Potree.Box3Helper(node.getBoundingBox());
  38953. // boxHelper.matrixAutoUpdate = false;
  38954. // boxHelper.matrix.copy(viewer.scene.pointclouds[0].matrixWorld);
  38955. // viewer.scene.scene.add(boxHelper);
  38956. //}
  38957. var sv = new Vector3().subVectors(segment.end, segment.start).setZ(0);
  38958. var segmentDir = sv.clone().normalize();
  38959. var points = new Points$1();
  38960. var nodeMatrix = new Matrix4().makeTranslation(...node.boundingBox.min.toArray());
  38961. var matrix = new Matrix4().multiplyMatrices(this.pointcloud.matrixWorld, nodeMatrix);
  38962. pointsProcessed = pointsProcessed + numPoints;
  38963. var accepted = null;
  38964. var mileage = null;
  38965. var acceptedPositions = null;
  38966. for (var result of this.getAccepted(numPoints, node, matrix, segment, segmentDir, points, totalMileage)) {
  38967. if (!result) {
  38968. var _duration = performance.now() - checkpoint;
  38969. //console.log(`getPointsInsideProfile yield after ${duration}ms`);
  38970. yield false;
  38971. checkpoint = performance.now();
  38972. } else {
  38973. [accepted, mileage, acceptedPositions] = result;
  38974. }
  38975. }
  38976. var duration = performance.now() - checkpoint;
  38977. if (duration > 4) {
  38978. //console.log(`getPointsInsideProfile yield after ${duration}ms`);
  38979. yield false;
  38980. checkpoint = performance.now();
  38981. }
  38982. points.data.position = acceptedPositions;
  38983. var relevantAttributes = Object.keys(geometry.attributes).filter(a => !["position", "indices"].includes(a));
  38984. for (var attributeName of relevantAttributes) {
  38985. var attribute = geometry.attributes[attributeName];
  38986. var numElements = attribute.array.length / numPoints;
  38987. if (numElements !== parseInt(numElements)) {
  38988. debugger;
  38989. }
  38990. var Type = attribute.array.constructor;
  38991. var filteredBuffer = new Type(numElements * accepted.length);
  38992. var source = attribute.array;
  38993. var _target = filteredBuffer;
  38994. for (var i = 0; i < accepted.length; i++) {
  38995. var index = accepted[i];
  38996. var _start = index * numElements;
  38997. var _end = _start + numElements;
  38998. var sub = source.subarray(_start, _end);
  38999. _target.set(sub, i * numElements);
  39000. }
  39001. points.data[attributeName] = filteredBuffer;
  39002. }
  39003. points.data['mileage'] = mileage;
  39004. points.numPoints = accepted.length;
  39005. segment.points.add(points);
  39006. }
  39007. totalMileage += segment.length;
  39008. }
  39009. for (var _segment of target.segments) {
  39010. target.boundingBox.union(_segment.points.boundingBox);
  39011. }
  39012. //console.log(`getPointsInsideProfile finished`);
  39013. yield true;
  39014. }
  39015. finishLevelThenCancel() {
  39016. if (this.cancelRequested) {
  39017. return;
  39018. }
  39019. this.maxDepth = this.highestLevelServed;
  39020. this.cancelRequested = true;
  39021. //console.log(`maxDepth: ${this.maxDepth}`);
  39022. }
  39023. cancel() {
  39024. this.callback.onCancel();
  39025. this.priorityQueue = new BinaryHeap(function (x) {
  39026. return 1 / x.weight;
  39027. });
  39028. var index = this.pointcloud.profileRequests.indexOf(this);
  39029. if (index >= 0) {
  39030. this.pointcloud.profileRequests.splice(index, 1);
  39031. }
  39032. }
  39033. }
  39034. function _OverloadYield(e, d) {
  39035. this.v = e, this.k = d;
  39036. }
  39037. function _applyDecoratedDescriptor(i, e, r, n, l) {
  39038. var a = {};
  39039. return Object.keys(n).forEach(function (i) {
  39040. a[i] = n[i];
  39041. }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) {
  39042. return n(i, e, r) || r;
  39043. }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer ? (Object.defineProperty(i, e, a), null) : a;
  39044. }
  39045. function _applyDecs2311(e, t, n, r, o, i) {
  39046. var a,
  39047. c,
  39048. u,
  39049. s,
  39050. f,
  39051. l,
  39052. p,
  39053. d = Symbol.metadata || Symbol.for("Symbol.metadata"),
  39054. m = Object.defineProperty,
  39055. h = Object.create,
  39056. y = [h(null), h(null)],
  39057. v = t.length;
  39058. function g(t, n, r) {
  39059. return function (o, i) {
  39060. n && (i = o, o = e);
  39061. for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []);
  39062. return r ? i : o;
  39063. };
  39064. }
  39065. function b(e, t, n, r) {
  39066. if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined"));
  39067. return e;
  39068. }
  39069. function applyDec(e, t, n, r, o, i, u, s, f, l, p) {
  39070. function d(e) {
  39071. if (!p(e)) throw new TypeError("Attempted to access private element on non-instance");
  39072. }
  39073. var h = [].concat(t[0]),
  39074. v = t[3],
  39075. w = !u,
  39076. D = 1 === o,
  39077. S = 3 === o,
  39078. j = 4 === o,
  39079. E = 2 === o;
  39080. function I(t, n, r) {
  39081. return function (o, i) {
  39082. return n && (i = o, o = e), r && r(o), P[t].call(o, i);
  39083. };
  39084. }
  39085. if (!w) {
  39086. var P = {},
  39087. k = [],
  39088. F = S ? "get" : j || D ? "set" : "value";
  39089. if (f ? (l || D ? P = {
  39090. get: _setFunctionName(function () {
  39091. return v(this);
  39092. }, r, "get"),
  39093. set: function (e) {
  39094. t[4](this, e);
  39095. }
  39096. } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) {
  39097. if ((c = y[+s][r]) && 7 != (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet");
  39098. y[+s][r] = o < 3 ? 1 : o;
  39099. }
  39100. }
  39101. for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) {
  39102. var T = b(h[O], "A decorator", "be", !0),
  39103. z = n ? h[O - 1] : void 0,
  39104. A = {},
  39105. H = {
  39106. kind: ["field", "accessor", "method", "getter", "setter", "class"][o],
  39107. name: r,
  39108. metadata: a,
  39109. addInitializer: function (e, t) {
  39110. if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished");
  39111. b(t, "An initializer", "be", !0), i.push(t);
  39112. }.bind(null, A)
  39113. };
  39114. if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = {
  39115. has: f ? p.bind() : function (e) {
  39116. return r in e;
  39117. }
  39118. }, j || (c.get = f ? E ? function (e) {
  39119. return d(e), P.value;
  39120. } : I("get", 0, d) : function (e) {
  39121. return e[r];
  39122. }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) {
  39123. e[r] = t;
  39124. }), N = T.call(z, D ? {
  39125. get: P.get,
  39126. set: P.set
  39127. } : P[F], H), A.v = 1, D) {
  39128. if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined");
  39129. } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N);
  39130. }
  39131. return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N;
  39132. }
  39133. function w(e) {
  39134. return m(e, d, {
  39135. configurable: !0,
  39136. enumerable: !0,
  39137. value: a
  39138. });
  39139. }
  39140. return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) {
  39141. e && f.push(g(e));
  39142. }, p = function (t, r) {
  39143. for (var i = 0; i < n.length; i++) {
  39144. var a = n[i],
  39145. c = a[1],
  39146. l = 7 & c;
  39147. if ((8 & c) == t && !l == r) {
  39148. var p = a[2],
  39149. d = !!a[3],
  39150. m = 16 & c;
  39151. applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) {
  39152. return _checkInRHS(t) === e;
  39153. } : o);
  39154. }
  39155. }
  39156. }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), {
  39157. e: c,
  39158. get c() {
  39159. var n = [];
  39160. return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)];
  39161. }
  39162. };
  39163. }
  39164. function _arrayLikeToArray(r, a) {
  39165. (null == a || a > r.length) && (a = r.length);
  39166. for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
  39167. return n;
  39168. }
  39169. function _arrayWithHoles(r) {
  39170. if (Array.isArray(r)) return r;
  39171. }
  39172. function _arrayWithoutHoles(r) {
  39173. if (Array.isArray(r)) return _arrayLikeToArray(r);
  39174. }
  39175. function _assertClassBrand(e, t, n) {
  39176. if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
  39177. throw new TypeError("Private element is not present on this object");
  39178. }
  39179. function _assertThisInitialized(e) {
  39180. if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  39181. return e;
  39182. }
  39183. function _asyncGeneratorDelegate(t) {
  39184. var e = {},
  39185. n = !1;
  39186. function pump(e, r) {
  39187. return n = !0, r = new Promise(function (n) {
  39188. n(t[e](r));
  39189. }), {
  39190. done: !1,
  39191. value: new _OverloadYield(r, 1)
  39192. };
  39193. }
  39194. return e["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function () {
  39195. return this;
  39196. }, e.next = function (t) {
  39197. return n ? (n = !1, t) : pump("next", t);
  39198. }, "function" == typeof t.throw && (e.throw = function (t) {
  39199. if (n) throw n = !1, t;
  39200. return pump("throw", t);
  39201. }), "function" == typeof t.return && (e.return = function (t) {
  39202. return n ? (n = !1, t) : pump("return", t);
  39203. }), e;
  39204. }
  39205. function _asyncIterator(r) {
  39206. var n,
  39207. t,
  39208. o,
  39209. e = 2;
  39210. for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) {
  39211. if (t && null != (n = r[t])) return n.call(r);
  39212. if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r));
  39213. t = "@@asyncIterator", o = "@@iterator";
  39214. }
  39215. throw new TypeError("Object is not async iterable");
  39216. }
  39217. function AsyncFromSyncIterator(r) {
  39218. function AsyncFromSyncIteratorContinuation(r) {
  39219. if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object."));
  39220. var n = r.done;
  39221. return Promise.resolve(r.value).then(function (r) {
  39222. return {
  39223. value: r,
  39224. done: n
  39225. };
  39226. });
  39227. }
  39228. return AsyncFromSyncIterator = function (r) {
  39229. this.s = r, this.n = r.next;
  39230. }, AsyncFromSyncIterator.prototype = {
  39231. s: null,
  39232. n: null,
  39233. next: function () {
  39234. return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
  39235. },
  39236. return: function (r) {
  39237. var n = this.s.return;
  39238. return void 0 === n ? Promise.resolve({
  39239. value: r,
  39240. done: !0
  39241. }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
  39242. },
  39243. throw: function (r) {
  39244. var n = this.s.return;
  39245. return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
  39246. }
  39247. }, new AsyncFromSyncIterator(r);
  39248. }
  39249. function asyncGeneratorStep(n, t, e, r, o, a, c) {
  39250. try {
  39251. var i = n[a](c),
  39252. u = i.value;
  39253. } catch (n) {
  39254. return void e(n);
  39255. }
  39256. i.done ? t(u) : Promise.resolve(u).then(r, o);
  39257. }
  39258. function _asyncToGenerator(n) {
  39259. return function () {
  39260. var t = this,
  39261. e = arguments;
  39262. return new Promise(function (r, o) {
  39263. var a = n.apply(t, e);
  39264. function _next(n) {
  39265. asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
  39266. }
  39267. function _throw(n) {
  39268. asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
  39269. }
  39270. _next(void 0);
  39271. });
  39272. };
  39273. }
  39274. function _awaitAsyncGenerator(e) {
  39275. return new _OverloadYield(e, 0);
  39276. }
  39277. function _callSuper(t, o, e) {
  39278. return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
  39279. }
  39280. function _checkInRHS(e) {
  39281. if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null"));
  39282. return e;
  39283. }
  39284. function _checkPrivateRedeclaration(e, t) {
  39285. if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
  39286. }
  39287. function _classCallCheck(a, n) {
  39288. if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
  39289. }
  39290. function _classNameTDZError(e) {
  39291. throw new ReferenceError('Class "' + e + '" cannot be referenced in computed property keys.');
  39292. }
  39293. function _classPrivateFieldGet2(s, a) {
  39294. return s.get(_assertClassBrand(s, a));
  39295. }
  39296. function _classPrivateFieldInitSpec(e, t, a) {
  39297. _checkPrivateRedeclaration(e, t), t.set(e, a);
  39298. }
  39299. function _classPrivateFieldLooseBase(e, t) {
  39300. if (!{}.hasOwnProperty.call(e, t)) throw new TypeError("attempted to use private field on non-instance");
  39301. return e;
  39302. }
  39303. var id = 0;
  39304. function _classPrivateFieldLooseKey(e) {
  39305. return "__private_" + id++ + "_" + e;
  39306. }
  39307. function _classPrivateFieldSet2(s, a, r) {
  39308. return s.set(_assertClassBrand(s, a), r), r;
  39309. }
  39310. function _classPrivateGetter(s, r, a) {
  39311. return a(_assertClassBrand(s, r));
  39312. }
  39313. function _classPrivateMethodInitSpec(e, a) {
  39314. _checkPrivateRedeclaration(e, a), a.add(e);
  39315. }
  39316. function _classPrivateSetter(s, r, a, t) {
  39317. return r(_assertClassBrand(s, a), t), t;
  39318. }
  39319. function _classStaticPrivateMethodGet(s, a, t) {
  39320. return _assertClassBrand(a, s), t;
  39321. }
  39322. function _construct(t, e, r) {
  39323. if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
  39324. var o = [null];
  39325. o.push.apply(o, e);
  39326. var p = new (t.bind.apply(t, o))();
  39327. return r && _setPrototypeOf(p, r.prototype), p;
  39328. }
  39329. function _defineProperties(e, r) {
  39330. for (var t = 0; t < r.length; t++) {
  39331. var o = r[t];
  39332. o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
  39333. }
  39334. }
  39335. function _createClass(e, r, t) {
  39336. return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
  39337. writable: !1
  39338. }), e;
  39339. }
  39340. function _createForOfIteratorHelper(r, e) {
  39341. var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  39342. if (!t) {
  39343. if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
  39344. t && (r = t);
  39345. var n = 0,
  39346. F = function () {};
  39347. return {
  39348. s: F,
  39349. n: function () {
  39350. return n >= r.length ? {
  39351. done: !0
  39352. } : {
  39353. done: !1,
  39354. value: r[n++]
  39355. };
  39356. },
  39357. e: function (r) {
  39358. throw r;
  39359. },
  39360. f: F
  39361. };
  39362. }
  39363. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  39364. }
  39365. var o,
  39366. a = !0,
  39367. u = !1;
  39368. return {
  39369. s: function () {
  39370. t = t.call(r);
  39371. },
  39372. n: function () {
  39373. var r = t.next();
  39374. return a = r.done, r;
  39375. },
  39376. e: function (r) {
  39377. u = !0, o = r;
  39378. },
  39379. f: function () {
  39380. try {
  39381. a || null == t.return || t.return();
  39382. } finally {
  39383. if (u) throw o;
  39384. }
  39385. }
  39386. };
  39387. }
  39388. function _createForOfIteratorHelperLoose(r, e) {
  39389. var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  39390. if (t) return (t = t.call(r)).next.bind(t);
  39391. if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
  39392. t && (r = t);
  39393. var o = 0;
  39394. return function () {
  39395. return o >= r.length ? {
  39396. done: !0
  39397. } : {
  39398. done: !1,
  39399. value: r[o++]
  39400. };
  39401. };
  39402. }
  39403. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  39404. }
  39405. function _createSuper(t) {
  39406. var r = _isNativeReflectConstruct();
  39407. return function () {
  39408. var e,
  39409. o = _getPrototypeOf(t);
  39410. if (r) {
  39411. var s = _getPrototypeOf(this).constructor;
  39412. e = Reflect.construct(o, arguments, s);
  39413. } else e = o.apply(this, arguments);
  39414. return _possibleConstructorReturn(this, e);
  39415. };
  39416. }
  39417. function _decorate(e, r, t, i) {
  39418. var o = _getDecoratorsApi();
  39419. if (i) for (var n = 0; n < i.length; n++) o = i[n](o);
  39420. var s = r(function (e) {
  39421. o.initializeInstanceElements(e, a.elements);
  39422. }, t),
  39423. a = o.decorateClass(_coalesceClassElements(s.d.map(_createElementDescriptor)), e);
  39424. return o.initializeClassElements(s.F, a.elements), o.runClassFinishers(s.F, a.finishers);
  39425. }
  39426. function _getDecoratorsApi() {
  39427. _getDecoratorsApi = function () {
  39428. return e;
  39429. };
  39430. var e = {
  39431. elementsDefinitionOrder: [["method"], ["field"]],
  39432. initializeInstanceElements: function (e, r) {
  39433. ["method", "field"].forEach(function (t) {
  39434. r.forEach(function (r) {
  39435. r.kind === t && "own" === r.placement && this.defineClassElement(e, r);
  39436. }, this);
  39437. }, this);
  39438. },
  39439. initializeClassElements: function (e, r) {
  39440. var t = e.prototype;
  39441. ["method", "field"].forEach(function (i) {
  39442. r.forEach(function (r) {
  39443. var o = r.placement;
  39444. if (r.kind === i && ("static" === o || "prototype" === o)) {
  39445. var n = "static" === o ? e : t;
  39446. this.defineClassElement(n, r);
  39447. }
  39448. }, this);
  39449. }, this);
  39450. },
  39451. defineClassElement: function (e, r) {
  39452. var t = r.descriptor;
  39453. if ("field" === r.kind) {
  39454. var i = r.initializer;
  39455. t = {
  39456. enumerable: t.enumerable,
  39457. writable: t.writable,
  39458. configurable: t.configurable,
  39459. value: void 0 === i ? void 0 : i.call(e)
  39460. };
  39461. }
  39462. Object.defineProperty(e, r.key, t);
  39463. },
  39464. decorateClass: function (e, r) {
  39465. var t = [],
  39466. i = [],
  39467. o = {
  39468. static: [],
  39469. prototype: [],
  39470. own: []
  39471. };
  39472. if (e.forEach(function (e) {
  39473. this.addElementPlacement(e, o);
  39474. }, this), e.forEach(function (e) {
  39475. if (!_hasDecorators(e)) return t.push(e);
  39476. var r = this.decorateElement(e, o);
  39477. t.push(r.element), t.push.apply(t, r.extras), i.push.apply(i, r.finishers);
  39478. }, this), !r) return {
  39479. elements: t,
  39480. finishers: i
  39481. };
  39482. var n = this.decorateConstructor(t, r);
  39483. return i.push.apply(i, n.finishers), n.finishers = i, n;
  39484. },
  39485. addElementPlacement: function (e, r, t) {
  39486. var i = r[e.placement];
  39487. if (!t && -1 !== i.indexOf(e.key)) throw new TypeError("Duplicated element (" + e.key + ")");
  39488. i.push(e.key);
  39489. },
  39490. decorateElement: function (e, r) {
  39491. for (var t = [], i = [], o = e.decorators, n = o.length - 1; n >= 0; n--) {
  39492. var s = r[e.placement];
  39493. s.splice(s.indexOf(e.key), 1);
  39494. var a = this.fromElementDescriptor(e),
  39495. l = this.toElementFinisherExtras((0, o[n])(a) || a);
  39496. e = l.element, this.addElementPlacement(e, r), l.finisher && i.push(l.finisher);
  39497. var c = l.extras;
  39498. if (c) {
  39499. for (var p = 0; p < c.length; p++) this.addElementPlacement(c[p], r);
  39500. t.push.apply(t, c);
  39501. }
  39502. }
  39503. return {
  39504. element: e,
  39505. finishers: i,
  39506. extras: t
  39507. };
  39508. },
  39509. decorateConstructor: function (e, r) {
  39510. for (var t = [], i = r.length - 1; i >= 0; i--) {
  39511. var o = this.fromClassDescriptor(e),
  39512. n = this.toClassDescriptor((0, r[i])(o) || o);
  39513. if (void 0 !== n.finisher && t.push(n.finisher), void 0 !== n.elements) {
  39514. e = n.elements;
  39515. for (var s = 0; s < e.length - 1; s++) for (var a = s + 1; a < e.length; a++) if (e[s].key === e[a].key && e[s].placement === e[a].placement) throw new TypeError("Duplicated element (" + e[s].key + ")");
  39516. }
  39517. }
  39518. return {
  39519. elements: e,
  39520. finishers: t
  39521. };
  39522. },
  39523. fromElementDescriptor: function (e) {
  39524. var r = {
  39525. kind: e.kind,
  39526. key: e.key,
  39527. placement: e.placement,
  39528. descriptor: e.descriptor
  39529. };
  39530. return Object.defineProperty(r, Symbol.toStringTag, {
  39531. value: "Descriptor",
  39532. configurable: !0
  39533. }), "field" === e.kind && (r.initializer = e.initializer), r;
  39534. },
  39535. toElementDescriptors: function (e) {
  39536. if (void 0 !== e) return _toArray(e).map(function (e) {
  39537. var r = this.toElementDescriptor(e);
  39538. return this.disallowProperty(e, "finisher", "An element descriptor"), this.disallowProperty(e, "extras", "An element descriptor"), r;
  39539. }, this);
  39540. },
  39541. toElementDescriptor: function (e) {
  39542. var r = e.kind + "";
  39543. if ("method" !== r && "field" !== r) throw new TypeError('An element descriptor\'s .kind property must be either "method" or "field", but a decorator created an element descriptor with .kind "' + r + '"');
  39544. var t = _toPropertyKey(e.key),
  39545. i = e.placement + "";
  39546. if ("static" !== i && "prototype" !== i && "own" !== i) throw new TypeError('An element descriptor\'s .placement property must be one of "static", "prototype" or "own", but a decorator created an element descriptor with .placement "' + i + '"');
  39547. var o = e.descriptor;
  39548. this.disallowProperty(e, "elements", "An element descriptor");
  39549. var n = {
  39550. kind: r,
  39551. key: t,
  39552. placement: i,
  39553. descriptor: Object.assign({}, o)
  39554. };
  39555. return "field" !== r ? this.disallowProperty(e, "initializer", "A method descriptor") : (this.disallowProperty(o, "get", "The property descriptor of a field descriptor"), this.disallowProperty(o, "set", "The property descriptor of a field descriptor"), this.disallowProperty(o, "value", "The property descriptor of a field descriptor"), n.initializer = e.initializer), n;
  39556. },
  39557. toElementFinisherExtras: function (e) {
  39558. return {
  39559. element: this.toElementDescriptor(e),
  39560. finisher: _optionalCallableProperty(e, "finisher"),
  39561. extras: this.toElementDescriptors(e.extras)
  39562. };
  39563. },
  39564. fromClassDescriptor: function (e) {
  39565. var r = {
  39566. kind: "class",
  39567. elements: e.map(this.fromElementDescriptor, this)
  39568. };
  39569. return Object.defineProperty(r, Symbol.toStringTag, {
  39570. value: "Descriptor",
  39571. configurable: !0
  39572. }), r;
  39573. },
  39574. toClassDescriptor: function (e) {
  39575. var r = e.kind + "";
  39576. if ("class" !== r) throw new TypeError('A class descriptor\'s .kind property must be "class", but a decorator created a class descriptor with .kind "' + r + '"');
  39577. this.disallowProperty(e, "key", "A class descriptor"), this.disallowProperty(e, "placement", "A class descriptor"), this.disallowProperty(e, "descriptor", "A class descriptor"), this.disallowProperty(e, "initializer", "A class descriptor"), this.disallowProperty(e, "extras", "A class descriptor");
  39578. var t = _optionalCallableProperty(e, "finisher");
  39579. return {
  39580. elements: this.toElementDescriptors(e.elements),
  39581. finisher: t
  39582. };
  39583. },
  39584. runClassFinishers: function (e, r) {
  39585. for (var t = 0; t < r.length; t++) {
  39586. var i = (0, r[t])(e);
  39587. if (void 0 !== i) {
  39588. if ("function" != typeof i) throw new TypeError("Finishers must return a constructor.");
  39589. e = i;
  39590. }
  39591. }
  39592. return e;
  39593. },
  39594. disallowProperty: function (e, r, t) {
  39595. if (void 0 !== e[r]) throw new TypeError(t + " can't have a ." + r + " property.");
  39596. }
  39597. };
  39598. return e;
  39599. }
  39600. function _createElementDescriptor(e) {
  39601. var r,
  39602. t = _toPropertyKey(e.key);
  39603. "method" === e.kind ? r = {
  39604. value: e.value,
  39605. writable: !0,
  39606. configurable: !0,
  39607. enumerable: !1
  39608. } : "get" === e.kind ? r = {
  39609. get: e.value,
  39610. configurable: !0,
  39611. enumerable: !1
  39612. } : "set" === e.kind ? r = {
  39613. set: e.value,
  39614. configurable: !0,
  39615. enumerable: !1
  39616. } : "field" === e.kind && (r = {
  39617. configurable: !0,
  39618. writable: !0,
  39619. enumerable: !0
  39620. });
  39621. var i = {
  39622. kind: "field" === e.kind ? "field" : "method",
  39623. key: t,
  39624. placement: e.static ? "static" : "field" === e.kind ? "own" : "prototype",
  39625. descriptor: r
  39626. };
  39627. return e.decorators && (i.decorators = e.decorators), "field" === e.kind && (i.initializer = e.value), i;
  39628. }
  39629. function _coalesceGetterSetter(e, r) {
  39630. void 0 !== e.descriptor.get ? r.descriptor.get = e.descriptor.get : r.descriptor.set = e.descriptor.set;
  39631. }
  39632. function _coalesceClassElements(e) {
  39633. for (var r = [], isSameElement = function (e) {
  39634. return "method" === e.kind && e.key === o.key && e.placement === o.placement;
  39635. }, t = 0; t < e.length; t++) {
  39636. var i,
  39637. o = e[t];
  39638. if ("method" === o.kind && (i = r.find(isSameElement))) {
  39639. if (_isDataDescriptor(o.descriptor) || _isDataDescriptor(i.descriptor)) {
  39640. if (_hasDecorators(o) || _hasDecorators(i)) throw new ReferenceError("Duplicated methods (" + o.key + ") can't be decorated.");
  39641. i.descriptor = o.descriptor;
  39642. } else {
  39643. if (_hasDecorators(o)) {
  39644. if (_hasDecorators(i)) throw new ReferenceError("Decorators can't be placed on different accessors with for the same property (" + o.key + ").");
  39645. i.decorators = o.decorators;
  39646. }
  39647. _coalesceGetterSetter(o, i);
  39648. }
  39649. } else r.push(o);
  39650. }
  39651. return r;
  39652. }
  39653. function _hasDecorators(e) {
  39654. return e.decorators && e.decorators.length;
  39655. }
  39656. function _isDataDescriptor(e) {
  39657. return void 0 !== e && !(void 0 === e.value && void 0 === e.writable);
  39658. }
  39659. function _optionalCallableProperty(e, r) {
  39660. var t = e[r];
  39661. if (void 0 !== t && "function" != typeof t) throw new TypeError("Expected '" + r + "' to be a function");
  39662. return t;
  39663. }
  39664. function _defaults(e, r) {
  39665. for (var t = Object.getOwnPropertyNames(r), o = 0; o < t.length; o++) {
  39666. var n = t[o],
  39667. a = Object.getOwnPropertyDescriptor(r, n);
  39668. a && a.configurable && void 0 === e[n] && Object.defineProperty(e, n, a);
  39669. }
  39670. return e;
  39671. }
  39672. function _defineAccessor(e, r, n, t) {
  39673. var c = {
  39674. configurable: !0,
  39675. enumerable: !0
  39676. };
  39677. return c[e] = t, Object.defineProperty(r, n, c);
  39678. }
  39679. function _defineProperty(e, r, t) {
  39680. return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
  39681. value: t,
  39682. enumerable: !0,
  39683. configurable: !0,
  39684. writable: !0
  39685. }) : e[r] = t, e;
  39686. }
  39687. function _extends() {
  39688. return _extends = Object.assign ? Object.assign.bind() : function (n) {
  39689. for (var e = 1; e < arguments.length; e++) {
  39690. var t = arguments[e];
  39691. for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
  39692. }
  39693. return n;
  39694. }, _extends.apply(null, arguments);
  39695. }
  39696. function _get() {
  39697. return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
  39698. var p = _superPropBase(e, t);
  39699. if (p) {
  39700. var n = Object.getOwnPropertyDescriptor(p, t);
  39701. return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
  39702. }
  39703. }, _get.apply(null, arguments);
  39704. }
  39705. function _getPrototypeOf(t) {
  39706. return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
  39707. return t.__proto__ || Object.getPrototypeOf(t);
  39708. }, _getPrototypeOf(t);
  39709. }
  39710. function _identity(t) {
  39711. return t;
  39712. }
  39713. function _importDeferProxy(e) {
  39714. var t = null,
  39715. constValue = function (e) {
  39716. return function () {
  39717. return e;
  39718. };
  39719. },
  39720. proxy = function (r) {
  39721. return function (n, o, f) {
  39722. return null === t && (t = e()), r(t, o, f);
  39723. };
  39724. };
  39725. return new Proxy({}, {
  39726. defineProperty: constValue(!1),
  39727. deleteProperty: constValue(!1),
  39728. get: proxy(Reflect.get),
  39729. getOwnPropertyDescriptor: proxy(Reflect.getOwnPropertyDescriptor),
  39730. getPrototypeOf: constValue(null),
  39731. isExtensible: constValue(!1),
  39732. has: proxy(Reflect.has),
  39733. ownKeys: proxy(Reflect.ownKeys),
  39734. preventExtensions: constValue(!0),
  39735. set: constValue(!1),
  39736. setPrototypeOf: constValue(!1)
  39737. });
  39738. }
  39739. function _inherits(t, e) {
  39740. if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
  39741. t.prototype = Object.create(e && e.prototype, {
  39742. constructor: {
  39743. value: t,
  39744. writable: !0,
  39745. configurable: !0
  39746. }
  39747. }), Object.defineProperty(t, "prototype", {
  39748. writable: !1
  39749. }), e && _setPrototypeOf(t, e);
  39750. }
  39751. function _inheritsLoose(t, o) {
  39752. t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o);
  39753. }
  39754. function _initializerDefineProperty(e, i, r, l) {
  39755. r && Object.defineProperty(e, i, {
  39756. enumerable: r.enumerable,
  39757. configurable: r.configurable,
  39758. writable: r.writable,
  39759. value: r.initializer ? r.initializer.call(l) : void 0
  39760. });
  39761. }
  39762. function _initializerWarningHelper(r, e) {
  39763. throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform.");
  39764. }
  39765. function _instanceof(n, e) {
  39766. return null != e && "undefined" != typeof Symbol && e[Symbol.hasInstance] ? !!e[Symbol.hasInstance](n) : n instanceof e;
  39767. }
  39768. function _interopRequireDefault(e) {
  39769. return e && e.__esModule ? e : {
  39770. default: e
  39771. };
  39772. }
  39773. function _getRequireWildcardCache(e) {
  39774. if ("function" != typeof WeakMap) return null;
  39775. var r = new WeakMap(),
  39776. t = new WeakMap();
  39777. return (_getRequireWildcardCache = function (e) {
  39778. return e ? t : r;
  39779. })(e);
  39780. }
  39781. function _interopRequireWildcard(e, r) {
  39782. if (!r && e && e.__esModule) return e;
  39783. if (null === e || "object" != typeof e && "function" != typeof e) return {
  39784. default: e
  39785. };
  39786. var t = _getRequireWildcardCache(r);
  39787. if (t && t.has(e)) return t.get(e);
  39788. var n = {
  39789. __proto__: null
  39790. },
  39791. a = Object.defineProperty && Object.getOwnPropertyDescriptor;
  39792. for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
  39793. var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
  39794. i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u];
  39795. }
  39796. return n.default = e, t && t.set(e, n), n;
  39797. }
  39798. function _isNativeFunction(t) {
  39799. try {
  39800. return -1 !== Function.toString.call(t).indexOf("[native code]");
  39801. } catch (n) {
  39802. return "function" == typeof t;
  39803. }
  39804. }
  39805. function _isNativeReflectConstruct() {
  39806. try {
  39807. var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
  39808. } catch (t) {}
  39809. return (_isNativeReflectConstruct = function () {
  39810. return !!t;
  39811. })();
  39812. }
  39813. function _iterableToArray(r) {
  39814. if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
  39815. }
  39816. function _iterableToArrayLimit(r, l) {
  39817. var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
  39818. if (null != t) {
  39819. var e,
  39820. n,
  39821. i,
  39822. u,
  39823. a = [],
  39824. f = !0,
  39825. o = !1;
  39826. try {
  39827. if (i = (t = t.call(r)).next, 0 === l) {
  39828. if (Object(t) !== t) return;
  39829. f = !1;
  39830. } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
  39831. } catch (r) {
  39832. o = !0, n = r;
  39833. } finally {
  39834. try {
  39835. if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
  39836. } finally {
  39837. if (o) throw n;
  39838. }
  39839. }
  39840. return a;
  39841. }
  39842. }
  39843. var REACT_ELEMENT_TYPE;
  39844. function _jsx(e, r, E, l) {
  39845. REACT_ELEMENT_TYPE || (REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103);
  39846. var o = e && e.defaultProps,
  39847. n = arguments.length - 3;
  39848. if (r || 0 === n || (r = {
  39849. children: void 0
  39850. }), 1 === n) r.children = l;else if (n > 1) {
  39851. for (var t = Array(n), f = 0; f < n; f++) t[f] = arguments[f + 3];
  39852. r.children = t;
  39853. }
  39854. if (r && o) for (var i in o) void 0 === r[i] && (r[i] = o[i]);else r || (r = o || {});
  39855. return {
  39856. $$typeof: REACT_ELEMENT_TYPE,
  39857. type: e,
  39858. key: void 0 === E ? null : "" + E,
  39859. ref: null,
  39860. props: r,
  39861. _owner: null
  39862. };
  39863. }
  39864. function _maybeArrayLike(r, a, e) {
  39865. if (a && !Array.isArray(a) && "number" == typeof a.length) {
  39866. var y = a.length;
  39867. return _arrayLikeToArray(a, void 0 !== e && e < y ? e : y);
  39868. }
  39869. return r(a, e);
  39870. }
  39871. function _newArrowCheck(n, r) {
  39872. if (n !== r) throw new TypeError("Cannot instantiate an arrow function");
  39873. }
  39874. function _nonIterableRest() {
  39875. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  39876. }
  39877. function _nonIterableSpread() {
  39878. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  39879. }
  39880. function _nullishReceiverError(r) {
  39881. throw new TypeError("Cannot set property of null or undefined.");
  39882. }
  39883. function _objectDestructuringEmpty(t) {
  39884. if (null == t) throw new TypeError("Cannot destructure " + t);
  39885. }
  39886. function ownKeys(e, r) {
  39887. var t = Object.keys(e);
  39888. if (Object.getOwnPropertySymbols) {
  39889. var o = Object.getOwnPropertySymbols(e);
  39890. r && (o = o.filter(function (r) {
  39891. return Object.getOwnPropertyDescriptor(e, r).enumerable;
  39892. })), t.push.apply(t, o);
  39893. }
  39894. return t;
  39895. }
  39896. function _objectSpread2(e) {
  39897. for (var r = 1; r < arguments.length; r++) {
  39898. var t = null != arguments[r] ? arguments[r] : {};
  39899. r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
  39900. _defineProperty(e, r, t[r]);
  39901. }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
  39902. Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
  39903. });
  39904. }
  39905. return e;
  39906. }
  39907. function _objectWithoutProperties(e, t) {
  39908. if (null == e) return {};
  39909. var o,
  39910. r,
  39911. i = _objectWithoutPropertiesLoose(e, t);
  39912. if (Object.getOwnPropertySymbols) {
  39913. var s = Object.getOwnPropertySymbols(e);
  39914. for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
  39915. }
  39916. return i;
  39917. }
  39918. function _objectWithoutPropertiesLoose(r, e) {
  39919. if (null == r) return {};
  39920. var t = {};
  39921. for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
  39922. if (e.includes(n)) continue;
  39923. t[n] = r[n];
  39924. }
  39925. return t;
  39926. }
  39927. function _possibleConstructorReturn(t, e) {
  39928. if (e && ("object" == typeof e || "function" == typeof e)) return e;
  39929. if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
  39930. return _assertThisInitialized(t);
  39931. }
  39932. function _readOnlyError(r) {
  39933. throw new TypeError('"' + r + '" is read-only');
  39934. }
  39935. function _regeneratorRuntime() {
  39936. "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
  39937. _regeneratorRuntime = function () {
  39938. return e;
  39939. };
  39940. var t,
  39941. e = {},
  39942. r = Object.prototype,
  39943. n = r.hasOwnProperty,
  39944. o = Object.defineProperty || function (t, e, r) {
  39945. t[e] = r.value;
  39946. },
  39947. i = "function" == typeof Symbol ? Symbol : {},
  39948. a = i.iterator || "@@iterator",
  39949. c = i.asyncIterator || "@@asyncIterator",
  39950. u = i.toStringTag || "@@toStringTag";
  39951. function define(t, e, r) {
  39952. return Object.defineProperty(t, e, {
  39953. value: r,
  39954. enumerable: !0,
  39955. configurable: !0,
  39956. writable: !0
  39957. }), t[e];
  39958. }
  39959. try {
  39960. define({}, "");
  39961. } catch (t) {
  39962. define = function (t, e, r) {
  39963. return t[e] = r;
  39964. };
  39965. }
  39966. function wrap(t, e, r, n) {
  39967. var i = e && e.prototype instanceof Generator ? e : Generator,
  39968. a = Object.create(i.prototype),
  39969. c = new Context(n || []);
  39970. return o(a, "_invoke", {
  39971. value: makeInvokeMethod(t, r, c)
  39972. }), a;
  39973. }
  39974. function tryCatch(t, e, r) {
  39975. try {
  39976. return {
  39977. type: "normal",
  39978. arg: t.call(e, r)
  39979. };
  39980. } catch (t) {
  39981. return {
  39982. type: "throw",
  39983. arg: t
  39984. };
  39985. }
  39986. }
  39987. e.wrap = wrap;
  39988. var h = "suspendedStart",
  39989. l = "suspendedYield",
  39990. f = "executing",
  39991. s = "completed",
  39992. y = {};
  39993. function Generator() {}
  39994. function GeneratorFunction() {}
  39995. function GeneratorFunctionPrototype() {}
  39996. var p = {};
  39997. define(p, a, function () {
  39998. return this;
  39999. });
  40000. var d = Object.getPrototypeOf,
  40001. v = d && d(d(values([])));
  40002. v && v !== r && n.call(v, a) && (p = v);
  40003. var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
  40004. function defineIteratorMethods(t) {
  40005. ["next", "throw", "return"].forEach(function (e) {
  40006. define(t, e, function (t) {
  40007. return this._invoke(e, t);
  40008. });
  40009. });
  40010. }
  40011. function AsyncIterator(t, e) {
  40012. function invoke(r, o, i, a) {
  40013. var c = tryCatch(t[r], t, o);
  40014. if ("throw" !== c.type) {
  40015. var u = c.arg,
  40016. h = u.value;
  40017. return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
  40018. invoke("next", t, i, a);
  40019. }, function (t) {
  40020. invoke("throw", t, i, a);
  40021. }) : e.resolve(h).then(function (t) {
  40022. u.value = t, i(u);
  40023. }, function (t) {
  40024. return invoke("throw", t, i, a);
  40025. });
  40026. }
  40027. a(c.arg);
  40028. }
  40029. var r;
  40030. o(this, "_invoke", {
  40031. value: function (t, n) {
  40032. function callInvokeWithMethodAndArg() {
  40033. return new e(function (e, r) {
  40034. invoke(t, n, e, r);
  40035. });
  40036. }
  40037. return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
  40038. }
  40039. });
  40040. }
  40041. function makeInvokeMethod(e, r, n) {
  40042. var o = h;
  40043. return function (i, a) {
  40044. if (o === f) throw Error("Generator is already running");
  40045. if (o === s) {
  40046. if ("throw" === i) throw a;
  40047. return {
  40048. value: t,
  40049. done: !0
  40050. };
  40051. }
  40052. for (n.method = i, n.arg = a;;) {
  40053. var c = n.delegate;
  40054. if (c) {
  40055. var u = maybeInvokeDelegate(c, n);
  40056. if (u) {
  40057. if (u === y) continue;
  40058. return u;
  40059. }
  40060. }
  40061. if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
  40062. if (o === h) throw o = s, n.arg;
  40063. n.dispatchException(n.arg);
  40064. } else "return" === n.method && n.abrupt("return", n.arg);
  40065. o = f;
  40066. var p = tryCatch(e, r, n);
  40067. if ("normal" === p.type) {
  40068. if (o = n.done ? s : l, p.arg === y) continue;
  40069. return {
  40070. value: p.arg,
  40071. done: n.done
  40072. };
  40073. }
  40074. "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
  40075. }
  40076. };
  40077. }
  40078. function maybeInvokeDelegate(e, r) {
  40079. var n = r.method,
  40080. o = e.iterator[n];
  40081. if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
  40082. var i = tryCatch(o, e.iterator, r.arg);
  40083. if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
  40084. var a = i.arg;
  40085. return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
  40086. }
  40087. function pushTryEntry(t) {
  40088. var e = {
  40089. tryLoc: t[0]
  40090. };
  40091. 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
  40092. }
  40093. function resetTryEntry(t) {
  40094. var e = t.completion || {};
  40095. e.type = "normal", delete e.arg, t.completion = e;
  40096. }
  40097. function Context(t) {
  40098. this.tryEntries = [{
  40099. tryLoc: "root"
  40100. }], t.forEach(pushTryEntry, this), this.reset(!0);
  40101. }
  40102. function values(e) {
  40103. if (e || "" === e) {
  40104. var r = e[a];
  40105. if (r) return r.call(e);
  40106. if ("function" == typeof e.next) return e;
  40107. if (!isNaN(e.length)) {
  40108. var o = -1,
  40109. i = function next() {
  40110. for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
  40111. return next.value = t, next.done = !0, next;
  40112. };
  40113. return i.next = i;
  40114. }
  40115. }
  40116. throw new TypeError(typeof e + " is not iterable");
  40117. }
  40118. return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
  40119. value: GeneratorFunctionPrototype,
  40120. configurable: !0
  40121. }), o(GeneratorFunctionPrototype, "constructor", {
  40122. value: GeneratorFunction,
  40123. configurable: !0
  40124. }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
  40125. var e = "function" == typeof t && t.constructor;
  40126. return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
  40127. }, e.mark = function (t) {
  40128. return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
  40129. }, e.awrap = function (t) {
  40130. return {
  40131. __await: t
  40132. };
  40133. }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
  40134. return this;
  40135. }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
  40136. void 0 === i && (i = Promise);
  40137. var a = new AsyncIterator(wrap(t, r, n, o), i);
  40138. return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
  40139. return t.done ? t.value : a.next();
  40140. });
  40141. }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
  40142. return this;
  40143. }), define(g, "toString", function () {
  40144. return "[object Generator]";
  40145. }), e.keys = function (t) {
  40146. var e = Object(t),
  40147. r = [];
  40148. for (var n in e) r.push(n);
  40149. return r.reverse(), function next() {
  40150. for (; r.length;) {
  40151. var t = r.pop();
  40152. if (t in e) return next.value = t, next.done = !1, next;
  40153. }
  40154. return next.done = !0, next;
  40155. };
  40156. }, e.values = values, Context.prototype = {
  40157. constructor: Context,
  40158. reset: function (e) {
  40159. if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
  40160. },
  40161. stop: function () {
  40162. this.done = !0;
  40163. var t = this.tryEntries[0].completion;
  40164. if ("throw" === t.type) throw t.arg;
  40165. return this.rval;
  40166. },
  40167. dispatchException: function (e) {
  40168. if (this.done) throw e;
  40169. var r = this;
  40170. function handle(n, o) {
  40171. return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
  40172. }
  40173. for (var o = this.tryEntries.length - 1; o >= 0; --o) {
  40174. var i = this.tryEntries[o],
  40175. a = i.completion;
  40176. if ("root" === i.tryLoc) return handle("end");
  40177. if (i.tryLoc <= this.prev) {
  40178. var c = n.call(i, "catchLoc"),
  40179. u = n.call(i, "finallyLoc");
  40180. if (c && u) {
  40181. if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
  40182. if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
  40183. } else if (c) {
  40184. if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
  40185. } else {
  40186. if (!u) throw Error("try statement without catch or finally");
  40187. if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
  40188. }
  40189. }
  40190. }
  40191. },
  40192. abrupt: function (t, e) {
  40193. for (var r = this.tryEntries.length - 1; r >= 0; --r) {
  40194. var o = this.tryEntries[r];
  40195. if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
  40196. var i = o;
  40197. break;
  40198. }
  40199. }
  40200. i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
  40201. var a = i ? i.completion : {};
  40202. return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
  40203. },
  40204. complete: function (t, e) {
  40205. if ("throw" === t.type) throw t.arg;
  40206. return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
  40207. },
  40208. finish: function (t) {
  40209. for (var e = this.tryEntries.length - 1; e >= 0; --e) {
  40210. var r = this.tryEntries[e];
  40211. if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
  40212. }
  40213. },
  40214. catch: function (t) {
  40215. for (var e = this.tryEntries.length - 1; e >= 0; --e) {
  40216. var r = this.tryEntries[e];
  40217. if (r.tryLoc === t) {
  40218. var n = r.completion;
  40219. if ("throw" === n.type) {
  40220. var o = n.arg;
  40221. resetTryEntry(r);
  40222. }
  40223. return o;
  40224. }
  40225. }
  40226. throw Error("illegal catch attempt");
  40227. },
  40228. delegateYield: function (e, r, n) {
  40229. return this.delegate = {
  40230. iterator: values(e),
  40231. resultName: r,
  40232. nextLoc: n
  40233. }, "next" === this.method && (this.arg = t), y;
  40234. }
  40235. }, e;
  40236. }
  40237. function set(e, r, t, o) {
  40238. return set = "undefined" != typeof Reflect && Reflect.set ? Reflect.set : function (e, r, t, o) {
  40239. var f,
  40240. i = _superPropBase(e, r);
  40241. if (i) {
  40242. if ((f = Object.getOwnPropertyDescriptor(i, r)).set) return f.set.call(o, t), !0;
  40243. if (!f.writable) return !1;
  40244. }
  40245. if (f = Object.getOwnPropertyDescriptor(o, r)) {
  40246. if (!f.writable) return !1;
  40247. f.value = t, Object.defineProperty(o, r, f);
  40248. } else _defineProperty(o, r, t);
  40249. return !0;
  40250. }, set(e, r, t, o);
  40251. }
  40252. function _set(e, r, t, o, f) {
  40253. if (!set(e, r, t, o || e) && f) throw new TypeError("failed to set property");
  40254. return t;
  40255. }
  40256. function _setFunctionName(e, t, n) {
  40257. "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : "");
  40258. try {
  40259. Object.defineProperty(e, "name", {
  40260. configurable: !0,
  40261. value: n ? n + " " + t : t
  40262. });
  40263. } catch (e) {}
  40264. return e;
  40265. }
  40266. function _setPrototypeOf(t, e) {
  40267. return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
  40268. return t.__proto__ = e, t;
  40269. }, _setPrototypeOf(t, e);
  40270. }
  40271. function _skipFirstGeneratorNext(t) {
  40272. return function () {
  40273. var r = t.apply(this, arguments);
  40274. return r.next(), r;
  40275. };
  40276. }
  40277. function _slicedToArray(r, e) {
  40278. return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
  40279. }
  40280. function _superPropBase(t, o) {
  40281. for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t)););
  40282. return t;
  40283. }
  40284. function _superPropGet(t, e, r, o) {
  40285. var p = _get(_getPrototypeOf(1 & o ? t.prototype : t), e, r);
  40286. return 2 & o ? function (t) {
  40287. return p.apply(r, t);
  40288. } : p;
  40289. }
  40290. function _superPropSet(t, e, o, r, p, f) {
  40291. return _set(_getPrototypeOf(f ? t.prototype : t), e, o, r, p);
  40292. }
  40293. function _taggedTemplateLiteral(e, t) {
  40294. return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, {
  40295. raw: {
  40296. value: Object.freeze(t)
  40297. }
  40298. }));
  40299. }
  40300. function _taggedTemplateLiteralLoose(e, t) {
  40301. return t || (t = e.slice(0)), e.raw = t, e;
  40302. }
  40303. function _tdz(e) {
  40304. throw new ReferenceError(e + " is not defined - temporal dead zone");
  40305. }
  40306. function _temporalRef(r, e) {
  40307. return r === _temporalUndefined ? _tdz(e) : r;
  40308. }
  40309. function _temporalUndefined() {}
  40310. function _toArray(r) {
  40311. return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest();
  40312. }
  40313. function _toConsumableArray(r) {
  40314. return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
  40315. }
  40316. function _toPrimitive(t, r) {
  40317. if ("object" != typeof t || !t) return t;
  40318. var e = t[Symbol.toPrimitive];
  40319. if (void 0 !== e) {
  40320. var i = e.call(t, r || "default");
  40321. if ("object" != typeof i) return i;
  40322. throw new TypeError("@@toPrimitive must return a primitive value.");
  40323. }
  40324. return ("string" === r ? String : Number)(t);
  40325. }
  40326. function _toPropertyKey(t) {
  40327. var i = _toPrimitive(t, "string");
  40328. return "symbol" == typeof i ? i : i + "";
  40329. }
  40330. function _toSetter(t, e, n) {
  40331. e || (e = []);
  40332. var r = e.length++;
  40333. return Object.defineProperty({}, "_", {
  40334. set: function (o) {
  40335. e[r] = o, t.apply(n, e);
  40336. }
  40337. });
  40338. }
  40339. function _typeof(o) {
  40340. "@babel/helpers - typeof";
  40341. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
  40342. return typeof o;
  40343. } : function (o) {
  40344. return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
  40345. }, _typeof(o);
  40346. }
  40347. function _unsupportedIterableToArray(r, a) {
  40348. if (r) {
  40349. if ("string" == typeof r) return _arrayLikeToArray(r, a);
  40350. var t = {}.toString.call(r).slice(8, -1);
  40351. return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
  40352. }
  40353. }
  40354. function _usingCtx() {
  40355. var r = "function" == typeof SuppressedError ? SuppressedError : function (r, e) {
  40356. var n = Error();
  40357. return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
  40358. },
  40359. e = {},
  40360. n = [];
  40361. function using(r, e) {
  40362. if (null != e) {
  40363. if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
  40364. if (r) var o = e[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
  40365. if (void 0 === o && (o = e[Symbol.dispose || Symbol.for("Symbol.dispose")], r)) var t = o;
  40366. if ("function" != typeof o) throw new TypeError("Object is not disposable.");
  40367. t && (o = function () {
  40368. try {
  40369. t.call(e);
  40370. } catch (r) {
  40371. return Promise.reject(r);
  40372. }
  40373. }), n.push({
  40374. v: e,
  40375. d: o,
  40376. a: r
  40377. });
  40378. } else r && n.push({
  40379. d: e,
  40380. a: r
  40381. });
  40382. return e;
  40383. }
  40384. return {
  40385. e: e,
  40386. u: using.bind(null, !1),
  40387. a: using.bind(null, !0),
  40388. d: function () {
  40389. var o,
  40390. t = this.e,
  40391. s = 0;
  40392. function next() {
  40393. for (; o = n.pop();) try {
  40394. if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
  40395. if (o.d) {
  40396. var r = o.d.call(o.v);
  40397. if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
  40398. } else s |= 1;
  40399. } catch (r) {
  40400. return err(r);
  40401. }
  40402. if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
  40403. if (t !== e) throw t;
  40404. }
  40405. function err(n) {
  40406. return t = t !== e ? new r(n, t) : n, next();
  40407. }
  40408. return next();
  40409. }
  40410. };
  40411. }
  40412. function _wrapAsyncGenerator(e) {
  40413. return function () {
  40414. return new AsyncGenerator(e.apply(this, arguments));
  40415. };
  40416. }
  40417. function AsyncGenerator(e) {
  40418. var r, t;
  40419. function resume(r, t) {
  40420. try {
  40421. var n = e[r](t),
  40422. o = n.value,
  40423. u = o instanceof _OverloadYield;
  40424. Promise.resolve(u ? o.v : o).then(function (t) {
  40425. if (u) {
  40426. var i = "return" === r ? "return" : "next";
  40427. if (!o.k || t.done) return resume(i, t);
  40428. t = e[i](t).value;
  40429. }
  40430. settle(n.done ? "return" : "normal", t);
  40431. }, function (e) {
  40432. resume("throw", e);
  40433. });
  40434. } catch (e) {
  40435. settle("throw", e);
  40436. }
  40437. }
  40438. function settle(e, n) {
  40439. switch (e) {
  40440. case "return":
  40441. r.resolve({
  40442. value: n,
  40443. done: !0
  40444. });
  40445. break;
  40446. case "throw":
  40447. r.reject(n);
  40448. break;
  40449. default:
  40450. r.resolve({
  40451. value: n,
  40452. done: !1
  40453. });
  40454. }
  40455. (r = r.next) ? resume(r.key, r.arg) : t = null;
  40456. }
  40457. this._invoke = function (e, n) {
  40458. return new Promise(function (o, u) {
  40459. var i = {
  40460. key: e,
  40461. arg: n,
  40462. resolve: o,
  40463. reject: u,
  40464. next: null
  40465. };
  40466. t ? t = t.next = i : (r = t = i, resume(e, n));
  40467. });
  40468. }, "function" != typeof e.return && (this.return = void 0);
  40469. }
  40470. AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () {
  40471. return this;
  40472. }, AsyncGenerator.prototype.next = function (e) {
  40473. return this._invoke("next", e);
  40474. }, AsyncGenerator.prototype.throw = function (e) {
  40475. return this._invoke("throw", e);
  40476. }, AsyncGenerator.prototype.return = function (e) {
  40477. return this._invoke("return", e);
  40478. };
  40479. function _wrapNativeSuper(t) {
  40480. var r = "function" == typeof Map ? new Map() : void 0;
  40481. return _wrapNativeSuper = function (t) {
  40482. if (null === t || !_isNativeFunction(t)) return t;
  40483. if ("function" != typeof t) throw new TypeError("Super expression must either be null or a function");
  40484. if (void 0 !== r) {
  40485. if (r.has(t)) return r.get(t);
  40486. r.set(t, Wrapper);
  40487. }
  40488. function Wrapper() {
  40489. return _construct(t, arguments, _getPrototypeOf(this).constructor);
  40490. }
  40491. return Wrapper.prototype = Object.create(t.prototype, {
  40492. constructor: {
  40493. value: Wrapper,
  40494. enumerable: !1,
  40495. writable: !0,
  40496. configurable: !0
  40497. }
  40498. }), _setPrototypeOf(Wrapper, t);
  40499. }, _wrapNativeSuper(t);
  40500. }
  40501. function _wrapRegExp() {
  40502. _wrapRegExp = function (e, r) {
  40503. return new BabelRegExp(e, void 0, r);
  40504. };
  40505. var e = RegExp.prototype,
  40506. r = new WeakMap();
  40507. function BabelRegExp(e, t, p) {
  40508. var o = RegExp(e, t);
  40509. return r.set(o, p || r.get(e)), _setPrototypeOf(o, BabelRegExp.prototype);
  40510. }
  40511. function buildGroups(e, t) {
  40512. var p = r.get(t);
  40513. return Object.keys(p).reduce(function (r, t) {
  40514. var o = p[t];
  40515. if ("number" == typeof o) r[t] = e[o];else {
  40516. for (var i = 0; void 0 === e[o[i]] && i + 1 < o.length;) i++;
  40517. r[t] = e[o[i]];
  40518. }
  40519. return r;
  40520. }, Object.create(null));
  40521. }
  40522. return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (r) {
  40523. var t = e.exec.call(this, r);
  40524. if (t) {
  40525. t.groups = buildGroups(t, this);
  40526. var p = t.indices;
  40527. p && (p.groups = buildGroups(p, this));
  40528. }
  40529. return t;
  40530. }, BabelRegExp.prototype[Symbol.replace] = function (t, p) {
  40531. if ("string" == typeof p) {
  40532. var o = r.get(this);
  40533. return e[Symbol.replace].call(this, t, p.replace(/\$<([^>]+)>/g, function (e, r) {
  40534. var t = o[r];
  40535. return "$" + (Array.isArray(t) ? t.join("$") : t);
  40536. }));
  40537. }
  40538. if ("function" == typeof p) {
  40539. var i = this;
  40540. return e[Symbol.replace].call(this, t, function () {
  40541. var e = arguments;
  40542. return "object" != typeof e[e.length - 1] && (e = [].slice.call(e)).push(buildGroups(e, i)), p.apply(this, e);
  40543. });
  40544. }
  40545. return e[Symbol.replace].call(this, t, p);
  40546. }, _wrapRegExp.apply(this, arguments);
  40547. }
  40548. function _writeOnlyError(r) {
  40549. throw new TypeError('"' + r + '" is write-only');
  40550. }
  40551. function _AwaitValue(t) {
  40552. this.wrapped = t;
  40553. }
  40554. function old_createMetadataMethodsForProperty(e, t, a, r) {
  40555. return {
  40556. getMetadata: function (o) {
  40557. old_assertNotFinished(r, "getMetadata"), old_assertMetadataKey(o);
  40558. var i = e[o];
  40559. if (void 0 !== i) if (1 === t) {
  40560. var n = i.public;
  40561. if (void 0 !== n) return n[a];
  40562. } else if (2 === t) {
  40563. var l = i.private;
  40564. if (void 0 !== l) return l.get(a);
  40565. } else if (Object.hasOwnProperty.call(i, "constructor")) return i.constructor;
  40566. },
  40567. setMetadata: function (o, i) {
  40568. old_assertNotFinished(r, "setMetadata"), old_assertMetadataKey(o);
  40569. var n = e[o];
  40570. if (void 0 === n && (n = e[o] = {}), 1 === t) {
  40571. var l = n.public;
  40572. void 0 === l && (l = n.public = {}), l[a] = i;
  40573. } else if (2 === t) {
  40574. var s = n.priv;
  40575. void 0 === s && (s = n.private = new Map()), s.set(a, i);
  40576. } else n.constructor = i;
  40577. }
  40578. };
  40579. }
  40580. function old_convertMetadataMapToFinal(e, t) {
  40581. var a = e[Symbol.metadata || Symbol.for("Symbol.metadata")],
  40582. r = Object.getOwnPropertySymbols(t);
  40583. if (0 !== r.length) {
  40584. for (var o = 0; o < r.length; o++) {
  40585. var i = r[o],
  40586. n = t[i],
  40587. l = a ? a[i] : null,
  40588. s = n.public,
  40589. c = l ? l.public : null;
  40590. s && c && Object.setPrototypeOf(s, c);
  40591. var d = n.private;
  40592. if (d) {
  40593. var u = Array.from(d.values()),
  40594. f = l ? l.private : null;
  40595. f && (u = u.concat(f)), n.private = u;
  40596. }
  40597. l && Object.setPrototypeOf(n, l);
  40598. }
  40599. a && Object.setPrototypeOf(t, a), e[Symbol.metadata || Symbol.for("Symbol.metadata")] = t;
  40600. }
  40601. }
  40602. function old_createAddInitializerMethod(e, t) {
  40603. return function (a) {
  40604. old_assertNotFinished(t, "addInitializer"), old_assertCallable(a, "An initializer"), e.push(a);
  40605. };
  40606. }
  40607. function old_memberDec(e, t, a, r, o, i, n, l, s) {
  40608. var c;
  40609. switch (i) {
  40610. case 1:
  40611. c = "accessor";
  40612. break;
  40613. case 2:
  40614. c = "method";
  40615. break;
  40616. case 3:
  40617. c = "getter";
  40618. break;
  40619. case 4:
  40620. c = "setter";
  40621. break;
  40622. default:
  40623. c = "field";
  40624. }
  40625. var d,
  40626. u,
  40627. f = {
  40628. kind: c,
  40629. name: l ? "#" + t : _toPropertyKey(t),
  40630. isStatic: n,
  40631. isPrivate: l
  40632. },
  40633. p = {
  40634. v: !1
  40635. };
  40636. if (0 !== i && (f.addInitializer = old_createAddInitializerMethod(o, p)), l) {
  40637. d = 2, u = Symbol(t);
  40638. var v = {};
  40639. 0 === i ? (v.get = a.get, v.set = a.set) : 2 === i ? v.get = function () {
  40640. return a.value;
  40641. } : (1 !== i && 3 !== i || (v.get = function () {
  40642. return a.get.call(this);
  40643. }), 1 !== i && 4 !== i || (v.set = function (e) {
  40644. a.set.call(this, e);
  40645. })), f.access = v;
  40646. } else d = 1, u = t;
  40647. try {
  40648. return e(s, Object.assign(f, old_createMetadataMethodsForProperty(r, d, u, p)));
  40649. } finally {
  40650. p.v = !0;
  40651. }
  40652. }
  40653. function old_assertNotFinished(e, t) {
  40654. if (e.v) throw Error("attempted to call " + t + " after decoration was finished");
  40655. }
  40656. function old_assertMetadataKey(e) {
  40657. if ("symbol" != typeof e) throw new TypeError("Metadata keys must be symbols, received: " + e);
  40658. }
  40659. function old_assertCallable(e, t) {
  40660. if ("function" != typeof e) throw new TypeError(t + " must be a function");
  40661. }
  40662. function old_assertValidReturnValue(e, t) {
  40663. var a = typeof t;
  40664. if (1 === e) {
  40665. if ("object" !== a || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
  40666. void 0 !== t.get && old_assertCallable(t.get, "accessor.get"), void 0 !== t.set && old_assertCallable(t.set, "accessor.set"), void 0 !== t.init && old_assertCallable(t.init, "accessor.init"), void 0 !== t.initializer && old_assertCallable(t.initializer, "accessor.initializer");
  40667. } else if ("function" !== a) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0");
  40668. }
  40669. function old_getInit(e) {
  40670. var t;
  40671. return null == (t = e.init) && (t = e.initializer) && void 0 !== console && console.warn(".initializer has been renamed to .init as of March 2022"), t;
  40672. }
  40673. function old_applyMemberDec(e, t, a, r, o, i, n, l, s) {
  40674. var c,
  40675. d,
  40676. u,
  40677. f,
  40678. p,
  40679. v,
  40680. y,
  40681. h = a[0];
  40682. if (n ? (0 === o || 1 === o ? (c = {
  40683. get: a[3],
  40684. set: a[4]
  40685. }, u = "get") : 3 === o ? (c = {
  40686. get: a[3]
  40687. }, u = "get") : 4 === o ? (c = {
  40688. set: a[3]
  40689. }, u = "set") : c = {
  40690. value: a[3]
  40691. }, 0 !== o && (1 === o && _setFunctionName(a[4], "#" + r, "set"), _setFunctionName(a[3], "#" + r, u))) : 0 !== o && (c = Object.getOwnPropertyDescriptor(t, r)), 1 === o ? f = {
  40692. get: c.get,
  40693. set: c.set
  40694. } : 2 === o ? f = c.value : 3 === o ? f = c.get : 4 === o && (f = c.set), "function" == typeof h) void 0 !== (p = old_memberDec(h, r, c, l, s, o, i, n, f)) && (old_assertValidReturnValue(o, p), 0 === o ? d = p : 1 === o ? (d = old_getInit(p), v = p.get || f.get, y = p.set || f.set, f = {
  40695. get: v,
  40696. set: y
  40697. }) : f = p);else for (var m = h.length - 1; m >= 0; m--) {
  40698. var b;
  40699. void 0 !== (p = old_memberDec(h[m], r, c, l, s, o, i, n, f)) && (old_assertValidReturnValue(o, p), 0 === o ? b = p : 1 === o ? (b = old_getInit(p), v = p.get || f.get, y = p.set || f.set, f = {
  40700. get: v,
  40701. set: y
  40702. }) : f = p, void 0 !== b && (void 0 === d ? d = b : "function" == typeof d ? d = [d, b] : d.push(b)));
  40703. }
  40704. if (0 === o || 1 === o) {
  40705. if (void 0 === d) d = function (e, t) {
  40706. return t;
  40707. };else if ("function" != typeof d) {
  40708. var g = d;
  40709. d = function (e, t) {
  40710. for (var a = t, r = 0; r < g.length; r++) a = g[r].call(e, a);
  40711. return a;
  40712. };
  40713. } else {
  40714. var _ = d;
  40715. d = function (e, t) {
  40716. return _.call(e, t);
  40717. };
  40718. }
  40719. e.push(d);
  40720. }
  40721. 0 !== o && (1 === o ? (c.get = f.get, c.set = f.set) : 2 === o ? c.value = f : 3 === o ? c.get = f : 4 === o && (c.set = f), n ? 1 === o ? (e.push(function (e, t) {
  40722. return f.get.call(e, t);
  40723. }), e.push(function (e, t) {
  40724. return f.set.call(e, t);
  40725. })) : 2 === o ? e.push(f) : e.push(function (e, t) {
  40726. return f.call(e, t);
  40727. }) : Object.defineProperty(t, r, c));
  40728. }
  40729. function old_applyMemberDecs(e, t, a, r, o) {
  40730. for (var i, n, l = new Map(), s = new Map(), c = 0; c < o.length; c++) {
  40731. var d = o[c];
  40732. if (Array.isArray(d)) {
  40733. var u,
  40734. f,
  40735. p,
  40736. v = d[1],
  40737. y = d[2],
  40738. h = d.length > 3,
  40739. m = v >= 5;
  40740. if (m ? (u = t, f = r, 0 != (v -= 5) && (p = n = n || [])) : (u = t.prototype, f = a, 0 !== v && (p = i = i || [])), 0 !== v && !h) {
  40741. var b = m ? s : l,
  40742. g = b.get(y) || 0;
  40743. if (!0 === g || 3 === g && 4 !== v || 4 === g && 3 !== v) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + y);
  40744. !g && v > 2 ? b.set(y, v) : b.set(y, !0);
  40745. }
  40746. old_applyMemberDec(e, u, d, y, v, m, h, f, p);
  40747. }
  40748. }
  40749. old_pushInitializers(e, i), old_pushInitializers(e, n);
  40750. }
  40751. function old_pushInitializers(e, t) {
  40752. t && e.push(function (e) {
  40753. for (var a = 0; a < t.length; a++) t[a].call(e);
  40754. return e;
  40755. });
  40756. }
  40757. function old_applyClassDecs(e, t, a, r) {
  40758. if (r.length > 0) {
  40759. for (var o = [], i = t, n = t.name, l = r.length - 1; l >= 0; l--) {
  40760. var s = {
  40761. v: !1
  40762. };
  40763. try {
  40764. var c = Object.assign({
  40765. kind: "class",
  40766. name: n,
  40767. addInitializer: old_createAddInitializerMethod(o, s)
  40768. }, old_createMetadataMethodsForProperty(a, 0, n, s)),
  40769. d = r[l](i, c);
  40770. } finally {
  40771. s.v = !0;
  40772. }
  40773. void 0 !== d && (old_assertValidReturnValue(10, d), i = d);
  40774. }
  40775. e.push(i, function () {
  40776. for (var e = 0; e < o.length; e++) o[e].call(i);
  40777. });
  40778. }
  40779. }
  40780. function _applyDecs(e, t, a) {
  40781. var r = [],
  40782. o = {},
  40783. i = {};
  40784. return old_applyMemberDecs(r, e, i, o, t), old_convertMetadataMapToFinal(e.prototype, i), old_applyClassDecs(r, e, o, a), old_convertMetadataMapToFinal(e, o), r;
  40785. }
  40786. function applyDecs2203Factory() {
  40787. function createAddInitializerMethod(e, t) {
  40788. return function (r) {
  40789. !function (e, t) {
  40790. if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
  40791. }(t), assertCallable(r, "An initializer"), e.push(r);
  40792. };
  40793. }
  40794. function memberDec(e, t, r, a, n, i, s, o) {
  40795. var c;
  40796. switch (n) {
  40797. case 1:
  40798. c = "accessor";
  40799. break;
  40800. case 2:
  40801. c = "method";
  40802. break;
  40803. case 3:
  40804. c = "getter";
  40805. break;
  40806. case 4:
  40807. c = "setter";
  40808. break;
  40809. default:
  40810. c = "field";
  40811. }
  40812. var l,
  40813. u,
  40814. f = {
  40815. kind: c,
  40816. name: s ? "#" + t : t,
  40817. static: i,
  40818. private: s
  40819. },
  40820. p = {
  40821. v: !1
  40822. };
  40823. 0 !== n && (f.addInitializer = createAddInitializerMethod(a, p)), 0 === n ? s ? (l = r.get, u = r.set) : (l = function () {
  40824. return this[t];
  40825. }, u = function (e) {
  40826. this[t] = e;
  40827. }) : 2 === n ? l = function () {
  40828. return r.value;
  40829. } : (1 !== n && 3 !== n || (l = function () {
  40830. return r.get.call(this);
  40831. }), 1 !== n && 4 !== n || (u = function (e) {
  40832. r.set.call(this, e);
  40833. })), f.access = l && u ? {
  40834. get: l,
  40835. set: u
  40836. } : l ? {
  40837. get: l
  40838. } : {
  40839. set: u
  40840. };
  40841. try {
  40842. return e(o, f);
  40843. } finally {
  40844. p.v = !0;
  40845. }
  40846. }
  40847. function assertCallable(e, t) {
  40848. if ("function" != typeof e) throw new TypeError(t + " must be a function");
  40849. }
  40850. function assertValidReturnValue(e, t) {
  40851. var r = typeof t;
  40852. if (1 === e) {
  40853. if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
  40854. void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
  40855. } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0");
  40856. }
  40857. function applyMemberDec(e, t, r, a, n, i, s, o) {
  40858. var c,
  40859. l,
  40860. u,
  40861. f,
  40862. p,
  40863. d,
  40864. h = r[0];
  40865. if (s ? c = 0 === n || 1 === n ? {
  40866. get: r[3],
  40867. set: r[4]
  40868. } : 3 === n ? {
  40869. get: r[3]
  40870. } : 4 === n ? {
  40871. set: r[3]
  40872. } : {
  40873. value: r[3]
  40874. } : 0 !== n && (c = Object.getOwnPropertyDescriptor(t, a)), 1 === n ? u = {
  40875. get: c.get,
  40876. set: c.set
  40877. } : 2 === n ? u = c.value : 3 === n ? u = c.get : 4 === n && (u = c.set), "function" == typeof h) void 0 !== (f = memberDec(h, a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? l = f : 1 === n ? (l = f.init, p = f.get || u.get, d = f.set || u.set, u = {
  40878. get: p,
  40879. set: d
  40880. }) : u = f);else for (var v = h.length - 1; v >= 0; v--) {
  40881. var g;
  40882. void 0 !== (f = memberDec(h[v], a, c, o, n, i, s, u)) && (assertValidReturnValue(n, f), 0 === n ? g = f : 1 === n ? (g = f.init, p = f.get || u.get, d = f.set || u.set, u = {
  40883. get: p,
  40884. set: d
  40885. }) : u = f, void 0 !== g && (void 0 === l ? l = g : "function" == typeof l ? l = [l, g] : l.push(g)));
  40886. }
  40887. if (0 === n || 1 === n) {
  40888. if (void 0 === l) l = function (e, t) {
  40889. return t;
  40890. };else if ("function" != typeof l) {
  40891. var y = l;
  40892. l = function (e, t) {
  40893. for (var r = t, a = 0; a < y.length; a++) r = y[a].call(e, r);
  40894. return r;
  40895. };
  40896. } else {
  40897. var m = l;
  40898. l = function (e, t) {
  40899. return m.call(e, t);
  40900. };
  40901. }
  40902. e.push(l);
  40903. }
  40904. 0 !== n && (1 === n ? (c.get = u.get, c.set = u.set) : 2 === n ? c.value = u : 3 === n ? c.get = u : 4 === n && (c.set = u), s ? 1 === n ? (e.push(function (e, t) {
  40905. return u.get.call(e, t);
  40906. }), e.push(function (e, t) {
  40907. return u.set.call(e, t);
  40908. })) : 2 === n ? e.push(u) : e.push(function (e, t) {
  40909. return u.call(e, t);
  40910. }) : Object.defineProperty(t, a, c));
  40911. }
  40912. function pushInitializers(e, t) {
  40913. t && e.push(function (e) {
  40914. for (var r = 0; r < t.length; r++) t[r].call(e);
  40915. return e;
  40916. });
  40917. }
  40918. return function (e, t, r) {
  40919. var a = [];
  40920. return function (e, t, r) {
  40921. for (var a, n, i = new Map(), s = new Map(), o = 0; o < r.length; o++) {
  40922. var c = r[o];
  40923. if (Array.isArray(c)) {
  40924. var l,
  40925. u,
  40926. f = c[1],
  40927. p = c[2],
  40928. d = c.length > 3,
  40929. h = f >= 5;
  40930. if (h ? (l = t, 0 != (f -= 5) && (u = n = n || [])) : (l = t.prototype, 0 !== f && (u = a = a || [])), 0 !== f && !d) {
  40931. var v = h ? s : i,
  40932. g = v.get(p) || 0;
  40933. if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p);
  40934. !g && f > 2 ? v.set(p, f) : v.set(p, !0);
  40935. }
  40936. applyMemberDec(e, l, c, p, f, h, d, u);
  40937. }
  40938. }
  40939. pushInitializers(e, a), pushInitializers(e, n);
  40940. }(a, e, t), function (e, t, r) {
  40941. if (r.length > 0) {
  40942. for (var a = [], n = t, i = t.name, s = r.length - 1; s >= 0; s--) {
  40943. var o = {
  40944. v: !1
  40945. };
  40946. try {
  40947. var c = r[s](n, {
  40948. kind: "class",
  40949. name: i,
  40950. addInitializer: createAddInitializerMethod(a, o)
  40951. });
  40952. } finally {
  40953. o.v = !0;
  40954. }
  40955. void 0 !== c && (assertValidReturnValue(10, c), n = c);
  40956. }
  40957. e.push(n, function () {
  40958. for (var e = 0; e < a.length; e++) a[e].call(n);
  40959. });
  40960. }
  40961. }(a, e, r), a;
  40962. };
  40963. }
  40964. var applyDecs2203Impl;
  40965. function _applyDecs2203(e, t, r) {
  40966. return (applyDecs2203Impl = applyDecs2203Impl || applyDecs2203Factory())(e, t, r);
  40967. }
  40968. function applyDecs2203RFactory() {
  40969. function createAddInitializerMethod(e, t) {
  40970. return function (r) {
  40971. !function (e, t) {
  40972. if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
  40973. }(t), assertCallable(r, "An initializer"), e.push(r);
  40974. };
  40975. }
  40976. function memberDec(e, t, r, n, a, i, o, s) {
  40977. var c;
  40978. switch (a) {
  40979. case 1:
  40980. c = "accessor";
  40981. break;
  40982. case 2:
  40983. c = "method";
  40984. break;
  40985. case 3:
  40986. c = "getter";
  40987. break;
  40988. case 4:
  40989. c = "setter";
  40990. break;
  40991. default:
  40992. c = "field";
  40993. }
  40994. var l,
  40995. u,
  40996. f = {
  40997. kind: c,
  40998. name: o ? "#" + t : _toPropertyKey(t),
  40999. static: i,
  41000. private: o
  41001. },
  41002. p = {
  41003. v: !1
  41004. };
  41005. 0 !== a && (f.addInitializer = createAddInitializerMethod(n, p)), 0 === a ? o ? (l = r.get, u = r.set) : (l = function () {
  41006. return this[t];
  41007. }, u = function (e) {
  41008. this[t] = e;
  41009. }) : 2 === a ? l = function () {
  41010. return r.value;
  41011. } : (1 !== a && 3 !== a || (l = function () {
  41012. return r.get.call(this);
  41013. }), 1 !== a && 4 !== a || (u = function (e) {
  41014. r.set.call(this, e);
  41015. })), f.access = l && u ? {
  41016. get: l,
  41017. set: u
  41018. } : l ? {
  41019. get: l
  41020. } : {
  41021. set: u
  41022. };
  41023. try {
  41024. return e(s, f);
  41025. } finally {
  41026. p.v = !0;
  41027. }
  41028. }
  41029. function assertCallable(e, t) {
  41030. if ("function" != typeof e) throw new TypeError(t + " must be a function");
  41031. }
  41032. function assertValidReturnValue(e, t) {
  41033. var r = typeof t;
  41034. if (1 === e) {
  41035. if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
  41036. void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
  41037. } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0");
  41038. }
  41039. function applyMemberDec(e, t, r, n, a, i, o, s) {
  41040. var c,
  41041. l,
  41042. u,
  41043. f,
  41044. p,
  41045. d,
  41046. h,
  41047. v = r[0];
  41048. if (o ? (0 === a || 1 === a ? (c = {
  41049. get: r[3],
  41050. set: r[4]
  41051. }, u = "get") : 3 === a ? (c = {
  41052. get: r[3]
  41053. }, u = "get") : 4 === a ? (c = {
  41054. set: r[3]
  41055. }, u = "set") : c = {
  41056. value: r[3]
  41057. }, 0 !== a && (1 === a && _setFunctionName(r[4], "#" + n, "set"), _setFunctionName(r[3], "#" + n, u))) : 0 !== a && (c = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? f = {
  41058. get: c.get,
  41059. set: c.set
  41060. } : 2 === a ? f = c.value : 3 === a ? f = c.get : 4 === a && (f = c.set), "function" == typeof v) void 0 !== (p = memberDec(v, n, c, s, a, i, o, f)) && (assertValidReturnValue(a, p), 0 === a ? l = p : 1 === a ? (l = p.init, d = p.get || f.get, h = p.set || f.set, f = {
  41061. get: d,
  41062. set: h
  41063. }) : f = p);else for (var g = v.length - 1; g >= 0; g--) {
  41064. var y;
  41065. void 0 !== (p = memberDec(v[g], n, c, s, a, i, o, f)) && (assertValidReturnValue(a, p), 0 === a ? y = p : 1 === a ? (y = p.init, d = p.get || f.get, h = p.set || f.set, f = {
  41066. get: d,
  41067. set: h
  41068. }) : f = p, void 0 !== y && (void 0 === l ? l = y : "function" == typeof l ? l = [l, y] : l.push(y)));
  41069. }
  41070. if (0 === a || 1 === a) {
  41071. if (void 0 === l) l = function (e, t) {
  41072. return t;
  41073. };else if ("function" != typeof l) {
  41074. var m = l;
  41075. l = function (e, t) {
  41076. for (var r = t, n = 0; n < m.length; n++) r = m[n].call(e, r);
  41077. return r;
  41078. };
  41079. } else {
  41080. var b = l;
  41081. l = function (e, t) {
  41082. return b.call(e, t);
  41083. };
  41084. }
  41085. e.push(l);
  41086. }
  41087. 0 !== a && (1 === a ? (c.get = f.get, c.set = f.set) : 2 === a ? c.value = f : 3 === a ? c.get = f : 4 === a && (c.set = f), o ? 1 === a ? (e.push(function (e, t) {
  41088. return f.get.call(e, t);
  41089. }), e.push(function (e, t) {
  41090. return f.set.call(e, t);
  41091. })) : 2 === a ? e.push(f) : e.push(function (e, t) {
  41092. return f.call(e, t);
  41093. }) : Object.defineProperty(t, n, c));
  41094. }
  41095. function applyMemberDecs(e, t) {
  41096. for (var r, n, a = [], i = new Map(), o = new Map(), s = 0; s < t.length; s++) {
  41097. var c = t[s];
  41098. if (Array.isArray(c)) {
  41099. var l,
  41100. u,
  41101. f = c[1],
  41102. p = c[2],
  41103. d = c.length > 3,
  41104. h = f >= 5;
  41105. if (h ? (l = e, 0 != (f -= 5) && (u = n = n || [])) : (l = e.prototype, 0 !== f && (u = r = r || [])), 0 !== f && !d) {
  41106. var v = h ? o : i,
  41107. g = v.get(p) || 0;
  41108. if (!0 === g || 3 === g && 4 !== f || 4 === g && 3 !== f) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + p);
  41109. !g && f > 2 ? v.set(p, f) : v.set(p, !0);
  41110. }
  41111. applyMemberDec(a, l, c, p, f, h, d, u);
  41112. }
  41113. }
  41114. return pushInitializers(a, r), pushInitializers(a, n), a;
  41115. }
  41116. function pushInitializers(e, t) {
  41117. t && e.push(function (e) {
  41118. for (var r = 0; r < t.length; r++) t[r].call(e);
  41119. return e;
  41120. });
  41121. }
  41122. return function (e, t, r) {
  41123. return {
  41124. e: applyMemberDecs(e, t),
  41125. get c() {
  41126. return function (e, t) {
  41127. if (t.length > 0) {
  41128. for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) {
  41129. var o = {
  41130. v: !1
  41131. };
  41132. try {
  41133. var s = t[i](n, {
  41134. kind: "class",
  41135. name: a,
  41136. addInitializer: createAddInitializerMethod(r, o)
  41137. });
  41138. } finally {
  41139. o.v = !0;
  41140. }
  41141. void 0 !== s && (assertValidReturnValue(10, s), n = s);
  41142. }
  41143. return [n, function () {
  41144. for (var e = 0; e < r.length; e++) r[e].call(n);
  41145. }];
  41146. }
  41147. }(e, r);
  41148. }
  41149. };
  41150. };
  41151. }
  41152. function _applyDecs2203R(e, t, r) {
  41153. return (_applyDecs2203R = applyDecs2203RFactory())(e, t, r);
  41154. }
  41155. function applyDecs2301Factory() {
  41156. function createAddInitializerMethod(e, t) {
  41157. return function (r) {
  41158. !function (e, t) {
  41159. if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
  41160. }(t), assertCallable(r, "An initializer"), e.push(r);
  41161. };
  41162. }
  41163. function assertInstanceIfPrivate(e, t) {
  41164. if (!e(t)) throw new TypeError("Attempted to access private element on non-instance");
  41165. }
  41166. function memberDec(e, t, r, n, a, i, s, o, c) {
  41167. var u;
  41168. switch (a) {
  41169. case 1:
  41170. u = "accessor";
  41171. break;
  41172. case 2:
  41173. u = "method";
  41174. break;
  41175. case 3:
  41176. u = "getter";
  41177. break;
  41178. case 4:
  41179. u = "setter";
  41180. break;
  41181. default:
  41182. u = "field";
  41183. }
  41184. var l,
  41185. f,
  41186. p = {
  41187. kind: u,
  41188. name: s ? "#" + t : _toPropertyKey(t),
  41189. static: i,
  41190. private: s
  41191. },
  41192. d = {
  41193. v: !1
  41194. };
  41195. if (0 !== a && (p.addInitializer = createAddInitializerMethod(n, d)), s || 0 !== a && 2 !== a) {
  41196. if (2 === a) l = function (e) {
  41197. return assertInstanceIfPrivate(c, e), r.value;
  41198. };else {
  41199. var h = 0 === a || 1 === a;
  41200. (h || 3 === a) && (l = s ? function (e) {
  41201. return assertInstanceIfPrivate(c, e), r.get.call(e);
  41202. } : function (e) {
  41203. return r.get.call(e);
  41204. }), (h || 4 === a) && (f = s ? function (e, t) {
  41205. assertInstanceIfPrivate(c, e), r.set.call(e, t);
  41206. } : function (e, t) {
  41207. r.set.call(e, t);
  41208. });
  41209. }
  41210. } else l = function (e) {
  41211. return e[t];
  41212. }, 0 === a && (f = function (e, r) {
  41213. e[t] = r;
  41214. });
  41215. var v = s ? c.bind() : function (e) {
  41216. return t in e;
  41217. };
  41218. p.access = l && f ? {
  41219. get: l,
  41220. set: f,
  41221. has: v
  41222. } : l ? {
  41223. get: l,
  41224. has: v
  41225. } : {
  41226. set: f,
  41227. has: v
  41228. };
  41229. try {
  41230. return e(o, p);
  41231. } finally {
  41232. d.v = !0;
  41233. }
  41234. }
  41235. function assertCallable(e, t) {
  41236. if ("function" != typeof e) throw new TypeError(t + " must be a function");
  41237. }
  41238. function assertValidReturnValue(e, t) {
  41239. var r = typeof t;
  41240. if (1 === e) {
  41241. if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
  41242. void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
  41243. } else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0");
  41244. }
  41245. function curryThis2(e) {
  41246. return function (t) {
  41247. e(this, t);
  41248. };
  41249. }
  41250. function applyMemberDec(e, t, r, n, a, i, s, o, c) {
  41251. var u,
  41252. l,
  41253. f,
  41254. p,
  41255. d,
  41256. h,
  41257. v,
  41258. y,
  41259. g = r[0];
  41260. if (s ? (0 === a || 1 === a ? (u = {
  41261. get: (d = r[3], function () {
  41262. return d(this);
  41263. }),
  41264. set: curryThis2(r[4])
  41265. }, f = "get") : 3 === a ? (u = {
  41266. get: r[3]
  41267. }, f = "get") : 4 === a ? (u = {
  41268. set: r[3]
  41269. }, f = "set") : u = {
  41270. value: r[3]
  41271. }, 0 !== a && (1 === a && _setFunctionName(u.set, "#" + n, "set"), _setFunctionName(u[f || "value"], "#" + n, f))) : 0 !== a && (u = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? p = {
  41272. get: u.get,
  41273. set: u.set
  41274. } : 2 === a ? p = u.value : 3 === a ? p = u.get : 4 === a && (p = u.set), "function" == typeof g) void 0 !== (h = memberDec(g, n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? l = h : 1 === a ? (l = h.init, v = h.get || p.get, y = h.set || p.set, p = {
  41275. get: v,
  41276. set: y
  41277. }) : p = h);else for (var m = g.length - 1; m >= 0; m--) {
  41278. var b;
  41279. void 0 !== (h = memberDec(g[m], n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? b = h : 1 === a ? (b = h.init, v = h.get || p.get, y = h.set || p.set, p = {
  41280. get: v,
  41281. set: y
  41282. }) : p = h, void 0 !== b && (void 0 === l ? l = b : "function" == typeof l ? l = [l, b] : l.push(b)));
  41283. }
  41284. if (0 === a || 1 === a) {
  41285. if (void 0 === l) l = function (e, t) {
  41286. return t;
  41287. };else if ("function" != typeof l) {
  41288. var I = l;
  41289. l = function (e, t) {
  41290. for (var r = t, n = 0; n < I.length; n++) r = I[n].call(e, r);
  41291. return r;
  41292. };
  41293. } else {
  41294. var w = l;
  41295. l = function (e, t) {
  41296. return w.call(e, t);
  41297. };
  41298. }
  41299. e.push(l);
  41300. }
  41301. 0 !== a && (1 === a ? (u.get = p.get, u.set = p.set) : 2 === a ? u.value = p : 3 === a ? u.get = p : 4 === a && (u.set = p), s ? 1 === a ? (e.push(function (e, t) {
  41302. return p.get.call(e, t);
  41303. }), e.push(function (e, t) {
  41304. return p.set.call(e, t);
  41305. })) : 2 === a ? e.push(p) : e.push(function (e, t) {
  41306. return p.call(e, t);
  41307. }) : Object.defineProperty(t, n, u));
  41308. }
  41309. function applyMemberDecs(e, t, r) {
  41310. for (var n, a, i, s = [], o = new Map(), c = new Map(), u = 0; u < t.length; u++) {
  41311. var l = t[u];
  41312. if (Array.isArray(l)) {
  41313. var f,
  41314. p,
  41315. d = l[1],
  41316. h = l[2],
  41317. v = l.length > 3,
  41318. y = d >= 5,
  41319. g = r;
  41320. if (y ? (f = e, 0 != (d -= 5) && (p = a = a || []), v && !i && (i = function (t) {
  41321. return _checkInRHS(t) === e;
  41322. }), g = i) : (f = e.prototype, 0 !== d && (p = n = n || [])), 0 !== d && !v) {
  41323. var m = y ? c : o,
  41324. b = m.get(h) || 0;
  41325. if (!0 === b || 3 === b && 4 !== d || 4 === b && 3 !== d) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
  41326. !b && d > 2 ? m.set(h, d) : m.set(h, !0);
  41327. }
  41328. applyMemberDec(s, f, l, h, d, y, v, p, g);
  41329. }
  41330. }
  41331. return pushInitializers(s, n), pushInitializers(s, a), s;
  41332. }
  41333. function pushInitializers(e, t) {
  41334. t && e.push(function (e) {
  41335. for (var r = 0; r < t.length; r++) t[r].call(e);
  41336. return e;
  41337. });
  41338. }
  41339. return function (e, t, r, n) {
  41340. return {
  41341. e: applyMemberDecs(e, t, n),
  41342. get c() {
  41343. return function (e, t) {
  41344. if (t.length > 0) {
  41345. for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) {
  41346. var s = {
  41347. v: !1
  41348. };
  41349. try {
  41350. var o = t[i](n, {
  41351. kind: "class",
  41352. name: a,
  41353. addInitializer: createAddInitializerMethod(r, s)
  41354. });
  41355. } finally {
  41356. s.v = !0;
  41357. }
  41358. void 0 !== o && (assertValidReturnValue(10, o), n = o);
  41359. }
  41360. return [n, function () {
  41361. for (var e = 0; e < r.length; e++) r[e].call(n);
  41362. }];
  41363. }
  41364. }(e, r);
  41365. }
  41366. };
  41367. };
  41368. }
  41369. function _applyDecs2301(e, t, r, n) {
  41370. return (_applyDecs2301 = applyDecs2301Factory())(e, t, r, n);
  41371. }
  41372. function _applyDecs2305(e, t, r, n, o, a) {
  41373. function i(e, t, r) {
  41374. return function (n, o) {
  41375. return r && r(n), e[t].call(n, o);
  41376. };
  41377. }
  41378. function c(e, t) {
  41379. for (var r = 0; r < e.length; r++) e[r].call(t);
  41380. return t;
  41381. }
  41382. function s(e, t, r, n) {
  41383. if ("function" != typeof e && (n || void 0 !== e)) throw new TypeError(t + " must " + (r || "be") + " a function" + (n ? "" : " or undefined"));
  41384. return e;
  41385. }
  41386. function applyDec(e, t, r, n, o, a, c, u, l, f, p, d, h) {
  41387. function m(e) {
  41388. if (!h(e)) throw new TypeError("Attempted to access private element on non-instance");
  41389. }
  41390. var y,
  41391. v = t[0],
  41392. g = t[3],
  41393. b = !u;
  41394. if (!b) {
  41395. r || Array.isArray(v) || (v = [v]);
  41396. var w = {},
  41397. S = [],
  41398. A = 3 === o ? "get" : 4 === o || d ? "set" : "value";
  41399. f ? (p || d ? w = {
  41400. get: _setFunctionName(function () {
  41401. return g(this);
  41402. }, n, "get"),
  41403. set: function (e) {
  41404. t[4](this, e);
  41405. }
  41406. } : w[A] = g, p || _setFunctionName(w[A], n, 2 === o ? "" : A)) : p || (w = Object.getOwnPropertyDescriptor(e, n));
  41407. }
  41408. for (var P = e, j = v.length - 1; j >= 0; j -= r ? 2 : 1) {
  41409. var D = v[j],
  41410. E = r ? v[j - 1] : void 0,
  41411. I = {},
  41412. O = {
  41413. kind: ["field", "accessor", "method", "getter", "setter", "class"][o],
  41414. name: n,
  41415. metadata: a,
  41416. addInitializer: function (e, t) {
  41417. if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
  41418. s(t, "An initializer", "be", !0), c.push(t);
  41419. }.bind(null, I)
  41420. };
  41421. try {
  41422. if (b) (y = s(D.call(E, P, O), "class decorators", "return")) && (P = y);else {
  41423. var k, F;
  41424. O.static = l, O.private = f, f ? 2 === o ? k = function (e) {
  41425. return m(e), w.value;
  41426. } : (o < 4 && (k = i(w, "get", m)), 3 !== o && (F = i(w, "set", m))) : (k = function (e) {
  41427. return e[n];
  41428. }, (o < 2 || 4 === o) && (F = function (e, t) {
  41429. e[n] = t;
  41430. }));
  41431. var N = O.access = {
  41432. has: f ? h.bind() : function (e) {
  41433. return n in e;
  41434. }
  41435. };
  41436. if (k && (N.get = k), F && (N.set = F), P = D.call(E, d ? {
  41437. get: w.get,
  41438. set: w.set
  41439. } : w[A], O), d) {
  41440. if ("object" == typeof P && P) (y = s(P.get, "accessor.get")) && (w.get = y), (y = s(P.set, "accessor.set")) && (w.set = y), (y = s(P.init, "accessor.init")) && S.push(y);else if (void 0 !== P) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
  41441. } else s(P, (p ? "field" : "method") + " decorators", "return") && (p ? S.push(P) : w[A] = P);
  41442. }
  41443. } finally {
  41444. I.v = !0;
  41445. }
  41446. }
  41447. return (p || d) && u.push(function (e, t) {
  41448. for (var r = S.length - 1; r >= 0; r--) t = S[r].call(e, t);
  41449. return t;
  41450. }), p || b || (f ? d ? u.push(i(w, "get"), i(w, "set")) : u.push(2 === o ? w[A] : i.call.bind(w[A])) : Object.defineProperty(e, n, w)), P;
  41451. }
  41452. function u(e, t) {
  41453. return Object.defineProperty(e, Symbol.metadata || Symbol.for("Symbol.metadata"), {
  41454. configurable: !0,
  41455. enumerable: !0,
  41456. value: t
  41457. });
  41458. }
  41459. if (arguments.length >= 6) var l = a[Symbol.metadata || Symbol.for("Symbol.metadata")];
  41460. var f = Object.create(null == l ? null : l),
  41461. p = function (e, t, r, n) {
  41462. var o,
  41463. a,
  41464. i = [],
  41465. s = function (t) {
  41466. return _checkInRHS(t) === e;
  41467. },
  41468. u = new Map();
  41469. function l(e) {
  41470. e && i.push(c.bind(null, e));
  41471. }
  41472. for (var f = 0; f < t.length; f++) {
  41473. var p = t[f];
  41474. if (Array.isArray(p)) {
  41475. var d = p[1],
  41476. h = p[2],
  41477. m = p.length > 3,
  41478. y = 16 & d,
  41479. v = !!(8 & d),
  41480. g = 0 == (d &= 7),
  41481. b = h + "/" + v;
  41482. if (!g && !m) {
  41483. var w = u.get(b);
  41484. if (!0 === w || 3 === w && 4 !== d || 4 === w && 3 !== d) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
  41485. u.set(b, !(d > 2) || d);
  41486. }
  41487. applyDec(v ? e : e.prototype, p, y, m ? "#" + h : _toPropertyKey(h), d, n, v ? a = a || [] : o = o || [], i, v, m, g, 1 === d, v && m ? s : r);
  41488. }
  41489. }
  41490. return l(o), l(a), i;
  41491. }(e, t, o, f);
  41492. return r.length || u(e, f), {
  41493. e: p,
  41494. get c() {
  41495. var t = [];
  41496. return r.length && [u(applyDec(e, [r], n, e.name, 5, f, t), f), c.bind(null, t, e)];
  41497. }
  41498. };
  41499. }
  41500. function _classApplyDescriptorDestructureSet(e, t) {
  41501. if (t.set) return "__destrObj" in t || (t.__destrObj = {
  41502. set value(r) {
  41503. t.set.call(e, r);
  41504. }
  41505. }), t.__destrObj;
  41506. if (!t.writable) throw new TypeError("attempted to set read only private field");
  41507. return t;
  41508. }
  41509. function _classApplyDescriptorGet(e, t) {
  41510. return t.get ? t.get.call(e) : t.value;
  41511. }
  41512. function _classApplyDescriptorSet(e, t, l) {
  41513. if (t.set) t.set.call(e, l);else {
  41514. if (!t.writable) throw new TypeError("attempted to set read only private field");
  41515. t.value = l;
  41516. }
  41517. }
  41518. function _classCheckPrivateStaticAccess(s, a, r) {
  41519. return _assertClassBrand(a, s, r);
  41520. }
  41521. function _classCheckPrivateStaticFieldDescriptor(t, e) {
  41522. if (void 0 === t) throw new TypeError("attempted to " + e + " private static field before its declaration");
  41523. }
  41524. function _classExtractFieldDescriptor(e, t) {
  41525. return _classPrivateFieldGet2(t, e);
  41526. }
  41527. function _classPrivateFieldDestructureSet(e, t) {
  41528. var r = _classPrivateFieldGet2(t, e);
  41529. return _classApplyDescriptorDestructureSet(e, r);
  41530. }
  41531. function _classPrivateFieldGet(e, t) {
  41532. var r = _classPrivateFieldGet2(t, e);
  41533. return _classApplyDescriptorGet(e, r);
  41534. }
  41535. function _classPrivateFieldSet(e, t, r) {
  41536. var s = _classPrivateFieldGet2(t, e);
  41537. return _classApplyDescriptorSet(e, s, r), r;
  41538. }
  41539. function _classPrivateMethodGet(s, a, r) {
  41540. return _assertClassBrand(a, s), r;
  41541. }
  41542. function _classPrivateMethodSet() {
  41543. throw new TypeError("attempted to reassign private method");
  41544. }
  41545. function _classStaticPrivateFieldDestructureSet(t, r, s) {
  41546. return _assertClassBrand(r, t), _classCheckPrivateStaticFieldDescriptor(s, "set"), _classApplyDescriptorDestructureSet(t, s);
  41547. }
  41548. function _classStaticPrivateFieldSpecGet(t, s, r) {
  41549. return _assertClassBrand(s, t), _classCheckPrivateStaticFieldDescriptor(r, "get"), _classApplyDescriptorGet(t, r);
  41550. }
  41551. function _classStaticPrivateFieldSpecSet(s, t, r, e) {
  41552. return _assertClassBrand(t, s), _classCheckPrivateStaticFieldDescriptor(r, "set"), _classApplyDescriptorSet(s, r, e), e;
  41553. }
  41554. function _classStaticPrivateMethodSet() {
  41555. throw new TypeError("attempted to set read only static private field");
  41556. }
  41557. function _defineEnumerableProperties(e, r) {
  41558. for (var t in r) {
  41559. var n = r[t];
  41560. n.configurable = n.enumerable = !0, "value" in n && (n.writable = !0), Object.defineProperty(e, t, n);
  41561. }
  41562. if (Object.getOwnPropertySymbols) for (var a = Object.getOwnPropertySymbols(r), b = 0; b < a.length; b++) {
  41563. var i = a[b];
  41564. (n = r[i]).configurable = n.enumerable = !0, "value" in n && (n.writable = !0), Object.defineProperty(e, i, n);
  41565. }
  41566. return e;
  41567. }
  41568. function dispose_SuppressedError(r, e) {
  41569. return "undefined" != typeof SuppressedError ? dispose_SuppressedError = SuppressedError : (dispose_SuppressedError = function (r, e) {
  41570. this.suppressed = e, this.error = r, this.stack = Error().stack;
  41571. }, dispose_SuppressedError.prototype = Object.create(Error.prototype, {
  41572. constructor: {
  41573. value: dispose_SuppressedError,
  41574. writable: !0,
  41575. configurable: !0
  41576. }
  41577. })), new dispose_SuppressedError(r, e);
  41578. }
  41579. function _dispose(r, e, s) {
  41580. function next() {
  41581. for (; r.length > 0;) try {
  41582. var o = r.pop(),
  41583. p = o.d.call(o.v);
  41584. if (o.a) return Promise.resolve(p).then(next, err);
  41585. } catch (r) {
  41586. return err(r);
  41587. }
  41588. if (s) throw e;
  41589. }
  41590. function err(r) {
  41591. return e = s ? new dispose_SuppressedError(e, r) : r, s = !0, next();
  41592. }
  41593. return next();
  41594. }
  41595. function _objectSpread(e) {
  41596. for (var r = 1; r < arguments.length; r++) {
  41597. var t = null != arguments[r] ? Object(arguments[r]) : {},
  41598. o = Object.keys(t);
  41599. "function" == typeof Object.getOwnPropertySymbols && o.push.apply(o, Object.getOwnPropertySymbols(t).filter(function (e) {
  41600. return Object.getOwnPropertyDescriptor(t, e).enumerable;
  41601. })), o.forEach(function (r) {
  41602. _defineProperty(e, r, t[r]);
  41603. });
  41604. }
  41605. return e;
  41606. }
  41607. function _using(o, n, e) {
  41608. if (null == n) return n;
  41609. if (Object(n) !== n) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
  41610. if (e) var r = n[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
  41611. if (null == r && (r = n[Symbol.dispose || Symbol.for("Symbol.dispose")]), "function" != typeof r) throw new TypeError("Property [Symbol.dispose] is not a function.");
  41612. return o.push({
  41613. v: n,
  41614. d: r,
  41615. a: e
  41616. }), n;
  41617. }
  41618. //import SorterWasm from './sorter.wasm'; //wasm加载报错: (Note that you need plugins to import files that are not JavaScript)
  41619. var SorterWasm = "AGFzbQEAAAAADwhkeWxpbmsuMAEEAAAAAAEhA2AAAGAWf39/f39/f39/f39/f39/f39/f39/fwBgAAF/AhIBA2VudgZtZW1vcnkCAwCAgAQDBAMAAQIHOQMRX193YXNtX2NhbGxfY3RvcnMAAAtzb3J0SW5kZXhlcwABE2Vtc2NyaXB0ZW5fdGxzX2luaXQAAgqSBgMDAAELhgYDAXwCewJ9An8gCyoCCLv9FCALKgIYu/0iAf0MAAAAAABAj0AAAAAAAECPQP3yASIX/SEBIhaZRAAAAAAAAOBBYwRAIBaqDAELQYCAgIB4CyEMAn8gF/0hACIWmUQAAAAAAADgQWMEQCAWqgwBC0GAgICAeAshDQJ/IAsqAii7RAAAAAAAQI9AoiIWmUQAAAAAAADgQWMEQCAWqgwBC0GAgICAeAshCwJAIBEgEGsiAyARSSIORQ0AIA39ESAM/RwBIAv9HAIhGEH4////ByEMQYiAgIB4IQ0gAyEQA0AgCSAQQQJ0aiABIBBBBHRq/QAAACAY/bUBIhf9GwAgF/0bAWogF/0bAmoiCzYCACALIAwgCyAMSBshDCALIA0gCyANShshDSAQQQFqIhAgEUcNAAsgDkUNACAPQQFrsyANsiAMspOVIRkgAyELA0ACfyAZIAkgC0ECdGoiASgCACAMa7KUIhqLQwAAAE9dBEAgGqgMAQtBgICAgHgLIRAgASAQNgIAIAogEEECdGoiASABKAIAQQFqNgIAIAtBAWoiCyARRw0ACwsgD0ECTwRAIAooAgAhEEEBIQsDQCAKIAtBAnRqIgEgASgCACAQaiIQNgIAIAtBAWoiCyAPRw0ACwsgAyARSARAIBEhEANAIAIgESAKIAkgEEEBayIQQQJ0IgFqKAIAQQJ0aiIPKAIAIhJrIgxBDGwiC2ogACAQQQR0aioCADgCACACIAtBBGoiDWogACABQQFyIhNBAnRqKgIAOAIAIAIgC0EIaiIOaiAAIAFBAnIiFEECdGoqAgA4AgAgBSAMQQJ0aiIMIAEgBGoiAS0AADoAACAMIAQgE2otAAA6AAEgDCAEIBRqLQAAOgACIAwgAS0AAzoAAyAHIAtqIAYgEEEYbGoiASoCADgCACAHIA1qIAEqAgQ4AgAgByAOaiABKgIIOAIAIAggC2ogASoCDDgCACAIIA1qIAEqAhA4AgAgCCAOaiABKgIUOAIAIA8gEkEBazYCACADIBBIDQALCwsEAEEACw==";
  41620. //sortIndexes 按照深度排序
  41621. function sortWorker(self) {
  41622. var wasmInstance;
  41623. var wasmMemory;
  41624. var useSharedMemory;
  41625. var integerBasedSort;
  41626. var dynamicMode;
  41627. var splatCount;
  41628. var indexesToSortOffset; //存储首地址
  41629. var sortedIndexesOffset = 0;
  41630. var transformIndexesOffset;
  41631. var transformsOffset;
  41632. var precomputedDistancesOffset;
  41633. var mappedDistancesOffset;
  41634. var frequenciesOffset;
  41635. var centersFloatOffset, centersIntOffset, sortedCentersOffset; //
  41636. var colorsOffset, sortedColorsOffset, covsOffset, sortedCovs1Offset, sortedCovs2Offset;
  41637. var modelViewProjOffset;
  41638. var countsZero;
  41639. var sortedIndexesOut;
  41640. var dataInited;
  41641. var Constants;
  41642. var memoryRequiredOut;
  41643. var sortedBufferIndex = 0;
  41644. var splatEnableSwapOut;
  41645. /* const uintToFloat = (function(){
  41646. const int32View = new Int32Array(1);
  41647. const floatView = new Float32Array(int32View.buffer);
  41648. return function(f) {
  41649. int32View[0] = f;
  41650. return floatView[0];
  41651. };
  41652. })(); */
  41653. function sort(splatSortCount, splatRenderCount, modelViewProj, usePrecomputedDistances, /* copyIndexesToSort, */copyPrecomputedDistances, copyTransforms) {
  41654. var sortStartTime = performance.now();
  41655. if (!dataInited) {
  41656. return self.postMessage({
  41657. 'sortDone': true,
  41658. 'splatSortCount': splatSortCount,
  41659. 'splatRenderCount': splatRenderCount,
  41660. 'sortTime': 0
  41661. });
  41662. }
  41663. //console.log('startSort')
  41664. if (!useSharedMemory) {
  41665. /* const indexesToSort = new Uint32Array(wasmMemory, indexesToSortOffset, copyIndexesToSort.byteLength / Potree.defines.gs3d.BytesPerInt);
  41666. indexesToSort.set(copyIndexesToSort); */
  41667. var transforms = new Float32Array(wasmMemory, transformsOffset, copyTransforms.byteLength / Constants.BytesPerFloat);
  41668. transforms.set(copyTransforms);
  41669. if (usePrecomputedDistances) {
  41670. var precomputedDistances;
  41671. if (integerBasedSort) {
  41672. //可以提高速度,但可能溢出。默认是true
  41673. precomputedDistances = new Int32Array(wasmMemory, precomputedDistancesOffset, copyPrecomputedDistances.byteLength / Constants.BytesPerInt);
  41674. } else {
  41675. precomputedDistances = new Float32Array(wasmMemory, precomputedDistancesOffset, copyPrecomputedDistances.byteLength / Constants.BytesPerFloat);
  41676. }
  41677. precomputedDistances.set(copyPrecomputedDistances);
  41678. }
  41679. }
  41680. if (!countsZero) countsZero = new Uint32Array(Constants.DepthMapRange);
  41681. new Float32Array(wasmMemory, modelViewProjOffset, 16).set(modelViewProj); //由于新数组已经与 WebAssembly 内存关联,实际上是将 modelViewProj 的数据复制到了 WebAssembly 内存的指定位置。
  41682. new Uint32Array(wasmMemory, frequenciesOffset, Constants.DepthMapRange).set(countsZero);
  41683. var sortStartTime1 = performance.now();
  41684. var swapBufferOffset = splatEnableSwapOut && sortedBufferIndex == 1 ? memoryRequiredOut : 0;
  41685. wasmInstance.exports.sortIndexes(centersFloatOffset, centersIntOffset, sortedCentersOffset + swapBufferOffset, precomputedDistancesOffset, colorsOffset, sortedColorsOffset + swapBufferOffset, covsOffset, sortedCovs1Offset + swapBufferOffset, sortedCovs2Offset + swapBufferOffset, mappedDistancesOffset, frequenciesOffset, modelViewProjOffset, sortedIndexesOffset, transformIndexesOffset, transformsOffset, Constants.DepthMapRange, splatSortCount, splatRenderCount, splatCount, usePrecomputedDistances, integerBasedSort, dynamicMode);
  41686. var sortMessage = {
  41687. 'sortDone': true,
  41688. 'splatSortCount': splatSortCount,
  41689. 'splatRenderCount': splatRenderCount,
  41690. 'sortTime': 0,
  41691. sortedBufferIndex
  41692. /* datas */
  41693. };
  41694. splatEnableSwapOut && (sortedBufferIndex = sortedBufferIndex == 1 ? 0 : 1);
  41695. /* if (!useSharedMemory) {
  41696. const sortedIndexes = new Uint32Array(wasmMemory, sortedIndexesOffset, splatRenderCount);
  41697. if (!sortedIndexesOut || sortedIndexesOut.length < splatRenderCount) {
  41698. sortedIndexesOut = new Uint32Array(splatRenderCount);
  41699. }
  41700. sortedIndexesOut.set(sortedIndexes);
  41701. sortMessage.sortedIndexes = sortedIndexesOut;
  41702. } */
  41703. var sortEndTime = performance.now();
  41704. sortMessage.sortTime = sortEndTime - sortStartTime;
  41705. self.postMessage(sortMessage);
  41706. }
  41707. self.onmessage = e => {
  41708. if (e.data.sort) {
  41709. //请求sort
  41710. var renderCount = e.data.sort.splatRenderCount || 0;
  41711. var sortCount = e.data.sort.splatSortCount || 0;
  41712. var usePrecomputedDistances = e.data.sort.usePrecomputedDistances;
  41713. var copyIndexesToSort;
  41714. var copyPrecomputedDistances;
  41715. var copyTransforms;
  41716. if (!useSharedMemory) {
  41717. //copyIndexesToSort = e.data.sort.indexesToSort;
  41718. copyTransforms = e.data.sort.transforms;
  41719. if (usePrecomputedDistances) copyPrecomputedDistances = e.data.sort.precomputedDistances;
  41720. }
  41721. sort(sortCount, renderCount, e.data.sort.modelViewProj, usePrecomputedDistances, copyPrecomputedDistances, copyTransforms);
  41722. } else if (e.data.init) {
  41723. //初始化 分配空间
  41724. // Yep, this is super hacky and gross :(
  41725. Constants = e.data.init.Constants;
  41726. splatCount = e.data.init.splatCount;
  41727. useSharedMemory = e.data.init.useSharedMemory;
  41728. integerBasedSort = e.data.init.integerBasedSort;
  41729. dynamicMode = e.data.init.dynamicMode;
  41730. splatEnableSwapOut = e.data.init.splatEnableSwapOut;
  41731. var CENTERS_BYTES_PER_ENTRY = integerBasedSort ? Constants.BytesPerInt * 4 : Constants.BytesPerFloat * 4;
  41732. var sorterWasmBytes = new Uint8Array(e.data.init.sorterWasmBytes);
  41733. var matrixSize = 16 * Constants.BytesPerFloat;
  41734. var memoryRequiredForIndexesToSort = splatCount * Constants.BytesPerInt;
  41735. var memoryRequiredForCenters = splatCount * CENTERS_BYTES_PER_ENTRY;
  41736. var memoryRequiredForCentersOut = splatCount * Constants.BytesPerFloat * 3;
  41737. //add:------
  41738. var memoryRequiredForColors = splatCount * 1 * 4; //4 byte
  41739. var memoryRequiredForCovsHalf = splatCount * Constants.BytesPerFloat * 3;
  41740. var memoryRequiredForModelViewProjectionMatrix = matrixSize;
  41741. var memoryRequiredForPrecomputedDistances = integerBasedSort ? splatCount * Constants.BytesPerInt : splatCount * Constants.BytesPerFloat;
  41742. var memoryRequiredForMappedDistances = splatCount * Constants.BytesPerInt;
  41743. //const memoryRequiredForSortedIndexes = splatCount * Constants.BytesPerInt;
  41744. var memoryRequiredForIntermediateSortBuffers = Constants.DepthMapRange * Constants.BytesPerInt * 2;
  41745. var memoryRequiredforTransformIndexes = dynamicMode ? splatCount * Constants.BytesPerInt : 0;
  41746. var memoryRequiredforTransforms = dynamicMode ? Constants.MaxScenes * matrixSize : 0;
  41747. var extraMemory = Constants.MemoryPageSize * 4 /* 32 */;
  41748. var totalRequiredMemory =
  41749. //memoryRequiredForIndexesToSort +
  41750. memoryRequiredForCenters * (integerBasedSort ? 2 : 1) +
  41751. //change !!
  41752. memoryRequiredForCentersOut * 1 + memoryRequiredForColors * 2 +
  41753. //add !!
  41754. memoryRequiredForCovsHalf * 4 +
  41755. //add !!
  41756. memoryRequiredForModelViewProjectionMatrix +
  41757. // memoryRequiredForPrecomputedDistances +
  41758. memoryRequiredForMappedDistances + memoryRequiredForIntermediateSortBuffers +
  41759. //memoryRequiredForSortedIndexes +
  41760. memoryRequiredforTransformIndexes + memoryRequiredforTransforms + extraMemory;
  41761. //输出要双buffer
  41762. if (splatEnableSwapOut) {
  41763. memoryRequiredOut = memoryRequiredForCentersOut + memoryRequiredForColors + memoryRequiredForCovsHalf * 2;
  41764. totalRequiredMemory += memoryRequiredOut;
  41765. }
  41766. var totalPagesRequired = Math.floor(totalRequiredMemory / Constants.MemoryPageSize) + 1;
  41767. var sorterWasmImport = {
  41768. module: {},
  41769. env: {
  41770. memory: new WebAssembly.Memory({
  41771. initial: totalPagesRequired * e.data.init.initialPagesRatio,
  41772. //2, //创建一个初始大小为 .. 页(每页64KiB)的内存实例
  41773. maximum: totalPagesRequired * 4,
  41774. shared: true
  41775. })
  41776. }
  41777. };
  41778. WebAssembly.compile(sorterWasmBytes).then(wasmModule => {
  41779. return WebAssembly.instantiate(wasmModule, sorterWasmImport);
  41780. }).then(instance => {
  41781. wasmInstance = instance;
  41782. //indexesToSortOffset = 0;
  41783. //centersOffset = indexesToSortOffset + memoryRequiredForIndexesToSort;
  41784. centersFloatOffset = 0;
  41785. if (integerBasedSort) {
  41786. centersIntOffset = centersFloatOffset + memoryRequiredForCenters;
  41787. }
  41788. colorsOffset = (integerBasedSort ? centersIntOffset : centersFloatOffset) + memoryRequiredForCenters;
  41789. covsOffset = colorsOffset + memoryRequiredForColors;
  41790. sortedCentersOffset = covsOffset + memoryRequiredForCovsHalf * 2;
  41791. sortedColorsOffset = sortedCentersOffset + memoryRequiredForCentersOut;
  41792. sortedCovs1Offset = sortedColorsOffset + memoryRequiredForColors;
  41793. sortedCovs2Offset = sortedCovs1Offset + memoryRequiredForCovsHalf;
  41794. modelViewProjOffset = sortedCovs2Offset + memoryRequiredForCovsHalf;
  41795. if (splatEnableSwapOut) {
  41796. modelViewProjOffset += memoryRequiredOut;
  41797. }
  41798. /*
  41799. sortedCentersOffset = (integerBasedSort ? centersIntOffset : centersFloatOffset) + memoryRequiredForCenters
  41800. colorsOffset = sortedCentersOffset + memoryRequiredForCentersOut
  41801. sortedColorsOffset = colorsOffset + memoryRequiredForColors
  41802. covsOffset = sortedColorsOffset + memoryRequiredForColors
  41803. sortedCovs1Offset = covsOffset + memoryRequiredForCovsHalf * 2
  41804. sortedCovs2Offset = sortedCovs1Offset + memoryRequiredForCovsHalf
  41805. modelViewProjOffset = sortedCovs2Offset + memoryRequiredForCovsHalf; */
  41806. mappedDistancesOffset = modelViewProjOffset + memoryRequiredForModelViewProjectionMatrix;
  41807. /* precomputedDistancesOffset = modelViewProjOffset + memoryRequiredForModelViewProjectionMatrix;
  41808. mappedDistancesOffset = precomputedDistancesOffset + memoryRequiredForPrecomputedDistances; */
  41809. frequenciesOffset = mappedDistancesOffset + memoryRequiredForMappedDistances;
  41810. //sortedIndexesOffset = frequenciesOffset + memoryRequiredForIntermediateSortBuffers;
  41811. transformIndexesOffset = frequenciesOffset + memoryRequiredForIntermediateSortBuffers;
  41812. transformsOffset = transformIndexesOffset + memoryRequiredforTransformIndexes;
  41813. wasmMemory = sorterWasmImport.env.memory.buffer; //SharedArrayBuffer
  41814. if (useSharedMemory) {
  41815. self.postMessage({
  41816. 'sortSetupPhase1Complete': true,
  41817. '//indexesToSortBuffer': wasmMemory,
  41818. 'sortedIndexesOffset': sortedIndexesOffset,
  41819. //'precomputedDistancesBuffer': wasmMemory,
  41820. 'precomputedDistancesOffset': precomputedDistancesOffset,
  41821. //'transformsBuffer': wasmMemory,
  41822. 'transformsOffset': transformsOffset,
  41823. centersFloatOffset,
  41824. centersIntOffset,
  41825. sortedCentersOffset,
  41826. colorsOffset,
  41827. sortedColorsOffset,
  41828. covsOffset,
  41829. sortedCovs1Offset,
  41830. sortedCovs2Offset,
  41831. memoryRequiredOut,
  41832. wasmMemory
  41833. });
  41834. } else {
  41835. self.postMessage({
  41836. 'sortSetupPhase1Complete': true
  41837. });
  41838. }
  41839. });
  41840. } else if (e.data.dataInited) {
  41841. dataInited = true;
  41842. }
  41843. };
  41844. }
  41845. function createSortWorker(splatCount, integerBasedSort, dynamicMode) {
  41846. var useSharedMemory = true;
  41847. var worker = new Worker(URL.createObjectURL(new Blob(['(', sortWorker.toString(), ')(self)'], {
  41848. type: 'application/javascript'
  41849. })));
  41850. var sorterWasmBinaryString = atob(SorterWasm); //二进制代码
  41851. var sorterWasmBytes = new Uint8Array(sorterWasmBinaryString.length);
  41852. for (var i = 0; i < sorterWasmBinaryString.length; i++) {
  41853. sorterWasmBytes[i] = sorterWasmBinaryString.charCodeAt(i);
  41854. }
  41855. worker.postMessage({
  41856. 'init': {
  41857. 'sorterWasmBytes': sorterWasmBytes.buffer,
  41858. 'splatCount': splatCount,
  41859. 'useSharedMemory': useSharedMemory,
  41860. 'integerBasedSort': integerBasedSort,
  41861. 'dynamicMode': dynamicMode,
  41862. splatEnableSwapOut: Potree.config.splatEnableSwapOut,
  41863. initialPagesRatio: Potree.browser.isMobile ? 1 : 1.3,
  41864. // Super hacky
  41865. 'Constants': {
  41866. 'BytesPerFloat': Potree.defines.gs3d.BytesPerFloat,
  41867. 'BytesPerInt': Potree.defines.gs3d.BytesPerInt,
  41868. 'DepthMapRange': Potree.defines.gs3d.DepthMapRange,
  41869. 'MemoryPageSize': Potree.defines.gs3d.MemoryPageSize,
  41870. 'MaxScenes': Potree.defines.gs3d.MaxScenes
  41871. }
  41872. }
  41873. });
  41874. return worker;
  41875. }
  41876. /*
  41877. 相关函数见 setupSortWorker updateSplatSort updateRenderIndexes addSplatBuffers
  41878. 不share buffer 的话似乎不可行
  41879. */
  41880. //从 GaussianSplats3D 里摘过来,用于显示webcloud型的lod 3dgs
  41881. var sortCount = 0;
  41882. var dummyGeometry = new BufferGeometry();
  41883. var dummyMaterial = new MeshBasicMaterial();
  41884. //只允许存在至多一个Splat
  41885. class Splat extends Mesh {
  41886. constructor() {
  41887. super(dummyGeometry, dummyMaterial);
  41888. _defineProperty(this, "gatherSceneNodesForSort", function () {
  41889. //将要渲染的点的index写入sortWorkerIndexesToSort的buffer
  41890. return function () {
  41891. var gatherAllNodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  41892. var time0 = performance.now();
  41893. var CenterType = this.integerBasedSort ? Int32Array : Float32Array;
  41894. var CENTERS_BYTES_PER_ENTRY = this.integerBasedSort ? Potree.defines.gs3d.BytesPerInt * 4 : Potree.defines.gs3d.BytesPerFloat * 4;
  41895. var COLORS_BYTES_PER_ENTRY = 1 * 4; //4 byte
  41896. var COVS_BYTES_PER_ENTRY = Potree.defines.gs3d.BytesPerFloat * 6;
  41897. var currentByteOffset = {
  41898. centers: 0,
  41899. centersInt: 0,
  41900. colors: 0,
  41901. covs: 0
  41902. };
  41903. var {
  41904. centersFloat,
  41905. centersInt,
  41906. colors,
  41907. covs
  41908. } = this.sortWorkerDatas.toSort;
  41909. var buffer = centersFloat.buffer; //大伙buffer都是同一个
  41910. this.currentNodes = Potree.visibleNodes.slice();
  41911. var i = 0,
  41912. nodeCount = Potree.visibleNodes.length,
  41913. splatCount = 0;
  41914. while (splatCount < Potree.config.maxSplatCount && i < nodeCount) {
  41915. var numPoints = Potree.visibleNodes[i].geometryNode.numPoints;
  41916. if (numPoints + splatCount > Potree.config.maxSplatCount) break;
  41917. splatCount += numPoints;
  41918. var c0 = numPoints * 3,
  41919. c1 = numPoints * 4,
  41920. c2 = numPoints * 6;
  41921. var geo = Potree.visibleNodes[i].geometryNode.geometry;
  41922. var destView = new Float32Array(buffer, centersFloat.byteOffset + currentByteOffset.centers, c1); //暂时也4位
  41923. destView.set(geo.attributes.centersFloat.array);
  41924. if (this.integerBasedSort) {
  41925. destView = new Int32Array(buffer, centersInt.byteOffset + currentByteOffset.centersInt, c1);
  41926. destView.set(geo.attributes.centersInt.array);
  41927. }
  41928. destView = new Uint8Array(buffer, colors.byteOffset + currentByteOffset.colors, c1);
  41929. destView.set(geo.attributes.rgba.array);
  41930. destView = new Float32Array(buffer, covs.byteOffset + currentByteOffset.covs, c2);
  41931. destView.set(geo.attributes.covs.array);
  41932. currentByteOffset.centersInt += numPoints * CENTERS_BYTES_PER_ENTRY;
  41933. currentByteOffset.centers += numPoints * CENTERS_BYTES_PER_ENTRY;
  41934. currentByteOffset.colors += numPoints * COLORS_BYTES_PER_ENTRY;
  41935. currentByteOffset.covs += numPoints * COVS_BYTES_PER_ENTRY;
  41936. i++;
  41937. }
  41938. this.sortWorker.postMessage({
  41939. 'dataInited': true
  41940. });
  41941. return {
  41942. 'splatRenderCount': splatCount
  41943. };
  41944. };
  41945. }());
  41946. _defineProperty(this, "updateSort", function () {
  41947. var mvpMatrix = new Matrix4();
  41948. var cameraPositionArray = [];
  41949. var lastSortViewDir = new Vector3(0, 0, -1);
  41950. var sortViewDir = new Vector3(0, 0, -1);
  41951. var lastSortViewPos = new Vector3();
  41952. var sortViewOffset = new Vector3();
  41953. var queuedSorts = [];
  41954. var partialSorts = [{
  41955. 'angleThreshold': 0.55,
  41956. 'sortFractions': [0.125, 0.33333, 0.75]
  41957. }, {
  41958. 'angleThreshold': 0.65,
  41959. 'sortFractions': [0.33333, 0.66667]
  41960. }, {
  41961. 'angleThreshold': 0.8,
  41962. 'sortFractions': [0.5]
  41963. }];
  41964. return async function () {
  41965. var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  41966. // Potree.visibleNodes || console.log('updateSort')
  41967. // this.sortWorkerDatas || console.log('updateSort')
  41968. if (this.sortRunning || this.unableSort || !this.sortWorkerDatas || !Potree.visibleNodes || !this.visible) return;
  41969. var camera = viewer.mainViewport.camera;
  41970. var angleDiff = 0;
  41971. var positionDiff = 0;
  41972. var needsRefreshForRotation = false;
  41973. var needsRefreshForPosition = false;
  41974. if (Potree.math.closeTo(Potree.visibleNodes.length, this.currentNodes.length, 10)) {
  41975. sortViewDir.set(0, 0, -1).applyQuaternion(camera.quaternion);
  41976. angleDiff = sortViewDir.dot(lastSortViewDir);
  41977. positionDiff = sortViewOffset.copy(camera.position).sub(lastSortViewPos).length();
  41978. if (!force) {
  41979. if (!this.sortNeededForSceneChange && !this.dynamicMode && queuedSorts.length === 0) {
  41980. if (angleDiff <= 0.99) needsRefreshForRotation = true;
  41981. if (positionDiff >= 1.0) needsRefreshForPosition = true;
  41982. if (!needsRefreshForRotation && !needsRefreshForPosition) return;
  41983. }
  41984. }
  41985. }
  41986. this.sortRunning = true;
  41987. var {
  41988. splatRenderCount
  41989. } = this.gatherSceneNodesForSort();
  41990. this.splatRenderCount = splatRenderCount;
  41991. mvpMatrix.copy(camera.matrixWorld).invert();
  41992. mvpMatrix.premultiply(camera.projectionMatrix);
  41993. mvpMatrix.multiply(this.matrixWorld);
  41994. /* if (this.gpuAcceleratedSort && (queuedSorts.length <= 1 || queuedSorts.length % 2 === 0)) {
  41995. await this.splatMesh.computeDistancesOnGPU(mvpMatrix, this.sortWorkerPrecomputedDistances);
  41996. } */
  41997. if (this.dynamicMode) {
  41998. queuedSorts.push(this.splatRenderCount);
  41999. } else {
  42000. if (queuedSorts.length === 0) {
  42001. for (var partialSort of partialSorts) {
  42002. if (angleDiff < partialSort.angleThreshold) {
  42003. for (var sortFraction of partialSort.sortFractions) {
  42004. queuedSorts.push(Math.floor(this.splatRenderCount * sortFraction));
  42005. }
  42006. break;
  42007. }
  42008. }
  42009. queuedSorts.push(this.splatRenderCount);
  42010. }
  42011. }
  42012. if (queuedSorts.length > 1) {
  42013. console.log(queuedSorts);
  42014. queuedSorts.length = 0;
  42015. }
  42016. //let sortCount = Math.min(queuedSorts.shift(), this.splatRenderCount);
  42017. //console.log('updateSort')
  42018. var sortCount = this.splatRenderCount;
  42019. cameraPositionArray[0] = camera.position.x;
  42020. cameraPositionArray[1] = camera.position.y;
  42021. cameraPositionArray[2] = camera.position.z;
  42022. var sortMessage = {
  42023. 'modelViewProj': mvpMatrix.elements,
  42024. 'cameraPosition': cameraPositionArray,
  42025. 'splatRenderCount': this.splatRenderCount,
  42026. 'splatSortCount': sortCount,
  42027. 'usePrecomputedDistances': this.gpuAcceleratedSort //也就是不用worker算而用gpu,见 computeDistancesOnGPU
  42028. };
  42029. /* if (this.splatMesh.dynamicMode) {
  42030. this.splatMesh.fillTransformsArray(this.sortWorkerTransforms);
  42031. }
  42032. if (!this.sharedMemoryForWorkers) {
  42033. //sortMessage.indexesToSort = this.sortWorkerIndexesToSort;
  42034. sortMessage.transforms = this.sortWorkerTransforms;
  42035. if (this.gpuAcceleratedSort) {
  42036. sortMessage.precomputedDistances = this.sortWorkerPrecomputedDistances;
  42037. }
  42038. }*/
  42039. this.sortPromise = new Promise(resolve => {
  42040. this.sortPromiseResolver = resolve;
  42041. });
  42042. this.sortWorker.postMessage({
  42043. 'sort': sortMessage
  42044. });
  42045. //if (queuedSorts.length === 0) {
  42046. lastSortViewPos.copy(camera.position);
  42047. lastSortViewDir.copy(sortViewDir);
  42048. //}
  42049. this.sortNeededForSceneChange = false;
  42050. };
  42051. }());
  42052. this.geometry = this.buildGeometry();
  42053. this.material = this.buildMaterial();
  42054. this.frustumCulled = false; //禁止视锥体剔除
  42055. this.focalAdjustment = 1;
  42056. this.integerBasedSort = true;
  42057. this.currentNodes = [];
  42058. Potree.Utils.setObjectLayers(this, 'model');
  42059. this.pointclouds = [];
  42060. var maxSplatCount = Potree.config.maxSplatCount;
  42061. var PosArrayType = this.integerBasedSort ? Int32Array : Float32Array;
  42062. this.sortWorker = createSortWorker(maxSplatCount, true, false);
  42063. this.sortWorker.onmessage = e => {
  42064. if (e.data.sortDone) {
  42065. this.sortRunning = false;
  42066. var {
  42067. centers,
  42068. colors,
  42069. covs1,
  42070. covs2
  42071. } = this.sortWorkerDatas.sorted[e.data.sortedBufferIndex];
  42072. this.updateRenderIndexes(centers, colors, covs1, covs2, e.data.splatRenderCount);
  42073. this.lastSortTime = e.data.sortTime;
  42074. this.sortPromiseResolver();
  42075. this.sortPromiseResolver = null;
  42076. viewer.dispatchEvent('content_changed'); //this.forceRenderNextFrame();
  42077. /* if (sortCount === 0) {
  42078. this.runAfterFirstSort.forEach((func) => {
  42079. func();
  42080. });
  42081. this.runAfterFirstSort.length = 0;
  42082. } */
  42083. sortCount++;
  42084. } else if (e.data.sortCanceled) {
  42085. this.sortRunning = false;
  42086. } else if (e.data.sortSetupPhase1Complete) {
  42087. //sortWorker init 完毕
  42088. console.log('Sorting web worker WASM setup complete.');
  42089. var CENTERS_BYTES_PER_ENTRY = this.integerBasedSort ? Potree.defines.gs3d.BytesPerInt * 4 : Potree.defines.gs3d.BytesPerFloat * 4;
  42090. this.sortWorkerDatas = {
  42091. sorted: [{
  42092. centers: new Float32Array(e.data.wasmMemory, e.data.sortedCentersOffset, maxSplatCount * 3),
  42093. colors: new Uint8Array(e.data.wasmMemory, e.data.sortedColorsOffset, maxSplatCount * 4),
  42094. covs1: new Float32Array(e.data.wasmMemory, e.data.sortedCovs1Offset, maxSplatCount * 3),
  42095. covs2: new Float32Array(e.data.wasmMemory, e.data.sortedCovs2Offset, maxSplatCount * 3)
  42096. }],
  42097. toSort: {
  42098. centersFloat: new Float32Array(e.data.wasmMemory, e.data.centersFloatOffset, maxSplatCount * 4),
  42099. colors: new Uint8Array(e.data.wasmMemory, e.data.colorsOffset, maxSplatCount * 4),
  42100. //所有类型参数均为:buffer, byteOffset, length, 第三个参数是item个数,而非字节数
  42101. covs: new Float32Array(e.data.wasmMemory, e.data.covsOffset, maxSplatCount * 6)
  42102. }
  42103. };
  42104. if (this.integerBasedSort) {
  42105. this.sortWorkerDatas.toSort.centersInt = new Int32Array(e.data.wasmMemory, e.data.centersIntOffset, maxSplatCount * 4);
  42106. }
  42107. if (Potree.config.splatEnableSwapOut) {
  42108. this.sortWorkerDatas.sorted.push({
  42109. centers: new Float32Array(e.data.wasmMemory, e.data.sortedCentersOffset + e.data.memoryRequiredOut, maxSplatCount * 3),
  42110. colors: new Uint8Array(e.data.wasmMemory, e.data.sortedColorsOffset + e.data.memoryRequiredOut, maxSplatCount * 4),
  42111. covs1: new Float32Array(e.data.wasmMemory, e.data.sortedCovs1Offset + e.data.memoryRequiredOut, maxSplatCount * 3),
  42112. covs2: new Float32Array(e.data.wasmMemory, e.data.sortedCovs2Offset + e.data.memoryRequiredOut, maxSplatCount * 3)
  42113. });
  42114. }
  42115. //if gpuAcceleratedSort and dont shareMemory
  42116. //this.sortWorkerPrecomputedDistances = new PosArrayType(e.data.wasmMemory, e.data.precomputedDistancesOffset, maxSplatCount);
  42117. //this.sortWorkerTransforms = new Float32Array(e.data.wasmMemory, e.data.transformsOffset, Potree.defines.gs3d.MaxScenes * 16);
  42118. //this.sortWorker.maxSplatCount = maxSplatCount;//总点数
  42119. console.log('Sorting web worker ready.');
  42120. this.updateSort();
  42121. }
  42122. };
  42123. viewer.addEventListener('camera_changed', e => {
  42124. var camera = e.viewport.camera;
  42125. var pos = camera.position;
  42126. if (e.viewport.name == 'MainView') {
  42127. this.updateSort();
  42128. if (e.changeInfo.projectionChanged) {
  42129. this.updateMaterial();
  42130. }
  42131. }
  42132. });
  42133. viewer.addEventListener('pointcloud_changed', e => {
  42134. this.updateSort();
  42135. });
  42136. this.updateMaterial();
  42137. }
  42138. addPointcloud(pointcloud) {
  42139. //添加点云,数据先借助点云加载,再转过来
  42140. var index = this.pointclouds.indexOf(pointcloud);
  42141. index == -1 && this.pointclouds.push(pointcloud);
  42142. pointcloud.isSplat = true;
  42143. pointcloud.matrixAutoUpdate = true;
  42144. //this.update()
  42145. }
  42146. transformCallBack() {
  42147. //其点云要和这一模一样
  42148. this.pointclouds.forEach(e => {
  42149. e.position.copy(this.position);
  42150. e.rotation.copy(this.rotation);
  42151. });
  42152. }
  42153. removePointcloud(pointcloud) {
  42154. //删除
  42155. var index = this.pointclouds.indexOf(pointcloud);
  42156. index > -1 && this.pointclouds.splice(index, 1);
  42157. //this.update()
  42158. pointcloud.isSplat = false;
  42159. }
  42160. buildGeometry() {
  42161. var baseGeometry = new BufferGeometry();
  42162. baseGeometry.setIndex([0, 1, 2, 0, 2, 3]);
  42163. // Vertices for the instanced quad
  42164. var positionsArray = new Float32Array(4 * 3);
  42165. var positions = new BufferAttribute(positionsArray, 3);
  42166. baseGeometry.setAttribute('position', positions);
  42167. positions.setXYZ(0, -1.0, -1.0, 0.0);
  42168. positions.setXYZ(1, -1.0, 1.0, 0.0);
  42169. positions.setXYZ(2, 1.0, 1.0, 0.0);
  42170. positions.setXYZ(3, 1.0, -1.0, 0.0);
  42171. positions.needsUpdate = true;
  42172. var geometry = new InstancedBufferGeometry().copy(baseGeometry);
  42173. /*
  42174. //给点加序号
  42175. const splatIndexArray = new Uint32Array(Potree.config.maxSplatCount);
  42176. const splatIndexes = new THREE.InstancedBufferAttribute(splatIndexArray, 1, false);
  42177. splatIndexes.setUsage(THREE.DynamicDrawUsage);
  42178. geometry.setAttribute('splatIndex', splatIndexes);
  42179. for(let i=0;i<Potree.config.maxSplatCount;i++){
  42180. splatIndexArray[i] = i;
  42181. } */
  42182. var posArray = new Float32Array(Potree.config.maxSplatCount * 3);
  42183. var centers = new InstancedBufferAttribute(posArray, 3, false);
  42184. centers.setUsage(DynamicDrawUsage);
  42185. geometry.setAttribute('center', centers);
  42186. var colorArray = new Uint8Array(Potree.config.maxSplatCount * 4);
  42187. var colors = new InstancedBufferAttribute(colorArray, 4, true); //第三个参数是normalized, 开启后 WebGL 会在内部将每个颜色分量从 [0, 255] 转换到 [0.0, 1.0] 范围
  42188. colors.setUsage(DynamicDrawUsage);
  42189. geometry.setAttribute('color', colors);
  42190. var covArray1 = new Float32Array(Potree.config.maxSplatCount * 3);
  42191. var covs1 = new InstancedBufferAttribute(covArray1, 3, false);
  42192. covs1.setUsage(DynamicDrawUsage);
  42193. geometry.setAttribute('covRow1', covs1);
  42194. var covArray2 = new Float32Array(Potree.config.maxSplatCount * 3);
  42195. var covs2 = new InstancedBufferAttribute(covArray2, 3, false);
  42196. covs2.setUsage(DynamicDrawUsage);
  42197. geometry.setAttribute('covRow2', covs2);
  42198. geometry.instanceCount = 0;
  42199. this.attrOrigin = {
  42200. center: posArray,
  42201. color: colorArray,
  42202. covRow1: covArray1,
  42203. covRow2: covArray2
  42204. };
  42205. return geometry;
  42206. }
  42207. buildMaterial() {
  42208. var maxScreenSpaceSplatSize = 2048; // 这啥
  42209. var vs = "\n precision highp float;\n #include <common>\n \n attribute vec3 center;\n attribute vec4 color;\n attribute vec3 covRow1;\n attribute vec3 covRow2;\n \n //attribute uint splatIndex; \n //uniform int splatCount; \n \n uniform vec2 focal;\n uniform float orthoZoom;\n uniform int orthographicMode;\n uniform int pointCloudModeEnabled;\n uniform float inverseFocalAdjustment;\n uniform vec2 viewport;\n //uniform vec2 basisViewport; = 1/viewport\n \n \n \n uniform float splatScale;\n \n varying vec4 vColor;\n varying vec2 vUv;\n\n varying vec2 vPosition;\n \n const float sqrt8 = sqrt(8.0);\n const float minAlpha = 1.0 / 255.0;\n \n void main () {\n\n mat4 transformModelViewMatrix = modelViewMatrix; \n \n vec4 viewCenter = transformModelViewMatrix * vec4(center, 1.0);\n\n vec4 clipCenter = projectionMatrix * viewCenter;\n\n float clip = 1.2 * clipCenter.w;\n if (clipCenter.z < -clip || clipCenter.x < -clip || clipCenter.x > clip || clipCenter.y < -clip || clipCenter.y > clip) {\n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n return;\n }\n\n vPosition = position.xy;\n vColor = color;\n \n //debug \u6D4B\u8BD5sort\u662F\u5426\u6B63\u786E. \u7531\u8FDC\u53CA\u8FD1\u7531\u9ED1\u53D8\u767D\n //float r = float(splatIndex) / float(splatCount) ;\n //vColor = vec4(r,r,r,1.0); \n\n mat3 Vrk = mat3( // Construct the 3D covariance matrix\n covRow1.x, covRow1.y, covRow1.z,\n covRow1.y, covRow2.x, covRow2.y,\n covRow1.z, covRow2.y, covRow2.z\n );\n \n //\u7FFB\u8BD1\u7ED3\u679C\uFF1A\u6784\u5EFA\u6295\u5F71\u77E9\u9635\u4EFF\u5C04\u8FD1\u4F3C\u7684\u96C5\u53EF\u6BD4\u77E9\u9635\u3002\u5B83\u5C06\u88AB\u7528\u6765\u53D8\u63623D\u534F\u65B9\u5DEE\u77E9\u9635\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5\u4F7F\u7528\u5B9E\u9645\u7684\u6295\u5F71\u77E9\u9635\uFF0C\u56E0\u4E3A\u4F7F\u7528\u5B9E\u9645\u6295\u5F71\u77E9\u9635\u8FDB\u884C\u53D8\u6362\u9700\u8981\u5305\u542B\u975E\u7EBF\u6027\u6210\u5206\uFF08\u900F\u89C6\u9664\u6CD5\uFF09\uFF0C\u8FD9\u4F1A\u5BFC\u81F4\u975E\u9AD8\u65AF\u7684\u7ED3\u679C\u3002\u8FD9\u91CC\u5047\u8BBE\u5F53\u524D\u7684\u6295\u5F71\u4E3A\u900F\u89C6\u6295\u5F71\u3002\n \n mat3 J;\n if (orthographicMode == 1) {\n J = transpose(mat3(orthoZoom, 0.0, 0.0,\n 0.0, orthoZoom, 0.0,\n 0.0, 0.0, 0.0));\n } else {\n float s = 1.0 / (viewCenter.z * viewCenter.z);\n J = mat3(\n focal.x / viewCenter.z, 0., -(focal.x * viewCenter.x) * s,\n 0., focal.y / viewCenter.z, -(focal.y * viewCenter.y) * s,\n 0., 0., 0.\n );\n }\n \n // Concatenate the projection approximation with the model-view transformation\n mat3 W = transpose(mat3(transformModelViewMatrix));\n mat3 T = W * J;\n\n // Transform the 3D covariance matrix (Vrk) to compute the 2D covariance matrix\n mat3 cov2Dm = transpose(T) * Vrk * T;\n \n \n cov2Dm[0][0] += 0.3;\n cov2Dm[1][1] += 0.3;\n float compensation = 1.0;\n \n \n \n vColor.a *= compensation;\n\n if (vColor.a < minAlpha) return;\n\n // We are interested in the upper-left 2x2 portion of the projected 3D covariance matrix because\n // we only care about the X and Y values. We want the X-diagonal, cov2Dm[0][0],\n // the Y-diagonal, cov2Dm[1][1], and the correlation between the two cov2Dm[0][1]. We don't\n // need cov2Dm[1][0] because it is a symetric matrix.\n vec3 cov2Dv = vec3(cov2Dm[0][0], cov2Dm[0][1], cov2Dm[1][1]);\n\n vec3 ndcCenter = clipCenter.xyz / clipCenter.w;\n\n float a = cov2Dv.x;\n float d = cov2Dv.z;\n float b = cov2Dv.y;\n float D = a * d - b * b;\n float trace = a + d; //\u8FFD\u8E2A\n float traceOver2 = 0.5 * trace;\n float term2 = sqrt(max(0.1f, traceOver2 * traceOver2 - D));\n float eigenValue1 = traceOver2 + term2; //\u7279\u5F81\u503CL1\n float eigenValue2 = traceOver2 - term2; //\u7279\u5F81\u503CL1\n\n if (pointCloudModeEnabled == 1) {// each splat is rendered as a filled circle\n eigenValue1 = eigenValue2 = 0.2;\n }\n\n if (eigenValue2 <= 0.0) return;\n\n vec2 eigenVector1 = normalize(vec2(b, eigenValue1 - a));\n // since the eigen vectors are orthogonal, we derive the second one from the first \u7531\u4E8E\u672C\u5F81\u5411\u91CF\u662F\u6B63\u4EA4\u7684\uFF0C\u56E0\u6B64\u6211\u4EEC\u4ECE\u7B2C\u4E00\u4E2A\u5BFC\u51FA\u7B2C\u4E8C\u4E2A\n vec2 eigenVector2 = vec2(eigenVector1.y, -eigenVector1.x);\n\n // We use sqrt(8) standard deviations\u504F\u5DEE instead of 3 to eliminate\u6D88\u9664 more of the splat with a very low opacity.\n vec2 basisVector1 = eigenVector1 * splatScale * min(sqrt8 * sqrt(eigenValue1), ".concat(parseInt(maxScreenSpaceSplatSize), ".0);\n vec2 basisVector2 = eigenVector2 * splatScale * min(sqrt8 * sqrt(eigenValue2), ").concat(parseInt(maxScreenSpaceSplatSize), ".0);\n\n vec2 ndcOffset = vec2(vPosition.x * basisVector1 + vPosition.y * basisVector2) / viewport * 2.0 * inverseFocalAdjustment;\n\n vec4 quadPos = vec4(ndcCenter.xy + ndcOffset, ndcCenter.z , 1.0);\n gl_Position = quadPos;\n\n // Scale the position data we send to the fragment shader\n vPosition *= sqrt8;\n }\n ");
  42210. var fs = "\n precision highp float;\n #include <common>\n \n uniform vec3 debugColor;\n\n varying vec4 vColor;\n varying vec2 vUv;\n\n varying vec2 vPosition;\n\n void main () {\n \n \n float A = dot(vPosition, vPosition);\n if (A > 8.0) discard; //position\u7684\u8303\u56F4\u534A\u5F84\u4E3A1\u3002\u6307\u4E00\u4E2Arectangle\u9762\u4E2D\u7684\u8303\u56F4\u3002\u692D\u5706\u5916\u7684\u5B8C\u5168\u900F\u660E\n vec3 color = vColor.rgb;\n\n float opacity = exp(-0.5 * A) * vColor.a; //\u5468\u56F4\u7684\u900F\u660E\u5EA6\u964D\u4F4E \u8FB9\u7F18\u5904\u6700\u9AD8\u900F\u660E\u5EA6\u4E3AMath.pow(Math.E, -4)= 0.0183 \n\n gl_FragColor = vec4(color.rgb, opacity); \n \n \n }\n ";
  42211. var uniforms = {
  42212. 'orthographicMode': {
  42213. 'type': 'i',
  42214. 'value': 0
  42215. },
  42216. 'focal': {
  42217. 'type': 'v2',
  42218. 'value': new Vector2()
  42219. },
  42220. 'orthoZoom': {
  42221. 'type': 'f',
  42222. 'value': 1.0
  42223. },
  42224. 'inverseFocalAdjustment': {
  42225. 'type': 'f',
  42226. 'value': 1.0
  42227. },
  42228. 'viewport': {
  42229. 'type': 'v2',
  42230. 'value': new Vector2()
  42231. },
  42232. /* 'basisViewport': {
  42233. 'type': 'v2',
  42234. 'value': new THREE.Vector2()
  42235. }, */
  42236. 'splatScale': {
  42237. 'type': 'f',
  42238. 'value': 1
  42239. },
  42240. 'pointCloudModeEnabled': {
  42241. 'type': 'i',
  42242. 'value': 0
  42243. },
  42244. splatCount: {
  42245. type: 'i',
  42246. value: 0
  42247. }
  42248. };
  42249. var material = new ShaderMaterial({
  42250. uniforms: uniforms,
  42251. vertexShader: vs,
  42252. fragmentShader: fs,
  42253. transparent: true,
  42254. alphaTest: 1.0,
  42255. blending: NormalBlending,
  42256. depthTest: false,
  42257. depthWrite: true,
  42258. side: DoubleSide
  42259. });
  42260. return material;
  42261. }
  42262. update() {
  42263. this.updateMesh();
  42264. }
  42265. switchAttrUpdateType(state) {
  42266. this.splatAttrSameMemory = state;
  42267. if (state == 1) {
  42268. this.geometry.attributes.center.array = this.attrOrigin.center;
  42269. this.geometry.attributes.color.array = this.attrOrigin.color;
  42270. this.geometry.attributes.covRow1.array = this.attrOrigin.covRow1;
  42271. this.geometry.attributes.covRow2.array = this.attrOrigin.covRow2;
  42272. }
  42273. }
  42274. updateRenderIndexes(globalCenters, globalColors, globalCovs1, globalCovs2, renderSplatCount) {
  42275. var geometry = this.geometry;
  42276. var start = performance.now();
  42277. if (!Potree.config.splatEnableSwapOut || this.splatAttrSameMemory) {
  42278. geometry.attributes.center.set(globalCenters);
  42279. geometry.attributes.center.needsUpdate = true;
  42280. geometry.attributes.color.set(globalColors);
  42281. geometry.attributes.color.needsUpdate = true;
  42282. geometry.attributes.covRow1.set(globalCovs1);
  42283. geometry.attributes.covRow1.needsUpdate = true;
  42284. geometry.attributes.covRow2.set(globalCovs2);
  42285. geometry.attributes.covRow2.needsUpdate = true;
  42286. } else {
  42287. //直接赋值速度快,需要双buffer否则会被擦写导致黑影。Potree.config.splatEnableSwapOut要在sortworker init时就确定
  42288. geometry.attributes.center.array = globalCenters;
  42289. geometry.attributes.center.needsUpdate = true; //不知为啥2025来再看并不会更流畅,可能这里时间减少了但gpu换buffer了需要时间吧? 另外流畅度更多取决于非sort时的,手机换buffer吃不消。
  42290. geometry.attributes.color.array = globalColors;
  42291. geometry.attributes.color.needsUpdate = true;
  42292. geometry.attributes.covRow1.array = globalCovs1;
  42293. geometry.attributes.covRow1.needsUpdate = true;
  42294. geometry.attributes.covRow2.array = globalCovs2;
  42295. geometry.attributes.covRow2.needsUpdate = true;
  42296. }
  42297. if (renderSplatCount > 0) geometry.instanceCount = renderSplatCount;
  42298. //console.log('updateRenderIndexes time:', performance.now() - start)
  42299. //this.material.uniforms.splatCount.value = renderSplatCount
  42300. }
  42301. updateMaterial() {
  42302. var camera = viewer.mainViewport.camera;
  42303. //this.material.uniforms.viewport.value.copy(viewer.mainViewport.resolution2);
  42304. var viewport = viewer.mainViewport.resolution2;
  42305. var focalMultiplier = camera.isOrthographicCamera ? 1.0 / window.devicePixelRatio : 1.0;
  42306. var focalAdjustment = this.focalAdjustment * focalMultiplier;
  42307. var focalLengthX = camera.projectionMatrix.elements[0] * 0.5 * viewport.x;
  42308. var focalLengthY = camera.projectionMatrix.elements[5] * 0.5 * viewport.y;
  42309. var inverseFocalAdjustment = 1.0 / focalAdjustment;
  42310. this.material.uniforms.viewport.value.copy(viewport);
  42311. this.material.uniforms.focal.value.set(focalLengthX * focalAdjustment, focalLengthY * focalAdjustment);
  42312. this.material.uniforms.orthographicMode.value = camera.isOrthographicCamera ? 1 : 0;
  42313. this.material.uniforms.orthoZoom.value = camera.zoom || 1.0;
  42314. this.material.uniforms.inverseFocalAdjustment.value = inverseFocalAdjustment;
  42315. if (this.dynamicMode) {
  42316. for (var i = 0; i < this.scenes.length; i++) {
  42317. this.material.uniforms.transforms.value[i].copy(this.getScene(i).transform);
  42318. }
  42319. }
  42320. this.material.uniformsNeedUpdate = true;
  42321. }
  42322. }
  42323. _defineProperty(Splat, "computeCovariance", function () {
  42324. //通过旋转和缩放计算协方差(决定姿态)得到6个数
  42325. var tempMatrix4 = new Matrix4();
  42326. var scaleMatrix = new Matrix3();
  42327. var rotationMatrix = new Matrix3();
  42328. var covarianceMatrix = new Matrix3();
  42329. var transformedCovariance = new Matrix3();
  42330. var transform3x3 = new Matrix3();
  42331. var transform3x3Transpose = new Matrix3();
  42332. var thf = DataUtils.toHalfFloat.bind(DataUtils);
  42333. return function (scale, rotation, transform, outCovariance) {
  42334. var outOffset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
  42335. var desiredOutputCompressionLevel = arguments.length > 5 ? arguments[5] : undefined;
  42336. tempMatrix4.makeScale(scale.x, scale.y, scale.z);
  42337. scaleMatrix.setFromMatrix4(tempMatrix4);
  42338. tempMatrix4.makeRotationFromQuaternion(rotation);
  42339. rotationMatrix.setFromMatrix4(tempMatrix4);
  42340. covarianceMatrix.copy(rotationMatrix).multiply(scaleMatrix);
  42341. transformedCovariance.copy(covarianceMatrix).transpose().premultiply(covarianceMatrix); //为什么要乘以自己的转置呀?
  42342. if (transform) {
  42343. //场景的整体transform 如果可能移动就不传,在sort时直接乘
  42344. transform3x3.setFromMatrix4(transform);
  42345. transform3x3Transpose.copy(transform3x3).transpose();
  42346. transformedCovariance.multiply(transform3x3Transpose);
  42347. transformedCovariance.premultiply(transform3x3);
  42348. }
  42349. if (desiredOutputCompressionLevel === 1) {
  42350. //压缩
  42351. outCovariance[outOffset] = thf(transformedCovariance.elements[0]);
  42352. outCovariance[outOffset + 1] = thf(transformedCovariance.elements[3]);
  42353. outCovariance[outOffset + 2] = thf(transformedCovariance.elements[6]);
  42354. outCovariance[outOffset + 3] = thf(transformedCovariance.elements[4]);
  42355. outCovariance[outOffset + 4] = thf(transformedCovariance.elements[7]);
  42356. outCovariance[outOffset + 5] = thf(transformedCovariance.elements[8]);
  42357. } else {
  42358. outCovariance[outOffset] = transformedCovariance.elements[0];
  42359. outCovariance[outOffset + 1] = transformedCovariance.elements[3];
  42360. outCovariance[outOffset + 2] = transformedCovariance.elements[6];
  42361. outCovariance[outOffset + 3] = transformedCovariance.elements[4];
  42362. outCovariance[outOffset + 4] = transformedCovariance.elements[7];
  42363. outCovariance[outOffset + 5] = transformedCovariance.elements[8];
  42364. }
  42365. /*
  42366. Vrk 中的元素分别是transformedCovariance的 [
  42367. 0,3,6,
  42368. 3,4,7,
  42369. 6,7,8
  42370. ]
  42371. */
  42372. };
  42373. }());
  42374. class WorkerPool {
  42375. constructor() {
  42376. this.workers = {};
  42377. }
  42378. getWorker(url) {
  42379. if (!this.workers[url]) {
  42380. this.workers[url] = [];
  42381. }
  42382. if (this.workers[url].length === 0) {
  42383. var _worker = new Worker(url);
  42384. this.workers[url].push(_worker);
  42385. }
  42386. var worker = this.workers[url].pop();
  42387. return worker;
  42388. }
  42389. returnWorker(url, worker) {
  42390. this.workers[url].push(worker);
  42391. }
  42392. }
  42393. ;
  42394. function createPointcloudData(pointcloud) {
  42395. var material = pointcloud.material;
  42396. var ranges = [];
  42397. for (var [name, value] of material.ranges) {
  42398. ranges.push({
  42399. name: name,
  42400. value: value
  42401. });
  42402. }
  42403. if (typeof material.elevationRange[0] === "number") {
  42404. ranges.push({
  42405. name: "elevationRange",
  42406. value: material.elevationRange
  42407. });
  42408. }
  42409. if (typeof material.intensityRange[0] === "number") {
  42410. ranges.push({
  42411. name: "intensityRange",
  42412. value: material.intensityRange
  42413. });
  42414. }
  42415. var pointSizeTypeName = Object.entries(Potree.PointSizeType).find(e => e[1] === material.pointSizeType)[0];
  42416. var jsonMaterial = {
  42417. activeAttributeName: material.activeAttributeName,
  42418. ranges: ranges,
  42419. size: material.size,
  42420. minSize: material.minSize,
  42421. pointSizeType: pointSizeTypeName,
  42422. matcap: material.matcap
  42423. };
  42424. var pcdata = {
  42425. name: pointcloud.name,
  42426. url: pointcloud.pcoGeometry.url,
  42427. position: pointcloud.position.toArray(),
  42428. rotation: pointcloud.rotation.toArray(),
  42429. scale: pointcloud.scale.toArray(),
  42430. material: jsonMaterial
  42431. };
  42432. return pcdata;
  42433. }
  42434. function createProfileData(profile) {
  42435. var data = {
  42436. uuid: profile.uuid,
  42437. name: profile.name,
  42438. points: profile.points.map(p => p.toArray()),
  42439. height: profile.height,
  42440. width: profile.width
  42441. };
  42442. return data;
  42443. }
  42444. function createVolumeData(volume) {
  42445. var data = {
  42446. uuid: volume.uuid,
  42447. type: volume.constructor.name,
  42448. name: volume.name,
  42449. position: volume.position.toArray(),
  42450. rotation: volume.rotation.toArray(),
  42451. scale: volume.scale.toArray(),
  42452. visible: volume.visible,
  42453. clip: volume.clip
  42454. };
  42455. return data;
  42456. }
  42457. function createCameraAnimationData(animation) {
  42458. var controlPoints = animation.controlPoints.map(cp => {
  42459. var cpdata = {
  42460. position: cp.position.toArray(),
  42461. target: cp.target.toArray()
  42462. };
  42463. return cpdata;
  42464. });
  42465. var data = {
  42466. uuid: animation.uuid,
  42467. name: animation.name,
  42468. duration: animation.duration,
  42469. t: animation.t,
  42470. curveType: animation.curveType,
  42471. visible: animation.visible,
  42472. controlPoints: controlPoints
  42473. };
  42474. return data;
  42475. }
  42476. function createMeasurementData(measurement) {
  42477. var data = {
  42478. uuid: measurement.uuid,
  42479. name: measurement.name,
  42480. points: measurement.points.map(p => p.position.toArray()),
  42481. showDistances: measurement.showDistances,
  42482. showCoordinates: measurement.showCoordinates,
  42483. showArea: measurement.showArea,
  42484. closed: measurement.closed,
  42485. showAngles: measurement.showAngles,
  42486. showHeight: measurement.showHeight,
  42487. showCircle: measurement.showCircle,
  42488. showAzimuth: measurement.showAzimuth,
  42489. showEdges: measurement.showEdges,
  42490. color: measurement.color.toArray()
  42491. };
  42492. return data;
  42493. }
  42494. function createOrientedImagesData(images) {
  42495. var data = {
  42496. cameraParamsPath: images.cameraParamsPath,
  42497. imageParamsPath: images.imageParamsPath
  42498. };
  42499. return data;
  42500. }
  42501. function createGeopackageData(geopackage) {
  42502. var data = {
  42503. path: geopackage.path
  42504. };
  42505. return data;
  42506. }
  42507. function createAnnotationData(annotation) {
  42508. var data = {
  42509. uuid: annotation.uuid,
  42510. title: annotation.title.toString(),
  42511. description: annotation.description,
  42512. position: annotation.position.toArray(),
  42513. offset: annotation.offset.toArray(),
  42514. children: []
  42515. };
  42516. if (annotation.cameraPosition) {
  42517. data.cameraPosition = annotation.cameraPosition.toArray();
  42518. }
  42519. if (annotation.cameraTarget) {
  42520. data.cameraTarget = annotation.cameraTarget.toArray();
  42521. }
  42522. if (typeof annotation.radius !== "undefined") {
  42523. data.radius = annotation.radius;
  42524. }
  42525. return data;
  42526. }
  42527. function createAnnotationsData(viewer) {
  42528. var map = new Map();
  42529. viewer.scene.annotations.traverseDescendants(a => {
  42530. var aData = createAnnotationData(a);
  42531. map.set(a, aData);
  42532. });
  42533. for (var [annotation, data] of map) {
  42534. for (var child of annotation.children) {
  42535. var childData = map.get(child);
  42536. data.children.push(childData);
  42537. }
  42538. }
  42539. var annotations = viewer.scene.annotations.children.map(a => map.get(a));
  42540. return annotations;
  42541. }
  42542. function createSettingsData(viewer) {
  42543. return {
  42544. pointBudget: viewer.getPointBudget(),
  42545. fov: viewer.getFOV(),
  42546. edlEnabled: viewer.getEDLEnabled(),
  42547. edlRadius: viewer.getEDLRadius(),
  42548. edlStrength: viewer.getEDLStrength(),
  42549. background: viewer.getBackground(),
  42550. minNodeSize: viewer.getMinNodeSize(),
  42551. showBoundingBoxes: viewer.getShowBoundingBox()
  42552. };
  42553. }
  42554. function createSceneContentData(viewer) {
  42555. var data = [];
  42556. var potreeObjects = [];
  42557. viewer.scene.scene.traverse(node => {
  42558. if (node.potree) {
  42559. potreeObjects.push(node);
  42560. }
  42561. });
  42562. for (var object of potreeObjects) {
  42563. if (object.potree.file) {
  42564. var saveObject = {
  42565. file: object.potree.file
  42566. };
  42567. data.push(saveObject);
  42568. }
  42569. }
  42570. return data;
  42571. }
  42572. function createViewData(viewer) {
  42573. var view = viewer.scene.view;
  42574. var data = {
  42575. position: view.position.toArray(),
  42576. target: view.getPivot().toArray()
  42577. };
  42578. return data;
  42579. }
  42580. function createClassificationData(viewer) {
  42581. var classifications = viewer.classifications;
  42582. var data = classifications;
  42583. return data;
  42584. }
  42585. function saveProject(viewer) {
  42586. var scene = viewer.scene;
  42587. var data = {
  42588. type: "Potree",
  42589. version: 1.7,
  42590. settings: createSettingsData(viewer),
  42591. view: createViewData(viewer),
  42592. classification: createClassificationData(viewer),
  42593. pointclouds: scene.pointclouds.map(createPointcloudData),
  42594. measurements: scene.measurements.map(createMeasurementData),
  42595. volumes: scene.volumes.map(createVolumeData),
  42596. cameraAnimations: scene.cameraAnimations.map(createCameraAnimationData),
  42597. profiles: scene.profiles.map(createProfileData),
  42598. annotations: createAnnotationsData(viewer),
  42599. orientedImages: scene.orientedImages.map(createOrientedImagesData),
  42600. geopackages: scene.geopackages.map(createGeopackageData)
  42601. // objects: createSceneContentData(viewer),
  42602. };
  42603. return data;
  42604. }
  42605. class ControlPoint {
  42606. constructor() {
  42607. this.position = new Vector3(0, 0, 0);
  42608. this.target = new Vector3(0, 0, 0);
  42609. this.positionHandle = null;
  42610. this.targetHandle = null;
  42611. }
  42612. }
  42613. ;
  42614. class CameraAnimation extends EventDispatcher$1 {
  42615. constructor(viewer) {
  42616. super();
  42617. this.viewer = viewer;
  42618. this.selectedElement = null;
  42619. this.controlPoints = [];
  42620. this.uuid = MathUtils.generateUUID();
  42621. this.node = new Object3D();
  42622. this.node.name = "camera animation";
  42623. this.viewer.scene.scene.add(this.node);
  42624. this.frustum = this.createFrustum();
  42625. this.node.add(this.frustum);
  42626. this.name = "Camera Animation";
  42627. this.duration = 5;
  42628. this.t = 0;
  42629. // "centripetal", "chordal", "catmullrom"
  42630. this.curveType = "centripetal";
  42631. this.visible = true;
  42632. this.createUpdateHook();
  42633. this.createPath();
  42634. }
  42635. static defaultFromView(viewer) {
  42636. var animation = new CameraAnimation(viewer);
  42637. var camera = viewer.scene.getActiveCamera();
  42638. var target = viewer.scene.view.getPivot();
  42639. var cpCenter = new Vector3(0.3 * camera.position.x + 0.7 * target.x, 0.3 * camera.position.y + 0.7 * target.y, 0.3 * camera.position.z + 0.7 * target.z);
  42640. var targetCenter = new Vector3(0.05 * camera.position.x + 0.95 * target.x, 0.05 * camera.position.y + 0.95 * target.y, 0.05 * camera.position.z + 0.95 * target.z);
  42641. var r = camera.position.distanceTo(target) * 0.3;
  42642. //const dir = target.clone().sub(camera.position).normalize();
  42643. var angle = Utils.computeAzimuth(camera.position, target);
  42644. var n = 5;
  42645. for (var i = 0; i < n; i++) {
  42646. var u = 1.5 * Math.PI * (i / n) + angle;
  42647. var dx = r * Math.cos(u);
  42648. var dy = r * Math.sin(u);
  42649. var cpPos = [cpCenter.x + dx, cpCenter.y + dy, cpCenter.z];
  42650. var targetPos = [targetCenter.x + dx * 0.1, targetCenter.y + dy * 0.1, targetCenter.z];
  42651. var cp = animation.createControlPoint();
  42652. cp.position.set(...cpPos);
  42653. cp.target.set(...targetPos);
  42654. }
  42655. return animation;
  42656. }
  42657. createUpdateHook() {
  42658. var viewer = this.viewer;
  42659. viewer.addEventListener("update", () => {
  42660. var camera = viewer.scene.getActiveCamera();
  42661. var {
  42662. width,
  42663. height
  42664. } = viewer.renderer.getSize(new Vector2());
  42665. this.node.visible = this.visible;
  42666. for (var cp of this.controlPoints) {
  42667. {
  42668. // position
  42669. var projected = cp.position.clone().project(camera);
  42670. var visible = this.visible && projected.z < 1 && projected.z > -1;
  42671. if (visible) {
  42672. var x = width * (projected.x * 0.5 + 0.5);
  42673. var y = height - height * (projected.y * 0.5 + 0.5);
  42674. cp.positionHandle.svg.style.left = x - cp.positionHandle.svg.clientWidth / 2;
  42675. cp.positionHandle.svg.style.top = y - cp.positionHandle.svg.clientHeight / 2;
  42676. cp.positionHandle.svg.style.display = "";
  42677. } else {
  42678. cp.positionHandle.svg.style.display = "none";
  42679. }
  42680. }
  42681. {
  42682. // target
  42683. var _projected = cp.target.clone().project(camera);
  42684. var _visible = this.visible && _projected.z < 1 && _projected.z > -1;
  42685. if (_visible) {
  42686. var _x = width * (_projected.x * 0.5 + 0.5);
  42687. var _y = height - height * (_projected.y * 0.5 + 0.5);
  42688. cp.targetHandle.svg.style.left = _x - cp.targetHandle.svg.clientWidth / 2;
  42689. cp.targetHandle.svg.style.top = _y - cp.targetHandle.svg.clientHeight / 2;
  42690. cp.targetHandle.svg.style.display = "";
  42691. } else {
  42692. cp.targetHandle.svg.style.display = "none";
  42693. }
  42694. }
  42695. }
  42696. this.line.material.resolution.set(width, height);
  42697. this.updatePath();
  42698. {
  42699. // frustum
  42700. var frame = this.at(this.t);
  42701. var frustum = this.frustum;
  42702. frustum.position.copy(frame.position);
  42703. frustum.lookAt(...frame.target.toArray());
  42704. frustum.scale.set(20, 20, 20);
  42705. frustum.material.resolution.set(width, height);
  42706. }
  42707. });
  42708. }
  42709. createControlPoint(index) {
  42710. if (index === undefined) {
  42711. index = this.controlPoints.length;
  42712. }
  42713. var cp = new ControlPoint();
  42714. if (this.controlPoints.length >= 2 && index === 0) {
  42715. var cp1 = this.controlPoints[0];
  42716. var cp2 = this.controlPoints[1];
  42717. var dir = cp1.position.clone().sub(cp2.position).multiplyScalar(0.5);
  42718. cp.position.copy(cp1.position).add(dir);
  42719. var tDir = cp1.target.clone().sub(cp2.target).multiplyScalar(0.5);
  42720. cp.target.copy(cp1.target).add(tDir);
  42721. } else if (this.controlPoints.length >= 2 && index === this.controlPoints.length) {
  42722. var _cp2 = this.controlPoints[this.controlPoints.length - 2];
  42723. var _cp3 = this.controlPoints[this.controlPoints.length - 1];
  42724. var _dir = _cp3.position.clone().sub(_cp2.position).multiplyScalar(0.5);
  42725. cp.position.copy(_cp2.position).add(_dir);
  42726. var _tDir = _cp3.target.clone().sub(_cp2.target).multiplyScalar(0.5);
  42727. cp.target.copy(_cp3.target).add(_tDir);
  42728. } else if (this.controlPoints.length >= 2) {
  42729. var _cp4 = this.controlPoints[index - 1];
  42730. var _cp5 = this.controlPoints[index];
  42731. cp.position.copy(_cp4.position.clone().add(_cp5.position).multiplyScalar(0.5));
  42732. cp.target.copy(_cp4.target.clone().add(_cp5.target).multiplyScalar(0.5));
  42733. }
  42734. // cp.position.copy(viewer.scene.view.position);
  42735. // cp.target.copy(viewer.scene.view.getPivot());
  42736. cp.positionHandle = this.createHandle(cp.position);
  42737. cp.targetHandle = this.createHandle(cp.target);
  42738. this.controlPoints.splice(index, 0, cp);
  42739. this.dispatchEvent({
  42740. type: "controlpoint_added",
  42741. controlpoint: cp
  42742. });
  42743. return cp;
  42744. }
  42745. removeControlPoint(cp) {
  42746. this.controlPoints = this.controlPoints.filter(_cp => _cp !== cp);
  42747. this.dispatchEvent({
  42748. type: "controlpoint_removed",
  42749. controlpoint: cp
  42750. });
  42751. cp.positionHandle.svg.remove();
  42752. cp.targetHandle.svg.remove();
  42753. // TODO destroy cp
  42754. }
  42755. createPath() {
  42756. {
  42757. // position
  42758. var geometry = new LineGeometry();
  42759. var material = new LineMaterial({
  42760. color: 0x00ff00,
  42761. dashSize: 5,
  42762. gapSize: 2,
  42763. linewidth: 2,
  42764. resolution: new Vector2(1000, 1000)
  42765. });
  42766. var line = new Line2(geometry, material);
  42767. this.line = line;
  42768. this.node.add(line);
  42769. }
  42770. {
  42771. // target
  42772. var _geometry = new LineGeometry();
  42773. var _material = new LineMaterial({
  42774. color: 0x0000ff,
  42775. dashSize: 5,
  42776. gapSize: 2,
  42777. linewidth: 2,
  42778. resolution: new Vector2(1000, 1000)
  42779. });
  42780. var _line = new Line2(_geometry, _material);
  42781. this.targetLine = _line;
  42782. this.node.add(_line);
  42783. }
  42784. }
  42785. createFrustum() {
  42786. var f = 0.3;
  42787. var positions = [0, 0, 0, -f, -f, +1, 0, 0, 0, f, -f, +1, 0, 0, 0, f, f, +1, 0, 0, 0, -f, f, +1, -f, -f, +1, f, -f, +1, f, -f, +1, f, f, +1, f, f, +1, -f, f, +1, -f, f, +1, -f, -f, +1];
  42788. var geometry = new LineGeometry();
  42789. geometry.setPositions(positions);
  42790. geometry.verticesNeedUpdate = true;
  42791. geometry.computeBoundingSphere();
  42792. var material = new LineMaterial({
  42793. color: 0xff0000,
  42794. linewidth: 2,
  42795. resolution: new Vector2(1000, 1000)
  42796. });
  42797. var line = new Line2(geometry, material);
  42798. line.computeLineDistances();
  42799. return line;
  42800. }
  42801. updatePath() {
  42802. {
  42803. // positions
  42804. var positions = this.controlPoints.map(cp => cp.position);
  42805. var first = positions[0];
  42806. var curve = new CatmullRomCurve3(positions);
  42807. curve.curveType = this.curveType;
  42808. var n = 100;
  42809. var curvePositions = [];
  42810. for (var k = 0; k <= n; k++) {
  42811. var t = k / n;
  42812. var position = curve.getPoint(t).sub(first);
  42813. curvePositions.push(position.x, position.y, position.z);
  42814. }
  42815. this.line.geometry.setPositions(curvePositions);
  42816. this.line.geometry.verticesNeedUpdate = true;
  42817. this.line.geometry.computeBoundingSphere();
  42818. this.line.position.copy(first);
  42819. this.line.computeLineDistances();
  42820. this.cameraCurve = curve;
  42821. }
  42822. {
  42823. // targets
  42824. var _positions = this.controlPoints.map(cp => cp.target);
  42825. var _first = _positions[0];
  42826. var _curve = new CatmullRomCurve3(_positions);
  42827. _curve.curveType = this.curveType;
  42828. var _n = 100;
  42829. var _curvePositions = [];
  42830. for (var _k = 0; _k <= _n; _k++) {
  42831. var _t = _k / _n;
  42832. var _position = _curve.getPoint(_t).sub(_first);
  42833. _curvePositions.push(_position.x, _position.y, _position.z);
  42834. }
  42835. this.targetLine.geometry.setPositions(_curvePositions);
  42836. this.targetLine.geometry.verticesNeedUpdate = true;
  42837. this.targetLine.geometry.computeBoundingSphere();
  42838. this.targetLine.position.copy(_first);
  42839. this.targetLine.computeLineDistances();
  42840. this.targetCurve = _curve;
  42841. }
  42842. }
  42843. at(t) {
  42844. if (t > 1) {
  42845. t = 1;
  42846. } else if (t < 0) {
  42847. t = 0;
  42848. }
  42849. var camPos = this.cameraCurve.getPointAt(t);
  42850. var target = this.targetCurve.getPointAt(t);
  42851. var frame = {
  42852. position: camPos,
  42853. target: target
  42854. };
  42855. return frame;
  42856. }
  42857. set(t) {
  42858. this.t = t;
  42859. }
  42860. createHandle(vector) {
  42861. var svgns = "http://www.w3.org/2000/svg";
  42862. var svg = document.createElementNS(svgns, "svg");
  42863. svg.setAttribute("width", "2em");
  42864. svg.setAttribute("height", "2em");
  42865. svg.setAttribute("position", "absolute");
  42866. svg.style.left = "50px";
  42867. svg.style.top = "50px";
  42868. svg.style.position = "absolute";
  42869. svg.style.zIndex = "10000";
  42870. var circle = document.createElementNS(svgns, 'circle');
  42871. circle.setAttributeNS(null, 'cx', "1em");
  42872. circle.setAttributeNS(null, 'cy', "1em");
  42873. circle.setAttributeNS(null, 'r', "0.5em");
  42874. circle.setAttributeNS(null, 'style', 'fill: red; stroke: black; stroke-width: 0.2em;');
  42875. svg.appendChild(circle);
  42876. var element = this.viewer.renderer.domElement.parentElement;
  42877. element.appendChild(svg);
  42878. var startDrag = evt => {
  42879. this.selectedElement = svg;
  42880. document.addEventListener("mousemove", drag);
  42881. };
  42882. var endDrag = evt => {
  42883. this.selectedElement = null;
  42884. document.removeEventListener("mousemove", drag);
  42885. };
  42886. var drag = evt => {
  42887. if (this.selectedElement) {
  42888. evt.preventDefault();
  42889. var rect = viewer.renderer.domElement.getBoundingClientRect();
  42890. var x = evt.clientX - rect.x;
  42891. var y = evt.clientY - rect.y;
  42892. var {
  42893. width,
  42894. height
  42895. } = this.viewer.renderer.getSize(new Vector2());
  42896. var camera = this.viewer.scene.getActiveCamera();
  42897. //const cp = this.controlPoints.find(cp => cp.handle.svg === svg);
  42898. var projected = vector.clone().project(camera);
  42899. projected.x = (x / width - 0.5) / 0.5;
  42900. projected.y = (-(y - height) / height - 0.5) / 0.5;
  42901. var unprojected = projected.clone().unproject(camera);
  42902. vector.set(unprojected.x, unprojected.y, unprojected.z);
  42903. }
  42904. };
  42905. svg.addEventListener('mousedown', startDrag);
  42906. svg.addEventListener('mouseup', endDrag);
  42907. var handle = {
  42908. svg: svg
  42909. };
  42910. return handle;
  42911. }
  42912. setVisible(visible) {
  42913. this.node.visible = visible;
  42914. var display = visible ? "" : "none";
  42915. for (var cp of this.controlPoints) {
  42916. cp.positionHandle.svg.style.display = display;
  42917. cp.targetHandle.svg.style.display = display;
  42918. }
  42919. this.visible = visible;
  42920. }
  42921. setDuration(duration) {
  42922. this.duration = duration;
  42923. }
  42924. getDuration(duration) {
  42925. return this.duration;
  42926. }
  42927. play() {
  42928. var tStart = performance.now();
  42929. var duration = this.duration;
  42930. var originalyVisible = this.visible;
  42931. this.setVisible(false);
  42932. var onUpdate = delta => {
  42933. var tNow = performance.now();
  42934. var elapsed = (tNow - tStart) / 1000;
  42935. var t = elapsed / duration;
  42936. this.set(t);
  42937. var frame = this.at(t);
  42938. viewer.scene.view.position.copy(frame.position);
  42939. viewer.scene.view.lookAt(frame.target);
  42940. if (t > 1) {
  42941. this.setVisible(originalyVisible);
  42942. this.viewer.removeEventListener("update", onUpdate);
  42943. }
  42944. };
  42945. this.viewer.addEventListener("update", onUpdate);
  42946. }
  42947. }
  42948. function loadPointCloud(viewer, data) {
  42949. var loadMaterial = target => {
  42950. if (data.material) {
  42951. if (data.material.activeAttributeName != null) {
  42952. target.activeAttributeName = data.material.activeAttributeName;
  42953. }
  42954. if (data.material.ranges != null) {
  42955. for (var range of data.material.ranges) {
  42956. if (range.name === "elevationRange") {
  42957. target.elevationRange = range.value;
  42958. } else if (range.name === "intensityRange") {
  42959. target.intensityRange = range.value;
  42960. } else {
  42961. target.setRange(range.name, range.value);
  42962. }
  42963. }
  42964. }
  42965. if (data.material.size != null) {
  42966. target.size = data.material.size;
  42967. }
  42968. if (data.material.minSize != null) {
  42969. target.minSize = data.material.minSize;
  42970. }
  42971. if (data.material.pointSizeType != null) {
  42972. target.pointSizeType = PointSizeType[data.material.pointSizeType];
  42973. }
  42974. if (data.material.matcap != null) {
  42975. target.matcap = data.material.matcap;
  42976. }
  42977. } else if (data.activeAttributeName != null) {
  42978. target.activeAttributeName = data.activeAttributeName;
  42979. } else {
  42980. // no material data
  42981. }
  42982. };
  42983. var promise = new Promise(resolve => {
  42984. var names = viewer.scene.pointclouds.map(p => p.name);
  42985. var alreadyExists = names.includes(data.name);
  42986. if (alreadyExists) {
  42987. resolve();
  42988. return;
  42989. }
  42990. Potree.loadPointCloud(data.url, data.name, e => {
  42991. var {
  42992. pointcloud
  42993. } = e;
  42994. pointcloud.position.set(...data.position);
  42995. pointcloud.rotation.set(...data.rotation);
  42996. pointcloud.scale.set(...data.scale);
  42997. loadMaterial(pointcloud.material);
  42998. viewer.scene.addPointCloud(pointcloud);
  42999. resolve(pointcloud);
  43000. });
  43001. });
  43002. return promise;
  43003. }
  43004. function loadMeasurement(viewer, data) {
  43005. var duplicate = viewer.scene.measurements.find(measure => measure.uuid === data.uuid);
  43006. if (duplicate) {
  43007. return;
  43008. }
  43009. var measure = new Measure();
  43010. measure.uuid = data.uuid;
  43011. measure.name = data.name;
  43012. measure.showDistances = data.showDistances;
  43013. measure.showCoordinates = data.showCoordinates;
  43014. measure.showArea = data.showArea;
  43015. measure.closed = data.closed;
  43016. measure.showAngles = data.showAngles;
  43017. measure.showHeight = data.showHeight;
  43018. measure.showCircle = data.showCircle;
  43019. measure.showAzimuth = data.showAzimuth;
  43020. measure.showEdges = data.showEdges;
  43021. // color
  43022. for (var point of data.points) {
  43023. var pos = new Vector3(...point);
  43024. measure.addMarker(pos);
  43025. }
  43026. viewer.scene.addMeasurement(measure);
  43027. }
  43028. function loadVolume(viewer, data) {
  43029. var duplicate = viewer.scene.volumes.find(volume => volume.uuid === data.uuid);
  43030. if (duplicate) {
  43031. return;
  43032. }
  43033. var volume = new Potree[data.type]();
  43034. volume.uuid = data.uuid;
  43035. volume.name = data.name;
  43036. volume.position.set(...data.position);
  43037. volume.rotation.set(...data.rotation);
  43038. volume.scale.set(...data.scale);
  43039. volume.visible = data.visible;
  43040. volume.clip = data.clip;
  43041. viewer.scene.addVolume(volume);
  43042. }
  43043. function loadCameraAnimation(viewer, data) {
  43044. var duplicate = viewer.scene.cameraAnimations.find(a => a.uuid === data.uuid);
  43045. if (duplicate) {
  43046. return;
  43047. }
  43048. var animation = new CameraAnimation(viewer);
  43049. animation.uuid = data.uuid;
  43050. animation.name = data.name;
  43051. animation.duration = data.duration;
  43052. animation.t = data.t;
  43053. animation.curveType = data.curveType;
  43054. animation.visible = data.visible;
  43055. animation.controlPoints = [];
  43056. for (var cpdata of data.controlPoints) {
  43057. var cp = animation.createControlPoint();
  43058. cp.position.set(...cpdata.position);
  43059. cp.target.set(...cpdata.target);
  43060. }
  43061. viewer.scene.addCameraAnimation(animation);
  43062. }
  43063. function loadOrientedImages(viewer, images) {
  43064. var {
  43065. cameraParamsPath,
  43066. imageParamsPath
  43067. } = images;
  43068. var duplicate = viewer.scene.orientedImages.find(i => i.imageParamsPath === imageParamsPath);
  43069. if (duplicate) {
  43070. return;
  43071. }
  43072. Potree.OrientedImageLoader.load(cameraParamsPath, imageParamsPath, viewer).then(images => {
  43073. viewer.scene.addOrientedImages(images);
  43074. });
  43075. }
  43076. function loadGeopackage(viewer, geopackage) {
  43077. var path = geopackage.path;
  43078. var duplicate = viewer.scene.geopackages.find(i => i.path === path);
  43079. if (duplicate) {
  43080. return;
  43081. }
  43082. var projection = viewer.getProjection();
  43083. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  43084. proj4.defs("pointcloud", projection);
  43085. var transform = proj4("WGS84", "pointcloud");
  43086. var params = {
  43087. transform: transform
  43088. };
  43089. Potree.GeoPackageLoader.loadUrl(path, params).then(data => {
  43090. viewer.scene.addGeopackage(data);
  43091. });
  43092. }
  43093. function loadSettings(viewer, data) {
  43094. if (!data) {
  43095. return;
  43096. }
  43097. viewer.setPointBudget(data.pointBudget);
  43098. viewer.setFOV(data.fov);
  43099. viewer.setEDLEnabled(data.edlEnabled);
  43100. viewer.setEDLRadius(data.edlRadius);
  43101. viewer.setEDLStrength(data.edlStrength);
  43102. viewer.setBackground(data.background);
  43103. viewer.setMinNodeSize(data.minNodeSize);
  43104. viewer.setShowBoundingBox(data.showBoundingBoxes);
  43105. }
  43106. function loadView(viewer, view) {
  43107. viewer.scene.view.position.set(...view.position);
  43108. viewer.scene.view.lookAt(...view.target);
  43109. }
  43110. function loadAnnotationItem(item) {
  43111. var annotation = new Annotation({
  43112. position: item.position,
  43113. title: item.title,
  43114. cameraPosition: item.cameraPosition,
  43115. cameraTarget: item.cameraTarget
  43116. });
  43117. annotation.description = item.description;
  43118. annotation.uuid = item.uuid;
  43119. if (item.offset) {
  43120. annotation.offset.set(...item.offset);
  43121. }
  43122. return annotation;
  43123. }
  43124. function loadAnnotations(viewer, data) {
  43125. if (!data) {
  43126. return;
  43127. }
  43128. var findDuplicate = item => {
  43129. var duplicate = null;
  43130. viewer.scene.annotations.traverse(a => {
  43131. if (a.uuid === item.uuid) {
  43132. duplicate = a;
  43133. }
  43134. });
  43135. return duplicate;
  43136. };
  43137. var traverse = (item, parent) => {
  43138. var duplicate = findDuplicate(item);
  43139. if (duplicate) {
  43140. return;
  43141. }
  43142. var annotation = loadAnnotationItem(item);
  43143. for (var childItem of item.children) {
  43144. traverse(childItem, annotation);
  43145. }
  43146. parent.add(annotation);
  43147. };
  43148. for (var item of data) {
  43149. traverse(item, viewer.scene.annotations);
  43150. }
  43151. }
  43152. function loadProfile(viewer, data) {
  43153. var {
  43154. name,
  43155. points
  43156. } = data;
  43157. var duplicate = viewer.scene.profiles.find(profile => profile.uuid === data.uuid);
  43158. if (duplicate) {
  43159. return;
  43160. }
  43161. var profile = new Potree.Profile();
  43162. profile.name = name;
  43163. profile.uuid = data.uuid;
  43164. profile.setWidth(data.width);
  43165. for (var point of points) {
  43166. profile.addMarker(new Vector3(...point));
  43167. }
  43168. viewer.scene.addProfile(profile);
  43169. }
  43170. function loadClassification(viewer, data) {
  43171. if (!data) {
  43172. return;
  43173. }
  43174. var classifications = data;
  43175. viewer.setClassifications(classifications);
  43176. }
  43177. async function loadProject(viewer, data) {
  43178. if (data.type !== "Potree") {
  43179. console.error("not a valid Potree project");
  43180. return;
  43181. }
  43182. loadSettings(viewer, data.settings);
  43183. loadView(viewer, data.view);
  43184. var pointcloudPromises = [];
  43185. for (var pointcloud of data.pointclouds) {
  43186. var promise = loadPointCloud(viewer, pointcloud);
  43187. pointcloudPromises.push(promise);
  43188. }
  43189. for (var measure of data.measurements) {
  43190. loadMeasurement(viewer, measure);
  43191. }
  43192. for (var volume of data.volumes) {
  43193. loadVolume(viewer, volume);
  43194. }
  43195. for (var animation of data.cameraAnimations) {
  43196. loadCameraAnimation(viewer, animation);
  43197. }
  43198. for (var profile of data.profiles) {
  43199. loadProfile(viewer, profile);
  43200. }
  43201. if (data.orientedImages) {
  43202. for (var images of data.orientedImages) {
  43203. loadOrientedImages(viewer, images);
  43204. }
  43205. }
  43206. loadAnnotations(viewer, data.annotations);
  43207. loadClassification(viewer, data.classification);
  43208. // need to load at least one point cloud that defines the scene projection,
  43209. // before we can load stuff in other projections such as geopackages
  43210. //await Promise.any(pointcloudPromises); // (not yet supported)
  43211. Utils.waitAny(pointcloudPromises).then(() => {
  43212. if (data.geopackages) {
  43213. for (var geopackage of data.geopackages) {
  43214. loadGeopackage(viewer, geopackage);
  43215. }
  43216. }
  43217. });
  43218. await Promise.all(pointcloudPromises);
  43219. }
  43220. //
  43221. // Algorithm by Christian Boucheny
  43222. // shader code taken and adapted from CloudCompare
  43223. //
  43224. // see
  43225. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  43226. // http://www.kitware.com/source/home/post/9
  43227. // https://tel.archives-ouvertes.fr/tel-00438464/document p. 115+ (french)
  43228. class EyeDomeLightingMaterial extends RawShaderMaterial {
  43229. //base
  43230. constructor() {
  43231. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  43232. super();
  43233. var uniforms = {
  43234. screenWidth: {
  43235. type: 'f',
  43236. value: 0
  43237. },
  43238. screenHeight: {
  43239. type: 'f',
  43240. value: 0
  43241. },
  43242. edlStrength: {
  43243. type: 'f',
  43244. value: 1.0
  43245. },
  43246. uNear: {
  43247. type: 'f',
  43248. value: 1.0
  43249. },
  43250. uFar: {
  43251. type: 'f',
  43252. value: 1.0
  43253. },
  43254. radius: {
  43255. type: 'f',
  43256. value: 1.0
  43257. },
  43258. neighbours: {
  43259. type: '2fv',
  43260. value: []
  43261. },
  43262. depthMap: {
  43263. type: 't',
  43264. value: null
  43265. },
  43266. uEDLColor: {
  43267. type: 't',
  43268. value: null
  43269. },
  43270. uEDLDepth: {
  43271. type: 't',
  43272. value: null
  43273. },
  43274. opacity: {
  43275. type: 'f',
  43276. value: 1.0
  43277. },
  43278. uProj: {
  43279. type: "Matrix4fv",
  43280. value: []
  43281. }
  43282. };
  43283. this.setValues({
  43284. uniforms: uniforms,
  43285. vertexShader: this.getDefines() + Shaders['edl.vs'],
  43286. fragmentShader: this.getDefines() + Shaders['edl.fs'],
  43287. lights: false
  43288. });
  43289. this.neighbourCount = 8;
  43290. }
  43291. getDefines() {
  43292. var defines = '';
  43293. defines += '#define NEIGHBOUR_COUNT ' + this.neighbourCount + '\n';
  43294. return defines;
  43295. }
  43296. updateShaderSource() {
  43297. var vs = this.getDefines() + Shaders['edl.vs'];
  43298. var fs = this.getDefines() + Shaders['edl.fs'];
  43299. this.setValues({
  43300. vertexShader: vs,
  43301. fragmentShader: fs
  43302. });
  43303. this.uniforms.neighbours.value = this.neighbours;
  43304. this.needsUpdate = true;
  43305. }
  43306. get neighbourCount() {
  43307. return this._neighbourCount;
  43308. }
  43309. set neighbourCount(value) {
  43310. if (this._neighbourCount !== value) {
  43311. //周围八个格子
  43312. this._neighbourCount = value;
  43313. this.neighbours = new Float32Array(this._neighbourCount * 2);
  43314. for (var c = 0; c < this._neighbourCount; c++) {
  43315. this.neighbours[2 * c + 0] = Math.cos(2 * c * Math.PI / this._neighbourCount);
  43316. this.neighbours[2 * c + 1] = Math.sin(2 * c * Math.PI / this._neighbourCount);
  43317. }
  43318. this.updateShaderSource();
  43319. }
  43320. }
  43321. }
  43322. /**
  43323. * laslaz code taken and adapted from plas.io js-laslaz
  43324. * http://plas.io/
  43325. * https://github.com/verma/plasio
  43326. *
  43327. * Thanks to Uday Verma and Howard Butler
  43328. *
  43329. */
  43330. class LasLazLoader {
  43331. constructor(version, extension) {
  43332. if (typeof version === 'string') {
  43333. this.version = new Version(version);
  43334. } else {
  43335. this.version = version;
  43336. }
  43337. this.extension = extension;
  43338. }
  43339. static progressCB() {}
  43340. load(node, callback) {
  43341. if (node.loaded) {
  43342. return;
  43343. }
  43344. var url = node.getURL();
  43345. if (this.version.equalOrHigher('1.4')) {
  43346. url += ".".concat(this.extension);
  43347. }
  43348. var xhr = XHRFactory.createXMLHttpRequest();
  43349. xhr.open('GET', url, true);
  43350. xhr.responseType = 'arraybuffer';
  43351. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  43352. xhr.onreadystatechange = () => {
  43353. if (xhr.readyState === 4) {
  43354. if (xhr.status === 200 || xhr.status === 0) {
  43355. var buffer = xhr.response;
  43356. this.parse(node, buffer, callback);
  43357. } else {
  43358. console.log('Failed to load file! HTTP status: ' + xhr.status + ', file: ' + url);
  43359. }
  43360. }
  43361. };
  43362. xhr.send(null);
  43363. }
  43364. async parse(node, buffer, callback) {
  43365. //add callback
  43366. var lf = new LASFile(buffer);
  43367. var handler = new LasLazBatcher(node);
  43368. try {
  43369. await lf.open();
  43370. lf.isOpen = true;
  43371. } catch (e) {
  43372. console.log("failed to open file. :(");
  43373. return;
  43374. }
  43375. var header = await lf.getHeader();
  43376. var skip = 1;
  43377. var totalRead = 0;
  43378. var totalToRead = skip <= 1 ? header.pointsCount : header.pointsCount / skip;
  43379. var hasMoreData = true;
  43380. while (hasMoreData) {
  43381. var data = await lf.readData(1000 * 1000, 0, skip);
  43382. handler.push(new LASDecoder(data.buffer, header.pointsFormatId, header.pointsStructSize, data.count, header.scale, header.offset, header.mins, header.maxs));
  43383. totalRead += data.count;
  43384. LasLazLoader.progressCB(totalRead / totalToRead);
  43385. hasMoreData = data.hasMoreData;
  43386. }
  43387. header.totalRead = totalRead;
  43388. header.versionAsString = lf.versionAsString;
  43389. header.isCompressed = lf.isCompressed;
  43390. LasLazLoader.progressCB(1);
  43391. try {
  43392. await lf.close();
  43393. lf.isOpen = false;
  43394. } catch (e) {
  43395. console.error("failed to close las/laz file!!!");
  43396. throw e;
  43397. }
  43398. callback(); //add
  43399. }
  43400. handle(node, url) {}
  43401. }
  43402. ;
  43403. class LasLazBatcher {
  43404. constructor(node) {
  43405. this.node = node;
  43406. }
  43407. push(lasBuffer) {
  43408. var workerPath = Potree.scriptPath + '/workers/LASDecoderWorker.js';
  43409. var worker = Potree.workerPool.getWorker(workerPath);
  43410. var node = this.node;
  43411. var pointAttributes = node.pcoGeometry.pointAttributes;
  43412. worker.onmessage = e => {
  43413. var geometry = new BufferGeometry();
  43414. var numPoints = lasBuffer.pointsCount;
  43415. var positions = new Float32Array(e.data.position);
  43416. var colors = new Uint8Array(e.data.color);
  43417. var intensities = new Float32Array(e.data.intensity);
  43418. var classifications = new Uint8Array(e.data.classification);
  43419. var returnNumbers = new Uint8Array(e.data.returnNumber);
  43420. var numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  43421. var pointSourceIDs = new Uint16Array(e.data.pointSourceID);
  43422. var indices = new Uint8Array(e.data.indices);
  43423. geometry.setAttribute('position', new BufferAttribute(positions, 3));
  43424. geometry.setAttribute('color', new BufferAttribute(colors, 4, true));
  43425. geometry.setAttribute('intensity', new BufferAttribute(intensities, 1));
  43426. geometry.setAttribute('classification', new BufferAttribute(classifications, 1));
  43427. geometry.setAttribute('return number', new BufferAttribute(returnNumbers, 1));
  43428. geometry.setAttribute('number of returns', new BufferAttribute(numberOfReturns, 1));
  43429. geometry.setAttribute('source id', new BufferAttribute(pointSourceIDs, 1));
  43430. geometry.setAttribute('indices', new BufferAttribute(indices, 4));
  43431. geometry.attributes.indices.normalized = true;
  43432. var _loop = function _loop(key) {
  43433. var range = e.data.ranges[key];
  43434. var attribute = pointAttributes.attributes.find(a => a.name === key);
  43435. attribute.range[0] = Math.min(attribute.range[0], range[0]);
  43436. attribute.range[1] = Math.max(attribute.range[1], range[1]);
  43437. };
  43438. for (var key in e.data.ranges) {
  43439. _loop(key);
  43440. }
  43441. var tightBoundingBox = new Box3(new Vector3().fromArray(e.data.tightBoundingBox.min), new Vector3().fromArray(e.data.tightBoundingBox.max));
  43442. geometry.boundingBox = this.node.boundingBox;
  43443. this.node.tightBoundingBox = tightBoundingBox;
  43444. this.node.geometry = geometry;
  43445. this.node.numPoints = numPoints;
  43446. this.node.loaded = true;
  43447. this.node.loading = false;
  43448. Potree.numNodesLoading--;
  43449. this.node.mean = new Vector3(...e.data.mean);
  43450. Potree.workerPool.returnWorker(workerPath, worker);
  43451. };
  43452. var message = {
  43453. buffer: lasBuffer.arrayb,
  43454. numPoints: lasBuffer.pointsCount,
  43455. pointSize: lasBuffer.pointSize,
  43456. pointFormatID: 2,
  43457. scale: lasBuffer.scale,
  43458. offset: lasBuffer.offset,
  43459. mins: lasBuffer.mins,
  43460. maxs: lasBuffer.maxs
  43461. };
  43462. worker.postMessage(message, [message.buffer]);
  43463. }
  43464. }
  43465. function parseAttributes(cloudjs) {
  43466. var version = new Version(cloudjs.version);
  43467. var replacements = {
  43468. "COLOR_PACKED": "rgba",
  43469. "RGBA": "rgba",
  43470. "INTENSITY": "intensity",
  43471. "CLASSIFICATION": "classification",
  43472. "GPS_TIME": "gps-time"
  43473. };
  43474. var replaceOldNames = old => {
  43475. if (replacements[old]) {
  43476. return replacements[old];
  43477. } else {
  43478. return old;
  43479. }
  43480. };
  43481. var pointAttributes = [];
  43482. if (version.upTo('1.7')) {
  43483. for (var attributeName of cloudjs.pointAttributes) {
  43484. var oldAttribute = PointAttribute[attributeName];
  43485. var attribute = {
  43486. name: oldAttribute.name,
  43487. size: oldAttribute.byteSize,
  43488. elements: oldAttribute.numElements,
  43489. elementSize: oldAttribute.byteSize / oldAttribute.numElements,
  43490. type: oldAttribute.type.name,
  43491. description: ""
  43492. };
  43493. pointAttributes.push(attribute);
  43494. }
  43495. } else {
  43496. pointAttributes.push(...cloudjs.pointAttributes);
  43497. }
  43498. {
  43499. var attributes = new PointAttributes();
  43500. var typeConversion = {
  43501. int8: PointAttributeTypes.DATA_TYPE_INT8,
  43502. int16: PointAttributeTypes.DATA_TYPE_INT16,
  43503. int32: PointAttributeTypes.DATA_TYPE_INT32,
  43504. int64: PointAttributeTypes.DATA_TYPE_INT64,
  43505. uint8: PointAttributeTypes.DATA_TYPE_UINT8,
  43506. uint16: PointAttributeTypes.DATA_TYPE_UINT16,
  43507. uint32: PointAttributeTypes.DATA_TYPE_UINT32,
  43508. uint64: PointAttributeTypes.DATA_TYPE_UINT64,
  43509. double: PointAttributeTypes.DATA_TYPE_DOUBLE,
  43510. float: PointAttributeTypes.DATA_TYPE_FLOAT
  43511. };
  43512. for (var jsAttribute of pointAttributes) {
  43513. if (jsAttribute.name == void 0) {
  43514. //add 有的是这个,也有的不是(点云编辑页的)
  43515. var attribute_ = PointAttribute[jsAttribute];
  43516. attributes.add(attribute_);
  43517. continue;
  43518. }
  43519. var name = replaceOldNames(jsAttribute.name);
  43520. var type = typeConversion[jsAttribute.type];
  43521. var numElements = jsAttribute.elements;
  43522. var description = jsAttribute.description;
  43523. var _attribute = new PointAttribute(name, type, numElements);
  43524. attributes.add(_attribute);
  43525. }
  43526. {
  43527. // check if it has normals
  43528. var hasNormals = pointAttributes.find(a => a.name === "NormalX") !== undefined && pointAttributes.find(a => a.name === "NormalY") !== undefined && pointAttributes.find(a => a.name === "NormalZ") !== undefined;
  43529. if (hasNormals) {
  43530. var vector = {
  43531. name: "NORMAL",
  43532. attributes: ["NormalX", "NormalY", "NormalZ"]
  43533. };
  43534. attributes.addVector(vector);
  43535. }
  43536. }
  43537. return attributes;
  43538. }
  43539. }
  43540. function lasLazAttributes(fMno) {
  43541. var attributes = new PointAttributes();
  43542. attributes.add(PointAttribute.POSITION_CARTESIAN);
  43543. attributes.add(new PointAttribute("rgba", PointAttributeTypes.DATA_TYPE_UINT8, 4));
  43544. attributes.add(new PointAttribute("intensity", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  43545. attributes.add(new PointAttribute("classification", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  43546. attributes.add(new PointAttribute("gps-time", PointAttributeTypes.DATA_TYPE_DOUBLE, 1));
  43547. attributes.add(new PointAttribute("number of returns", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  43548. attributes.add(new PointAttribute("return number", PointAttributeTypes.DATA_TYPE_UINT8, 1));
  43549. attributes.add(new PointAttribute("source id", PointAttributeTypes.DATA_TYPE_UINT16, 1));
  43550. //attributes.add(new PointAttribute("pointSourceID", PointAttributeTypes.DATA_TYPE_INT8, 4));
  43551. return attributes;
  43552. }
  43553. class POCLoader {
  43554. static load(url, timeStamp, callback) {
  43555. //add timeStamp
  43556. try {
  43557. var pco = new PointCloudOctreeGeometry();
  43558. pco.timeStamp = timeStamp;
  43559. pco.url = url;
  43560. var xhr = XHRFactory.createXMLHttpRequest();
  43561. xhr.open('GET', url + '?m=' + timeStamp, true);
  43562. xhr.onreadystatechange = function () {
  43563. if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
  43564. var fMno = JSON.parse(xhr.responseText);
  43565. var version = new Version(fMno.version);
  43566. // assume octreeDir is absolute if it starts with http
  43567. if (fMno.octreeDir.indexOf('http') === 0) {
  43568. pco.octreeDir = fMno.octreeDir;
  43569. } else {
  43570. pco.octreeDir = url + '/../' + fMno.octreeDir;
  43571. }
  43572. pco.spacing = fMno.spacing;
  43573. pco.hierarchyStepSize = fMno.hierarchyStepSize;
  43574. pco.pointAttributes = fMno.pointAttributes;
  43575. var min = new Vector3(fMno.boundingBox.lx, fMno.boundingBox.ly, fMno.boundingBox.lz);
  43576. var max = new Vector3(fMno.boundingBox.ux, fMno.boundingBox.uy, fMno.boundingBox.uz);
  43577. var boundingBox = new Box3(min, max);
  43578. var tightBoundingBox = boundingBox.clone();
  43579. if (fMno.tightBoundingBox) {
  43580. //这个才是真实的bounding,前面那个bounding的size是个正方体,似乎取了最长边作为边长
  43581. tightBoundingBox.min.copy(new Vector3(fMno.tightBoundingBox.lx, fMno.tightBoundingBox.ly, fMno.tightBoundingBox.lz));
  43582. tightBoundingBox.max.copy(new Vector3(fMno.tightBoundingBox.ux, fMno.tightBoundingBox.uy, fMno.tightBoundingBox.uz));
  43583. }
  43584. var offset = min.clone(); //将成为点云的position,被我用作旋转中心(但在点云中不那么居中,navvis也是这样, 这样可能是为了让模型在这数据的bounding上)
  43585. boundingBox.min.sub(offset); //点云的真实坐标的min都是0,0,0吗(我看案例是,因绕角落旋转,也就是原点)
  43586. boundingBox.max.sub(offset);
  43587. tightBoundingBox.min.sub(offset);
  43588. tightBoundingBox.max.sub(offset);
  43589. //改
  43590. //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 ",
  43591. //"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" //给地图
  43592. pco.boundingBox = boundingBox;
  43593. pco.tightBoundingBox = tightBoundingBox;
  43594. pco.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  43595. pco.tightBoundingSphere = tightBoundingBox.getBoundingSphere(new Sphere());
  43596. pco.offset = offset;
  43597. if (fMno.pointAttributes === 'LAS') {
  43598. pco.loader = new LasLazLoader(fMno.version, "las");
  43599. pco.pointAttributes = lasLazAttributes(fMno);
  43600. } else if (fMno.pointAttributes === 'LAZ') {
  43601. pco.loader = new LasLazLoader(fMno.version, "laz");
  43602. pco.pointAttributes = lasLazAttributes(fMno);
  43603. } else {
  43604. pco.loader = new BinaryLoader(fMno.version, boundingBox, fMno.scale);
  43605. pco.pointAttributes = parseAttributes(fMno);
  43606. }
  43607. var nodes = {};
  43608. {
  43609. // load root
  43610. var name = 'r';
  43611. var root = new PointCloudOctreeGeometryNode(name, pco, boundingBox);
  43612. root.level = 0;
  43613. root.hasChildren = true;
  43614. root.spacing = pco.spacing;
  43615. if (version.upTo('1.5')) {
  43616. root.numPoints = fMno.hierarchy[0][1];
  43617. } else {
  43618. root.numPoints = 0;
  43619. }
  43620. pco.root = root;
  43621. pco.root.load();
  43622. nodes[name] = root;
  43623. }
  43624. // load remaining hierarchy
  43625. if (version.upTo('1.4')) {
  43626. for (var i = 1; i < fMno.hierarchy.length; i++) {
  43627. var _name = fMno.hierarchy[i][0];
  43628. var numPoints = fMno.hierarchy[i][1];
  43629. var index = parseInt(_name.charAt(_name.length - 1));
  43630. var parentName = _name.substring(0, _name.length - 1);
  43631. var parentNode = nodes[parentName];
  43632. var level = _name.length - 1;
  43633. //let boundingBox = POCLoader.createChildAABB(parentNode.boundingBox, index);
  43634. var _boundingBox = Utils.createChildAABB(parentNode.boundingBox, index);
  43635. var node = new PointCloudOctreeGeometryNode(_name, pco, _boundingBox);
  43636. node.level = level;
  43637. node.numPoints = numPoints;
  43638. node.spacing = pco.spacing / Math.pow(2, level);
  43639. parentNode.addChild(node);
  43640. nodes[_name] = node;
  43641. }
  43642. }
  43643. pco.nodes = nodes;
  43644. callback(pco);
  43645. }
  43646. };
  43647. xhr.send(null);
  43648. } catch (e) {
  43649. console.log("loading failed: '" + url + "'");
  43650. console.log(e);
  43651. callback();
  43652. }
  43653. }
  43654. loadPointAttributes(mno) {
  43655. var fpa = mno.pointAttributes;
  43656. var pa = new PointAttributes();
  43657. for (var i = 0; i < fpa.length; i++) {
  43658. var pointAttribute = PointAttribute[fpa[i]];
  43659. pa.add(pointAttribute);
  43660. }
  43661. return pa;
  43662. }
  43663. createChildAABB(aabb, index) {
  43664. var min = aabb.min.clone();
  43665. var max = aabb.max.clone();
  43666. var size = new Vector3().subVectors(max, min);
  43667. if ((index & 0b0001) > 0) {
  43668. min.z += size.z / 2;
  43669. } else {
  43670. max.z -= size.z / 2;
  43671. }
  43672. if ((index & 0b0010) > 0) {
  43673. min.y += size.y / 2;
  43674. } else {
  43675. max.y -= size.y / 2;
  43676. }
  43677. if ((index & 0b0100) > 0) {
  43678. min.x += size.x / 2;
  43679. } else {
  43680. max.x -= size.x / 2;
  43681. }
  43682. return new Box3(min, max);
  43683. }
  43684. }
  43685. class OctreeGeometry {
  43686. constructor() {
  43687. this.url = null;
  43688. this.spacing = 0;
  43689. this.boundingBox = null;
  43690. this.root = null;
  43691. this.pointAttributes = null;
  43692. this.loader = null;
  43693. }
  43694. }
  43695. ;
  43696. class OctreeGeometryNode {
  43697. constructor(name, octreeGeometry, boundingBox) {
  43698. this.id = OctreeGeometryNode.IDCount++;
  43699. this.name = name;
  43700. this.index = parseInt(name.charAt(name.length - 1));
  43701. this.octreeGeometry = octreeGeometry;
  43702. this.boundingBox = boundingBox;
  43703. this.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  43704. this.children = {};
  43705. this.numPoints = 0;
  43706. this.level = null;
  43707. this.oneTimeDisposeHandlers = [];
  43708. }
  43709. isGeometryNode() {
  43710. return true;
  43711. }
  43712. getLevel() {
  43713. return this.level;
  43714. }
  43715. isTreeNode() {
  43716. return false;
  43717. }
  43718. isLoaded() {
  43719. return this.loaded;
  43720. }
  43721. getBoundingSphere() {
  43722. return this.boundingSphere;
  43723. }
  43724. getBoundingBox() {
  43725. return this.boundingBox;
  43726. }
  43727. getChildren() {
  43728. var children = [];
  43729. for (var i = 0; i < 8; i++) {
  43730. if (this.children[i]) {
  43731. children.push(this.children[i]);
  43732. }
  43733. }
  43734. return children;
  43735. }
  43736. getBoundingBox() {
  43737. return this.boundingBox;
  43738. }
  43739. load() {
  43740. if (Potree.numNodesLoading >= Potree.maxNodesLoading) {
  43741. return;
  43742. }
  43743. this.octreeGeometry.loader.load(this);
  43744. }
  43745. getNumPoints() {
  43746. return this.numPoints;
  43747. }
  43748. dispose() {
  43749. if (this.geometry && this.parent != null) {
  43750. this.geometry.dispose();
  43751. this.geometry = null;
  43752. this.loaded = false;
  43753. // this.dispatchEvent( { type: 'dispose' } );
  43754. for (var i = 0; i < this.oneTimeDisposeHandlers.length; i++) {
  43755. var handler = this.oneTimeDisposeHandlers[i];
  43756. handler();
  43757. }
  43758. this.oneTimeDisposeHandlers = [];
  43759. }
  43760. }
  43761. }
  43762. ;
  43763. OctreeGeometryNode.IDCount = 0;
  43764. // let loadedNodes = new Set();
  43765. class NodeLoader {
  43766. constructor(url) {
  43767. this.url = url;
  43768. }
  43769. async load(node) {
  43770. if (node.loaded || node.loading) {
  43771. return;
  43772. }
  43773. node.loading = true;
  43774. Potree.numNodesLoading++;
  43775. // console.log(node.name, node.numPoints);
  43776. // if(loadedNodes.has(node.name)){
  43777. // // debugger;
  43778. // }
  43779. // loadedNodes.add(node.name);
  43780. try {
  43781. if (node.nodeType === 2) {
  43782. await this.loadHierarchy(node);
  43783. }
  43784. var {
  43785. byteOffset,
  43786. byteSize
  43787. } = node;
  43788. var urlOctree = "".concat(this.url, "/../octree.bin");
  43789. var first = byteOffset;
  43790. var last = byteOffset + byteSize - 1n;
  43791. var buffer;
  43792. if (byteSize === 0n) {
  43793. buffer = new ArrayBuffer(0);
  43794. console.warn("loaded node with 0 bytes: ".concat(node.name));
  43795. } else {
  43796. var response = await fetch(urlOctree, {
  43797. headers: {
  43798. 'content-type': 'multipart/byteranges',
  43799. 'Range': "bytes=".concat(first, "-").concat(last)
  43800. }
  43801. });
  43802. buffer = await response.arrayBuffer();
  43803. }
  43804. var workerPath;
  43805. if (this.metadata.encoding === "BROTLI") {
  43806. workerPath = Potree.scriptPath + '/workers/2.0/DecoderWorker_brotli.js';
  43807. } else {
  43808. workerPath = Potree.scriptPath + '/workers/2.0/DecoderWorker.js';
  43809. }
  43810. var worker = Potree.workerPool.getWorker(workerPath);
  43811. worker.onmessage = function (e) {
  43812. var data = e.data;
  43813. var buffers = data.attributeBuffers;
  43814. Potree.workerPool.returnWorker(workerPath, worker);
  43815. var geometry = new BufferGeometry();
  43816. for (var property in buffers) {
  43817. var _buffer = buffers[property].buffer;
  43818. if (property === "position") {
  43819. geometry.setAttribute('position', new BufferAttribute(new Float32Array(_buffer), 3));
  43820. } else if (property === "rgba") {
  43821. geometry.setAttribute('rgba', new BufferAttribute(new Uint8Array(_buffer), 4, true));
  43822. } else if (property === "NORMAL") {
  43823. //geometry.setAttribute('rgba', new THREE.BufferAttribute(new Uint8Array(buffer), 4, true));
  43824. geometry.setAttribute('normal', new BufferAttribute(new Float32Array(_buffer), 3));
  43825. } else if (property === "INDICES") {
  43826. var bufferAttribute = new BufferAttribute(new Uint8Array(_buffer), 4);
  43827. bufferAttribute.normalized = true;
  43828. geometry.setAttribute('indices', bufferAttribute);
  43829. } else {
  43830. var _bufferAttribute = new BufferAttribute(new Float32Array(_buffer), 1);
  43831. var batchAttribute = buffers[property].attribute;
  43832. _bufferAttribute.potree = {
  43833. offset: buffers[property].offset,
  43834. scale: buffers[property].scale,
  43835. preciseBuffer: buffers[property].preciseBuffer,
  43836. range: batchAttribute.range
  43837. };
  43838. geometry.setAttribute(property, _bufferAttribute);
  43839. }
  43840. }
  43841. // indices ??
  43842. node.density = data.density;
  43843. node.geometry = geometry;
  43844. node.loaded = true;
  43845. node.loading = false;
  43846. Potree.numNodesLoading--;
  43847. };
  43848. var pointAttributes = node.octreeGeometry.pointAttributes;
  43849. var scale = node.octreeGeometry.scale;
  43850. var box = node.boundingBox;
  43851. var min = node.octreeGeometry.offset.clone().add(box.min);
  43852. var size = box.max.clone().sub(box.min);
  43853. var max = min.clone().add(size);
  43854. var numPoints = node.numPoints;
  43855. var offset = node.octreeGeometry.loader.offset;
  43856. var message = {
  43857. name: node.name,
  43858. buffer: buffer,
  43859. pointAttributes: pointAttributes,
  43860. scale: scale,
  43861. min: min,
  43862. max: max,
  43863. size: size,
  43864. offset: offset,
  43865. numPoints: numPoints
  43866. };
  43867. worker.postMessage(message, [message.buffer]);
  43868. } catch (e) {
  43869. node.loaded = false;
  43870. node.loading = false;
  43871. Potree.numNodesLoading--;
  43872. console.log("failed to load ".concat(node.name));
  43873. console.log(e);
  43874. console.log("trying again!");
  43875. }
  43876. }
  43877. parseHierarchy(node, buffer) {
  43878. var view = new DataView(buffer);
  43879. var tStart = performance.now();
  43880. var bytesPerNode = 22;
  43881. var numNodes = buffer.byteLength / bytesPerNode;
  43882. var octree = node.octreeGeometry;
  43883. // let nodes = [node];
  43884. var nodes = new Array(numNodes);
  43885. nodes[0] = node;
  43886. var nodePos = 1;
  43887. for (var i = 0; i < numNodes; i++) {
  43888. var current = nodes[i];
  43889. var type = view.getUint8(i * bytesPerNode + 0);
  43890. var childMask = view.getUint8(i * bytesPerNode + 1);
  43891. var numPoints = view.getUint32(i * bytesPerNode + 2, true);
  43892. var byteOffset = view.getBigInt64(i * bytesPerNode + 6, true);
  43893. var byteSize = view.getBigInt64(i * bytesPerNode + 14, true);
  43894. // if(byteSize === 0n){
  43895. // // debugger;
  43896. // }
  43897. if (current.nodeType === 2) {
  43898. // replace proxy with real node
  43899. current.byteOffset = byteOffset;
  43900. current.byteSize = byteSize;
  43901. current.numPoints = numPoints;
  43902. } else if (type === 2) {
  43903. // load proxy
  43904. current.hierarchyByteOffset = byteOffset;
  43905. current.hierarchyByteSize = byteSize;
  43906. current.numPoints = numPoints;
  43907. } else {
  43908. // load real node
  43909. current.byteOffset = byteOffset;
  43910. current.byteSize = byteSize;
  43911. current.numPoints = numPoints;
  43912. }
  43913. if (current.byteSize === 0n) {
  43914. // workaround for issue #1125
  43915. // some inner nodes erroneously report >0 points even though have 0 points
  43916. // however, they still report a byteSize of 0, so based on that we now set node.numPoints to 0
  43917. current.numPoints = 0;
  43918. }
  43919. current.nodeType = type;
  43920. if (current.nodeType === 2) {
  43921. continue;
  43922. }
  43923. for (var childIndex = 0; childIndex < 8; childIndex++) {
  43924. var childExists = (1 << childIndex & childMask) !== 0;
  43925. if (!childExists) {
  43926. continue;
  43927. }
  43928. var childName = current.name + childIndex;
  43929. var childAABB = createChildAABB(current.boundingBox, childIndex);
  43930. var child = new OctreeGeometryNode(childName, octree, childAABB);
  43931. child.name = childName;
  43932. child.spacing = current.spacing / 2;
  43933. child.level = current.level + 1;
  43934. current.children[childIndex] = child;
  43935. child.parent = current;
  43936. // nodes.push(child);
  43937. nodes[nodePos] = child;
  43938. nodePos++;
  43939. }
  43940. // if((i % 500) === 0){
  43941. // yield;
  43942. // }
  43943. }
  43944. var duration = performance.now() - tStart;
  43945. // if(duration > 20){
  43946. // let msg = `duration: ${duration}ms, numNodes: ${numNodes}`;
  43947. // console.log(msg);
  43948. // }
  43949. }
  43950. async loadHierarchy(node) {
  43951. var {
  43952. hierarchyByteOffset,
  43953. hierarchyByteSize
  43954. } = node;
  43955. var hierarchyPath = "".concat(this.url, "/../hierarchy.bin");
  43956. var first = hierarchyByteOffset;
  43957. var last = first + hierarchyByteSize - 1n;
  43958. var response = await fetch(hierarchyPath, {
  43959. headers: {
  43960. 'content-type': 'multipart/byteranges',
  43961. 'Range': "bytes=".concat(first, "-").concat(last)
  43962. }
  43963. });
  43964. var buffer = await response.arrayBuffer();
  43965. this.parseHierarchy(node, buffer);
  43966. // let promise = new Promise((resolve) => {
  43967. // let generator = this.parseHierarchy(node, buffer);
  43968. // let repeatUntilDone = () => {
  43969. // let result = generator.next();
  43970. // if(result.done){
  43971. // resolve();
  43972. // }else{
  43973. // requestAnimationFrame(repeatUntilDone);
  43974. // }
  43975. // };
  43976. // repeatUntilDone();
  43977. // });
  43978. // await promise;
  43979. }
  43980. }
  43981. var tmpVec3 = new Vector3();
  43982. function createChildAABB(aabb, index) {
  43983. var min = aabb.min.clone();
  43984. var max = aabb.max.clone();
  43985. var size = tmpVec3.subVectors(max, min);
  43986. if ((index & 0b0001) > 0) {
  43987. min.z += size.z / 2;
  43988. } else {
  43989. max.z -= size.z / 2;
  43990. }
  43991. if ((index & 0b0010) > 0) {
  43992. min.y += size.y / 2;
  43993. } else {
  43994. max.y -= size.y / 2;
  43995. }
  43996. if ((index & 0b0100) > 0) {
  43997. min.x += size.x / 2;
  43998. } else {
  43999. max.x -= size.x / 2;
  44000. }
  44001. return new Box3(min, max);
  44002. }
  44003. var typenameTypeattributeMap = {
  44004. "double": PointAttributeTypes.DATA_TYPE_DOUBLE,
  44005. "float": PointAttributeTypes.DATA_TYPE_FLOAT,
  44006. "int8": PointAttributeTypes.DATA_TYPE_INT8,
  44007. "uint8": PointAttributeTypes.DATA_TYPE_UINT8,
  44008. "int16": PointAttributeTypes.DATA_TYPE_INT16,
  44009. "uint16": PointAttributeTypes.DATA_TYPE_UINT16,
  44010. "int32": PointAttributeTypes.DATA_TYPE_INT32,
  44011. "uint32": PointAttributeTypes.DATA_TYPE_UINT32,
  44012. "int64": PointAttributeTypes.DATA_TYPE_INT64,
  44013. "uint64": PointAttributeTypes.DATA_TYPE_UINT64
  44014. };
  44015. class OctreeLoader {
  44016. static parseAttributes(jsonAttributes) {
  44017. var attributes = new PointAttributes();
  44018. var replacements = {
  44019. "rgb": "rgba"
  44020. };
  44021. for (var jsonAttribute of jsonAttributes) {
  44022. var {
  44023. name,
  44024. description,
  44025. size,
  44026. numElements,
  44027. elementSize,
  44028. min,
  44029. max
  44030. } = jsonAttribute;
  44031. var type = typenameTypeattributeMap[jsonAttribute.type];
  44032. var potreeAttributeName = replacements[name] ? replacements[name] : name;
  44033. var attribute = new PointAttribute(potreeAttributeName, type, numElements);
  44034. if (numElements === 1) {
  44035. attribute.range = [min[0], max[0]];
  44036. } else {
  44037. attribute.range = [min, max];
  44038. }
  44039. if (name === "gps-time") {
  44040. // HACK: Guard against bad gpsTime range in metadata, see potree/potree#909
  44041. if (attribute.range[0] === attribute.range[1]) {
  44042. attribute.range[1] += 1;
  44043. }
  44044. }
  44045. attribute.initialRange = attribute.range;
  44046. attributes.add(attribute);
  44047. }
  44048. {
  44049. // check if it has normals
  44050. var hasNormals = attributes.attributes.find(a => a.name === "NormalX") !== undefined && attributes.attributes.find(a => a.name === "NormalY") !== undefined && attributes.attributes.find(a => a.name === "NormalZ") !== undefined;
  44051. if (hasNormals) {
  44052. var vector = {
  44053. name: "NORMAL",
  44054. attributes: ["NormalX", "NormalY", "NormalZ"]
  44055. };
  44056. attributes.addVector(vector);
  44057. }
  44058. }
  44059. return attributes;
  44060. }
  44061. static async load(url) {
  44062. var response = await fetch(url);
  44063. var metadata = await response.json();
  44064. var attributes = OctreeLoader.parseAttributes(metadata.attributes);
  44065. var loader = new NodeLoader(url);
  44066. loader.metadata = metadata;
  44067. loader.attributes = attributes;
  44068. loader.scale = metadata.scale;
  44069. loader.offset = metadata.offset;
  44070. var octree = new OctreeGeometry();
  44071. octree.url = url;
  44072. octree.spacing = metadata.spacing;
  44073. octree.scale = metadata.scale;
  44074. // let aPosition = metadata.attributes.find(a => a.name === "position");
  44075. // octree
  44076. var min = new Vector3(...metadata.boundingBox.min);
  44077. var max = new Vector3(...metadata.boundingBox.max);
  44078. var boundingBox = new Box3(min, max);
  44079. var offset = min.clone();
  44080. boundingBox.min.sub(offset);
  44081. boundingBox.max.sub(offset);
  44082. octree.projection = metadata.projection;
  44083. octree.boundingBox = boundingBox;
  44084. octree.tightBoundingBox = boundingBox.clone();
  44085. octree.boundingSphere = boundingBox.getBoundingSphere(new Sphere());
  44086. octree.tightBoundingSphere = boundingBox.getBoundingSphere(new Sphere());
  44087. octree.offset = offset;
  44088. octree.pointAttributes = OctreeLoader.parseAttributes(metadata.attributes);
  44089. octree.loader = loader;
  44090. var root = new OctreeGeometryNode("r", octree, boundingBox);
  44091. root.level = 0;
  44092. root.nodeType = 2;
  44093. root.hierarchyByteOffset = 0n;
  44094. root.hierarchyByteSize = BigInt(metadata.hierarchy.firstChunkSize);
  44095. root.hasChildren = false;
  44096. root.spacing = octree.spacing;
  44097. root.byteOffset = 0;
  44098. octree.root = root;
  44099. loader.load(root);
  44100. var result = {
  44101. geometry: octree
  44102. };
  44103. return result;
  44104. }
  44105. }
  44106. ;
  44107. /**
  44108. * @author Connor Manning
  44109. */
  44110. class EptLoader {
  44111. static async load(file, callback) {
  44112. var response = await fetch(file);
  44113. var json = await response.json();
  44114. var url = file.substr(0, file.lastIndexOf('ept.json'));
  44115. var geometry = new Potree.PointCloudEptGeometry(url, json);
  44116. var root = new Potree.PointCloudEptGeometryNode(geometry);
  44117. geometry.root = root;
  44118. geometry.root.load();
  44119. callback(geometry);
  44120. }
  44121. }
  44122. ;
  44123. class EptBinaryLoader {
  44124. extension() {
  44125. return '.bin';
  44126. }
  44127. workerPath() {
  44128. return Potree.scriptPath + '/workers/EptBinaryDecoderWorker.js';
  44129. }
  44130. load(node) {
  44131. if (node.loaded) return;
  44132. var url = node.url() + this.extension();
  44133. var xhr = XHRFactory.createXMLHttpRequest();
  44134. xhr.open('GET', url, true);
  44135. xhr.responseType = 'arraybuffer';
  44136. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  44137. xhr.onreadystatechange = () => {
  44138. if (xhr.readyState === 4) {
  44139. if (xhr.status === 200) {
  44140. var buffer = xhr.response;
  44141. this.parse(node, buffer);
  44142. } else {
  44143. console.log('Failed ' + url + ': ' + xhr.status);
  44144. }
  44145. }
  44146. };
  44147. try {
  44148. xhr.send(null);
  44149. } catch (e) {
  44150. console.log('Failed request: ' + e);
  44151. }
  44152. }
  44153. parse(node, buffer) {
  44154. var workerPath = this.workerPath();
  44155. var worker = Potree.workerPool.getWorker(workerPath);
  44156. worker.onmessage = function (e) {
  44157. var g = new BufferGeometry();
  44158. var numPoints = e.data.numPoints;
  44159. var position = new Float32Array(e.data.position);
  44160. g.setAttribute('position', new BufferAttribute(position, 3));
  44161. var indices = new Uint8Array(e.data.indices);
  44162. g.setAttribute('indices', new BufferAttribute(indices, 4));
  44163. if (e.data.color) {
  44164. var color = new Uint8Array(e.data.color);
  44165. g.setAttribute('color', new BufferAttribute(color, 4, true));
  44166. }
  44167. if (e.data.intensity) {
  44168. var intensity = new Float32Array(e.data.intensity);
  44169. g.setAttribute('intensity', new BufferAttribute(intensity, 1));
  44170. }
  44171. if (e.data.classification) {
  44172. var classification = new Uint8Array(e.data.classification);
  44173. g.setAttribute('classification', new BufferAttribute(classification, 1));
  44174. }
  44175. if (e.data.returnNumber) {
  44176. var returnNumber = new Uint8Array(e.data.returnNumber);
  44177. g.setAttribute('return number', new BufferAttribute(returnNumber, 1));
  44178. }
  44179. if (e.data.numberOfReturns) {
  44180. var numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  44181. g.setAttribute('number of returns', new BufferAttribute(numberOfReturns, 1));
  44182. }
  44183. if (e.data.pointSourceId) {
  44184. var pointSourceId = new Uint16Array(e.data.pointSourceId);
  44185. g.setAttribute('source id', new BufferAttribute(pointSourceId, 1));
  44186. }
  44187. g.attributes.indices.normalized = true;
  44188. var tightBoundingBox = new Box3(new Vector3().fromArray(e.data.tightBoundingBox.min), new Vector3().fromArray(e.data.tightBoundingBox.max));
  44189. node.doneLoading(g, tightBoundingBox, numPoints, new Vector3(...e.data.mean));
  44190. Potree.workerPool.returnWorker(workerPath, worker);
  44191. };
  44192. var toArray = v => [v.x, v.y, v.z];
  44193. var message = {
  44194. buffer: buffer,
  44195. schema: node.ept.schema,
  44196. scale: node.ept.eptScale,
  44197. offset: node.ept.eptOffset,
  44198. mins: toArray(node.key.b.min)
  44199. };
  44200. worker.postMessage(message, [message.buffer]);
  44201. }
  44202. }
  44203. ;
  44204. /**
  44205. * laslaz code taken and adapted from plas.io js-laslaz
  44206. * http://plas.io/
  44207. * https://github.com/verma/plasio
  44208. *
  44209. * Thanks to Uday Verma and Howard Butler
  44210. *
  44211. */
  44212. class EptLaszipLoader {
  44213. load(node) {
  44214. if (node.loaded) return;
  44215. var url = node.url() + '.laz';
  44216. var xhr = XHRFactory.createXMLHttpRequest();
  44217. xhr.open('GET', url, true);
  44218. xhr.responseType = 'arraybuffer';
  44219. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  44220. xhr.onreadystatechange = () => {
  44221. if (xhr.readyState === 4) {
  44222. if (xhr.status === 200) {
  44223. var buffer = xhr.response;
  44224. this.parse(node, buffer);
  44225. } else {
  44226. console.log('Failed ' + url + ': ' + xhr.status);
  44227. }
  44228. }
  44229. };
  44230. xhr.send(null);
  44231. }
  44232. async parse(node, buffer) {
  44233. var lf = new LASFile(buffer);
  44234. var handler = new EptLazBatcher(node);
  44235. try {
  44236. await lf.open();
  44237. lf.isOpen = true;
  44238. var header = await lf.getHeader();
  44239. {
  44240. var i = 0;
  44241. var toArray = v => [v.x, v.y, v.z];
  44242. var mins = toArray(node.key.b.min);
  44243. var maxs = toArray(node.key.b.max);
  44244. var hasMoreData = true;
  44245. while (hasMoreData) {
  44246. var data = await lf.readData(1000000, 0, 1);
  44247. var d = new LASDecoder(data.buffer, header.pointsFormatId, header.pointsStructSize, data.count, header.scale, header.offset, mins, maxs);
  44248. d.extraBytes = header.extraBytes;
  44249. d.pointsFormatId = header.pointsFormatId;
  44250. handler.push(d);
  44251. i += data.count;
  44252. hasMoreData = data.hasMoreData;
  44253. }
  44254. header.totalRead = i;
  44255. header.versionAsString = lf.versionAsString;
  44256. header.isCompressed = lf.isCompressed;
  44257. await lf.close();
  44258. lf.isOpen = false;
  44259. }
  44260. } catch (err) {
  44261. console.error('Error reading LAZ:', err);
  44262. if (lf.isOpen) {
  44263. await lf.close();
  44264. lf.isOpen = false;
  44265. }
  44266. throw err;
  44267. }
  44268. }
  44269. }
  44270. ;
  44271. class EptLazBatcher {
  44272. constructor(node) {
  44273. this.node = node;
  44274. }
  44275. push(las) {
  44276. var workerPath = Potree.scriptPath + '/workers/EptLaszipDecoderWorker.js';
  44277. var worker = Potree.workerPool.getWorker(workerPath);
  44278. worker.onmessage = e => {
  44279. var g = new BufferGeometry();
  44280. var numPoints = las.pointsCount;
  44281. var positions = new Float32Array(e.data.position);
  44282. var colors = new Uint8Array(e.data.color);
  44283. var intensities = new Float32Array(e.data.intensity);
  44284. var classifications = new Uint8Array(e.data.classification);
  44285. var returnNumbers = new Uint8Array(e.data.returnNumber);
  44286. var numberOfReturns = new Uint8Array(e.data.numberOfReturns);
  44287. var pointSourceIDs = new Uint16Array(e.data.pointSourceID);
  44288. var indices = new Uint8Array(e.data.indices);
  44289. var gpsTime = new Float32Array(e.data.gpsTime);
  44290. g.setAttribute('position', new BufferAttribute(positions, 3));
  44291. g.setAttribute('rgba', new BufferAttribute(colors, 4, true));
  44292. g.setAttribute('intensity', new BufferAttribute(intensities, 1));
  44293. g.setAttribute('classification', new BufferAttribute(classifications, 1));
  44294. g.setAttribute('return number', new BufferAttribute(returnNumbers, 1));
  44295. g.setAttribute('number of returns', new BufferAttribute(numberOfReturns, 1));
  44296. g.setAttribute('source id', new BufferAttribute(pointSourceIDs, 1));
  44297. g.setAttribute('indices', new BufferAttribute(indices, 4));
  44298. g.setAttribute('gpsTime', new BufferAttribute(gpsTime, 1));
  44299. this.node.gpsTime = e.data.gpsMeta;
  44300. g.attributes.indices.normalized = true;
  44301. var tightBoundingBox = new Box3(new Vector3().fromArray(e.data.tightBoundingBox.min), new Vector3().fromArray(e.data.tightBoundingBox.max));
  44302. this.node.doneLoading(g, tightBoundingBox, numPoints, new Vector3(...e.data.mean));
  44303. Potree.workerPool.returnWorker(workerPath, worker);
  44304. };
  44305. var message = {
  44306. buffer: las.arrayb,
  44307. numPoints: las.pointsCount,
  44308. pointSize: las.pointSize,
  44309. pointFormatID: las.pointsFormatId,
  44310. scale: las.scale,
  44311. offset: las.offset,
  44312. mins: las.mins,
  44313. maxs: las.maxs
  44314. };
  44315. worker.postMessage(message, [message.buffer]);
  44316. }
  44317. }
  44318. ;
  44319. class EptZstandardLoader extends EptBinaryLoader {
  44320. extension() {
  44321. return '.zst';
  44322. }
  44323. workerPath() {
  44324. return Potree.scriptPath + '/workers/EptZstandardDecoderWorker.js';
  44325. }
  44326. }
  44327. ;
  44328. /* proj4.defs("CGCS2000","+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0 +ellps=WGS84 +units=m +no_defs")
  44329. function transformCGCS2000ToWGS84([lng, lat]) {
  44330. // Define the CGCS2000 and WGS84 coordinate systems
  44331. const transformed = proj4("CGCS2000", "LOCAL", [lng, lat]);
  44332. return transformed
  44333. }
  44334. */
  44335. class ShapefileLoader {
  44336. constructor() {
  44337. //this.transform = null;
  44338. }
  44339. async load(path, color) {
  44340. var matLine = new LineMaterial({
  44341. color: color || 0xff0000,
  44342. lineWidth: 3,
  44343. // in pixels
  44344. resolution: new Vector2(1000, 1000),
  44345. dashed: false
  44346. });
  44347. var features = await this.loadShapefileFeatures(path);
  44348. if (!features) {
  44349. console.error('no features', path);
  44350. return;
  44351. }
  44352. var node = new Object3D();
  44353. var transform = await this.loadProj(path, node);
  44354. if (!transform) {
  44355. transform = this.analyseTransform(features, path, node); //自己根据数字来猜测,经纬度一般能准,但数字很大的话就不对了。用户自己移动吧
  44356. }
  44357. var jump = 0;
  44358. for (var feature of features) {
  44359. //5是碎的
  44360. //if(feature.geometry.type!= 'MultiLineString' || ++jump != 5) continue
  44361. var fnode = this.featureToSceneNode(feature, matLine, transform);
  44362. fnode && node.add(fnode);
  44363. }
  44364. var setResolution = (x, y) => {
  44365. matLine.resolution.set(x, y);
  44366. };
  44367. var result = {
  44368. features: features,
  44369. node: node,
  44370. setResolution: setResolution
  44371. };
  44372. return result;
  44373. }
  44374. featureToSceneNode(feature, matLine, transform) {
  44375. //console.log(feature)
  44376. var geometry = feature.geometry;
  44377. var color = new Color(1, 1, 1);
  44378. if (!transform) {
  44379. transform = v => v; //{forward: (v) => v};
  44380. }
  44381. if (geometry.type === "Point") {
  44382. var sg = new SphereGeometry(1, 18, 18);
  44383. var sm = new MeshNormalMaterial();
  44384. var s = new Mesh(sg, sm);
  44385. var [long, lat] = geometry.coordinates;
  44386. var pos = transform /* .forward */([long, lat]);
  44387. s.position.set(...pos, 20);
  44388. s.scale.set(10, 10, 10);
  44389. return s;
  44390. } else if (geometry.type === "LineString") {
  44391. var coordinates = [];
  44392. var min = new Vector3(Infinity, Infinity, Infinity);
  44393. for (var i = 0; i < geometry.coordinates.length; i++) {
  44394. var [_long, _lat] = geometry.coordinates[i];
  44395. var _pos = transform /* .forward */([_long, _lat]);
  44396. min.x = Math.min(min.x, _pos[0]);
  44397. min.y = Math.min(min.y, _pos[1]);
  44398. min.z = Math.min(min.z, 20);
  44399. coordinates.push(..._pos, 20);
  44400. if (i > 0 && i < geometry.coordinates.length - 1) {
  44401. coordinates.push(..._pos, 20);
  44402. }
  44403. }
  44404. for (var _i = 0; _i < coordinates.length; _i += 3) {
  44405. coordinates[_i + 0] -= min.x;
  44406. coordinates[_i + 1] -= min.y;
  44407. coordinates[_i + 2] -= min.z;
  44408. }
  44409. var lineGeometry = new LineGeometry();
  44410. lineGeometry.setPositions(coordinates);
  44411. var line = new Line2(lineGeometry, matLine);
  44412. line.computeLineDistances();
  44413. line.scale.set(1, 1, 1);
  44414. line.position.copy(min);
  44415. return line;
  44416. } else if (geometry.type === "MultiLineString") {
  44417. //xzw add 江门的那个文件
  44418. var _coordinates = [];
  44419. //console.warn('MultiLineString') //多组连续线段,组之间不连续
  44420. var _min = new Vector3(Infinity, Infinity, Infinity);
  44421. var _loop = function _loop() {
  44422. var points = geometry.coordinates[_i2]; //有时候是两个点有时候多个
  44423. var coordinateSlice = [];
  44424. points.forEach(point => {
  44425. var [long, lat] = point;
  44426. var pos = transform /* .forward */([long, lat]);
  44427. _min.x = Math.min(_min.x, pos[0]);
  44428. _min.y = Math.min(_min.y, pos[1]);
  44429. _min.z = Math.min(_min.z, 20);
  44430. coordinateSlice.push(new Vector3(pos[0], pos[1], 20));
  44431. });
  44432. _coordinates.push(coordinateSlice);
  44433. };
  44434. for (var _i2 = 0; _i2 < geometry.coordinates.length; _i2++) {
  44435. _loop();
  44436. }
  44437. _coordinates.forEach(coordinateSlice => coordinateSlice.forEach(point => point.sub(_min)));
  44438. var _line = LineDraw.createFatLine(_coordinates, {
  44439. uncontinuous: true,
  44440. mat: matLine
  44441. /* color: 0xff0000,
  44442. dashSize: 0.5,
  44443. gapSize: 0.2,
  44444. lineWidth: config$1.measure.lineWidth, */
  44445. });
  44446. _line.position.copy(_min);
  44447. return _line;
  44448. } else if (geometry.type === "Polygon") {
  44449. for (var pc of geometry.coordinates) {
  44450. var _coordinates2 = [];
  44451. var _min2 = new Vector3(Infinity, Infinity, Infinity);
  44452. for (var _i3 = 0; _i3 < pc.length; _i3++) {
  44453. var [_long2, _lat2] = pc[_i3];
  44454. var _pos2 = transform /* .forward */([_long2, _lat2]);
  44455. _min2.x = Math.min(_min2.x, _pos2[0]);
  44456. _min2.y = Math.min(_min2.y, _pos2[1]);
  44457. _min2.z = Math.min(_min2.z, 20);
  44458. _coordinates2.push(..._pos2, 20);
  44459. if (_i3 > 0 && _i3 < pc.length - 1) {
  44460. _coordinates2.push(..._pos2, 20);
  44461. }
  44462. }
  44463. for (var _i4 = 0; _i4 < _coordinates2.length; _i4 += 3) {
  44464. _coordinates2[_i4 + 0] -= _min2.x;
  44465. _coordinates2[_i4 + 1] -= _min2.y;
  44466. _coordinates2[_i4 + 2] -= _min2.z;
  44467. }
  44468. var _lineGeometry = new LineGeometry();
  44469. _lineGeometry.setPositions(_coordinates2);
  44470. var _line2 = new Line2(_lineGeometry, matLine);
  44471. _line2.computeLineDistances();
  44472. _line2.scale.set(1, 1, 1);
  44473. _line2.position.copy(_min2);
  44474. return _line2;
  44475. }
  44476. } else {
  44477. console.log("unhandled feature: ", geometry.type);
  44478. }
  44479. function getLine(coordinates) {}
  44480. }
  44481. async loadShapefileFeatures(file) {
  44482. var features = [];
  44483. if (file.split('.').pop() == 'shp') {
  44484. var source = await shapefile.open(file);
  44485. while (true) {
  44486. var result = await source.read();
  44487. if (result.done) {
  44488. break;
  44489. }
  44490. //value中的properties来自dbf,但该属性没有被用到,是否可以不加载
  44491. if (result.value && result.value.type === 'Feature' && result.value.geometry !== undefined) {
  44492. features.push(result.value);
  44493. }
  44494. }
  44495. return features;
  44496. } else if (file.split('.').pop() == 'json') {
  44497. return new Promise((resolve, reject) => {
  44498. Potree.loadFile(file, {}, data => {
  44499. console.log(data);
  44500. resolve(data.features);
  44501. });
  44502. });
  44503. }
  44504. }
  44505. analyseTransform(features, path, node) {
  44506. //xzw只能自己暂时判断下 ,最好能根据.prj判断
  44507. if (viewer.transform) {
  44508. var count = 0,
  44509. maxCount = 100;
  44510. var notLonLat, _transform;
  44511. var prjJson = node.prjJson;
  44512. if (prjJson && prjJson.unit) {
  44513. if (prjJson.unit.name.toLowerCase() == 'meter') {
  44514. //'degree'
  44515. notLonLat = true;
  44516. }
  44517. } else {
  44518. var judge = coord => {
  44519. if (!(coord[0] >= -180 && coord[0] <= 180 && coord[1] >= -90 && coord[1] <= 90)) {
  44520. //如果超出经纬度范围,那就不是经纬度
  44521. notLonLat = true;
  44522. node.prjNotSure = true; //不确定,不设定默认位置
  44523. }
  44524. count++;
  44525. }; //数字很小的话一般都是经纬度吧,就当作确定了
  44526. for (var feature of features) {
  44527. if (count > maxCount) break;
  44528. for (var arr of feature.geometry.coordinates) {
  44529. if (arr[0] instanceof Array) {
  44530. for (var coord of arr) {
  44531. judge(coord);
  44532. if (count > maxCount || notLonLat) break;
  44533. }
  44534. } else {
  44535. judge(arr);
  44536. if (count > maxCount || notLonLat) break;
  44537. }
  44538. }
  44539. }
  44540. }
  44541. if (notLonLat) {
  44542. /* transform = (v)=>{
  44543. let a = viewer.transform.lonlatTo4550.inverse(v) //这种类型和不使用transform很接近
  44544. return viewer.transform.lonlatToLocal.forward(a)
  44545. } */
  44546. console.log('该shape不使用transform', path.split('/').pop());
  44547. } else {
  44548. _transform = viewer.transform.lonlatToLocal.forward;
  44549. console.log('根据坐标数值猜测,该shape使用经纬度', path.split('/').pop());
  44550. }
  44551. return _transform;
  44552. //loaders.shapeLoader.transform = viewer.transform.lonlatToLocal.forward;
  44553. } else {
  44554. node.prjNotSure = true;
  44555. console.log('该shape没用任何transform 因为场景没有设置经纬度', path.split('/').pop());
  44556. }
  44557. }
  44558. async loadProj(path, model) {
  44559. var a = path.split('/');
  44560. var name = a.pop().split('.')[0];
  44561. path = a.join('/') + '/' + name + '.prj';
  44562. return new Promise((resolve, reject) => {
  44563. Potree.loadFile(path, {
  44564. returnText: true
  44565. }, e => {
  44566. name += '_proj';
  44567. var projDef = parsePrjToProj4(e, model);
  44568. proj4.defs(name, projDef);
  44569. console.log('loadedProj:', name, '解析得def: ', projDef, '原:', e, 'json:', model.prjJson);
  44570. try {
  44571. var proj = proj4(name, "LOCAL");
  44572. var _transform2 = _ref => {
  44573. var [lng, lat] = _ref;
  44574. return proj.forward([lng, lat]);
  44575. };
  44576. resolve(_transform2);
  44577. } catch (e) {
  44578. console.warn(e, '建立proj4 transform 失败', name);
  44579. resolve();
  44580. }
  44581. }, () => {
  44582. resolve();
  44583. });
  44584. });
  44585. return transform;
  44586. }
  44587. }
  44588. ;
  44589. function parsePrjToProj4(prjString, model) {
  44590. var _json$geogcs;
  44591. //将prj的内容变为proj4的transform
  44592. var def = '';
  44593. var json = model.prjJson = prjToJson(prjString);
  44594. var projectionType;
  44595. var datum = '';
  44596. var ellipsoid = '';
  44597. var centralLon = '0',
  44598. centralLat = '0';
  44599. var scaleFactor = '1';
  44600. var falseEasting = '0',
  44601. falseNorthing = '0';
  44602. if (json.projection == 'Transverse_Mercator') {
  44603. projectionType = 'tmerc';
  44604. } else if (!json.projection) {
  44605. projectionType = 'longlat';
  44606. } else {
  44607. projectionType = projection;
  44608. console.log('unknown projection:', json.projection);
  44609. }
  44610. if (json.parameters) {
  44611. falseEasting = json.parameters.false_easting;
  44612. falseNorthing = json.parameters.false_northing;
  44613. centralLon = json.parameters.central_meridian;
  44614. centralLat = json.parameters.latitude_of_origin;
  44615. scaleFactor = json.parameters.scale_factor;
  44616. }
  44617. if ((_json$geogcs = json.geogcs) !== null && _json$geogcs !== void 0 && _json$geogcs.spheroid) {
  44618. var spheroid = json.geogcs.spheroid.name.toLowerCase().replace('_', '');
  44619. if (spheroid.includes('wgs84') || spheroid.includes('wgs1984')) ellipsoid = 'WGS84';
  44620. }
  44621. def += "+proj=".concat(projectionType, " ");
  44622. def += "+lat_0=".concat(centralLat, " ");
  44623. def += "+lon_0=".concat(centralLon, " ");
  44624. def += "+k=".concat(scaleFactor, " ");
  44625. def += "+x_0=".concat(falseEasting, " ");
  44626. def += "+y_0=".concat(falseNorthing, " ");
  44627. ellipsoid && (def += "+ellps=".concat(ellipsoid, " "));
  44628. def += '+units=m +no_defs';
  44629. return def;
  44630. }
  44631. function prjToJson(prjString) {
  44632. //将prj的内容变为json
  44633. var result = {};
  44634. // 提取 PROJCS 和 GEOGCS 信息
  44635. var projcsMatch = prjString.match(/PROJCS\["([^"]+)",(.*)\]/);
  44636. if (projcsMatch) {
  44637. result.projcsName = projcsMatch[1];
  44638. var geoPart = projcsMatch[2];
  44639. // 解析 GEOGCS 部分
  44640. var geoMatch = geoPart.match(/GEOGCS\["([^"]+)",DATUM\["([^"]+)",SPHEROID\["([^"]+)",([0-9.]+),([0-9.]+)\]\],PRIMEM\["([^"]+)",([0-9.]+)\],UNIT\["([^"]+)",([0-9.]+)\]/);
  44641. if (geoMatch) {
  44642. result.geogcs = {
  44643. name: geoMatch[1],
  44644. datum: geoMatch[2],
  44645. spheroid: {
  44646. name: geoMatch[3],
  44647. semiMajorAxis: parseFloat(geoMatch[4]),
  44648. inverseFlattening: parseFloat(geoMatch[5])
  44649. },
  44650. primeMeridian: {
  44651. name: geoMatch[6],
  44652. value: parseFloat(geoMatch[7])
  44653. },
  44654. unit: {
  44655. name: geoMatch[8],
  44656. conversionFactor: parseFloat(geoMatch[9])
  44657. }
  44658. };
  44659. }
  44660. // 解析 PROJECTION 部分
  44661. var projMatch = geoPart.match(/PROJECTION\["([^"]+)"\]/);
  44662. if (projMatch) {
  44663. result.projection = projMatch[1];
  44664. }
  44665. // 解析 PARAMETER 部分
  44666. var parameters = {};
  44667. var paramMatches = geoPart.matchAll(/PARAMETER\["([^"]+)",([-\d.]+)\]/g);
  44668. for (var match of paramMatches) {
  44669. parameters[match[1]] = parseFloat(match[2]);
  44670. }
  44671. result.parameters = parameters;
  44672. // 解析 UNIT 部分
  44673. var unitMatch = geoPart.match(/UNIT\["([^"]+)",([-\d.]+)\]/);
  44674. if (unitMatch) {
  44675. result.unit = {
  44676. name: unitMatch[1],
  44677. conversionFactor: parseFloat(unitMatch[2])
  44678. };
  44679. }
  44680. } else {
  44681. // 如果没有 PROJCS,则尝试解析 GEOGCS
  44682. var _geoMatch = prjString.match(/GEOGCS\["([^"]+)",DATUM\["([^"]+)",SPHEROID\["([^"]+)",([0-9.]+),([0-9.]+)\]\],PRIMEM\["([^"]+)",([0-9.]+)\],UNIT\["([^"]+)",([0-9.]+)\]/);
  44683. if (_geoMatch) {
  44684. result.geogcs = {
  44685. name: _geoMatch[1],
  44686. datum: _geoMatch[2],
  44687. spheroid: {
  44688. name: _geoMatch[3],
  44689. semiMajorAxis: parseFloat(_geoMatch[4]),
  44690. inverseFlattening: parseFloat(_geoMatch[5])
  44691. },
  44692. primeMeridian: {
  44693. name: _geoMatch[6],
  44694. value: parseFloat(_geoMatch[7])
  44695. },
  44696. unit: {
  44697. name: _geoMatch[8],
  44698. conversionFactor: parseFloat(_geoMatch[9])
  44699. }
  44700. };
  44701. }
  44702. }
  44703. return result;
  44704. }
  44705. /*
  44706. function parsePrjToProj4(prjString) {
  44707. // 初始化 Proj4 字符串的部分
  44708. let proj4Def = ''
  44709. // 提取关键信息
  44710. const prjParts = prjString.match(/(\w+)\[(.*?)\]/g);
  44711. let projectionType = '';
  44712. let datum = '';
  44713. let ellipsoid = '';
  44714. let centralMeridian = '';
  44715. let scaleFactor = '1';
  44716. let falseEasting = '0';
  44717. let falseNorthing = '0';
  44718. let latitudeOfOrigin = '0';
  44719. prjParts.forEach(part => {
  44720. if (part.includes('PROJECTION')) {
  44721. projectionType = part.match(/"([^"]+)"/)[1].toLowerCase().replace('_', '');
  44722. //xzw:
  44723. if(projectionType == 'transversemercator') projectionType = 'tmerc'
  44724. }else if (part.includes('DATUM')) {
  44725. datum = part.match(/"([^"]+)"/)[1];
  44726. } else if (part.includes('SPHEROID')) {
  44727. ellipsoid = part.match(/"([^"]+)"/)[1].toLowerCase();
  44728. } else if (part.includes('PARAMETER')) {
  44729. let paramName = part.match(/"([^"]+)"/)[1].toLowerCase().replace(/ /g, '_');
  44730. let paramValue = part.match(/(-?\d+\.?\d*)/)[1];
  44731. switch (paramName) {
  44732. case 'central_meridian':
  44733. centralMeridian = paramValue;
  44734. break;
  44735. case 'scale_factor':
  44736. scaleFactor = paramValue;
  44737. break;
  44738. case 'false_easting':
  44739. falseEasting = paramValue;
  44740. break;
  44741. case 'false_northing':
  44742. falseNorthing = paramValue;
  44743. break;
  44744. case 'latitude_of_origin':
  44745. latitudeOfOrigin = paramValue;
  44746. break;
  44747. }
  44748. }
  44749. });
  44750. // 构建完整的 Proj4 定义字符串
  44751. if(!projectionType && prjString.includes('GCS_WGS_1984')) projectionType = 'longlat'
  44752. projectionType && (proj4Def += `+proj=${projectionType} `)
  44753. proj4Def += `+lat_0=${latitudeOfOrigin} `;
  44754. proj4Def += `+lon_0=${centralMeridian} `;
  44755. proj4Def += `+k=${scaleFactor} `;
  44756. proj4Def += `+x_0=${falseEasting} `;
  44757. proj4Def += `+y_0=${falseNorthing} `;
  44758. ellipsoid && (proj4Def += `+ellps=${ellipsoid} `);
  44759. proj4Def += '+units=m +no_defs';
  44760. return proj4Def;
  44761. }
  44762. */
  44763. /*
  44764. function parsePrjToProj4(prjString) {
  44765. // 初始化 Proj4 参数对象
  44766. let proj4Params = {};
  44767. // 提取 PROJCS 和 GEOGCS 部分
  44768. const projcsMatch = prjString.match(/PROJCS\["([^"]+)",(.*)\]/);
  44769. if (projcsMatch){
  44770. const projcsName = projcsMatch[1];
  44771. const geoPart = projcsMatch[2];
  44772. // 解析 GEOGCS 部分
  44773. const datumMatch = geoPart.match(/DATUM\["([^"]+)",SPHEROID\["([^"]+)",([0-9.]+),([0-9.]+)\]\]/);
  44774. if (datumMatch) {
  44775. proj4Params.datum = datumMatch[1].toLowerCase();
  44776. proj4Params.ellps = datumMatch[2].toLowerCase();
  44777. proj4Params.a = parseFloat(datumMatch[3]); // Semi-major axis
  44778. proj4Params.rf = parseFloat(datumMatch[4]); // Inverse flattening
  44779. }
  44780. // 解析 PROJECTION 部分
  44781. const projMatch = geoPart.match(/PROJECTION\["([^"]+)"\]/);
  44782. if (projMatch) {
  44783. proj4Params.proj = projMatch[1].toLowerCase().replace(/_/g, '');
  44784. }
  44785. // 解析 PARAMETER 部分
  44786. const paramMatches = geoPart.matchAll(/PARAMETER\["([^"]+)",([-\d.]+)\]/g);
  44787. for (const match of paramMatches) {
  44788. const paramName = match[1].toLowerCase().replace(/ /g, '_');
  44789. const paramValue = parseFloat(match[2]);
  44790. switch (paramName) {
  44791. case 'false_easting':
  44792. proj4Params.x_0 = paramValue;
  44793. break;
  44794. case 'false_northing':
  44795. proj4Params.y_0 = paramValue;
  44796. break;
  44797. case 'central_meridian':
  44798. proj4Params.lon_0 = paramValue;
  44799. break;
  44800. case 'scale_factor':
  44801. proj4Params.k = paramValue;
  44802. break;
  44803. case 'latitude_of_origin':
  44804. proj4Params.lat_0 = paramValue;
  44805. break;
  44806. }
  44807. }
  44808. // 设置单位
  44809. proj4Params.units = "m"; // 默认米
  44810. proj4Params.no_defs = true;
  44811. // 构建 Proj4 字符串
  44812. let proj4Def = '+proj=' + proj4Params.proj;
  44813. proj4Def += ' +lat_0=' + proj4Params.lat_0;
  44814. proj4Def += ' +lon_0=' + proj4Params.lon_0;
  44815. proj4Def += ' +k=' + proj4Params.k;
  44816. proj4Def += ' +x_0=' + proj4Params.x_0;
  44817. proj4Def += ' +y_0=' + proj4Params.y_0;
  44818. proj4Def += ' +ellps=' + proj4Params.ellps;
  44819. proj4Def += ' +units=' + proj4Params.units;
  44820. proj4Def += ' +no_defs';
  44821. return proj4Def;
  44822. }
  44823. */
  44824. //shp必须,dbf目前没用,prj最好有
  44825. var defaultColors = {
  44826. "landuse": [0.5, 0.5, 0.5],
  44827. "natural": [0.0, 1.0, 0.0],
  44828. "places": [1.0, 0.0, 1.0],
  44829. "points": [0.0, 1.0, 1.0],
  44830. "roads": [1.0, 1.0, 0.0],
  44831. "waterways": [0.0, 0.0, 1.0],
  44832. "default": [0.9, 0.6, 0.1]
  44833. };
  44834. function getColor(feature) {
  44835. var color = defaultColors[feature];
  44836. if (!color) {
  44837. color = defaultColors["default"];
  44838. }
  44839. return color;
  44840. }
  44841. class Geopackage$1 {
  44842. constructor() {
  44843. this.path = null;
  44844. this.node = null;
  44845. }
  44846. }
  44847. ;
  44848. class GeoPackageLoader {
  44849. constructor() {}
  44850. static async loadUrl(url, params) {
  44851. await Promise.all([Utils.loadScript("".concat(Potree.scriptPath, "/lazylibs/geopackage/geopackage.js")), Utils.loadScript("".concat(Potree.scriptPath, "/lazylibs/sql.js/sql-wasm.js"))]);
  44852. var result = await fetch(url);
  44853. var buffer = await result.arrayBuffer();
  44854. params = params || {};
  44855. params.source = url;
  44856. return GeoPackageLoader.loadBuffer(buffer, params);
  44857. }
  44858. static async loadBuffer(buffer, params) {
  44859. await Promise.all([Utils.loadScript("".concat(Potree.scriptPath, "/lazylibs/geopackage/geopackage.js")), Utils.loadScript("".concat(Potree.scriptPath, "/lazylibs/sql.js/sql-wasm.js"))]);
  44860. params = params || {};
  44861. var resolver = async resolve => {
  44862. var transform = params.transform;
  44863. if (!transform) {
  44864. transform = {
  44865. forward: arg => arg
  44866. };
  44867. }
  44868. var wasmPath = "".concat(Potree.scriptPath, "/lazylibs/sql.js/sql-wasm.wasm");
  44869. var SQL = await initSqlJs({
  44870. locateFile: filename => wasmPath
  44871. });
  44872. var u8 = new Uint8Array(buffer);
  44873. var data = await geopackage.open(u8);
  44874. window.data = data;
  44875. var geopackageNode = new Object3D();
  44876. geopackageNode.name = params.source;
  44877. geopackageNode.potree = {
  44878. source: params.source
  44879. };
  44880. var geo = new Geopackage$1();
  44881. geo.path = params.source;
  44882. geo.node = geopackageNode;
  44883. var tables = data.getTables();
  44884. for (var table of tables.features) {
  44885. var dao = data.getFeatureDao(table);
  44886. var boundingBox = dao.getBoundingBox();
  44887. boundingBox = boundingBox.projectBoundingBox(dao.projection, 'EPSG:4326');
  44888. var geoJson = data.queryForGeoJSONFeaturesInTable(table, boundingBox);
  44889. var matLine = new LineMaterial({
  44890. color: new Color().setRGB(...getColor(table)),
  44891. linewidth: 2,
  44892. resolution: new Vector2(1000, 1000),
  44893. dashed: false
  44894. });
  44895. var node = new Object3D();
  44896. node.name = table;
  44897. geo.node.add(node);
  44898. for (var [index, feature] of Object.entries(geoJson)) {
  44899. //const featureNode = GeoPackageLoader.featureToSceneNode(feature, matLine, transform);
  44900. var featureNode = GeoPackageLoader.featureToSceneNode(feature, matLine, dao.projection, transform);
  44901. node.add(featureNode);
  44902. }
  44903. }
  44904. resolve(geo);
  44905. };
  44906. return new Promise(resolver);
  44907. }
  44908. static featureToSceneNode(feature, matLine, geopackageProjection, transform) {
  44909. var geometry = feature.geometry;
  44910. var color = new Color(1, 1, 1);
  44911. if (feature.geometry.type === "Point") {
  44912. var sg = new SphereGeometry(1, 18, 18);
  44913. var sm = new MeshNormalMaterial();
  44914. var s = new Mesh(sg, sm);
  44915. var [long, lat] = geometry.coordinates;
  44916. var pos = transform.forward(geopackageProjection.forward([long, lat]));
  44917. s.position.set(...pos, 20);
  44918. s.scale.set(10, 10, 10);
  44919. return s;
  44920. } else if (geometry.type === "LineString") {
  44921. var coordinates = [];
  44922. var min = new Vector3(Infinity, Infinity, Infinity);
  44923. for (var i = 0; i < geometry.coordinates.length; i++) {
  44924. var [_long, _lat] = geometry.coordinates[i];
  44925. var _pos = transform.forward(geopackageProjection.forward([_long, _lat]));
  44926. min.x = Math.min(min.x, _pos[0]);
  44927. min.y = Math.min(min.y, _pos[1]);
  44928. min.z = Math.min(min.z, 20);
  44929. coordinates.push(..._pos, 20);
  44930. if (i > 0 && i < geometry.coordinates.length - 1) {
  44931. coordinates.push(..._pos, 20);
  44932. }
  44933. }
  44934. for (var _i = 0; _i < coordinates.length; _i += 3) {
  44935. coordinates[_i + 0] -= min.x;
  44936. coordinates[_i + 1] -= min.y;
  44937. coordinates[_i + 2] -= min.z;
  44938. }
  44939. var lineGeometry = new LineGeometry();
  44940. lineGeometry.setPositions(coordinates);
  44941. var line = new Line2(lineGeometry, matLine);
  44942. line.computeLineDistances();
  44943. line.scale.set(1, 1, 1);
  44944. line.position.copy(min);
  44945. return line;
  44946. } else if (geometry.type === "Polygon") {
  44947. for (var pc of geometry.coordinates) {
  44948. var _coordinates = [];
  44949. var _min = new Vector3(Infinity, Infinity, Infinity);
  44950. for (var _i2 = 0; _i2 < pc.length; _i2++) {
  44951. var [_long2, _lat2] = pc[_i2];
  44952. var _pos2 = transform.forward(geopackageProjection.forward([_long2, _lat2]));
  44953. _min.x = Math.min(_min.x, _pos2[0]);
  44954. _min.y = Math.min(_min.y, _pos2[1]);
  44955. _min.z = Math.min(_min.z, 20);
  44956. _coordinates.push(..._pos2, 20);
  44957. if (_i2 > 0 && _i2 < pc.length - 1) {
  44958. _coordinates.push(..._pos2, 20);
  44959. }
  44960. }
  44961. for (var _i3 = 0; _i3 < _coordinates.length; _i3 += 3) {
  44962. _coordinates[_i3 + 0] -= _min.x;
  44963. _coordinates[_i3 + 1] -= _min.y;
  44964. _coordinates[_i3 + 2] -= _min.z;
  44965. }
  44966. var _lineGeometry = new LineGeometry();
  44967. _lineGeometry.setPositions(_coordinates);
  44968. var _line = new Line2(_lineGeometry, matLine);
  44969. _line.computeLineDistances();
  44970. _line.scale.set(1, 1, 1);
  44971. _line.position.copy(_min);
  44972. return _line;
  44973. }
  44974. } else {
  44975. console.log("unhandled feature: ", feature);
  44976. }
  44977. }
  44978. }
  44979. ;
  44980. class ClipVolume extends Object3D {
  44981. constructor(args) {
  44982. super();
  44983. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  44984. this.name = "clip_volume_" + this.constructor.counter;
  44985. var alpha = args.alpha || 0;
  44986. var beta = args.beta || 0;
  44987. var gamma = args.gamma || 0;
  44988. this.rotation.x = alpha;
  44989. this.rotation.y = beta;
  44990. this.rotation.z = gamma;
  44991. this.clipOffset = 0.001;
  44992. this.clipRotOffset = 1;
  44993. var boxGeometry = new BoxGeometry(1, 1, 1);
  44994. boxGeometry.computeBoundingBox();
  44995. var boxFrameGeometry = new Geometry();
  44996. {
  44997. // bottom
  44998. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  44999. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  45000. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  45001. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  45002. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  45003. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  45004. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  45005. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  45006. // top
  45007. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  45008. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  45009. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  45010. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  45011. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  45012. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  45013. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  45014. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  45015. // sides
  45016. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  45017. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  45018. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  45019. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  45020. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  45021. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  45022. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  45023. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  45024. boxFrameGeometry.colors.push(new Vector3(1, 1, 1));
  45025. }
  45026. var planeFrameGeometry = new Geometry();
  45027. {
  45028. // middle line
  45029. planeFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.0));
  45030. planeFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.0));
  45031. planeFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.0));
  45032. planeFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.0));
  45033. planeFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.0));
  45034. planeFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.0));
  45035. planeFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.0));
  45036. planeFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.0));
  45037. }
  45038. this.dimension = new Vector3(1, 1, 1);
  45039. this.material = new MeshBasicMaterial({
  45040. color: 0x00ff00,
  45041. transparent: true,
  45042. opacity: 0.3,
  45043. depthTest: true,
  45044. depthWrite: false
  45045. });
  45046. this.box = new Mesh(boxGeometry, this.material);
  45047. this.box.geometry.computeBoundingBox();
  45048. this.boundingBox = this.box.geometry.boundingBox;
  45049. this.add(this.box);
  45050. this.frame = new LineSegments(boxFrameGeometry, new LineBasicMaterial({
  45051. color: 0x000000
  45052. }));
  45053. this.add(this.frame);
  45054. this.planeFrame = new LineSegments(planeFrameGeometry, new LineBasicMaterial({
  45055. color: 0xff0000
  45056. }));
  45057. this.add(this.planeFrame);
  45058. // set default thickness
  45059. this.setScaleZ(0.1);
  45060. // create local coordinate system
  45061. var createArrow = (name, direction, color) => {
  45062. var material = new MeshBasicMaterial({
  45063. color: color,
  45064. depthTest: false,
  45065. depthWrite: false
  45066. });
  45067. var shaftGeometry = new Geometry();
  45068. shaftGeometry.vertices.push(new Vector3(0, 0, 0));
  45069. shaftGeometry.vertices.push(new Vector3(0, 1, 0));
  45070. var shaftMaterial = new LineBasicMaterial({
  45071. color: color,
  45072. depthTest: false,
  45073. depthWrite: false,
  45074. transparent: true
  45075. });
  45076. var shaft = new Line(shaftGeometry, shaftMaterial);
  45077. shaft.name = name + "_shaft";
  45078. var headGeometry = new CylinderGeometry(0, 0.04, 0.1, 10, 1, false);
  45079. var headMaterial = material;
  45080. var head = new Mesh(headGeometry, headMaterial);
  45081. head.name = name + "_head";
  45082. head.position.y = 1;
  45083. var arrow = new Object3D();
  45084. arrow.name = name;
  45085. arrow.add(shaft);
  45086. arrow.add(head);
  45087. return arrow;
  45088. };
  45089. this.arrowX = createArrow("arrow_x", new Vector3(1, 0, 0), 0xFF0000);
  45090. this.arrowY = createArrow("arrow_y", new Vector3(0, 1, 0), 0x00FF00);
  45091. this.arrowZ = createArrow("arrow_z", new Vector3(0, 0, 1), 0x0000FF);
  45092. this.arrowX.rotation.z = -Math.PI / 2;
  45093. this.arrowZ.rotation.x = Math.PI / 2;
  45094. this.arrowX.visible = false;
  45095. this.arrowY.visible = false;
  45096. this.arrowZ.visible = false;
  45097. this.add(this.arrowX);
  45098. this.add(this.arrowY);
  45099. this.add(this.arrowZ);
  45100. {
  45101. // event listeners
  45102. this.addEventListener("ui_select", e => {
  45103. this.arrowX.visible = true;
  45104. this.arrowY.visible = true;
  45105. this.arrowZ.visible = true;
  45106. });
  45107. this.addEventListener("ui_deselect", e => {
  45108. this.arrowX.visible = false;
  45109. this.arrowY.visible = false;
  45110. this.arrowZ.visible = false;
  45111. });
  45112. this.addEventListener("select", e => {
  45113. var scene_header = $("#" + this.name + " .scene_header");
  45114. if (!scene_header.next().is(":visible")) {
  45115. scene_header.click();
  45116. }
  45117. });
  45118. this.addEventListener("deselect", e => {
  45119. var scene_header = $("#" + this.name + " .scene_header");
  45120. if (scene_header.next().is(":visible")) {
  45121. scene_header.click();
  45122. }
  45123. });
  45124. }
  45125. this.update();
  45126. }
  45127. setClipOffset(offset) {
  45128. this.clipOffset = offset;
  45129. }
  45130. setClipRotOffset(offset) {
  45131. this.clipRotOffset = offset;
  45132. }
  45133. setScaleX(x) {
  45134. this.box.scale.x = x;
  45135. this.frame.scale.x = x;
  45136. this.planeFrame.scale.x = x;
  45137. }
  45138. setScaleY(y) {
  45139. this.box.scale.y = y;
  45140. this.frame.scale.y = y;
  45141. this.planeFrame.scale.y = y;
  45142. }
  45143. setScaleZ(z) {
  45144. this.box.scale.z = z;
  45145. this.frame.scale.z = z;
  45146. this.planeFrame.scale.z = z;
  45147. }
  45148. offset(args) {
  45149. var cs = args.cs || null;
  45150. var axis = args.axis || null;
  45151. var dir = args.dir || null;
  45152. if (!cs || !axis || !dir) return;
  45153. if (axis === "x") {
  45154. if (cs === "local") {
  45155. this.position.add(this.localX.clone().multiplyScalar(dir * this.clipOffset));
  45156. } else if (cs === "global") {
  45157. this.position.x = this.position.x + dir * this.clipOffset;
  45158. }
  45159. } else if (axis === "y") {
  45160. if (cs === "local") {
  45161. this.position.add(this.localY.clone().multiplyScalar(dir * this.clipOffset));
  45162. } else if (cs === "global") {
  45163. this.position.y = this.position.y + dir * this.clipOffset;
  45164. }
  45165. } else if (axis === "z") {
  45166. if (cs === "local") {
  45167. this.position.add(this.localZ.clone().multiplyScalar(dir * this.clipOffset));
  45168. } else if (cs === "global") {
  45169. this.position.z = this.position.z + dir * this.clipOffset;
  45170. }
  45171. }
  45172. this.dispatchEvent({
  45173. "type": "clip_volume_changed",
  45174. "viewer": viewer,
  45175. "volume": this
  45176. });
  45177. }
  45178. rotate(args) {
  45179. var cs = args.cs || null;
  45180. var axis = args.axis || null;
  45181. var dir = args.dir || null;
  45182. if (!cs || !axis || !dir) return;
  45183. if (cs === "local") {
  45184. if (axis === "x") {
  45185. this.rotateOnAxis(new Vector3(1, 0, 0), dir * this.clipRotOffset * Math.PI / 180);
  45186. } else if (axis === "y") {
  45187. this.rotateOnAxis(new Vector3(0, 1, 0), dir * this.clipRotOffset * Math.PI / 180);
  45188. } else if (axis === "z") {
  45189. this.rotateOnAxis(new Vector3(0, 0, 1), dir * this.clipRotOffset * Math.PI / 180);
  45190. }
  45191. } else if (cs === "global") {
  45192. var rotaxis = new Vector4(1, 0, 0, 0);
  45193. if (axis === "y") {
  45194. rotaxis = new Vector4(0, 1, 0, 0);
  45195. } else if (axis === "z") {
  45196. rotaxis = new Vector4(0, 0, 1, 0);
  45197. }
  45198. this.updateMatrixWorld();
  45199. var invM = newthis.matrixWorld.clone().invert();
  45200. rotaxis = rotaxis.applyMatrix4(invM).normalize();
  45201. rotaxis = new Vector3(rotaxis.x, rotaxis.y, rotaxis.z);
  45202. this.rotateOnAxis(rotaxis, dir * this.clipRotOffset * Math.PI / 180);
  45203. }
  45204. this.updateLocalSystem();
  45205. this.dispatchEvent({
  45206. "type": "clip_volume_changed",
  45207. "viewer": viewer,
  45208. "volume": this
  45209. });
  45210. }
  45211. update() {
  45212. this.boundingBox = this.box.geometry.boundingBox;
  45213. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  45214. this.box.visible = false;
  45215. this.updateLocalSystem();
  45216. }
  45217. updateLocalSystem() {
  45218. // extract local coordinate axes
  45219. var rotQuat = this.getWorldQuaternion();
  45220. this.localX = new Vector3(1, 0, 0).applyQuaternion(rotQuat).normalize();
  45221. this.localY = new Vector3(0, 1, 0).applyQuaternion(rotQuat).normalize();
  45222. this.localZ = new Vector3(0, 0, 1).applyQuaternion(rotQuat).normalize();
  45223. }
  45224. raycast(raycaster, intersects) {
  45225. var is = [];
  45226. this.box.raycast(raycaster, is);
  45227. if (is.length > 0) {
  45228. var I = is[0];
  45229. intersects.push({
  45230. distance: I.distance,
  45231. object: this,
  45232. point: I.point.clone()
  45233. });
  45234. }
  45235. }
  45236. }
  45237. ;
  45238. //这个文件只是clipping polygon的,没用到
  45239. class ClippingTool extends EventDispatcher$1 {
  45240. constructor(viewer) {
  45241. super();
  45242. this.viewer = viewer;
  45243. this.maxPolygonVertices = 8;
  45244. this.addEventListener("start_inserting_clipping_volume", e => {
  45245. this.viewer.dispatchEvent({
  45246. type: "cancel_insertions"
  45247. });
  45248. });
  45249. this.sceneMarker = new Scene();
  45250. this.sceneVolume = new Scene();
  45251. this.sceneVolume.name = "scene_clip_volume";
  45252. this.viewer.inputHandler.registerInteractiveScene(this.sceneVolume);
  45253. this.onRemove = e => {
  45254. this.sceneVolume.remove(e.volume);
  45255. };
  45256. this.onAdd = e => {
  45257. this.sceneVolume.add(e.volume);
  45258. };
  45259. this.viewer.inputHandler.addEventListener("delete", e => {
  45260. var volumes = e.selection.filter(e => e instanceof ClipVolume);
  45261. volumes.forEach(e => this.viewer.scene.removeClipVolume(e));
  45262. var polyVolumes = e.selection.filter(e => e instanceof PolygonClipVolume);
  45263. polyVolumes.forEach(e => this.viewer.scene.removePolygonClipVolume(e));
  45264. });
  45265. }
  45266. setScene(scene) {
  45267. if (this.scene === scene) {
  45268. return;
  45269. }
  45270. if (this.scene) {
  45271. this.scene.removeEventListeners("clip_volume_added", this.onAdd);
  45272. this.scene.removeEventListeners("clip_volume_removed", this.onRemove);
  45273. this.scene.removeEventListeners("polygon_clip_volume_added", this.onAdd);
  45274. this.scene.removeEventListeners("polygon_clip_volume_removed", this.onRemove);
  45275. }
  45276. this.scene = scene;
  45277. this.scene.addEventListener("clip_volume_added", this.onAdd);
  45278. this.scene.addEventListener("clip_volume_removed", this.onRemove);
  45279. this.scene.addEventListener("polygon_clip_volume_added", this.onAdd);
  45280. this.scene.addEventListener("polygon_clip_volume_removed", this.onRemove);
  45281. }
  45282. startInsertion() {
  45283. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  45284. var type = args.type || null;
  45285. if (!type) return null;
  45286. var domElement = this.viewer.renderer.domElement;
  45287. var canvasSize = this.viewer.renderer.getSize(new Vector2());
  45288. var svg = $("\n\t\t<svg height=\"".concat(canvasSize.height, "\" width=\"").concat(canvasSize.width, "\" style=\"position:absolute; pointer-events: none\">\n\n\t\t\t<defs>\n\t\t\t\t <marker id=\"diamond\" markerWidth=\"24\" markerHeight=\"24\" refX=\"12\" refY=\"12\"\n\t\t\t\t\t\tmarkerUnits=\"userSpaceOnUse\">\n\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"6\" fill=\"white\" stroke=\"black\" stroke-width=\"3\"/>\n\t\t\t\t</marker>\n\t\t\t</defs>\n\n\t\t\t<polyline fill=\"none\" stroke=\"black\" \n\t\t\t\tstyle=\"stroke:rgb(0, 0, 0);\n\t\t\t\tstroke-width:6;\"\n\t\t\t\tstroke-dasharray=\"9, 6\"\n\t\t\t\tstroke-dashoffset=\"2\"\n\t\t\t\t/>\n\n\t\t\t<polyline fill=\"none\" stroke=\"black\" \n\t\t\t\tstyle=\"stroke:rgb(255, 255, 255);\n\t\t\t\tstroke-width:2;\"\n\t\t\t\tstroke-dasharray=\"5, 10\"\n\t\t\t\tmarker-start=\"url(#diamond)\" \n\t\t\t\tmarker-mid=\"url(#diamond)\" \n\t\t\t\tmarker-end=\"url(#diamond)\" \n\t\t\t\t/>\n\t\t</svg>"));
  45289. $(domElement.parentElement).append(svg);
  45290. var polyClipVol = new PolygonClipVolume(this.viewer.scene.getActiveCamera().clone());
  45291. this.dispatchEvent({
  45292. "type": "start_inserting_clipping_volume"
  45293. });
  45294. this.viewer.scene.addPolygonClipVolume(polyClipVol);
  45295. this.sceneMarker.add(polyClipVol);
  45296. var cancel = {
  45297. callback: null
  45298. };
  45299. var insertionCallback = e => {
  45300. if (e.button === MOUSE.LEFT) {
  45301. polyClipVol.addMarker();
  45302. // SVC Screen Line
  45303. svg.find("polyline").each((index, target) => {
  45304. var newPoint = svg[0].createSVGPoint();
  45305. newPoint.x = e.offsetX;
  45306. newPoint.y = e.offsetY;
  45307. var polyline = target.points.appendItem(newPoint);
  45308. });
  45309. if (polyClipVol.markers.length > this.maxPolygonVertices) {
  45310. cancel.callback();
  45311. }
  45312. this.viewer.inputHandler.startDragging(polyClipVol.markers[polyClipVol.markers.length - 1]);
  45313. } else if (e.button === MOUSE.RIGHT) {
  45314. cancel.callback(e);
  45315. }
  45316. };
  45317. cancel.callback = e => {
  45318. //let first = svg.find("polyline")[0].points[0];
  45319. //svg.find("polyline").each((index, target) => {
  45320. // let newPoint = svg[0].createSVGPoint();
  45321. // newPoint.x = first.x;
  45322. // newPoint.y = first.y;
  45323. // let polyline = target.points.appendItem(newPoint);
  45324. //});
  45325. svg.remove();
  45326. if (polyClipVol.markers.length > 3) {
  45327. polyClipVol.removeLastMarker();
  45328. polyClipVol.initialized = true;
  45329. } else {
  45330. this.viewer.scene.removePolygonClipVolume(polyClipVol);
  45331. }
  45332. this.viewer.renderer.domElement.removeEventListener("mouseup", insertionCallback, true);
  45333. this.viewer.removeEventListener("cancel_insertions", cancel.callback);
  45334. this.viewer.inputHandler.enabled = true;
  45335. };
  45336. this.viewer.addEventListener("cancel_insertions", cancel.callback);
  45337. this.viewer.renderer.domElement.addEventListener("mouseup", insertionCallback, true);
  45338. this.viewer.inputHandler.enabled = false;
  45339. polyClipVol.addMarker();
  45340. this.viewer.inputHandler.startDragging(polyClipVol.markers[polyClipVol.markers.length - 1]);
  45341. return polyClipVol;
  45342. }
  45343. update() {}
  45344. }
  45345. ;
  45346. var GeoTIFF = function (exports) {
  45347. 'use strict';
  45348. var Endianness = new Enum({
  45349. LITTLE: "II",
  45350. BIG: "MM"
  45351. });
  45352. var Type = new Enum({
  45353. BYTE: {
  45354. value: 1,
  45355. bytes: 1
  45356. },
  45357. ASCII: {
  45358. value: 2,
  45359. bytes: 1
  45360. },
  45361. SHORT: {
  45362. value: 3,
  45363. bytes: 2
  45364. },
  45365. LONG: {
  45366. value: 4,
  45367. bytes: 4
  45368. },
  45369. RATIONAL: {
  45370. value: 5,
  45371. bytes: 8
  45372. },
  45373. SBYTE: {
  45374. value: 6,
  45375. bytes: 1
  45376. },
  45377. UNDEFINED: {
  45378. value: 7,
  45379. bytes: 1
  45380. },
  45381. SSHORT: {
  45382. value: 8,
  45383. bytes: 2
  45384. },
  45385. SLONG: {
  45386. value: 9,
  45387. bytes: 4
  45388. },
  45389. SRATIONAL: {
  45390. value: 10,
  45391. bytes: 8
  45392. },
  45393. FLOAT: {
  45394. value: 11,
  45395. bytes: 4
  45396. },
  45397. DOUBLE: {
  45398. value: 12,
  45399. bytes: 8
  45400. }
  45401. });
  45402. var Tag = new Enum({
  45403. IMAGE_WIDTH: 256,
  45404. IMAGE_HEIGHT: 257,
  45405. BITS_PER_SAMPLE: 258,
  45406. COMPRESSION: 259,
  45407. PHOTOMETRIC_INTERPRETATION: 262,
  45408. STRIP_OFFSETS: 273,
  45409. ORIENTATION: 274,
  45410. SAMPLES_PER_PIXEL: 277,
  45411. ROWS_PER_STRIP: 278,
  45412. STRIP_BYTE_COUNTS: 279,
  45413. X_RESOLUTION: 282,
  45414. Y_RESOLUTION: 283,
  45415. PLANAR_CONFIGURATION: 284,
  45416. RESOLUTION_UNIT: 296,
  45417. SOFTWARE: 305,
  45418. COLOR_MAP: 320,
  45419. SAMPLE_FORMAT: 339,
  45420. MODEL_PIXEL_SCALE: 33550,
  45421. // [GeoTIFF] TYPE: double N: 3
  45422. MODEL_TIEPOINT: 33922,
  45423. // [GeoTIFF] TYPE: double N: 6 * NUM_TIEPOINTS
  45424. GEO_KEY_DIRECTORY: 34735,
  45425. // [GeoTIFF] TYPE: short N: >= 4
  45426. GEO_DOUBLE_PARAMS: 34736,
  45427. // [GeoTIFF] TYPE: short N: variable
  45428. GEO_ASCII_PARAMS: 34737 // [GeoTIFF] TYPE: ascii N: variable
  45429. });
  45430. var typeMapping = new Map([[Type.BYTE, Uint8Array], [Type.ASCII, Uint8Array], [Type.SHORT, Uint16Array], [Type.LONG, Uint32Array], [Type.RATIONAL, Uint32Array], [Type.SBYTE, Int8Array], [Type.UNDEFINED, Uint8Array], [Type.SSHORT, Int16Array], [Type.SLONG, Int32Array], [Type.SRATIONAL, Int32Array], [Type.FLOAT, Float32Array], [Type.DOUBLE, Float64Array]]);
  45431. class IFDEntry {
  45432. constructor(tag, type, count, offset, value) {
  45433. this.tag = tag;
  45434. this.type = type;
  45435. this.count = count;
  45436. this.offset = offset;
  45437. this.value = value;
  45438. }
  45439. }
  45440. class Image {
  45441. constructor() {
  45442. this.width = 0;
  45443. this.height = 0;
  45444. this.buffer = null;
  45445. this.metadata = [];
  45446. }
  45447. }
  45448. class Reader {
  45449. constructor() {}
  45450. static read(data) {
  45451. var endiannessTag = String.fromCharCode(...Array.from(data.slice(0, 2)));
  45452. var endianness = Endianness.fromValue(endiannessTag);
  45453. var tiffCheckTag = data.readUInt8(2);
  45454. if (tiffCheckTag !== 42) {
  45455. throw new Error("not a valid tiff file");
  45456. }
  45457. var offsetToFirstIFD = data.readUInt32LE(4);
  45458. console.log("offsetToFirstIFD", offsetToFirstIFD);
  45459. var ifds = [];
  45460. var IFDsRead = false;
  45461. var currentIFDOffset = offsetToFirstIFD;
  45462. var i = 0;
  45463. while (IFDsRead || i < 100) {
  45464. console.log("currentIFDOffset", currentIFDOffset);
  45465. var numEntries = data.readUInt16LE(currentIFDOffset);
  45466. var nextIFDOffset = data.readUInt32LE(currentIFDOffset + 2 + numEntries * 12);
  45467. console.log("next offset: ", currentIFDOffset + 2 + numEntries * 12);
  45468. var entryBuffer = data.slice(currentIFDOffset + 2, currentIFDOffset + 2 + 12 * numEntries);
  45469. for (var _i = 0; _i < numEntries; _i++) {
  45470. var tag = Tag.fromValue(entryBuffer.readUInt16LE(_i * 12));
  45471. var type = Type.fromValue(entryBuffer.readUInt16LE(_i * 12 + 2));
  45472. var count = entryBuffer.readUInt32LE(_i * 12 + 4);
  45473. var offsetOrValue = entryBuffer.readUInt32LE(_i * 12 + 8);
  45474. var valueBytes = type.bytes * count;
  45475. var value = void 0;
  45476. if (valueBytes <= 4) {
  45477. value = offsetOrValue;
  45478. } else {
  45479. var valueBuffer = new Uint8Array(valueBytes);
  45480. valueBuffer.set(data.slice(offsetOrValue, offsetOrValue + valueBytes));
  45481. var ArrayType = typeMapping.get(type);
  45482. value = new ArrayType(valueBuffer.buffer);
  45483. if (type === Type.ASCII) {
  45484. value = String.fromCharCode(...value);
  45485. }
  45486. }
  45487. var ifd = new IFDEntry(tag, type, count, offsetOrValue, value);
  45488. ifds.push(ifd);
  45489. }
  45490. console.log("nextIFDOffset", nextIFDOffset);
  45491. if (nextIFDOffset === 0) {
  45492. break;
  45493. }
  45494. currentIFDOffset = nextIFDOffset;
  45495. i++;
  45496. }
  45497. var ifdForTag = tag => {
  45498. for (var entry of ifds) {
  45499. if (entry.tag === tag) {
  45500. return entry;
  45501. }
  45502. }
  45503. return null;
  45504. };
  45505. var width = ifdForTag(Tag.IMAGE_WIDTH, ifds).value;
  45506. var height = ifdForTag(Tag.IMAGE_HEIGHT, ifds).value;
  45507. var compression = ifdForTag(Tag.COMPRESSION, ifds).value;
  45508. var rowsPerStrip = ifdForTag(Tag.ROWS_PER_STRIP, ifds).value;
  45509. var ifdStripOffsets = ifdForTag(Tag.STRIP_OFFSETS, ifds);
  45510. var ifdStripByteCounts = ifdForTag(Tag.STRIP_BYTE_COUNTS, ifds);
  45511. var numStrips = Math.ceil(height / rowsPerStrip);
  45512. var stripByteCounts = [];
  45513. for (var _i2 = 0; _i2 < ifdStripByteCounts.count; _i2++) {
  45514. var _type = ifdStripByteCounts.type;
  45515. var offset = ifdStripByteCounts.offset + _i2 * _type.bytes;
  45516. var _value = void 0;
  45517. if (_type === Type.SHORT) {
  45518. _value = data.readUInt16LE(offset);
  45519. } else if (_type === Type.LONG) {
  45520. _value = data.readUInt32LE(offset);
  45521. }
  45522. stripByteCounts.push(_value);
  45523. }
  45524. var stripOffsets = [];
  45525. for (var _i3 = 0; _i3 < ifdStripOffsets.count; _i3++) {
  45526. var _type2 = ifdStripOffsets.type;
  45527. var _offset = ifdStripOffsets.offset + _i3 * _type2.bytes;
  45528. var _value2 = void 0;
  45529. if (_type2 === Type.SHORT) {
  45530. _value2 = data.readUInt16LE(_offset);
  45531. } else if (_type2 === Type.LONG) {
  45532. _value2 = data.readUInt32LE(_offset);
  45533. }
  45534. stripOffsets.push(_value2);
  45535. }
  45536. var imageBuffer = new Uint8Array(width * height * 3);
  45537. var linesProcessed = 0;
  45538. for (var _i4 = 0; _i4 < numStrips; _i4++) {
  45539. var stripOffset = stripOffsets[_i4];
  45540. var stripBytes = stripByteCounts[_i4];
  45541. var stripData = data.slice(stripOffset, stripOffset + stripBytes);
  45542. var lineBytes = width * 3;
  45543. for (var y = 0; y < rowsPerStrip; y++) {
  45544. var line = stripData.slice(y * lineBytes, y * lineBytes + lineBytes);
  45545. imageBuffer.set(line, linesProcessed * lineBytes);
  45546. if (line.length === lineBytes) {
  45547. linesProcessed++;
  45548. } else {
  45549. break;
  45550. }
  45551. }
  45552. }
  45553. console.log("width: ".concat(width));
  45554. console.log("height: ".concat(height));
  45555. console.log("numStrips: ".concat(numStrips));
  45556. console.log("stripByteCounts", stripByteCounts.join(", "));
  45557. console.log("stripOffsets", stripOffsets.join(", "));
  45558. var image = new Image();
  45559. image.width = width;
  45560. image.height = height;
  45561. image.buffer = imageBuffer;
  45562. image.metadata = ifds;
  45563. return image;
  45564. }
  45565. }
  45566. class Exporter {
  45567. constructor() {}
  45568. static toTiffBuffer(image) {
  45569. var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  45570. var offsetToFirstIFD = 8;
  45571. var headerBuffer = new Uint8Array([0x49, 0x49, 42, 0, offsetToFirstIFD, 0, 0, 0]);
  45572. var [width, height] = [image.width, image.height];
  45573. var ifds = [new IFDEntry(Tag.IMAGE_WIDTH, Type.SHORT, 1, null, width), new IFDEntry(Tag.IMAGE_HEIGHT, Type.SHORT, 1, null, height), new IFDEntry(Tag.BITS_PER_SAMPLE, Type.SHORT, 4, null, new Uint16Array([8, 8, 8, 8])), new IFDEntry(Tag.COMPRESSION, Type.SHORT, 1, null, 1), new IFDEntry(Tag.PHOTOMETRIC_INTERPRETATION, Type.SHORT, 1, null, 2), new IFDEntry(Tag.ORIENTATION, Type.SHORT, 1, null, 1), new IFDEntry(Tag.SAMPLES_PER_PIXEL, Type.SHORT, 1, null, 4), new IFDEntry(Tag.ROWS_PER_STRIP, Type.LONG, 1, null, height), new IFDEntry(Tag.STRIP_BYTE_COUNTS, Type.LONG, 1, null, width * height * 3), new IFDEntry(Tag.PLANAR_CONFIGURATION, Type.SHORT, 1, null, 1), new IFDEntry(Tag.RESOLUTION_UNIT, Type.SHORT, 1, null, 1), new IFDEntry(Tag.SOFTWARE, Type.ASCII, 6, null, "......"), new IFDEntry(Tag.STRIP_OFFSETS, Type.LONG, 1, null, null), new IFDEntry(Tag.X_RESOLUTION, Type.RATIONAL, 1, null, new Uint32Array([1, 1])), new IFDEntry(Tag.Y_RESOLUTION, Type.RATIONAL, 1, null, new Uint32Array([1, 1]))];
  45574. if (params.ifdEntries) {
  45575. ifds.push(...params.ifdEntries);
  45576. }
  45577. var valueOffset = offsetToFirstIFD + 2 + ifds.length * 12 + 4;
  45578. // create 12 byte buffer for each ifd and variable length buffers for ifd values
  45579. var ifdEntryBuffers = new Map();
  45580. var ifdValueBuffers = new Map();
  45581. for (var ifd of ifds) {
  45582. var entryBuffer = new ArrayBuffer(12);
  45583. var entryView = new DataView(entryBuffer);
  45584. var valueBytes = ifd.type.bytes * ifd.count;
  45585. entryView.setUint16(0, ifd.tag.value, true);
  45586. entryView.setUint16(2, ifd.type.value, true);
  45587. entryView.setUint32(4, ifd.count, true);
  45588. if (ifd.count === 1 && ifd.type.bytes <= 4) {
  45589. entryView.setUint32(8, ifd.value, true);
  45590. } else {
  45591. entryView.setUint32(8, valueOffset, true);
  45592. var valueBuffer = new Uint8Array(ifd.count * ifd.type.bytes);
  45593. if (ifd.type === Type.ASCII) {
  45594. valueBuffer.set(new Uint8Array(ifd.value.split("").map(c => c.charCodeAt(0))));
  45595. } else {
  45596. valueBuffer.set(new Uint8Array(ifd.value.buffer));
  45597. }
  45598. ifdValueBuffers.set(ifd.tag, valueBuffer);
  45599. valueOffset = valueOffset + valueBuffer.byteLength;
  45600. }
  45601. ifdEntryBuffers.set(ifd.tag, entryBuffer);
  45602. }
  45603. var imageBufferOffset = valueOffset;
  45604. new DataView(ifdEntryBuffers.get(Tag.STRIP_OFFSETS)).setUint32(8, imageBufferOffset, true);
  45605. var concatBuffers = buffers => {
  45606. var totalLength = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
  45607. var merged = new Uint8Array(totalLength);
  45608. var offset = 0;
  45609. for (var buffer of buffers) {
  45610. merged.set(new Uint8Array(buffer), offset);
  45611. offset += buffer.byteLength;
  45612. }
  45613. return merged;
  45614. };
  45615. var ifdBuffer = concatBuffers([new Uint16Array([ifds.length]), ...ifdEntryBuffers.values(), new Uint32Array([0])]);
  45616. var ifdValueBuffer = concatBuffers([...ifdValueBuffers.values()]);
  45617. var tiffBuffer = concatBuffers([headerBuffer, ifdBuffer, ifdValueBuffer, image.buffer]);
  45618. return {
  45619. width: width,
  45620. height: height,
  45621. buffer: tiffBuffer
  45622. };
  45623. }
  45624. }
  45625. exports.Tag = Tag;
  45626. exports.Type = Type;
  45627. exports.IFDEntry = IFDEntry;
  45628. exports.Image = Image;
  45629. exports.Reader = Reader;
  45630. exports.Exporter = Exporter;
  45631. return exports;
  45632. }({});
  45633. class Message {
  45634. constructor(content) {
  45635. this.content = content;
  45636. var closeIcon = "".concat(exports.resourcePath, "/icons/close.svg");
  45637. this.element = $("\n\t\t\t<div class=\"potree_message\">\n\t\t\t\t<span name=\"content_container\" style=\"flex-grow: 1; padding: 5px\"></span>\n\t\t\t\t<img name=\"close\" src=\"".concat(closeIcon, "\" class=\"button-icon\" style=\"width: 16px; height: 16px;\">\n\t\t\t</div>"));
  45638. this.elClose = this.element.find("img[name=close]");
  45639. this.elContainer = this.element.find("span[name=content_container]");
  45640. if (typeof content === "string") {
  45641. this.elContainer.append($("<span>".concat(content, "</span>")));
  45642. } else {
  45643. this.elContainer.append(content);
  45644. }
  45645. }
  45646. setMessage(content) {
  45647. this.elContainer.empty();
  45648. if (typeof content === "string") {
  45649. this.elContainer.append($("<span>".concat(content, "</span>")));
  45650. } else {
  45651. this.elContainer.append(content);
  45652. }
  45653. }
  45654. }
  45655. class PointCloudSM {
  45656. constructor(potreeRenderer) {
  45657. this.potreeRenderer = potreeRenderer;
  45658. this.threeRenderer = this.potreeRenderer.threeRenderer;
  45659. this.target = new WebGLRenderTarget(2 * 1024, 2 * 1024, {
  45660. minFilter: LinearFilter,
  45661. magFilter: LinearFilter,
  45662. format: RGBAFormat,
  45663. type: FloatType
  45664. });
  45665. this.target.depthTexture = new DepthTexture();
  45666. this.target.depthTexture.type = UnsignedIntType;
  45667. //this.threeRenderer.setClearColor(0x000000, 1);
  45668. this.threeRenderer.setClearColor(0xff0000, 1);
  45669. //HACK? removed while moving to three.js 109
  45670. //this.threeRenderer.clearTarget(this.target, true, true, true);
  45671. {
  45672. var oldTarget = this.threeRenderer.getRenderTarget();
  45673. this.threeRenderer.setRenderTarget(this.target);
  45674. this.threeRenderer.clear(true, true, true);
  45675. this.threeRenderer.setRenderTarget(oldTarget);
  45676. }
  45677. }
  45678. setLight(light) {
  45679. this.light = light;
  45680. var fov = 180 * light.angle / Math.PI;
  45681. var aspect = light.shadow.mapSize.width / light.shadow.mapSize.height;
  45682. var near = 0.1;
  45683. var far = light.distance === 0 ? 10000 : light.distance;
  45684. this.camera = new PerspectiveCamera(fov, aspect, near, far);
  45685. this.camera.up.set(0, 0, 1);
  45686. this.camera.position.copy(light.position);
  45687. var target = new Vector3().subVectors(light.position, light.getWorldDirection(new Vector3()));
  45688. this.camera.lookAt(target);
  45689. this.camera.updateProjectionMatrix();
  45690. this.camera.updateMatrix();
  45691. this.camera.updateMatrixWorld();
  45692. this.camera.matrixWorldInverse.copy(this.camera.matrixWorld).invert();
  45693. }
  45694. setSize(width, height) {
  45695. if (this.target.width !== width || this.target.height !== height) {
  45696. this.target.dispose();
  45697. }
  45698. this.target.setSize(width, height);
  45699. }
  45700. render(scene, camera) {
  45701. this.threeRenderer.setClearColor(0x000000, 1);
  45702. var oldTarget = this.threeRenderer.getRenderTarget();
  45703. this.threeRenderer.setRenderTarget(this.target);
  45704. this.threeRenderer.clear(true, true, true);
  45705. this.potreeRenderer.render(scene, this.camera, this.target, {});
  45706. this.threeRenderer.setRenderTarget(oldTarget);
  45707. }
  45708. }
  45709. class Label extends EventDispatcher {
  45710. constructor() {
  45711. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  45712. super();
  45713. this.position = o.pos;
  45714. this.text = o.text || '';
  45715. this.elem = $('<div class="hide"><a></a></div>');
  45716. o.className && this.elem.addClass(o.className);
  45717. this.elem.find('a').html(this.text);
  45718. $("#potree_labels").append(this.elem);
  45719. this.pos2d = new Vector3();
  45720. this.dom = o.dom || viewer.renderArea;
  45721. this.camera = o.camera || viewer.scene.getActiveCamera();
  45722. var update = e => {
  45723. this.update(e);
  45724. };
  45725. viewer.addEventListener('camera_changed', update);
  45726. this.addEventListener('dispose', () => {
  45727. viewer.removeEventListener('camera_changed', update);
  45728. this.dispose();
  45729. });
  45730. }
  45731. update() {
  45732. if (!this.position || this.elem.hasClass('unvisible')) return;
  45733. var p = Utils.getPos2d(this.position, viewer.mainViewport, this.dom);
  45734. if (!p.trueSide) {
  45735. this.elem.addClass("hide");
  45736. return;
  45737. }
  45738. this.elem.css({
  45739. left: p.pos.x + 'px',
  45740. top: p.pos.y + 'px'
  45741. });
  45742. this.elem.removeClass("hide");
  45743. this.pos2d = p.vector;
  45744. }
  45745. setVisible(visi) {
  45746. if (!visi) {
  45747. this.elem.addClass("unvisible");
  45748. } else {
  45749. this.elem.removeClass("unvisible");
  45750. this.update();
  45751. }
  45752. }
  45753. setText(text) {
  45754. this.text = text || '';
  45755. this.elem.find('a').html(this.text);
  45756. }
  45757. setPos(pos) {
  45758. this.position = pos;
  45759. }
  45760. dispose() {
  45761. this.elem.remove();
  45762. this.removeAllListeners();
  45763. }
  45764. }
  45765. //THREE.Vector2.name1 = 'ctrlPolygon'
  45766. var verticalLine = new Line3();
  45767. //控制点和边的合集。具有可以拖拽修改的功能,拖拽时能防止线相交。
  45768. class ctrlPolygon extends Object3D {
  45769. constructor(type, prop) {
  45770. super();
  45771. this.Type = type;
  45772. this.maxMarkers = Number.MAX_SAFE_INTEGER;
  45773. this.transformData(prop);
  45774. for (var i in prop) {
  45775. this[i] = prop[i];
  45776. }
  45777. this.color = this.color || config$1.measure.default.color;
  45778. if ((this.atPlane || this.showArea) && this.closed && this.dimension == '2d') {
  45779. this.areaPlane = this.createAreaPlane();
  45780. this.add(this.areaPlane);
  45781. }
  45782. //数据--刚开始一定是空的
  45783. this.points = [];
  45784. //mesh 不一定有
  45785. this.markers = [];
  45786. this.edges = [];
  45787. this.center;
  45788. }
  45789. initData(prop) {
  45790. //开始加数据
  45791. prop.dataset_points && (this.dataset_points = prop.dataset_points);
  45792. prop.datasetId && (this.datasetId = prop.datasetId);
  45793. prop.points_datasets && (this.points_datasets = prop.points_datasets);
  45794. if (Potree.settings.editType == 'merge' || this.measureType == 'MulDistance Ring') {
  45795. //融合页面没有地图,measure的不需要指定datasetId,每个点都有各自的datasetId,跟着各自的模型走
  45796. if (this.dataset_points) {
  45797. this.dataset_points = this.dataset_points.map(e => {
  45798. return e && new Vector3().copy(e);
  45799. });
  45800. var oldPoints = prop.points;
  45801. prop.points = this.dataset_points.map((p, i) => {
  45802. var point = Potree.Utils.datasetPosTransform({
  45803. fromDataset: true,
  45804. datasetId: this.points_datasets[i],
  45805. position: p
  45806. });
  45807. return point || oldPoints && oldPoints[i]; //path 不在模型上的点直接使用prop.points
  45808. });
  45809. if (prop.points.some(e => e == void 0)) {
  45810. return false;
  45811. }
  45812. } else {
  45813. this.dataset_points = [];
  45814. }
  45815. }
  45816. if (prop.points) {
  45817. for (var p of prop.points) {
  45818. var pos = new Vector3().copy(p);
  45819. this.addMarker({
  45820. point: pos
  45821. });
  45822. }
  45823. if (Potree.settings.editType != 'merge' && this.measureType != 'MulDistance Ring') {
  45824. if (this.datasetId != void 0) {
  45825. //初始化位置
  45826. if (this.dataset_points) {
  45827. this.dataset_points = this.dataset_points.map(e => {
  45828. return e && new Vector3().copy(e);
  45829. });
  45830. this.transformByPointcloud(); //根据dataset_points和this.datasetId生成points
  45831. }
  45832. } else {
  45833. if (prop.dataset_points && prop.dataset_points.some(e => e != void 0)) {
  45834. console.error('存在测量线的datasetId为空而dataset_points有值,请检查并删除:' + this.sid); //存在过的bug,原因未知,可能是后台处理dataset时替换的错误:http://192.168.0.21/index.php?m=bug&f=view&bugID=23601
  45835. console.log(this);
  45836. }
  45837. }
  45838. }
  45839. this.facePlane = this.getFacePlane();
  45840. this.getPoint2dInfo(this.points);
  45841. this.update({
  45842. ifUpdateMarkers: true
  45843. });
  45844. //this.dragChange(new THREE.Vector3().copy(prop.points[prop.points.length-1]), prop.points.length-1);
  45845. this.setSelected(false);
  45846. this.markers.forEach(marker => {
  45847. marker.dispatchEvent('addHoverEvent');
  45848. });
  45849. return true;
  45850. }
  45851. }
  45852. addMarker() {
  45853. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  45854. var index = o.index == void 0 ? this.points.length : o.index; //要当第几个
  45855. this.points = [...this.points.slice(0, index), o.point.clone(), ...this.points.slice(index, this.points.length)];
  45856. //this.points.push(o.point);
  45857. if ('dataset_point' in o) {
  45858. //需要增加,可能是null
  45859. this.dataset_points = this.dataset_points ? [...this.dataset_points.slice(0, index), o.dataset_point && o.dataset_point.clone(), ...this.dataset_points.slice(index, this.dataset_points.length)] : null; //如果原本是null,新加的应该也是
  45860. }
  45861. if ('points_dataset' in o) {
  45862. this.points_datasets = [...this.points_datasets.slice(0, index), o.points_dataset, ...this.points_datasets.slice(index, this.points_datasets.length)];
  45863. }
  45864. if (o.marker) {
  45865. this.add(o.marker);
  45866. this.markers = [...this.markers.slice(0, index), o.marker, ...this.markers.slice(index, this.markers.length)];
  45867. this.updateMarker(o.marker, o.point);
  45868. o.marker.addEventListener('drag', this.dragMarker.bind(this), {
  45869. importance: 2
  45870. });
  45871. o.marker.addEventListener('drop', this.dropMarker.bind(this), {
  45872. importance: 2
  45873. });
  45874. o.marker.createTime = Date.now();
  45875. var addHoverEvent = e => {
  45876. var mouseover = e => {
  45877. this.setMarkerSelected(e.object, 'hover', 'single');
  45878. viewer.dispatchEvent({
  45879. type: "CursorChange",
  45880. action: "add",
  45881. name: "markerMove"
  45882. });
  45883. };
  45884. var mouseleave = e => {
  45885. this.setMarkerSelected(e.object, 'unhover', 'single');
  45886. viewer.dispatchEvent({
  45887. type: "CursorChange",
  45888. action: "remove",
  45889. name: "markerMove"
  45890. });
  45891. };
  45892. o.marker.addEventListener('mouseover', mouseover);
  45893. o.marker.addEventListener('mouseleave', mouseleave);
  45894. o.marker.addEventListener('startDragging', e => {
  45895. //for mobile
  45896. this.setMarkerSelected(o.marker, 'hover', 'single');
  45897. this.dispatchEvent('startDragging');
  45898. });
  45899. o.marker.addEventListener('drop', e => {
  45900. //for mobile
  45901. this.setMarkerSelected(o.marker, 'unhover', 'single');
  45902. });
  45903. o.marker.removeEventListener('addHoverEvent', addHoverEvent);
  45904. };
  45905. o.marker.addEventListener('addHoverEvent', addHoverEvent); //当非isNew时才添加事件
  45906. if (!this.isNew) {
  45907. o.marker.dispatchEvent('addHoverEvent');
  45908. }
  45909. }
  45910. if (o.edge) {
  45911. this.add(o.edge);
  45912. this.edges = [...this.edges.slice(0, index), o.edge, ...this.edges.slice(index, this.edges.length)];
  45913. }
  45914. }
  45915. dragMarker(e) {
  45916. var I, atMap;
  45917. if (e.hoverViewport != e.drag.dragViewport) {
  45918. //不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
  45919. viewer.dispatchEvent({
  45920. type: "CursorChange",
  45921. action: "add",
  45922. name: "polygon_AtWrongPlace"
  45923. });
  45924. return;
  45925. }
  45926. if (e.drag.pointerDelta.length() == 0 && !this.isNew) {
  45927. //部分设备(华为matePad11)在touchstart后立即执行了touchmove,导致marker立即移动,需要屏蔽..(刚创建时也会是0)
  45928. return;
  45929. }
  45930. viewer.dispatchEvent({
  45931. type: "CursorChange",
  45932. action: "remove",
  45933. name: "polygon_AtWrongPlace"
  45934. });
  45935. atMap = e.drag.dragViewport.name == 'mapViewport';
  45936. if (atMap && this.unableDragAtMap) {
  45937. e.drag.object = null; //取消拖拽
  45938. return;
  45939. }
  45940. e.drag.object.isDragging = true;
  45941. I = e.intersect && (e.intersect.adsorption ? e.intersect.location : e.intersect.orthoIntersect || e.intersect.location);
  45942. if (!I) {
  45943. if (this.zPlaneWhenNoIntersect != void 0) {
  45944. var {
  45945. x,
  45946. y
  45947. } = Potree.Utils.getPointerPosAtHeight(this.zPlaneWhenNoIntersect, e.pointer);
  45948. I = new Vector3(x, y, this.zPlaneWhenNoIntersect);
  45949. }
  45950. if (viewer.inputHandler.pressedKeys[18] || Potree.settings.dragPolyBeyondPoint) {
  45951. //alt dragPolyBeyondPoint可以平移拖拽到无点的地方---测试用
  45952. var i = this.markers.indexOf(e.drag.object);
  45953. I = this.points[i].clone();
  45954. var projected = I.clone().project(e.drag.dragViewport.camera);
  45955. projected.x = e.pointer.x;
  45956. projected.y = e.pointer.y;
  45957. var unprojected = projected.clone().unproject(e.drag.dragViewport.camera);
  45958. I.copy(unprojected);
  45959. }
  45960. }
  45961. if (I) {
  45962. var _i = this.markers.indexOf(e.drag.object);
  45963. if (_i !== -1) {
  45964. this.dragChange(I.clone(), _i, atMap);
  45965. if (this.points_datasets) {
  45966. if (e.intersect) {
  45967. if (e.intersect.pointcloud) this.points_datasets[_i] = e.intersect.pointcloud.dataset_id;else if (e.intersect.object) this.points_datasets[_i] = e.intersect.object.dataset_id;else {
  45968. //地图
  45969. if (this.measureType == 'MulDistance Ring') {
  45970. //因为它的每个point跟着各自的dataset走,而不是整体的dataset
  45971. var pointcloud = viewer.findClosestDatasetOnMap(I) || viewer.scene.pointclouds[0];
  45972. this.points_datasets[_i] = pointcloud.dataset_id;
  45973. } else this.points_datasets[_i] = null;
  45974. }
  45975. } else if (this.zPlaneWhenNoIntersect != void 0) {
  45976. this.points_datasets[_i] = this.dataset_points[_i] = null;
  45977. }
  45978. }
  45979. }
  45980. this.editStateChange(true);
  45981. return true;
  45982. }
  45983. }
  45984. dragChange(intersectPos, i, atMap) {
  45985. var len = this.markers.length;
  45986. var oldPoint = this.points[i];
  45987. if (atMap) {
  45988. intersectPos.setZ(oldPoint.z); //在地图上拖拽,不改变其高度。
  45989. }
  45990. var location = intersectPos.clone();
  45991. if (this.faceDirection && this.maxMarkers == 2 && len == 2) {
  45992. //add 固定方向的点不直接拖拽
  45993. var p1 = this.markers[0].position;
  45994. if (this.faceDirection == 'horizontal') {
  45995. var projectPos = location.clone().setZ(p1.z);
  45996. } else {
  45997. var projectPos = p1.clone().setZ(location.z);
  45998. }
  45999. //var p2 = p1.clone().add(this.direction)
  46000. //var projectPos = math.getFootPoint(location, p1, p2)
  46001. LineDraw.updateLine(this.guideLine, [location, projectPos]);
  46002. location = projectPos;
  46003. this.guideLine.visible = true;
  46004. } else if (len > 1) {
  46005. var points = this.points.map(e => e.clone());
  46006. points[i].copy(location); //算normal需要提前确认point
  46007. //若为定义了面朝向的矩形
  46008. if (this.faceDirection == 'horizontal') {
  46009. if (len == 2) {
  46010. location.setZ(points[0].z);
  46011. }
  46012. if (!this.facePlane) {
  46013. //一个点就能确定面
  46014. this.facePlane = new Plane().setFromNormalAndCoplanarPoint(new Vector3(0, 0, 1), this.points[0]);
  46015. }
  46016. } else if (this.faceDirection == 'vertical') {
  46017. //当有两个点时, 有两个方向的可能
  46018. if (len == 2) {
  46019. if (this.isRect) {
  46020. var _vec = points[0].clone().sub(location);
  46021. if (Math.sqrt(_vec.x * _vec.x + _vec.y * _vec.y) > Math.abs(_vec.z)) {
  46022. //水平(高度差小于水平距离时)
  46023. location.setZ(points[0].z);
  46024. //this.cannotConfirmNormal = false;//能确定面为水平方向
  46025. } else {
  46026. //垂直 (当两点一样时也属于这种)
  46027. location.setX(points[0].x);
  46028. location.setY(points[0].y);
  46029. //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
  46030. }
  46031. }
  46032. } else {
  46033. {
  46034. //判断cannotConfirmNormal. 如果前几段都在竖直线上,就不能固定出面方向。
  46035. this.cannotConfirmNormal = true;
  46036. var max = this.isRect ? 1 : len - 2;
  46037. for (var _i2 = 0; _i2 < max; _i2++) {
  46038. var _p = points[_i2].clone();
  46039. var _p2 = points[_i2 + 1].clone();
  46040. var _vec2 = _p.sub(_p2);
  46041. if (_vec2.x != 0 || _vec2.y != 0) {
  46042. this.cannotConfirmNormal = false;
  46043. break;
  46044. }
  46045. }
  46046. }
  46047. if (!this.facePlane || this.cannotConfirmNormal) {
  46048. //三个点且为水平方向时,计算面
  46049. var points_ = points.map(e => new Vector2(e.x, e.y));
  46050. var points2 = this.getDifferentPoint(points_, 2);
  46051. if (points2) {
  46052. var normal = math.getNormal2d({
  46053. p1: points2[0],
  46054. p2: points2[1]
  46055. });
  46056. normal = new Vector3(normal.x, normal.y, 0);
  46057. this.facePlane = new Plane().setFromNormalAndCoplanarPoint(normal, this.points[0]);
  46058. }
  46059. }
  46060. }
  46061. }
  46062. if (len > 2) {
  46063. if (!this.faceDirection && this.showArea) {
  46064. if (len == 3 || this.isRect) this.cannotConfirmNormal = true; //当第三个点固定后(有四个点时)才能固定面
  46065. if (!this.facePlane || this.cannotConfirmNormal) {
  46066. var points3 = this.getDifferentPoint(points, 3); //只有找到三个不同的点算拥有面和area
  46067. if (points3) {
  46068. this.facePlane = new Plane().setFromCoplanarPoints(...points3);
  46069. }
  46070. }
  46071. }
  46072. if (this.atPlane && this.facePlane && !this.cannotConfirmNormal) {
  46073. //之后加的点一定要在面上
  46074. if (atMap) {
  46075. //地图上用垂直线,得到和面的交点。
  46076. verticalLine.set(location.clone().setZ(100000), location.clone().setZ(-100000)); //确保长度范围覆盖所有测量面
  46077. location = this.facePlane.intersectLine(verticalLine, new Vector3());
  46078. if (!location) return;
  46079. } else {
  46080. location = this.facePlane.projectPoint(intersectPos, new Vector3());
  46081. }
  46082. }
  46083. points[i].copy(location); //再copy确认一次
  46084. if (len == 3 && this.faceDirection == 'horizontal' && this.closed) {
  46085. //normal方向还不确定 会影响label在里侧还是外侧
  46086. var facePlane = new Plane().setFromCoplanarPoints(...points);
  46087. if (facePlane.normal.z && facePlane.normal.z * this.facePlane.normal.z < 0) {
  46088. this.facePlane.normal.z *= -1, this.facePlane.constant *= -1;
  46089. //console.log(this.facePlane.normal, this.facePlane.constant)
  46090. }
  46091. }
  46092. if (this.isRect) {
  46093. //是矩形 (即使没有faceDirection也能执行)
  46094. //根据前两个点计算当前和下一个点
  46095. var p1 = points[(i - 2 + len) % len];
  46096. var p2 = points[(i - 1 + len) % len];
  46097. if (p1.equals(p2)) {
  46098. //意外情况:重复点两次 ( bug点,改了好多遍)
  46099. if (this.faceDirection == 'vertical') {
  46100. p2.add(new Vector3(0, 0, 0.0001));
  46101. } else {
  46102. p2.add(new Vector3(0, 0.0001, 0));
  46103. }
  46104. }
  46105. //p3 : location
  46106. var foot = math.getFootPoint(location, p1, p2); //p2 修改p2到垂足的位置
  46107. var vec = foot.clone().sub(location);
  46108. var p4 = p1.clone().sub(vec);
  46109. points[(i - 1 + len) % len].copy(foot);
  46110. points[(i + 1) % len].copy(p4);
  46111. this.setPosition((i - 1 + len) % len, foot); //p2
  46112. this.setPosition((i + 1) % len, p4);
  46113. }
  46114. this.getPoint2dInfo(points);
  46115. var isIntersectSelf = this.atPlane && this.closed && !this.isRect && this.point2dInfo && this.intersectSelf(this.point2dInfo.points2d); //检测相交
  46116. this.isIntersectSelf = isIntersectSelf;
  46117. if (isIntersectSelf) {
  46118. //not-allowed
  46119. if (!this.isNew && isIntersectSelf == 'lastLine') this.isIntersectSelf = 'all'; //已经画好了就不用特别对待最后一条线
  46120. if (this.isIntersectSelf == 'lastLine') {
  46121. Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', false);
  46122. Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', false);
  46123. } else {
  46124. viewer.dispatchEvent({
  46125. type: "CursorChange",
  46126. action: "add",
  46127. name: "polygon_isIntersectSelf"
  46128. });
  46129. return;
  46130. }
  46131. }
  46132. if (!this.isIntersectSelf) {
  46133. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true);
  46134. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true);
  46135. }
  46136. if (!this.isIntersectSelf || this.isIntersectSelf == 'lastLine') {
  46137. viewer.dispatchEvent({
  46138. type: "CursorChange",
  46139. action: "remove",
  46140. name: "polygon_isIntersectSelf"
  46141. });
  46142. }
  46143. }
  46144. var showGuideLine = len > 1 && (this.faceDirection || len > 3);
  46145. if (showGuideLine && this.guideLine) {
  46146. LineDraw.updateLine(this.guideLine, [intersectPos, location]);
  46147. this.guideLine.visible = true;
  46148. }
  46149. //console.log(this.points.map(e=>e.toArray()))
  46150. }
  46151. if (this.restrictArea) {
  46152. var holes = this.restrictArea.holes.concat(this.restrictArea.parentHoles);
  46153. var holesPoints = holes.filter(e => e != this && e.points.length > 2).map(e => e.points);
  46154. if (!math.isPointInArea(this.restrictArea.points, holesPoints, location)) {
  46155. viewer.dispatchEvent({
  46156. type: "CursorChange",
  46157. action: "add",
  46158. name: "polygon_AtWrongPlace"
  46159. });
  46160. this.isAtWrongPlace = true;
  46161. return;
  46162. }
  46163. //就不处理相交线了。 有个缺点:floor上的hole可以限制room,但hole不受room限制,会导致room的marker被框在hole里而动不了。只能去调整hole了
  46164. }
  46165. viewer.dispatchEvent({
  46166. type: "CursorChange",
  46167. action: "remove",
  46168. name: "polygon_AtWrongPlace"
  46169. });
  46170. this.isAtWrongPlace = false;
  46171. this.setPosition(i, location);
  46172. this.update({
  46173. index: this.isRect ? null : i
  46174. });
  46175. this.dispatchEvent({
  46176. type: 'dragChange',
  46177. index: i
  46178. });
  46179. }
  46180. dropMarker(e) {
  46181. //console.log('dropMarker')
  46182. if (this.isNew && e.pressDistance > Potree.config.clickMaxDragDis) {
  46183. //拖拽的话返回
  46184. return this.continueDrag(null, e);
  46185. }
  46186. if (e.hoverViewport != e.drag.dragViewport) {
  46187. //copy from dragMarker, for sitemodel, only mapViewport can be dropped
  46188. return this.continueDrag(null, e);
  46189. }
  46190. if (e.isTouch) {
  46191. if (e.hoverViewport != viewer.mainViewport && this.unableDragAtMap) {
  46192. viewer.dispatchEvent({
  46193. type: 'reticule_forbit',
  46194. v: true
  46195. });
  46196. //console.log('reticule_forbit',true)
  46197. return this.continueDrag(null, e);
  46198. } else {
  46199. viewer.dispatchEvent({
  46200. type: 'reticule_forbit',
  46201. v: false
  46202. });
  46203. //console.log('reticule_forbit',false)
  46204. }
  46205. this.isNew && this.dragMarker(e); //isNew触屏点击时必须先更新下点,因为指尖不在屏幕上时没更新。但对已经创建的marker点击时不应该更新
  46206. }
  46207. if (e.button != MOUSE.RIGHT && (
  46208. //右键click的话继续执行,因为会停止
  46209. this.isIntersectSelf == 'all' && this.isNew //有线相交了
  46210. || this.isAtWrongPlace && this.isNew || !e.isAtDomElement && this.isNew //如果是刚添加时在其他dom点击, 不要响应
  46211. || e.hoverViewport != viewer.mainViewport && this.unableDragAtMap //垂直的测量线不允许在地图上放点
  46212. || (this.isNew || this.forbitRepeatPoint) && !this.getDifferentPoint(this.points, this.points.length) //不允许和之前的点相同, 但这句在点云稀疏时会导致难结束
  46213. )) {
  46214. return this.continueDrag(null, e);
  46215. }
  46216. //console.log('drop marker' )
  46217. var i = this.markers.indexOf(e.drag.object);
  46218. if (i !== -1) {
  46219. this.dispatchEvent({
  46220. 'type': 'marker_dropped',
  46221. 'index': i
  46222. });
  46223. if (this.markers.length > 2 && this.facePlane) this.cannotConfirmNormal = false;
  46224. this.guideLine && (this.guideLine.visible = false);
  46225. }
  46226. this.setMarkerSelected(e.drag.object, 'unhover', 'single');
  46227. this.editStateChange(false);
  46228. e.drag.endDragFun && e.drag.endDragFun(e); // addmarker
  46229. //if(this.changeCallBack)this.changeCallBack()
  46230. return true;
  46231. }
  46232. getFacePlane(force) {
  46233. //最普通一种get方法,根据顶点。且假设所有点已经共面,且不重合
  46234. if ( /* !this.atPlane || */this.points.length < 3) return;
  46235. /* this.facePlane = new THREE.Plane().setFromCoplanarPoints(...this.points.slice(0,3) ) */
  46236. var facePlane = this.facePlane;
  46237. if (force || !this.atPlane || !facePlane) {
  46238. //多折线 没有实时更新facePlane所以重新算
  46239. var normal = new Vector3(),
  46240. len = this.points.length - 2;
  46241. for (var i = 0; i < len; i++) {
  46242. //获取normal的顺序方法必须和setFromCoplanarPoints一致
  46243. var vec0 = new Vector3().subVectors(this.points[i + 2], this.points[i + 1]);
  46244. var vec1 = new Vector3().subVectors(this.points[i], this.points[i + 1]);
  46245. var nor = vec0.cross(vec1).normalize();
  46246. normal.add(nor);
  46247. }
  46248. normal.normalize();
  46249. facePlane = new Plane().setFromNormalAndCoplanarPoint(normal, this.points[0]);
  46250. }
  46251. return facePlane;
  46252. }
  46253. getPoint2dInfo(points) {
  46254. //在更新areaplane之前必须更新过point2dInfo (针对所有点在同一平面上的)
  46255. if (this.facePlane && (this.atPlane || Potree.settings.areaAtNotPlane)) {
  46256. var facePlane = this.getFacePlane();
  46257. var originPoint0 = points[0].clone();
  46258. var qua = math.getQuaBetween2Vector(facePlane.normal, new Vector3(0, 0, 1), new Vector3(0, 0, 1));
  46259. var points2d = points.map(e => e.clone().applyQuaternion(qua));
  46260. this.point2dInfo = {
  46261. originPoint0,
  46262. points2d,
  46263. quaInverse: qua.clone().invert()
  46264. };
  46265. }
  46266. }
  46267. setPosition(index, position) {
  46268. //拖拽后设置位置
  46269. var point = this.points[index];
  46270. point.copy(position);
  46271. /* if(this.datasetId){
  46272. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.datasetId, position:point.clone()})
  46273. } */
  46274. /* if(Potree.settings.editType == 'merge'){
  46275. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true,this.points_datasets[i], position:point.clone()})
  46276. } */
  46277. var marker = this.markers[index];
  46278. this.updateMarker(marker, point);
  46279. }
  46280. updateMarker(marker, pos) {
  46281. marker.position.copy(pos);
  46282. marker.waitUpdate();
  46283. }
  46284. intersectSelf(points2d) {
  46285. //add
  46286. var len = points2d.length;
  46287. for (var i = 0; i < len; i++) {
  46288. for (var j = i + 2; j < len; j++) {
  46289. if (Math.abs(j - len - i) < 2) continue; //不和邻边比
  46290. var p1 = points2d[i];
  46291. var p2 = points2d[i + 1];
  46292. var p3 = points2d[j];
  46293. var p4 = points2d[(j + 1) % len];
  46294. if (p1.equals(p2) || p3.equals(p4) || p1.equals(p3) || p2.equals(p3) || p1.equals(p4) || p2.equals(p4)) continue;
  46295. var line1 = [p1, p2];
  46296. var line2 = [p3, p4];
  46297. var intersect = math.isLineIntersect(line1, line2, false, 0.001);
  46298. if (intersect) {
  46299. if (i == len - 1 || j == len - 1) {
  46300. //最后一条线。如果还没绘制完,最后的线还没定下,可被允许继续绘制,但无法显示面积。
  46301. return 'lastLine';
  46302. } else {
  46303. return 'all';
  46304. }
  46305. break;
  46306. }
  46307. }
  46308. }
  46309. }
  46310. removeMarker(index) {
  46311. this.points.splice(index, 1);
  46312. var marker = this.markers[index];
  46313. this.markers.splice(index, 1);
  46314. marker.dispose ? marker.dispose() : marker.parent.remove(marker);
  46315. var edgeIndex = index; //(index === 0) ? 0 : (index - 1);
  46316. var edge = this.edges[edgeIndex];
  46317. if (edge) {
  46318. this.remove(edge);
  46319. this.edges.splice(edgeIndex, 1);
  46320. edge.geometry.dispose();
  46321. }
  46322. this.point2dInfo && this.point2dInfo.points2d.splice(index, 1); //add
  46323. this.dispatchEvent({
  46324. type: 'removeMarker',
  46325. index,
  46326. marker
  46327. });
  46328. }
  46329. createAreaPlane(mat) {
  46330. var geometry = new Geometry();
  46331. var mesh = new Mesh(geometry, mat);
  46332. return mesh;
  46333. }
  46334. updateAreaPlane() {
  46335. this.areaPlane.geometry.dispose();
  46336. if (this.points.length > 2) {
  46337. if (this.isPrism) {
  46338. var z = this.horizonZ || 0;
  46339. var points2d = this.points.map(e => e.clone().setZ(z));
  46340. this.areaPlane.geometry = MeshDraw.getShapeGeo(points2d); //z=0
  46341. var center = math.getCenterOfGravityPoint(points2d); //重心
  46342. this.areaPlaneCenter = new Vector3(center.x, center.y, z);
  46343. this.areaPlane.position.z = z;
  46344. } else if (this.point2dInfo) {
  46345. if (Potree.settings.areaAtNotPlane) {
  46346. //测点不在同一平面的面积. (缺点:容易出现三角缺块, 以及搭错线导致超出理想边界外。在平面上n个点能构成n-2个三角形,但空间中更多个,所以若要指定出类似平面那样n-2个三角形是有多种可能的。故暂不开放。 用d3.Delaunay结果更差) //测试桥面 SG-arqnGgAR7om&formal
  46347. //参考 http://indoor.popsmart.cn:8084/sxswsw-sx/ 找到场景中面积测量线的方法:window.scene.children[18].children[0].material.color.r = 1
  46348. var geometry = new Geometry();
  46349. var faceArray = [],
  46350. triangles = ShapeUtils.triangulateShape(this.point2dInfo.points2d, []); //因为它只关注xy平面,垂直画就容易错,所以用转到平面的points2d来识别三角。
  46351. if (triangles.length == 0) return;
  46352. this._area = 0;
  46353. for (var i = 0; i < triangles.length; i++) {
  46354. faceArray[i] = new Face3(triangles[i][0], triangles[i][1], triangles[i][2]);
  46355. var nor = new Vector3().crossVectors(new Vector3().subVectors(this.points[triangles[i][0]], this.points[triangles[i][2]]), new Vector3().subVectors(this.points[triangles[i][1]], this.points[triangles[i][2]]));
  46356. this._area += nor.length() / 2;
  46357. nor.normalize();
  46358. faceArray[i].normal.copy(nor);
  46359. }
  46360. geometry.vertices = this.points;
  46361. geometry.faces = faceArray;
  46362. this.areaPlane.geometry = new BufferGeometry().fromGeometry(geometry); //不知道为何不转为bufferGeometry显示不出
  46363. //this.center
  46364. //参考getFacePlane 在这里建立_normal?
  46365. } else {
  46366. //if(this.point2dInfo){//旧的。 之前的规定点要在同一平面
  46367. this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d);
  46368. var _center = math.getCenterOfGravityPoint(this.point2dInfo.points2d); //重心
  46369. var firstPos = this.point2dInfo.points2d[0].clone();
  46370. firstPos.z = 0; //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
  46371. firstPos.applyQuaternion(this.point2dInfo.quaInverse);
  46372. var vec = this.point2dInfo.originPoint0.clone().sub(firstPos);
  46373. _center = new Vector3(_center.x, _center.y, 0);
  46374. _center.applyQuaternion(this.point2dInfo.quaInverse);
  46375. this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse);
  46376. this.areaPlane.position.copy(vec);
  46377. _center.add(vec);
  46378. this.center = _center;
  46379. //}
  46380. }
  46381. }
  46382. } else {
  46383. this.areaPlane.geometry = new Geometry();
  46384. }
  46385. }
  46386. getCenter(type) {
  46387. if (this.center) {
  46388. return this.center.clone();
  46389. } else {
  46390. var center = this.points.reduce(function (total, currentValue) {
  46391. return total.add(currentValue);
  46392. }, new Vector3());
  46393. this.points.length && center.multiplyScalar(1 / this.points.length);
  46394. return center; //求不出重心呜呜
  46395. }
  46396. }
  46397. getIndex(index, add) {
  46398. var lastIndex = this.points.length - 1;
  46399. if (add == -1) return index === 0 ? this.closed ? lastIndex : null : index - 1;else if (add == 1) return index + 1 > lastIndex ? this.closed ? 0 : null : index + 1;
  46400. }
  46401. getPoint(index, add) {
  46402. var index_ = this.getIndex(index, add);
  46403. return index_ == null ? null : this.points[index_];
  46404. }
  46405. updateEdge(index, p1, p2) {
  46406. this.edges[index] && LineDraw.updateLine(this.edges[index], p1, p2);
  46407. }
  46408. update() {
  46409. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  46410. if (this.points.length === 0) {
  46411. return;
  46412. }
  46413. //performance.mark('measureUpdate-start')
  46414. var lastIndex = this.points.length - 1;
  46415. if (options.index != void 0) {
  46416. //更新第几个点
  46417. this.updateMarker(this.markers[options.index], this.points[options.index]);
  46418. var previousIndex = this.getIndex(options.index, -1);
  46419. var nextIndex = this.getIndex(options.index, +1);
  46420. /* if( this.closed || nextIndex != 0 ) this.updateEdge(options.index, [this.points[options.index], this.points[nextIndex]]) //LineDraw.updateLine( this.edges[options.index], [this.points[options.index], this.points[nextIndex]])
  46421. if( this.closed || previousIndex != lastIndex ) this.updateEdge(previousIndex, [this.points[options.index], this.points[previousIndex]]) //LineDraw.updateLine( this.edges[previousIndex], [this.points[options.index], this.points[previousIndex]])
  46422. */
  46423. if (nextIndex != null) this.updateEdge(options.index, [this.points[options.index], this.points[nextIndex]]);
  46424. if (previousIndex != null) this.updateEdge(previousIndex, [this.points[options.index], this.points[previousIndex]]); //LineDraw.updateLine( this.edges[previousIndex], [this.points[options.index], this.points[previousIndex]])
  46425. } else {
  46426. for (var index = 0; index <= lastIndex; index++) {
  46427. var _nextIndex = this.getIndex(index, +1);
  46428. var _previousIndex = this.getIndex(index, -1);
  46429. var point = this.points[index];
  46430. var nextPoint = this.points[_nextIndex];
  46431. var previousPoint = this.points[_previousIndex];
  46432. if (options.ifUpdateMarkers) {
  46433. this.updateMarker(this.markers[index], point);
  46434. }
  46435. if (!nextPoint /* this.closed && nextIndex == 0 */) break; //add
  46436. {
  46437. this.updateEdge(index, [point, nextPoint]);
  46438. /* let edge = this.edges[index];
  46439. if(edge){
  46440. LineDraw.updateLine(edge, [point, nextPoint])
  46441. } */
  46442. }
  46443. }
  46444. }
  46445. if (this.areaPlane) {
  46446. this.updateAreaPlane();
  46447. }
  46448. //this.dispatchEvent({type:'update'})
  46449. viewer.dispatchEvent('content_changed');
  46450. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed'); //暂时先这么都通知
  46451. //performance.mark('measureUpdate-end')
  46452. //let measure = performance.measure('measure-','measureUpdate-start', 'measureUpdate-end' );
  46453. //console.log('update-time', measure.duration)
  46454. }
  46455. createPrismLines(color) {
  46456. this.lineMesh = LineDraw.createLine([], {
  46457. color
  46458. });
  46459. this.lineMesh.name = 'PrismLines';
  46460. this.add(this.lineMesh);
  46461. }
  46462. updatePrismLines() {
  46463. if (!this.lineMesh) return;
  46464. var positions = [];
  46465. var length = this.points.length;
  46466. this.points.forEach((point, index) => {
  46467. //竖线:
  46468. positions.push(point.clone().setZ(this.zMin), point.clone().setZ(this.zMax));
  46469. //横线
  46470. var nextPoint = this.points[(index + 1) % length];
  46471. if (!nextPoint) return; //when length==1
  46472. positions.push(point.clone().setZ(this.zMax), nextPoint.clone().setZ(this.zMax)); //上横线
  46473. positions.push(point.clone().setZ(this.zMin), nextPoint.clone().setZ(this.zMin)); //下横线
  46474. });
  46475. LineDraw.moveLine(this.lineMesh, positions);
  46476. viewer.dispatchEvent('content_changed');
  46477. }
  46478. dispose() {
  46479. //add
  46480. this.parent.remove(this);
  46481. this.markers.forEach(e => e.dispose && e.dispose());
  46482. this.edges.forEach(e => e.geometry.dispose());
  46483. }
  46484. reDraw() {
  46485. var restMarkerCount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  46486. //重新开始画
  46487. var pointCount = this.points.length - restMarkerCount; // restMarkerCount为需要留下的marker数量
  46488. while (pointCount > 0) {
  46489. this.removeMarker(--pointCount);
  46490. }
  46491. this.point2dInfo = null;
  46492. this.facePlane = null;
  46493. }
  46494. setMarkerSelected() {}
  46495. editStateChange(state) {
  46496. if (!state) {
  46497. viewer.dispatchEvent({
  46498. type: "CursorChange",
  46499. action: "remove",
  46500. name: "polygon_isIntersectSelf"
  46501. });
  46502. viewer.dispatchEvent({
  46503. type: "CursorChange",
  46504. action: "remove",
  46505. name: "polygon_AtWrongPlace"
  46506. });
  46507. viewer.dispatchEvent({
  46508. type: 'reticule_forbit',
  46509. v: false
  46510. });
  46511. this.markers.forEach(e => e.isDragging = false);
  46512. }
  46513. }
  46514. transformData(prop) {
  46515. var pick = (defaul, alternative) => {
  46516. if (defaul != null) {
  46517. return defaul;
  46518. } else {
  46519. return alternative;
  46520. }
  46521. };
  46522. prop.showDistances = prop.showDistances === null ? true : prop.showDistances;
  46523. prop.showArea = pick(prop.showArea, false);
  46524. prop.showAngles = pick(prop.showAngles, false);
  46525. prop.showCoordinates = pick(prop.showCoordinates, false);
  46526. prop.showHeight = pick(prop.showHeight, false);
  46527. prop.showCircle = pick(prop.showCircle, false);
  46528. prop.showAzimuth = pick(prop.showAzimuth, false);
  46529. prop.showEdges = pick(prop.showEdges, true);
  46530. prop.closed = pick(prop.closed, false);
  46531. prop.maxMarkers = pick(prop.maxMarkers, Infinity);
  46532. prop.direction = prop.direction; //add
  46533. prop.type = prop.type;
  46534. prop.showGuideLine = pick(prop.showGuideLine, false);
  46535. prop.isRect = pick(prop.isRect, false);
  46536. }
  46537. setSelected() {}
  46538. continueDrag(marker, e) {
  46539. var object = marker || e.drag.object;
  46540. object.isDragging = true;
  46541. this.editStateChange(true);
  46542. var timer = setTimeout(() => {
  46543. //等 drag=null之后 //右键拖拽结束后需要重新得到drag
  46544. if (this.parent && object.parent && object.isDragging) {
  46545. //console.log('continueDrag')
  46546. viewer.inputHandler.startDragging(object, {
  46547. endDragFun: e.drag.endDragFun,
  46548. notPressMouse: e.drag.notPressMouse,
  46549. dragViewport: e.drag.dragViewport
  46550. });
  46551. }
  46552. }, 1);
  46553. return timer;
  46554. }
  46555. getDifferentPoint(points, count) {
  46556. //for facePlane
  46557. var result = [];
  46558. for (var i = 0; i < points.length; i++) {
  46559. var p = points[i];
  46560. if (result.find(e => e.equals(p))) continue;else result.push(p);
  46561. if (result.length == count) break;
  46562. }
  46563. if (result.length == count || count == void 0) return result;
  46564. }
  46565. getTotalDistance() {
  46566. if (this.points.length === 0) {
  46567. return 0;
  46568. }
  46569. var distance = 0;
  46570. for (var i = 1; i < this.points.length; i++) {
  46571. var prev = this.points[i - 1];
  46572. var curr = this.points[i];
  46573. var d = prev.distanceTo(curr);
  46574. distance += d;
  46575. }
  46576. if (this.closed && this.points.length > 1) {
  46577. var first = this.points[0];
  46578. var last = this.points[this.points.length - 1];
  46579. var _d = last.distanceTo(first);
  46580. distance += _d;
  46581. }
  46582. this.totalLength = distance;
  46583. return distance;
  46584. }
  46585. }
  46586. var texLoader$6 = new TextureLoader();
  46587. var defaultColor$1 = new Color(config$1.measure.default.color);
  46588. var highlightColor = new Color(config$1.measure.highlight.color);
  46589. var color = new Color(config$1.measure.color);
  46590. var textColor = new Color(config$1.measure.textColor);
  46591. var markerMaps;
  46592. var textSizeRatio = math.linearClamp(window.outerWidth * window.outerHeight, [360 * 720, 1920 * 1080], [0.7, 1]); //pc字显示大一些 用
  46593. var lineDepthInfo = {
  46594. clipDistance: 15,
  46595. //4,//消失距离
  46596. occlusionDistance: 3 //1,//变为backColor距离
  46597. };
  46598. var markerMapShrink = browser.isMobile() ? 0.4 : 0.8; //触屏需要更大的热区
  46599. var markerSizeInfo = {
  46600. width2d: 18 / markerMapShrink // nearBound : 1.5, farBound : 15,
  46601. };
  46602. /* const markerSizeInfo = {
  46603. minSize : 10 , maxSize : 15 , nearBound : 1.5, farBound : 15,
  46604. } */
  46605. var labelSizeInfo = {
  46606. width2d: 200
  46607. };
  46608. var mainLabelProp = {
  46609. //backgroundColor: {r: defaultColor.r*255, g: defaultColor.g*255, b: defaultColor.b*255, a:config.measure.default.opacity},
  46610. backgroundColor: {
  46611. r: 0,
  46612. g: 0,
  46613. b: 0,
  46614. a: 0
  46615. },
  46616. textColor: {
  46617. r: textColor.r * 255,
  46618. g: textColor.g * 255,
  46619. b: textColor.b * 255,
  46620. a: 1.0
  46621. },
  46622. textBorderColor: {
  46623. r: 255,
  46624. g: 255,
  46625. b: 255,
  46626. a: 1.0
  46627. },
  46628. textBorderThick: 3,
  46629. fontsize: 14 * textSizeRatio,
  46630. borderRadius: 12,
  46631. margin: {
  46632. x: 20,
  46633. y: 4
  46634. },
  46635. renderOrder: Potree.config.renderOrders.measureLabel,
  46636. pickOrder: Potree.config.renderOrders.measureLabel,
  46637. transform2D: {
  46638. x: 0,
  46639. y: -0.15
  46640. },
  46641. useDepth: true,
  46642. // 2023.10 尽量不让数字被挡住
  46643. clipDistance: 10,
  46644. //消失距离
  46645. occlusionDistance: 10,
  46646. //变为backColor距离
  46647. maxOcclusionFactor: 0.3,
  46648. maxClipFactor: 0.8,
  46649. maxLineWidth: 300,
  46650. lineSpace: 6
  46651. };
  46652. var subLabelProp = {
  46653. backgroundColor: {
  46654. r: 255,
  46655. g: 255,
  46656. b: 255,
  46657. a: 0
  46658. },
  46659. textColor: {
  46660. r: textColor.r * 255,
  46661. g: textColor.g * 255,
  46662. b: textColor.b * 255,
  46663. a: 1.0
  46664. },
  46665. textBorderColor: {
  46666. r: 255,
  46667. g: 255,
  46668. b: 255,
  46669. a: 1.0
  46670. },
  46671. textBorderThick: 3,
  46672. fontsize: 13 * textSizeRatio,
  46673. renderOrder: Potree.config.renderOrders.measureLabelSub,
  46674. pickOrder: Potree.config.renderOrders.measureLabelSub,
  46675. transform2D: {
  46676. x: 0,
  46677. y: -0.13
  46678. }
  46679. };
  46680. var angle = MathUtils.degToRad(5); //显示水平垂直辅助线的最小角度
  46681. var guideShowMinAngle = {
  46682. min: angle,
  46683. max: Math.PI / 2 - angle
  46684. };
  46685. class Measure$1 extends ctrlPolygon {
  46686. constructor(prop) {
  46687. prop.dimension = '2d';
  46688. super('measure', prop);
  46689. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  46690. this.name = this.name || this.measureType + this.constructor.counter;
  46691. this.selectStates = {};
  46692. this.edgeLabels = [];
  46693. this.coordinateLabels = [];
  46694. this.area = {
  46695. value: 0,
  46696. string: ''
  46697. };
  46698. this.expands = [];
  46699. if (this.showArea) {
  46700. this.areaLabel = this.createAreaLabel();
  46701. this.add(this.areaLabel);
  46702. }
  46703. //add:
  46704. if (this.atPlane || this.faceDirection) {
  46705. //是一个平面上的话
  46706. this.createGuideLine();
  46707. }
  46708. if (this.measureType == 'Distance' /* || this.measureType.includes('MulDistance') */) {
  46709. this.createHorVerGuideLine();
  46710. }
  46711. this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem);
  46712. //Potree.Utils.setObjectLayers(this, 'measure' ) //取消:scene单独渲染应该不需要设置layer
  46713. if (this.measureType == 'MulDistance' || this.measureType == 'Hor MulDistance' || this.measureType == 'Ver MulDistance') {
  46714. //this.showTotalDis = true
  46715. this.totalDisLabel = this.createTotalDisLabel();
  46716. this.add(this.totalDisLabel);
  46717. }
  46718. //addMarkers:
  46719. this.initData(prop);
  46720. this.pointsPos2d = new Map(); //屏幕上的二维坐标
  46721. this.points_datasets || (this.points_datasets = []); //存每个点是哪个数据集
  46722. this.addEventListener('marker_dropped', e => {
  46723. this.updateDatasetBelong(e.index);
  46724. });
  46725. this.addEventListener('isVisible', () => {
  46726. viewer.mapViewer && viewer.mapViewer.dispatchEvent({
  46727. type: 'content_changed'
  46728. });
  46729. });
  46730. this.lastDropTime = 0;
  46731. }
  46732. initData(prop) {
  46733. var makeIt = super.initData(prop);
  46734. if (makeIt) {
  46735. this.edges.forEach(edge => {
  46736. edge.dispatchEvent('addHoverEvent');
  46737. });
  46738. } else {
  46739. this.failBuilded = true;
  46740. }
  46741. if (prop.expands) {
  46742. //基本不会从这加
  46743. for (var data of prop.expands) {
  46744. this.addExpand(data);
  46745. }
  46746. }
  46747. }
  46748. updateDatasetBelong(changeIndex) {
  46749. //更新所属数据集
  46750. if (Potree.settings.editType == "merge" || this.measureType == 'MulDistance Ring') {
  46751. //点直接跟着数据集走,不用找整体的datasetId
  46752. this.dataset_points[changeIndex] = Potree.Utils.datasetPosTransform({
  46753. toDataset: true,
  46754. datasetId: this.points_datasets[changeIndex],
  46755. position: this.points[changeIndex].clone()
  46756. });
  46757. return;
  46758. }
  46759. var old = this.datasetId;
  46760. var maxCount = {
  46761. id: null,
  46762. count: 0
  46763. };
  46764. var datasets = {};
  46765. this.points_datasets.forEach(e => {
  46766. if (e == void 0) return;
  46767. if (datasets[e]) {
  46768. datasets[e]++;
  46769. } else {
  46770. datasets[e] = 1;
  46771. }
  46772. });
  46773. for (var i in datasets) {
  46774. if (datasets[i] > maxCount.count) {
  46775. maxCount = {
  46776. id: i,
  46777. count: datasets[i]
  46778. };
  46779. }
  46780. }
  46781. this.datasetId = maxCount.count > 0 ? maxCount.id : null;
  46782. //if(this.datasetId != old){
  46783. //this.dispatchEvent({type:'changeDatasetId'})
  46784. if (this.datasetId == void 0) {
  46785. this.dataset_points = null; //可能为空或[null,null...]
  46786. } else {
  46787. this.dataset_points = this.points.map(e => {
  46788. return Potree.Utils.datasetPosTransform({
  46789. toDataset: true,
  46790. datasetId: this.datasetId,
  46791. position: e.clone()
  46792. });
  46793. });
  46794. }
  46795. //}
  46796. }
  46797. transformByPointcloud() {
  46798. //每次移动点云 or 加载测量线时要获取一下当前position //有地图时
  46799. if (this.datasetId == void 0) return;
  46800. this.points = this.dataset_points.map(e => {
  46801. return Potree.Utils.datasetPosTransform({
  46802. fromDataset: true,
  46803. datasetId: this.datasetId,
  46804. position: e.clone()
  46805. });
  46806. });
  46807. this.getPoint2dInfo(this.points);
  46808. this.update({
  46809. ifUpdateMarkers: true
  46810. });
  46811. this.setSelected(false); //隐藏edgelabel
  46812. }
  46813. changeColor(color) {
  46814. this.color = color; //'#ffffff'
  46815. this.edges.forEach(e => e.material = this.getMat('edgeDefault')); //update
  46816. this.markers.forEach(e => e.material = this.getMat('markerDefault'));
  46817. this.areaPlane && (this.areaPlane.material = this.getMat('planeDefault'));
  46818. this.expands.forEach(e => e.edges.forEach(a => a.material = this.getMat('edgeExpand')));
  46819. viewer.dispatchEvent('content_changed');
  46820. }
  46821. update() {
  46822. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  46823. if (options.index == -1) return;
  46824. super.update(options);
  46825. if (this.showCoordinates && this.points.length > 0) {
  46826. var position = this.points[0];
  46827. this.markers[0].position.copy(position);
  46828. {
  46829. // coordinate labels
  46830. var coordinateLabel = this.coordinateLabels[0];
  46831. var pos = [position.toArray()];
  46832. if (viewer.transform) {
  46833. var lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray());
  46834. var EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat);
  46835. pos.push(lonlat, EPSG4550);
  46836. }
  46837. //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  46838. var msg = pos.map(a => a.map(p => Utils.addCommas(p.toFixed(10))).join(", ")).join("<br>");
  46839. coordinateLabel.setText(msg);
  46840. coordinateLabel.setPos(position);
  46841. coordinateLabel.setVisible(true); //this.showCoordinates;
  46842. }
  46843. return;
  46844. }
  46845. var setEdgeLabel = (label, p1, p2, distance, type) => {
  46846. //设置label位置和字
  46847. this.setEdgeLabelPos(label, p1, p2);
  46848. distance = distance == void 0 ? p1.distanceTo(p2) : distance;
  46849. //var text = viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 1 , true)//distance要传0.1 这个factor
  46850. var text = this.getConvertString(distance, 'distance');
  46851. this.showArea || type == 'addTitle' && (text = this.labelAddName(text));
  46852. label.setText(text);
  46853. return distance;
  46854. };
  46855. var lastIndex = this.points.length - 1;
  46856. var setLabel = index => {
  46857. if (index == null) return;
  46858. var previousIndex = this.getIndex(index, -1);
  46859. var nextIndex = this.getIndex(index, +1);
  46860. var previousPoint = this.points[previousIndex];
  46861. var point = this.points[index];
  46862. var nextPoint = this.points[nextIndex];
  46863. if (this.showDistances) {
  46864. // edge labels
  46865. var edgeLabel = this.edgeLabels[index];
  46866. var distance = nextPoint && point.distanceTo(nextPoint);
  46867. this.edges[index].distance_ = distance;
  46868. edgeLabel.shouldVisi = nextPoint && (index < lastIndex || this.isRect || this.closed && !this.isNew) && distance > 0;
  46869. //this.closed || edgeLabel.setVisible(edgeLabel.shouldVisi) //closed的在setEdgesDisplay中设置
  46870. Utils.updateVisible(edgeLabel, 'shouldVisi', edgeLabel.shouldVisi, 2);
  46871. if (edgeLabel.shouldVisi) {
  46872. edgeLabel.lineDir = new Vector3().subVectors(point, nextPoint).normalize(); //[point,nextPoint]
  46873. setEdgeLabel(edgeLabel, point, nextPoint, distance, this.measureType != 'MulDistance' && 'addTitle');
  46874. }
  46875. }
  46876. };
  46877. if (options.index != void 0) {
  46878. //更新第几个点
  46879. setLabel(options.index);
  46880. var previousIndex = this.getIndex(options.index, -1);
  46881. setLabel(previousIndex);
  46882. } else {
  46883. for (var index = 0; index <= lastIndex; index++) {
  46884. setLabel(index);
  46885. }
  46886. }
  46887. if (Potree.config.measure.mulLabelHideFaraway) {
  46888. this.measureType == 'MulDistance' && this.clearEdgeLabelVisi();
  46889. }
  46890. if (this.measureType == 'Distance' && this.points.length > 1) {
  46891. //设置水平垂直辅助线
  46892. var pTop, pBtm;
  46893. if (this.points[0].z > this.points[1].z) {
  46894. pTop = this.points[0];
  46895. pBtm = this.points[1];
  46896. } else {
  46897. pTop = this.points[1];
  46898. pBtm = this.points[0];
  46899. }
  46900. var projectPos = new Vector3(pTop.x, pTop.y, pBtm.z); //两条guideline的交点
  46901. {
  46902. //倾斜角度太小的时候不显示
  46903. var tan = pTop.distanceTo(projectPos) / pBtm.distanceTo(projectPos);
  46904. var _angle = Math.atan(tan);
  46905. this.shouldShowHorVerGuide = _angle > guideShowMinAngle.min && _angle < guideShowMinAngle.max;
  46906. }
  46907. LineDraw.updateLine(this.verGuideEdge, [pTop, projectPos]);
  46908. LineDraw.updateLine(this.horGuideEdge, [pBtm, projectPos]);
  46909. setEdgeLabel(this.verEdgeLabel, pTop, projectPos);
  46910. setEdgeLabel(this.horEdgeLabel, pBtm, projectPos);
  46911. this.verGuideEdge.visible = this.horGuideEdge.visible = this.shouldShowHorVerGuide;
  46912. this.verEdgeLabel.visible = this.horEdgeLabel.visible = this.shouldShowHorVerGuide;
  46913. }
  46914. if (this.showArea && this.points.length > 2) {
  46915. // update area
  46916. var _msg = this.getArea().string;
  46917. _msg = this.labelAddName(_msg);
  46918. this.areaLabel.setPos(this.getCenter('areaPlaneCenter'));
  46919. this.areaLabel.setText(_msg);
  46920. Utils.updateVisible(this.areaLabel, 'setVisible', true); //this.areaLabel.setVisible(true)
  46921. }
  46922. if (this.totalDisLabel) {
  46923. this.ifShowTotalDis();
  46924. Utils.updateVisible(this.totalDisLabel, 'setVisible', this.showTotalDis);
  46925. this.edgeLabels.forEach(e => Utils.updateVisible(e, 'showTotalDis', !this.showTotalDis));
  46926. if (this.showTotalDis) {
  46927. var dis = this.getTotalDistance();
  46928. var _msg2 = this.getConvertString(dis, 'distance');
  46929. _msg2 = this.labelAddName(_msg2);
  46930. this.center = null;
  46931. this.center = this.getCenter();
  46932. this.totalDisLabel.setPos(this.center);
  46933. this.totalDisLabel.setText(_msg2);
  46934. }
  46935. }
  46936. this.expands.forEach(e => e.update(options));
  46937. }
  46938. labelAddName(msg) {
  46939. var _this$title;
  46940. if (Potree.config.measure.showName && (_this$title = this.title) !== null && _this$title !== void 0 && _this$title.trim()) {
  46941. msg = [this.title, msg];
  46942. }
  46943. return msg;
  46944. }
  46945. getArea() {
  46946. var area;
  46947. if (this._area != void 0) {
  46948. area = this._area;
  46949. } else if (this.point2dInfo) {
  46950. area = Math.abs(math.getArea(this.point2dInfo.points2d)); //this.getArea();
  46951. } else {
  46952. //mulDistance Ring 2d面
  46953. area = Math.abs(math.getArea(this.points));
  46954. }
  46955. var msg = this.getConvertString(area, 'area');
  46956. //let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
  46957. this.area = {
  46958. value: area,
  46959. string: msg
  46960. };
  46961. return this.area;
  46962. }
  46963. getConvertString(num, type) {
  46964. return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, true, {
  46965. 'imperial': {
  46966. minFactor: 0.01
  46967. },
  46968. 'metric': {
  46969. minFactor: 0.01
  46970. }
  46971. });
  46972. }
  46973. ifShowTotalDis() {
  46974. var show = this.points.length > 2;
  46975. if (show) {
  46976. var maxDis = 0.15;
  46977. var lastIndex = this.points.length - 1;
  46978. for (var i = 0; i < lastIndex; i++) {
  46979. var len = this.edges[i].distance_;
  46980. if (len > maxDis) {
  46981. show = false;
  46982. break;
  46983. }
  46984. }
  46985. }
  46986. this.showTotalDis = show;
  46987. /* 连续测量:
  46988. 1. ≥2次测量,单个距离<15cm时,居中显示总长, hover、选中时显示每段长度
  46989. 2. 若连续测量的线段中,大于等于1段超出15cm,所有线段均显示长度
  46990. -------------------
  46991. */
  46992. }
  46993. clearEdgeLabelVisi() {
  46994. //修改点位置后清空,下次render时会自动getEdgeLabelVisi
  46995. var lastIndex = this.points.length - 1;
  46996. for (var index = 0; index <= lastIndex; index++) {
  46997. if (!this.closed && index == lastIndex) continue;
  46998. var edgeLabel = this.edgeLabels[index];
  46999. edgeLabel.visiMap.clear();
  47000. }
  47001. }
  47002. getEdgeLabelVisi(viewport) {
  47003. //获取多折线的edgelabel在不同视图里的可见性。要保证任何时候label能出现的线最小二维长度一致
  47004. var camera = viewport.camera;
  47005. var lastIndex = this.points.length - 1;
  47006. /* let pos2ds = this.points.map(point=> point.clone().project(camera) ) //即使只是旋转也会变动,尤其是转到屏幕外后变为显示。所以不用这种
  47007. let minDis = 0.01; */
  47008. var minDis = 0.02,
  47009. minAngleRatio = 0.07,
  47010. minAngle;
  47011. var vecs;
  47012. var forceShow;
  47013. if (camera.type == 'OrthographicCamera') {
  47014. minDis *= Math.pow(camera.top / camera.zoom, 2);
  47015. //console.log(minDis)
  47016. } else {
  47017. if (Potree.settings.displayMode == 'showPanos' && viewer.images360.zoomLevel == Potree.settings.zoom.max) {
  47018. forceShow = true; //当zoom到最大时强制显示,避免有的线太短永远显示不出长度
  47019. } else {
  47020. vecs = this.points.map(point => new Vector3().subVectors(point, camera.position).normalize());
  47021. minAngleRatio /= viewport.resolution.y / 1000 / textSizeRatio; //角度占fov最小比率
  47022. minAngle = minAngleRatio * MathUtils.degToRad(camera.fov);
  47023. }
  47024. }
  47025. for (var index = 0; index <= lastIndex; index++) {
  47026. if (!this.closed && index == lastIndex) continue;
  47027. var edgeLabel = this.edgeLabels[index];
  47028. var nextIndex = index + 1 > lastIndex ? 0 : index + 1;
  47029. var previousIndex = index === 0 ? lastIndex : index - 1;
  47030. var point = this.points[index];
  47031. var nextPoint = this.points[nextIndex];
  47032. /* let point2d = pos2ds[index];
  47033. let nextPoint2d = pos2ds[nextIndex];
  47034. let dis2d = point2d.distanceToSquared(nextPoint2d)
  47035. let v = dis2d > minDis //可见长度太小,为避免拥挤,不显示
  47036. edgeLabel.visiMap.set(camera, v) */
  47037. var v = void 0;
  47038. if (forceShow) {
  47039. v = true;
  47040. } else if (camera.type == 'OrthographicCamera') {
  47041. var vec = new Vector3().subVectors(point, nextPoint);
  47042. var projVec = vec.projectOnPlane(viewport.view.direction);
  47043. v = projVec.lengthSq() > minDis;
  47044. } else {
  47045. var vec0 = vecs[index];
  47046. var vec1 = vecs[nextIndex];
  47047. v = Math.acos(vec0.dot(vec1)) > minAngle; //角度过小代表可见长度太小,为避免拥挤,不显示
  47048. }
  47049. edgeLabel.visiMap.set(camera, v);
  47050. }
  47051. }
  47052. setEdgeLabelPos(label, p1, p2) {
  47053. //调整label的位置,使倾斜后看起来在线的中心,而不要挡住端点
  47054. var center = new Vector3().addVectors(p1, p2).multiplyScalar(0.5);
  47055. return label.setPos(center);
  47056. if (label.lineDir && label.lineDir.length() > 0) {
  47057. if (viewer.mainViewport.camera.type == 'OrthographicCamera') {
  47058. label.setPos(center);
  47059. } else {
  47060. //根据视线和线的夹角(后又加入相机和两个端点距离差)来决定标签偏移位置。+
  47061. var eyePos = viewer.mainViewport.camera.position;
  47062. var dir = viewer.mainViewport.view.direction; //new THREE.Vector3().subVectors(center,eyePos).normalize()
  47063. /*let centerDir = new THREE.Vector3().subVectors(center,eyePos).normalize()
  47064. if(centerDir.dot(dir)<0){//中点在相机后方,就不设置
  47065. label.setPos(center)
  47066. return
  47067. } */
  47068. var cos = dir.dot(label.lineDir);
  47069. var nearPoint = cos > 0 ? p2 : p1; //近端点。
  47070. var far = cos > 0 ? p1 : p2; //远端点。
  47071. var nearPointDir = new Vector3().subVectors(nearPoint, eyePos); //.normalize()
  47072. //使label在中点和近端点中变化, 近端点可能到了相机后方,需要投影到相机所在平面上
  47073. if (nearPointDir.dot(dir) < 0) {
  47074. //近端点到了相机后方,前移。
  47075. //let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera , true ); //暂且只看水平fov
  47076. //if(nearPointDir.dot(dir)<Math.cos(hfov/2)){//近端点在镜头外,前移。 --但是这个就得把点转化成在镜头边缘而非左右两边(camDirPlane上)
  47077. var ray = new Raycaster();
  47078. ray.set(nearPoint, cos > 0 ? label.lineDir : label.lineDir.clone().negate());
  47079. var camDirPlane = new Plane().setFromNormalAndCoplanarPoint(dir, eyePos);
  47080. nearPoint = ray.ray.intersectPlane(camDirPlane, new Vector3());
  47081. if (!nearPoint) {
  47082. //线是垂直的,视线是水平的时候
  47083. return label.setPos(center);
  47084. }
  47085. }
  47086. //防止离远了之后也偏移很多,但远了之后相机到端点vec和到中点的vec的夹角接近,不需要怎么偏移的。
  47087. var dis1 = nearPoint.distanceToSquared(eyePos);
  47088. var dis2 = far.distanceToSquared(eyePos);
  47089. var diff = Math.abs(dis1 / dis2);
  47090. diff < 1 && (diff = 1 / diff);
  47091. diff = math.linearClamp(diff, [0, 30], [0, 1]);
  47092. var efficiency = 0.7; // 0-1 数值越高,r越容易接近1或-1,label越容易在倾斜后靠近近端点。
  47093. //let r = 0.5*efficiency*cos + 0.5
  47094. var r = 0.5 * efficiency * diff * cos + 0.5;
  47095. r = MathUtils.clamp(r, 0.1, 0.9);
  47096. //视线越接近线的方向,标签应该越往近端点偏移,防止看起来几乎在远端。
  47097. if (cos > 0) {
  47098. center = p1.clone().multiplyScalar(1 - r).add(nearPoint.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
  47099. } else {
  47100. center = nearPoint.clone().multiplyScalar(1 - r).add(p2.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
  47101. }
  47102. label.setPos(center);
  47103. }
  47104. //归零
  47105. //this.orient2dInfo = null
  47106. //this.markers.forEach(e=>e.needsUpdate=true)
  47107. } else {
  47108. label.setPos(center);
  47109. }
  47110. }
  47111. cloneMarker(cloneIndex, index) {
  47112. return this.addMarker({
  47113. index,
  47114. point: this.points[cloneIndex],
  47115. dataset_point: this.dataset_points && this.dataset_points[cloneIndex],
  47116. points_dataset: this.points_datasets[cloneIndex]
  47117. });
  47118. }
  47119. addMarker() {
  47120. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  47121. var index = o.index == void 0 ? this.points.length : o.index; //要当第几个
  47122. var marker = o.marker || new Sprite$2({
  47123. mat: this.getMat('markerDefault'),
  47124. sizeInfo: markerSizeInfo,
  47125. name: "measure_point"
  47126. });
  47127. //Potree.Utils.setObjectLayers(marker, 'measure' )
  47128. marker.pickOrder = marker.renderOrder = Potree.config.renderOrders.measureMarker;
  47129. marker.markerSelectStates = {};
  47130. marker.addEventListener('startDragging', e => {
  47131. /* if(e.drag.dragViewport.name == 'MainView') */viewer.inputHandler.dispatchEvent({
  47132. type: 'measuring',
  47133. v: true,
  47134. cause: 'startDragging',
  47135. situation: 'dragging',
  47136. object: this
  47137. });
  47138. //add for 调试,方便后期增加点
  47139. if (!this.isNew && viewer.inputHandler.pressedKeys['M'.charCodeAt(0)] && this.points.length < this.maxMarkers) {
  47140. viewer.measuringTool.history.beforeChange(this);
  47141. var curIndex = this.markers.indexOf(marker);
  47142. this.cloneMarker(curIndex, curIndex + 1);
  47143. }
  47144. this.isNew || viewer.measuringTool.history.beforeChange(this);
  47145. });
  47146. marker.addEventListener('drop', e => {
  47147. if (e.button != MOUSE.LEFT) return;
  47148. viewer.inputHandler.dispatchEvent({
  47149. type: 'measuring',
  47150. v: false,
  47151. cause: 'stopDragging',
  47152. situation: 'dragging',
  47153. object: this
  47154. });
  47155. this.lastDropTime = Date.now();
  47156. if (Potree.settings.adsorption) {
  47157. this.isNew || viewer.viewports.forEach(viewport => {
  47158. this.getPointsPos2d(viewport, true); //forceUpdate
  47159. });
  47160. }
  47161. this.isNew || viewer.measuringTool.history.afterChange(this);
  47162. });
  47163. marker.addEventListener('click', () => {
  47164. if (viewer.measuringTool.editMode == 'delPoint') {
  47165. /* if(this.points.length == this.minMarkers){//--前端去重绘
  47166. viewer.scene.removeMeasurement(this)
  47167. }else{ */
  47168. viewer.measuringTool.history.beforeChange(this);
  47169. var _index = this.markers.indexOf(marker);
  47170. this.removeMarker(_index);
  47171. viewer.measuringTool.history.afterChange(this);
  47172. this.dispatchEvent('changed');
  47173. //}
  47174. }
  47175. });
  47176. //marker.measure = this
  47177. var edge;
  47178. {
  47179. // edges
  47180. edge = o.edge || LineDraw.createFatLine([], {
  47181. mat: this.getMat('edgeDefault')
  47182. });
  47183. edge.pickOrder = 0;
  47184. //Potree.Utils.setObjectLayers(edge, 'measure' )
  47185. var addHoverEvent = () => {
  47186. //当非isNew时才添加事件
  47187. var mouseover = e => {
  47188. /* if(this.measureType == 'MulDistance'){
  47189. } */
  47190. this.setSelected(true, 'edge');
  47191. };
  47192. var mouseleave = e => {
  47193. this.setSelected(false, 'edge');
  47194. };
  47195. edge.addEventListener('mouseover', mouseover);
  47196. edge.addEventListener('mouseleave', mouseleave);
  47197. edge.removeEventListener('addHoverEvent', addHoverEvent);
  47198. edge.addEventListener('click', e => {
  47199. var now = Date.now();
  47200. if (now - this.lastDropTime < 100) return; //防止拖拽marker时误触导致focus, 以及点到marker不focus
  47201. if (viewer.measuringTool.editMode == 'addPoint' && this.points.length < this.maxMarkers) {
  47202. viewer.measuringTool.history.beforeChange(this);
  47203. var _index2 = this.edges.indexOf(edge) + 1;
  47204. var nextIndex = _index2 % this.edges.length;
  47205. var point = math.getFootPoint(e.hoveredElement.point, this.points[_index2 - 1], this.points[nextIndex]);
  47206. this.addMarker({
  47207. index: _index2,
  47208. point,
  47209. dataset_point: this.dataset_points && new Vector3(),
  47210. //初始化
  47211. points_dataset: this.points_datasets[_index2 - 1] //使用前一个的
  47212. });
  47213. this.updateDatasetBelong(_index2); //获取dataset_point
  47214. viewer.measuringTool.history.afterChange(this);
  47215. this.dispatchEvent('changed');
  47216. //this.update({})
  47217. } else {
  47218. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure'); //正在添加测量线时不要focus其他线(容易误触)
  47219. }
  47220. });
  47221. };
  47222. edge.addEventListener('addHoverEvent', addHoverEvent);
  47223. if (!this.isNew) {
  47224. edge.dispatchEvent('addHoverEvent');
  47225. }
  47226. }
  47227. super.addMarker(Object.assign(o, {
  47228. index,
  47229. marker,
  47230. edge
  47231. }));
  47232. if (this.showEdges) {
  47233. // edge labels
  47234. var edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed);
  47235. this.edgeLabels = [...this.edgeLabels.slice(0, index), edgeLabel, ...this.edgeLabels.slice(index, this.edgeLabels.length)];
  47236. }
  47237. if (this.showCoordinates) {
  47238. // coordinate labels
  47239. var coordinateLabel = new Label({
  47240. className: 'measure_pointPos',
  47241. camera: viewer.scene.getActiveCamera()
  47242. });
  47243. coordinateLabel.setVisible(false);
  47244. this.coordinateLabels.push(coordinateLabel);
  47245. }
  47246. var event = {
  47247. type: 'marker_added',
  47248. measurement: this,
  47249. marker: marker
  47250. };
  47251. this.dispatchEvent(event);
  47252. this.expands.forEach(e => e.addMarker(o));
  47253. //this.setMarker(this.points.length - 1, point);
  47254. this.update({
  47255. index
  47256. }); //更新一下倒数第二条线
  47257. return marker; //add
  47258. }
  47259. editStateChange(state) {
  47260. //主要针对edgeLabels显示切换,编辑时显示
  47261. super.editStateChange(state);
  47262. if (!state) {
  47263. this.editStateTimer = setTimeout(() => {
  47264. if (!this.isEditing) {
  47265. this.dispatchEvent({
  47266. type: 'editStateChange',
  47267. state: false
  47268. });
  47269. this.setEdgesDisplay(false);
  47270. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true);
  47271. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true);
  47272. }
  47273. }, 100);
  47274. } else {
  47275. if (!this.isEditing) {
  47276. this.dispatchEvent({
  47277. type: 'editStateChange',
  47278. state: true
  47279. });
  47280. this.setEdgesDisplay(true);
  47281. clearTimeout(this.editStateTimer);
  47282. }
  47283. }
  47284. this.isEditing = state;
  47285. }
  47286. setMarkerSelected(marker, state, hoverObject) {
  47287. //console.warn(marker.id , state, hoverObject)
  47288. marker.markerSelectStates[hoverObject] = state;
  47289. var absoluteState = false;
  47290. for (var i in marker.markerSelectStates) {
  47291. if (marker.markerSelectStates[i] == 'hover') {
  47292. absoluteState = true;
  47293. break;
  47294. }
  47295. }
  47296. if (absoluteState) {
  47297. marker.material = this.getMat('markerSelect');
  47298. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker + 1;
  47299. } else {
  47300. marker.material = this.getMat('markerDefault');
  47301. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker;
  47302. }
  47303. marker.selected = absoluteState;
  47304. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  47305. viewer.dispatchEvent('content_changed');
  47306. }
  47307. setEdgesDisplay(state, ignoreGuideLine) {
  47308. this.closed && this.edgeLabels.forEach(e => Utils.updateVisible(e, 'hover', state));
  47309. if (this.totalDisLabel && !viewer.screenshoting) {
  47310. this.edgeLabels.forEach(e => Utils.updateVisible(e, 'hover', state, 1, state ? 'add' : 'cancel'));
  47311. Utils.updateVisible(this.totalDisLabel, 'hover', !state);
  47312. }
  47313. if (!ignoreGuideLine && this.measureType == 'Distance') {
  47314. this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide);
  47315. }
  47316. }
  47317. setSelected(state, hoverObject) {
  47318. //add
  47319. //console.log('setSelected',state, hoverObject)
  47320. var absoluteState = !!state;
  47321. if (hoverObject) {
  47322. //如果没有hoverObject且state为false 就强制取消选中态
  47323. this.selectStates[hoverObject] = state;
  47324. for (var i in this.selectStates) {
  47325. if (this.selectStates[i]) {
  47326. absoluteState = true;
  47327. break;
  47328. }
  47329. }
  47330. }
  47331. if (absoluteState) {
  47332. this.markers.forEach(e => this.setMarkerSelected(e, 'hover', 'selectAll'));
  47333. this.edges.forEach(e => {
  47334. e.renderOrder = Potree.config.renderOrders.line + 1;
  47335. e.material = this.getMat('edgeSelect');
  47336. });
  47337. this.areaPlane && (this.areaPlane.material = this.getMat('planeSelected'));
  47338. //this.areaLabel && this.areaLabel.elem.addClass('highLight')
  47339. //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight') )
  47340. this.setEdgesDisplay(true, hoverObject == "screenshot");
  47341. this.areaLabel && setLabelHightState(this.areaLabel, true);
  47342. this.closed || this.edgeLabels.forEach(e => setLabelHightState(e, true));
  47343. } else {
  47344. this.markers.forEach(e => this.setMarkerSelected(e, 'unhover', 'selectAll'));
  47345. this.edges.forEach(e => e.material = this.getMat('edgeDefault'));
  47346. this.areaPlane && (this.areaPlane.material = this.getMat('planeDefault'));
  47347. this.setEdgesDisplay(false, hoverObject == "screenshot");
  47348. //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
  47349. //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight') )
  47350. this.areaLabel && setLabelHightState(this.areaLabel, false);
  47351. this.closed || this.edgeLabels.forEach(e => setLabelHightState(e, false));
  47352. }
  47353. this.selected = absoluteState;
  47354. if (hoverObject != 'byList') {
  47355. //this.bus && this.bus.emit('highlight', this.selected)
  47356. this.dispatchEvent({
  47357. type: 'highlight',
  47358. state: this.selected
  47359. }); //列表高亮
  47360. }
  47361. viewer.dispatchEvent('content_changed');
  47362. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  47363. }
  47364. removeMarker(index) {
  47365. super.removeMarker(index);
  47366. this.points_datasets.splice(index, 1);
  47367. this.dataset_points && this.dataset_points.splice(index, 1);
  47368. this.coordinateLabels.splice(index, 1);
  47369. var edgeIndex = index; //(index === 0) ? 0 : (index - 1);
  47370. if (this.edgeLabels[edgeIndex]) {
  47371. this.edgeLabels[edgeIndex].dispose();
  47372. this.edgeLabels.splice(edgeIndex, 1);
  47373. }
  47374. this.expands.forEach(e => e.removeMarker(index));
  47375. this.update({
  47376. index: this.getIndex(index, -1)
  47377. });
  47378. this.dispatchEvent({
  47379. type: 'marker_removed',
  47380. measurement: this
  47381. });
  47382. }
  47383. setPosition(index, position) {
  47384. super.setPosition(index, position);
  47385. var event = {
  47386. type: 'marker_moved',
  47387. measure: this,
  47388. index: index,
  47389. position: position.clone()
  47390. };
  47391. this.dispatchEvent(event);
  47392. }
  47393. dispose() {
  47394. //add
  47395. var labels = this.edgeLabels.concat(this.coordinateLabels);
  47396. this.areaLabel && labels.push(this.areaLabel);
  47397. labels.forEach(e => e.dispose());
  47398. this.expands.forEach(e => e.dispose());
  47399. this.expands.length = 0;
  47400. super.dispose();
  47401. this.dispatchEvent('disposed');
  47402. }
  47403. getAngleBetweenLines(cornerPoint, point1, point2) {
  47404. var v1 = new Vector3().subVectors(point1, cornerPoint);
  47405. var v2 = new Vector3().subVectors(point2, cornerPoint);
  47406. // avoid the error printed by threejs if denominator is 0
  47407. var denominator = Math.sqrt(v1.lengthSq() * v2.lengthSq());
  47408. if (denominator === 0) {
  47409. return 0;
  47410. } else {
  47411. return v1.angleTo(v2);
  47412. }
  47413. }
  47414. getAngle(index) {
  47415. if (this.points.length < 3 || index >= this.points.length) {
  47416. return 0;
  47417. }
  47418. var previous = index === 0 ? this.points[this.points.length - 1] : this.points[index - 1];
  47419. var point = this.points[index];
  47420. var next = this.points[(index + 1) % this.points.length];
  47421. return this.getAngleBetweenLines(point, previous, next);
  47422. }
  47423. // updateAzimuth(){
  47424. // // if(this.points.length !== 2){
  47425. // // return;
  47426. // // }
  47427. // // const azimuth = this.azimuth;
  47428. // // const [p0, p1] = this.points;
  47429. // // const r = p0.distanceTo(p1);
  47430. // }
  47431. createGuideLine() {
  47432. //add 辅助线
  47433. var guideLine = LineDraw.createFatLine([], {
  47434. mat: this.getMat('edgeGuide')
  47435. });
  47436. guideLine.visible = false;
  47437. this.guideLine = guideLine;
  47438. this.add(guideLine);
  47439. }
  47440. createHorVerGuideLine() {
  47441. //创建水平与垂直辅助线,仅距离测量有。
  47442. var verGuideEdge = LineDraw.createFatLine([], {
  47443. mat: this.getMat('edgeGuide')
  47444. });
  47445. verGuideEdge.visible = false;
  47446. this.verGuideEdge = verGuideEdge;
  47447. verGuideEdge.name = 'verGuideEdge';
  47448. var horGuideEdge = LineDraw.createFatLine([], {
  47449. mat: this.getMat('edgeGuide')
  47450. });
  47451. horGuideEdge.visible = false;
  47452. horGuideEdge.name = 'horGuideEdge';
  47453. this.horGuideEdge = horGuideEdge;
  47454. this.add(this.verGuideEdge);
  47455. this.add(this.horGuideEdge);
  47456. //label:
  47457. this.verEdgeLabel = this.createEdgeLabel('verGuideEdge');
  47458. this.horEdgeLabel = this.createEdgeLabel('horGuideEdge');
  47459. }
  47460. createEdgeLabel(name, hasHoverEvent) {
  47461. var inf = {
  47462. sizeInfo: labelSizeInfo,
  47463. name: name || 'edgeLabel'
  47464. };
  47465. if (name && name.includes('Guide')) {
  47466. inf.fontsize = 12;
  47467. }
  47468. var edgeLabel = new TextSprite$2($.extend({}, hasHoverEvent ? mainLabelProp : subLabelProp, inf));
  47469. if (hasHoverEvent) {
  47470. edgeLabel.addEventListener('mouseover', () => {
  47471. this.setSelected(true, 'edgeLabel');
  47472. });
  47473. edgeLabel.addEventListener('mouseleave', () => {
  47474. this.setSelected(false, 'edgeLabel');
  47475. });
  47476. edgeLabel.addEventListener('click', e => {
  47477. this.isNew || viewer.measuringTool.isAdding || e.button == MOUSE.LEFT && viewer.focusOnObject(this, 'measure');
  47478. });
  47479. }
  47480. edgeLabel.visible = false;
  47481. edgeLabel.measure = this;
  47482. edgeLabel.sprite.material.depthTestWhenPick = true;
  47483. //Potree.Utils.setObjectLayers(edgeLabel, 'measure' )
  47484. this.add(edgeLabel);
  47485. if (this.measureType == 'MulDistance') {
  47486. edgeLabel.visiMap = new Map();
  47487. }
  47488. return edgeLabel;
  47489. }
  47490. createAreaLabel() {
  47491. var areaLabel = this.createCenterLabel('areaLabel');
  47492. return areaLabel;
  47493. }
  47494. createTotalDisLabel() {
  47495. var totalDisLabel = this.createCenterLabel('totalDisLabel');
  47496. return totalDisLabel;
  47497. }
  47498. createCenterLabel(name) {
  47499. var centerLabel = new TextSprite$2($.extend({}, mainLabelProp, {
  47500. sizeInfo: labelSizeInfo,
  47501. name,
  47502. transform2D: null,
  47503. fontsize: 16 * textSizeRatio
  47504. }));
  47505. centerLabel.addEventListener('mouseover', () => {
  47506. this.isNew || this.setSelected(true, 'centerLabel');
  47507. });
  47508. centerLabel.addEventListener('mouseleave', () => {
  47509. this.isNew || this.setSelected(false, 'centerLabel');
  47510. });
  47511. centerLabel.addEventListener('click', () => {
  47512. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure');
  47513. });
  47514. //Potree.Utils.setObjectLayers(centerLabel, 'measure' )
  47515. Utils.updateVisible(centerLabel, 'setVisible', false);
  47516. return centerLabel;
  47517. }
  47518. getMat(type) {
  47519. if (!Measure$1.Mats) {
  47520. //不变色的部分
  47521. Measure$1.Mats = {
  47522. edgeGuide: LineDraw.createFatLineMat($.extend({}, lineDepthInfo, {
  47523. color: config$1.measure.guide.color,
  47524. dashSize: 0.1,
  47525. gapSize: 0.02,
  47526. dashed: true,
  47527. lineWidth: config$1.measure.lineWidth / 2
  47528. })),
  47529. multiColors: {}
  47530. };
  47531. {
  47532. markerMaps = [texLoader$6.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  47533. //pic_point_s32
  47534. texLoader$6.load(Potree.resourcePath + '/textures/pic_point32.png')];
  47535. markerMaps.forEach(map => {
  47536. map.repeat.set(1 / markerMapShrink, 1 / markerMapShrink);
  47537. map.offset.set((markerMapShrink - 1) / 2 / markerMapShrink, (markerMapShrink - 1) / 2 / markerMapShrink);
  47538. });
  47539. markerMaps[0].minFilter = 1006; //禁黑边
  47540. }
  47541. }
  47542. var mat = Measure$1.Mats[type];
  47543. var multiColors = Measure$1.Mats.multiColors;
  47544. //console.log('getMat', this.name, this.color, type)
  47545. if (!mat) {
  47546. var colorObject = multiColors[this.color];
  47547. if (!colorObject) {
  47548. var c = new Color().set(this.color).getHSL({
  47549. h: 0,
  47550. s: 0,
  47551. l: 0
  47552. });
  47553. var expandColor = new Color().setHSL(c.h, c.s, c.l >= 0.4 ? c.l - 0.3 : c.l + 0.3);
  47554. var expandSelectedColor = new Color().setHSL(c.h, c.s > 0.5 ? c.s - 0.2 : c.s + 0.2, c.l >= 0.6 ? c.l - 0.1 : c.l + 0.1);
  47555. colorObject = {
  47556. edgeDefault: LineDraw.createFatLineMat($.extend({}, lineDepthInfo, {
  47557. color: this.color || config$1.measure.default.color,
  47558. lineWidth: config$1.measure.lineWidth,
  47559. useDepth: true,
  47560. dashWithDepth: true,
  47561. // 只在被遮住的部分显示虚线,因为实线容易挡住label
  47562. dashed: true,
  47563. dashSize: 0.04,
  47564. gapSize: 0.04,
  47565. transparent: true,
  47566. opacity: config$1.measure.default.opacity,
  47567. depthTestWhenPick: true
  47568. })),
  47569. edgeSelect: LineDraw.createFatLineMat($.extend({}, lineDepthInfo, {
  47570. color: this.color || config$1.measure.highlight.color,
  47571. //'#f0ff00',
  47572. dashSize: 0.5,
  47573. gapSize: 0.2,
  47574. lineWidth: config$1.measure.lineWidth,
  47575. transparent: true,
  47576. opacity: config$1.measure.highlight.opacity
  47577. })),
  47578. edgeExpand: LineDraw.createFatLineMat($.extend({}, lineDepthInfo, {
  47579. color: expandColor,
  47580. useDepth: true,
  47581. lineWidth: 2,
  47582. transparent: true,
  47583. opacity: config$1.measure.default.opacity
  47584. })),
  47585. 'edgeExpand-selected': LineDraw.createFatLineMat($.extend({}, lineDepthInfo, {
  47586. color: expandSelectedColor,
  47587. useDepth: true,
  47588. lineWidth: 2,
  47589. transparent: true,
  47590. opacity: config$1.measure.highlight.opacity
  47591. })),
  47592. markerDefault: new DepthBasicMaterial($.extend({}, lineDepthInfo, {
  47593. transparent: !0,
  47594. opacity: 1,
  47595. map: markerMaps[0],
  47596. useDepth: true,
  47597. color: this.color
  47598. //mapScale: markerMapShrink
  47599. })),
  47600. markerSelect: new BasicMaterial({
  47601. transparent: !0,
  47602. opacity: 1,
  47603. depthTest: false,
  47604. map: markerMaps[1]
  47605. }),
  47606. planeDefault: new DepthBasicMaterial($.extend({}, lineDepthInfo, {
  47607. color: this.color || color,
  47608. side: DoubleSide,
  47609. opacity: 0.2,
  47610. transparent: true,
  47611. useDepth: true
  47612. })),
  47613. planeSelected: new MeshBasicMaterial({
  47614. color: this.color || color,
  47615. side: DoubleSide,
  47616. opacity: 0.3,
  47617. transparent: true
  47618. //wireframe:true
  47619. })
  47620. };
  47621. colorObject.markerSelect.defines.replaceColor = ''; //将绿色部分替换成color
  47622. colorObject.markerSelect.uniforms.newMapColor = {
  47623. type: 'v3',
  47624. value: new Color(this.color)
  47625. };
  47626. colorObject.markerSelect.onBeforeCompile = function (shader) {
  47627. shader.fragmentShader = shader.fragmentShader.replace('uniform sampler2D map;', "uniform sampler2D map; uniform vec3 newMapColor;") //将图中绿色#00C8AF换成指定色
  47628. .replace('gl_FragColor = texColor * color_;', "\n vec3 texWhite = vec3(1.0,1.0,1.0); //\u4E2D\u5FC3\u90E8\u5206\u767D\u8272\u4E0D\u53D8\uFF0C\u5916\u56F4\u539F\u672C\u7EFF\u8272\u7684r\u521A\u597D\u4E3A0\uFF0C\u6240\u4EE5r\u503C\u8D8A\u9AD8\u8D8A\u5F80\u767D\u8272\u8FC7\u6E21\n texColor.rgb = mix(newMapColor, texWhite, texColor.r); \n gl_FragColor = texColor * color_;");
  47629. };
  47630. multiColors[this.color] = colorObject;
  47631. {
  47632. //清理不用的colorObject
  47633. var measures = viewer.scene.measurements.filter(e => e instanceof Measure$1);
  47634. measures.includes(this) || measures.push(this);
  47635. for (var co in multiColors) {
  47636. multiColors[co].useCount = 0;
  47637. }
  47638. measures.forEach(e => {
  47639. multiColors[e.color].useCount++;
  47640. });
  47641. var deletes = [];
  47642. for (var _co in multiColors) {
  47643. if (multiColors[_co].useCount == 0) {
  47644. deletes.push(_co);
  47645. delete multiColors[_co].useCount;
  47646. for (var i in multiColors[_co]) {
  47647. multiColors[_co][i].dispose();
  47648. }
  47649. }
  47650. }
  47651. deletes.forEach(co => delete multiColors[co]);
  47652. }
  47653. }
  47654. mat = colorObject[type];
  47655. }
  47656. return mat;
  47657. }
  47658. createAreaPlane() {
  47659. return super.createAreaPlane(this.getMat('planeDefault'));
  47660. }
  47661. raycast(raycaster, intersects) {
  47662. for (var i = 0; i < this.points.length; i++) {
  47663. var marker = this.markers[i];
  47664. marker.raycast(raycaster, intersects);
  47665. }
  47666. // recalculate distances because they are not necessarely correct
  47667. // for scaled objects.
  47668. // see https://github.com/mrdoob/three.js/issues/5827
  47669. // TODO: remove this once the bug has been fixed
  47670. for (var _i = 0; _i < intersects.length; _i++) {
  47671. var I = intersects[_i];
  47672. I.distance = raycaster.ray.origin.distanceTo(I.point);
  47673. }
  47674. intersects.sort(function (a, b) {
  47675. return a.distance - b.distance;
  47676. });
  47677. }
  47678. getPointsPos2d(viewport, update) {
  47679. //获取屏幕上的二维坐标
  47680. var ps = this.pointsPos2d.get(viewport);
  47681. if (update || !ps) {
  47682. var points = this.points.map(e => {
  47683. var p = Potree.Utils.getPos2d(e, viewport, viewer.renderArea);
  47684. p.pos3d = e.clone(), p.object = this;
  47685. return p;
  47686. });
  47687. this.pointsPos2d.set(viewport, points);
  47688. console.log('updatePointsPos2d', this.uuid, viewport.name);
  47689. }
  47690. return this.pointsPos2d.get(viewport);
  47691. }
  47692. transformData(prop) {
  47693. if (prop.measureType == 'Point') {
  47694. prop.showCoordinates = true, prop.closed = true, prop.maxMarkers = 1, prop.minMarkers = 1;
  47695. } else if (prop.measureType == 'Distance') {
  47696. prop.showDistances = true, prop.showEdges = true, prop.maxMarkers = 2, prop.minMarkers = 2;
  47697. } else if (prop.measureType == 'MulDistance') {
  47698. prop.showDistances = true, prop.showEdges = true, prop.minMarkers = 2;
  47699. } else if (prop.measureType == 'MulDistance Ring') {
  47700. prop.showDistances = true, prop.showEdges = true, prop.showArea = true, prop.closed = true, prop.minMarkers = 3;
  47701. } else if (prop.measureType == 'Ver MulDistance') {
  47702. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.minMarkers = 2;
  47703. prop.faceDirection = "vertical";
  47704. prop.unableDragAtMap = true;
  47705. } else if (prop.measureType == 'Hor MulDistance') {
  47706. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.minMarkers = 2;
  47707. prop.faceDirection = "horizontal";
  47708. } else if (prop.measureType == 'Ver Distance') {
  47709. prop.showDistances = true, prop.showEdges = true, prop.maxMarkers = 2, prop.minMarkers = 2, prop.faceDirection = "vertical";
  47710. prop.unableDragAtMap = true;
  47711. } else if (prop.measureType == 'Hor Distance') {
  47712. prop.showDistances = true, prop.showEdges = true, prop.maxMarkers = 2, prop.minMarkers = 2, prop.faceDirection = "horizontal";
  47713. } else if (prop.measureType == 'Area') {
  47714. prop.showDistances = true, Potree.settings.areaAtNotPlane || (prop.atPlane = true);
  47715. prop.showEdges = true, prop.closed = true, prop.minMarkers = 3;
  47716. } else if (prop.measureType == 'Hor Area') {
  47717. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.closed = true, prop.minMarkers = 3;
  47718. prop.faceDirection = "horizontal";
  47719. } else if (prop.measureType == 'Ver Area') {
  47720. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.closed = true, prop.minMarkers = 3;
  47721. prop.faceDirection = "vertical";
  47722. prop.unableDragAtMap = true;
  47723. } else if (prop.measureType == 'Rect Area') {
  47724. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.closed = true, prop.minMarkers = 4;
  47725. prop.maxMarkers = 4;
  47726. } else if (prop.measureType == 'Hor Rect Area') {
  47727. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.closed = true, prop.minMarkers = 4;
  47728. prop.maxMarkers = 4;
  47729. prop.isRect = true;
  47730. prop.faceDirection = "horizontal";
  47731. } else if (prop.measureType == 'Ver Rect Area') {
  47732. prop.showDistances = true, prop.atPlane = true, prop.showEdges = true, prop.closed = true, prop.minMarkers = 4;
  47733. prop.maxMarkers = 4;
  47734. prop.isRect = true;
  47735. prop.faceDirection = "vertical";
  47736. prop.unableDragAtMap = true;
  47737. }
  47738. if (prop.atPlane && prop.closed) {
  47739. //atPlane在同一平面上
  47740. prop.showArea = true;
  47741. }
  47742. super.transformData(prop);
  47743. }
  47744. setUnitSystem(unitSystem) {
  47745. //console.log(this.name +':' +this.unitSystem)
  47746. if (unitSystem != this.unitSystem) {
  47747. if (unitSystem == "metric") {} else if (unitSystem == 'imperial') {}
  47748. this.unitSystem = unitSystem;
  47749. this.expands.forEach(e => e.unitSystem = unitSystem);
  47750. this.update();
  47751. }
  47752. }
  47753. reDraw() {
  47754. var restMarkerCount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  47755. //重新开始画
  47756. super.reDraw(restMarkerCount);
  47757. if (this.measureType == 'Distance') {
  47758. this.shouldShowHorVerGuide = false;
  47759. this.setEdgesDisplay(false);
  47760. }
  47761. if (this.showArea) {
  47762. this.area = {
  47763. value: 0
  47764. };
  47765. this.areaLabel && Utils.updateVisible(this.areaLabel, 'setVisible', false);
  47766. }
  47767. if (this.totalDisLabel && this.showTotalDis) {
  47768. Utils.updateVisible(this.totalDisLabel, 'setVisible', false);
  47769. }
  47770. viewer.inputHandler.dispatchEvent({
  47771. type: 'measuring',
  47772. v: true,
  47773. cause: 'reDraw',
  47774. object: this,
  47775. situation: 'dragging'
  47776. });
  47777. }
  47778. addExpand(data) {
  47779. //{offset,color}
  47780. data.measure = this;
  47781. var expand = new ExpandLine(data);
  47782. this.expands.push(expand);
  47783. viewer.scene.overlayScene.add(expand); //this.add(expand) //因为其可见性不随父结点所以分开
  47784. }
  47785. removeExpand(expand) {
  47786. var index = this.expands.indexOf(expand);
  47787. if (index > -1) {
  47788. expand.dispose();
  47789. this.expands.splice(index, 1);
  47790. //this.remove(expand)
  47791. }
  47792. }
  47793. }
  47794. function setLabelHightState(label, state) {
  47795. if (state) {
  47796. var _color = new Color(Potree.config.measure.highlight.color);
  47797. //label.sprite.material.opacity = config.measure.highlight.opacity
  47798. //label.setBackgroundColor({r:255*color.r, g:255*color.g, b:255*color.b, a:config.measure.highlight.opacity})
  47799. label.sprite.material.useDepth = false;
  47800. //label.textColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a: 1}
  47801. } else {
  47802. //label.setBackgroundColor({r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a:config.measure.default.opacity})
  47803. label.sprite.material.useDepth = true;
  47804. //label.sprite.material.opacity = 0.98
  47805. //label.textColor = {r: 255, g: 255, b: 255, a: 1}
  47806. }
  47807. label.updateTexture();
  47808. }
  47809. function createCircleRadiusLabel$1() {
  47810. var circleRadiusLabel = new TextSprite$2("");
  47811. circleRadiusLabel.setTextColor({
  47812. r: 140,
  47813. g: 250,
  47814. b: 140,
  47815. a: 1.0
  47816. });
  47817. circleRadiusLabel.setBorderColor({
  47818. r: 0,
  47819. g: 0,
  47820. b: 0,
  47821. a: 1.0
  47822. });
  47823. circleRadiusLabel.setBackgroundColor({
  47824. r: 0,
  47825. g: 0,
  47826. b: 0,
  47827. a: 1.0
  47828. });
  47829. circleRadiusLabel.fontsize = 16;
  47830. circleRadiusLabel.material.depthTest = false;
  47831. circleRadiusLabel.material.opacity = 1;
  47832. circleRadiusLabel.visible = false;
  47833. return circleRadiusLabel;
  47834. }
  47835. function createCircleRadiusLine$1() {
  47836. var circleRadiusLine = LineDraw.createFatLine([], {
  47837. color: 0xff0000,
  47838. dashSize: 0.5,
  47839. gapSize: 0.2,
  47840. lineWidth: config$1.measure.lineWidth
  47841. });
  47842. circleRadiusLine.visible = false;
  47843. return circleRadiusLine;
  47844. }
  47845. function createCircleLine$1() {
  47846. var coordinates = [];
  47847. var n = 128;
  47848. for (var i = 0; i <= n; i++) {
  47849. var u0 = 2 * Math.PI * (i / n);
  47850. var u1 = 2 * Math.PI * (i + 1) / n;
  47851. var p0 = new Vector3(Math.cos(u0), Math.sin(u0), 0);
  47852. var p1 = new Vector3(Math.cos(u1), Math.sin(u1), 0);
  47853. coordinates.push(p0, p1);
  47854. }
  47855. var circleLine = LineDraw.createFatLine(coordinates, {
  47856. color: 0xff0000,
  47857. dashSize: 0.5,
  47858. gapSize: 0.2,
  47859. lineWidth: config$1.measure.lineWidth
  47860. });
  47861. return circleLine;
  47862. }
  47863. function createLine$1() {
  47864. var line = LineDraw.createFatLine([], {
  47865. color: 0xff0000,
  47866. dashSize: 0.5,
  47867. gapSize: 0.2,
  47868. lineWidth: config$1.measure.lineWidth
  47869. });
  47870. return line;
  47871. }
  47872. function createCircle$1() {
  47873. var coordinates = [];
  47874. var n = 128;
  47875. for (var i = 0; i <= n; i++) {
  47876. var u0 = 2 * Math.PI * (i / n);
  47877. var u1 = 2 * Math.PI * (i + 1) / n;
  47878. var p0 = new Vector3(Math.cos(u0), Math.sin(u0), 0);
  47879. var p1 = new Vector3(Math.cos(u1), Math.sin(u1), 0);
  47880. coordinates.push(p0, p1);
  47881. }
  47882. var line = LineDraw.createFatLine(coordinates, {
  47883. color: 0xff0000,
  47884. dashSize: 0.5,
  47885. gapSize: 0.2,
  47886. lineWidth: config$1.measure.lineWidth
  47887. });
  47888. return line;
  47889. }
  47890. //缓冲区扩展,随measure改变,不可拖拽
  47891. class ExpandLine extends ctrlPolygon {
  47892. constructor(prop) {
  47893. prop.points = prop.measure.points.map(e => e.clone()); //先复制 用来加marker
  47894. prop.unitSystem = prop.measure.unitSystem;
  47895. prop.atPlane = prop.measure.atPlane;
  47896. prop.closed = prop.measure.closed;
  47897. super('expandLine', prop);
  47898. this.name = 'measureExpand_' + prop.measure.name;
  47899. this.initData(prop);
  47900. //offset 正数为朝外
  47901. }
  47902. update() {
  47903. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  47904. //暂时每次都全部更新,以后再改
  47905. var points = this.measure.points;
  47906. var count = this.measure.points.length;
  47907. var newPoints = [];
  47908. var facePlane = this.getFacePlane(true); //更新normal. 不用measure的是因为measure没更新normal
  47909. var normal = facePlane === null || facePlane === void 0 ? void 0 : facePlane.normal; //this.measure.facePlane.normal
  47910. if (!normal) return; //暂时不知道怎么写
  47911. var offset = this.offset; //Potree.math.getArea(this.measure.point2dInfo.points2d) > 0 ? -this.offset : this.offset // 时针受normal影响
  47912. //console.log('offset',offset, 'normal', normal.toArray(), 'clockwise', Potree.math.getArea(this.measure.point2dInfo.points2d) > 0)
  47913. for (var i = 0; i < count; i++) {
  47914. var O = points[i]; //该点
  47915. var A = this.measure.getPoint(i, -1); //points[i-1] //上一个点
  47916. var B = this.measure.getPoint(i, 1); //points[i+1] //下一个点
  47917. var p1 = void 0,
  47918. p2 = void 0; //该点两边的折点
  47919. var sideVec = void 0; //该点两边对应的向量
  47920. //如果是线段的话,
  47921. if (!A || !B) {
  47922. //端点
  47923. var vec = new Vector3().subVectors(i == 0 ? B : O, i == 0 ? O : A);
  47924. sideVec = new Vector3().crossVectors(normal, vec).normalize().multiplyScalar(offset);
  47925. //sideVec = new THREE.Vector3().copy(math.getNormal2d({p1: i==0 ? B : O, p2: i==0 ? O : A})).setZ(0).multiplyScalar(this.halfPathWidth) //垂线
  47926. } else {
  47927. var OA = new Vector3().subVectors(A, O).normalize(); //只保证俯视角度正确。(如果两点有高度差,该段四个点不会在同一平面,看起来有扭转,有的地方会肥大,但从俯视角度看是正确的。)
  47928. var OB = new Vector3().subVectors(B, O).normalize();
  47929. var _angle2 = math.getAngle(OA, OB, normal);
  47930. if (math.closeTo(_angle2, 0, 1e-4) || math.closeTo(_angle2, Math.PI, 1e-4) || math.closeTo(_angle2, -Math.PI, 1e-4)) {
  47931. //这时候直接加两个向量算出的平分线不准,故直接找垂线
  47932. var _vec = new Vector3().subVectors(O, A);
  47933. sideVec = new Vector3().crossVectors(normal, _vec).normalize().multiplyScalar(offset);
  47934. //sideVec = new THREE.Vector3().copy(math.getNormal2d({p1: O, p2: A})) //垂线
  47935. //console.log('接近0或180',angle, sideVec)
  47936. } else {
  47937. var midVecLength = offset / Math.sin(_angle2 / 2);
  47938. sideVec = new Vector3().addVectors(OA, OB).normalize().multiplyScalar(midVecLength); //角平分线 ( 和上一个方向保持在同一侧,故而顺时针和逆时针方向不同 )
  47939. }
  47940. }
  47941. var p = new Vector3().addVectors(O, sideVec);
  47942. newPoints.push(p);
  47943. }
  47944. this.points = newPoints;
  47945. super.update();
  47946. }
  47947. changeOffset(offset) {
  47948. this.offset = offset;
  47949. this.update();
  47950. }
  47951. addMarker() {
  47952. var {
  47953. point,
  47954. index
  47955. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  47956. super.addMarker({
  47957. index,
  47958. point,
  47959. edge: LineDraw.createFatLine([], {
  47960. mat: this.measure.getMat('edgeExpand')
  47961. })
  47962. });
  47963. }
  47964. getArea() {
  47965. if (!this.closed) return;
  47966. this.getPoint2dInfo(this.points);
  47967. this.measure.getArea.call(this);
  47968. this.measure.getArea();
  47969. var area = Math.abs(this.measure.area.value - this.area.value);
  47970. this.area = {
  47971. value: area,
  47972. string: this.getConvertString(area, 'area')
  47973. };
  47974. return this.area;
  47975. }
  47976. setSelected(state) {
  47977. this.edges.forEach(e => {
  47978. e.material = this.measure.getMat(state ? 'edgeExpand-selected' : 'edgeExpand');
  47979. });
  47980. viewer.dispatchEvent('content_changed');
  47981. }
  47982. }
  47983. ExpandLine.prototype.getPoint2dInfo = Measure$1.prototype.getPoint2dInfo;
  47984. ExpandLine.prototype.getConvertString = Measure$1.prototype.getConvertString;
  47985. /*
  47986. 按alt鼠标滚轮或WS键放慢。
  47987. 按Alt键可以平行屏幕拖拽点。&dragPolyBeyondPoint 后缀在拖拽到无点云区域也是此效果。
  47988. 按M键拖拽点可以复制出当前点
  47989. */
  47990. //处理cursor优先级
  47991. var CursorDeal = {
  47992. priorityEvent: [
  47993. //在前面的优先级高
  47994. {
  47995. 'grabbing': 'grabbing'
  47996. },
  47997. //通用
  47998. {
  47999. 'hoverGrab': 'grab'
  48000. },
  48001. //通用
  48002. {
  48003. pen_delPoint: "url({Potree.resourcePath}/images/polygon_mark/pic_pen_sub.png),auto"
  48004. }, {
  48005. pen_addPoint: "url({Potree.resourcePath}/images/polygon_mark/pic_pen_add.png),auto"
  48006. }, {
  48007. pen: "url({Potree.resourcePath}/images/polygon_mark/pic_pen.png),auto"
  48008. }, {
  48009. 'pointer': 'pointer'
  48010. },
  48011. //通用
  48012. {
  48013. 'hoverMonitor': 'pointer'
  48014. }, {
  48015. 'zoomInCloud': 'zoom-in'
  48016. }, {
  48017. 'hoverPano': 'pointer'
  48018. }, {
  48019. "notAllowed-default": 'not-allowed'
  48020. }, {
  48021. 'connectPano': "url({Potree.resourcePath}/images/connect.png),auto"
  48022. }, {
  48023. 'disconnectPano': "url({Potree.resourcePath}/images/connect-dis.png),auto"
  48024. }, {
  48025. 'hoverLine': 'pointer'
  48026. }, {
  48027. 'hoverTranHandle': 'grab'
  48028. }, {
  48029. "movePointcloud": 'move'
  48030. }, {
  48031. "polygon_isIntersectSelf": 'not-allowed'
  48032. }, {
  48033. "polygon_AtWrongPlace": 'not-allowed'
  48034. }, {
  48035. 'delPoint': 'url("https://4dkk.4dage.com/v4-test/www/sdk/images/polygon_mark/pic_pen_sub.png"), auto'
  48036. }, {
  48037. "markerMove": 'grab'
  48038. }, {
  48039. 'addPoint': 'url("https://4dkk.4dage.com/v4-test/www/sdk/images/polygon_mark/pic_pen_add.png"), auto'
  48040. }, {
  48041. 'mapClipMove': 'move'
  48042. }, {
  48043. 'mapClipRotate': "url({Potree.resourcePath}/images/rotate-cursor.png),auto"
  48044. }, {
  48045. 'rotatePointcloud': "url({Potree.resourcePath}/images/rotate-cursor.png),auto"
  48046. }, {
  48047. 'siteModelFloorDrag': 'row-resize'
  48048. }, {
  48049. 'addSth': 'cell'
  48050. } //or crosshair
  48051. ],
  48052. list: [],
  48053. //当前存在的cursor状态
  48054. currentCursorIndex: null,
  48055. init: function init(viewer, viewers) {
  48056. this.priorityEvent.forEach(e => {
  48057. //刚开始Potree.resourcePath没值,现在换
  48058. for (var i in e) {
  48059. e[i] = Common$1.replaceAll(e[i], '{Potree.resourcePath}', Potree.resourcePath);
  48060. }
  48061. });
  48062. this.domElements = viewers.map(e => e.renderArea);
  48063. viewer.addEventListener("CursorChange", e => {
  48064. if (e.action == 'add') {
  48065. this.add(e.name);
  48066. } else {
  48067. this.remove(e.name);
  48068. }
  48069. });
  48070. },
  48071. add: function add(name) {
  48072. var priorityItem = this.priorityEvent.find(e => e[name]);
  48073. if (!priorityItem) {
  48074. console.error('CursorDeal 未定义优先级 name:' + name);
  48075. return;
  48076. }
  48077. if (!this.list.includes(name)) {
  48078. this.judge({
  48079. addItem: priorityItem,
  48080. name
  48081. });
  48082. this.list.push(name);
  48083. }
  48084. },
  48085. remove: function remove(name) {
  48086. var index = this.list.indexOf(name);
  48087. if (index > -1) {
  48088. this.list.splice(index, 1);
  48089. this.judge();
  48090. }
  48091. },
  48092. judge: function judge() {
  48093. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  48094. //console.log(o,this.list)
  48095. if (o.addItem) {
  48096. var addIndex = this.priorityEvent.indexOf(o.addItem);
  48097. if (addIndex < this.currentCursorIndex || this.currentCursorIndex == void 0) {
  48098. this.domElements.forEach(e => e.style.cursor = o.addItem[o.name]);
  48099. this.currentCursorIndex = addIndex;
  48100. }
  48101. } else {
  48102. var levelMax = {
  48103. index: Infinity,
  48104. cursor: null
  48105. };
  48106. this.list.forEach(name => {
  48107. var priorityItem = this.priorityEvent.find(e => e[name]);
  48108. var index = this.priorityEvent.indexOf(priorityItem);
  48109. if (index < levelMax.index) {
  48110. levelMax.index = index;
  48111. levelMax.cursor = priorityItem[name];
  48112. }
  48113. });
  48114. this.currentCursorIndex = levelMax.index;
  48115. this.domElements.forEach(e => e.style.cursor = levelMax.cursor || '');
  48116. }
  48117. }
  48118. };
  48119. var texLoader$7 = new TextureLoader();
  48120. var labelSizeInfo$1 = {
  48121. width2d: 180
  48122. }; //稍微小点防止字体模糊
  48123. var titleLineHeight = 2;
  48124. var arrowCountMax = 1000; //箭头总数不能超过这个值。 The count value passed into the constructor represents the maximum number of instances of this mesh. You can change the number of instances at runtime to an integer value in the range [0, count].If you need more instances than the original count value, you have to create a new InstancedMesh.
  48125. var lastArrowCamPos,
  48126. lastArrowCount = 0;
  48127. var depthProps = {
  48128. useDepth: true,
  48129. //startClipDis : 0.5,
  48130. clipDistance: 0.5,
  48131. //消失距离
  48132. //startOcclusDis: 0.5,
  48133. occlusionDistance: 0.3,
  48134. //变为backColor距离
  48135. maxOcclusionFactor: 0.9,
  48136. maxClipFactor: 1
  48137. };
  48138. var planeGeo$2 = new PlaneBufferGeometry(1, 1);
  48139. var voidGeometry = new BufferGeometry();
  48140. var markerMats, dragPointMat;
  48141. var getMarkerMat = function getMarkerMat(name) {
  48142. if (!markerMats) {
  48143. markerMats = {
  48144. default: new DepthBasicMaterial($.extend({}, depthProps, {
  48145. transparent: true,
  48146. map: texLoader$7.load(Potree.resourcePath + '/textures/dot_n.png'),
  48147. opacity: 0.9
  48148. })),
  48149. drag: new DepthBasicMaterial({
  48150. transparent: true,
  48151. useDepth: false,
  48152. map: texLoader$7.load(Potree.resourcePath + '/textures/dot_s.png')
  48153. }),
  48154. delete: new DepthBasicMaterial({
  48155. transparent: true,
  48156. useDepth: false,
  48157. map: texLoader$7.load(Potree.resourcePath + '/textures/dot_r.png')
  48158. }),
  48159. adding: new DepthBasicMaterial({
  48160. transparent: true,
  48161. opacity: 0.3,
  48162. useDepth: false,
  48163. map: texLoader$7.load(Potree.resourcePath + '/textures/dot_n.png')
  48164. })
  48165. };
  48166. for (var i in markerMats) {
  48167. markerMats[i].map.anisotropy = 4;
  48168. }
  48169. }
  48170. return markerMats[name];
  48171. };
  48172. var getMeshQuaInPath = lineDir => {
  48173. var quaBase = new Quaternion().setFromEuler(new Euler(-Math.PI / 2, 0, Math.PI / 2));
  48174. return math.getQuaFromPosAim(new Vector3(), lineDir).multiply(quaBase);
  48175. };
  48176. var getEndCaps = function () {
  48177. var endCap, map;
  48178. return function (path) {
  48179. if (!endCap) {
  48180. map = texLoader$7.load(Potree.resourcePath + '/textures/whiteCircle.png');
  48181. map.anisotropy = 3;
  48182. map.repeat.set(0.5, 1);
  48183. //map.magFilter = THREE.NearestFilter
  48184. var mesh = new Mesh(planeGeo$2);
  48185. mesh.scale.x = 0.5;
  48186. mesh.position.x = -0.25;
  48187. //Potree.Utils.setObjectLayers(mesh,'measure')
  48188. endCap = new Object3D();
  48189. endCap.add(mesh);
  48190. }
  48191. var endCaps = [];
  48192. var material = path.edge.material.clone();
  48193. material.map = map;
  48194. delete material.defines.mapOverlay;
  48195. for (var i = 0; i < 2; i++) {
  48196. var cap = endCap.clone();
  48197. cap.children[0].material = material;
  48198. path.add(cap);
  48199. endCaps.push(cap);
  48200. }
  48201. return endCaps;
  48202. };
  48203. }();
  48204. var setMarkerScale = (marker, halfPathWidth) => {
  48205. var s = halfPathWidth * 2.9;
  48206. marker.scale.set(s, s, s);
  48207. };
  48208. var fakeMarker;
  48209. var lastFadeTime;
  48210. var showFakeMarker = (path, position) => {
  48211. //添加marker时指示位置
  48212. if (!fakeMarker) {
  48213. fakeMarker = new Mesh(planeGeo$2, getMarkerMat('adding'));
  48214. fakeMarker.name = 'fakeMarker';
  48215. fakeMarker.renderOrder = Potree.config.renderOrders.path.marker;
  48216. }
  48217. setMarkerScale(fakeMarker, path.halfPathWidth);
  48218. path.add(fakeMarker);
  48219. fakeMarker.position.copy(position);
  48220. Potree.Utils.updateVisible(fakeMarker, 'add', true);
  48221. viewer.dispatchEvent('content_changed');
  48222. return fakeMarker;
  48223. };
  48224. var hideFakeMarker = () => {
  48225. fakeMarker && Potree.Utils.updateVisible(fakeMarker, 'add', false);
  48226. lastFadeTime = Date.now();
  48227. };
  48228. class Path$1 extends ctrlPolygon {
  48229. constructor(prop) {
  48230. super('Path', prop);
  48231. this.zPlaneWhenNoIntersect = 0; //允许不在model上,直接绘制此高度的水平面上
  48232. this.markerLabels = [];
  48233. this.points_datasets || (this.points_datasets = []); //存每个点是哪个数据集
  48234. this.hoverStates = {};
  48235. this.selectStates = {};
  48236. this.setFadeFar(null);
  48237. this.geoPoints = [];
  48238. this.lineHeight = prop.lineHeight == void 0 ? titleLineHeight : prop.lineHeight;
  48239. {
  48240. var group = new Object3D();
  48241. group.name = 'titleGroup';
  48242. this.titleLabel = new TextSprite$2(Object.assign({}, depthProps, {
  48243. text: '',
  48244. sizeInfo: {
  48245. width2d: 200
  48246. },
  48247. textColor: {
  48248. r: 255,
  48249. g: 255,
  48250. b: 255,
  48251. a: 1.0
  48252. },
  48253. backgroundColor: {
  48254. r: 0,
  48255. g: 0,
  48256. b: 0,
  48257. a: 0.5
  48258. },
  48259. borderRadius: 6,
  48260. fontsize: this.fontsize || 13,
  48261. renderOrder: Potree.config.renderOrders.path.label,
  48262. pickOrder: Potree.config.renderOrders.path.label,
  48263. clipDistance: 10,
  48264. fadeFar: this.fadeFar,
  48265. transform2Dpercent: {
  48266. x: 0,
  48267. y: 0.5
  48268. },
  48269. //向上移动一半
  48270. maxLineWidth: 300,
  48271. textAlign: Potree.settings.isOfficial && 'left'
  48272. }));
  48273. this.titleLabel.sprite.material.depthTest = false;
  48274. var line = LineDraw.createFatLine([new Vector3(0, 0, 0), new Vector3(0, 0, this.lineHeight)], Object.assign({}, depthProps, {
  48275. color: '#ffffff',
  48276. lineWidth: 1,
  48277. transparent: true,
  48278. fadeFar: this.fadeFar
  48279. }));
  48280. line.renderOrder = Potree.config.renderOrders.line;
  48281. line.name = 'line';
  48282. this.titleLine = line;
  48283. group.add(line);
  48284. group.add(this.titleLabel);
  48285. this.titleLabel.position.z = this.lineHeight;
  48286. this.add(group);
  48287. this.setTitleVisi(this.titleLabel.parent, false, 'noPoint');
  48288. this.setTitle(Potree.settings.isOfficial ? '' : 'title');
  48289. if (!dragPointMat) {
  48290. var map = texLoader$7.load(Potree.resourcePath + '/textures/whiteCircle.png', () => {});
  48291. dragPointMat = {
  48292. default: new MeshBasicMaterial({
  48293. map,
  48294. transparent: true,
  48295. color: '#0fe',
  48296. opacity: 0,
  48297. depthTest: false
  48298. }),
  48299. hover: new MeshBasicMaterial({
  48300. map,
  48301. transparent: true,
  48302. color: '#0fe',
  48303. opacity: 0.4,
  48304. depthTest: false
  48305. })
  48306. };
  48307. }
  48308. this.lineDragPoint = new Mesh(planeGeo$2, dragPointMat.default); //修改线高度时出现的小圆点
  48309. this.lineDragPoint.scale.set(0.15, 0.15, 0.15);
  48310. this.lineDragPoint.name = 'lineDragPoint';
  48311. this.lineDragPoint.renderOrder = this.lineDragPoint.pickOrder = 10;
  48312. this.titleLabel.add(this.lineDragPoint);
  48313. var hoverState = {},
  48314. grabbingObject;
  48315. var setDragPointState = state => {
  48316. this.lineDragPoint.material = state ? dragPointMat.hover : dragPointMat.default;
  48317. this.titleLabel.sprite.material.opacity = state ? 0.5 : 1;
  48318. };
  48319. var autoPointState = () => {
  48320. setDragPointState(this.editEnable && (hoverState.lineDragPoint || grabbingObject == 'lineDragPoint'));
  48321. };
  48322. var autoCursor = () => {
  48323. if (this.editEnable && Object.values(hoverState).some(e => e)) {
  48324. CursorDeal.add('hoverGrab');
  48325. } else {
  48326. CursorDeal.remove('hoverGrab');
  48327. }
  48328. autoPointState();
  48329. };
  48330. [line, this.lineDragPoint].forEach(e => e.addEventListener('mouseover', e => {
  48331. hoverState[e.target.name] = 1;
  48332. autoCursor();
  48333. }));
  48334. [line, this.lineDragPoint].forEach(e => e.addEventListener('mouseleave', e => {
  48335. hoverState[e.target.name] = 0;
  48336. autoCursor();
  48337. }));
  48338. [line, this.lineDragPoint].forEach(e => e.addEventListener('startDragging', e => {
  48339. grabbingObject = e.target.name;
  48340. this.editEnable && (CursorDeal.add('grabbing'), autoPointState());
  48341. }));
  48342. [line, this.lineDragPoint].forEach(e => e.addEventListener('drop', e => {
  48343. grabbingObject = null;
  48344. this.editEnable && (CursorDeal.remove('grabbing'), autoPointState());
  48345. }));
  48346. [line, this.lineDragPoint].forEach(e => e.addEventListener('drag', e => {
  48347. if (this.editEnable) {
  48348. //一旦用户拖动了title,title就固定了,不再随着path居中
  48349. if (e.target.name == 'line') {
  48350. var _e$intersect, _e$intersect3, _e$intersect4;
  48351. var position;
  48352. if ((_e$intersect = e.intersect) !== null && _e$intersect !== void 0 && _e$intersect.location) {
  48353. var _e$intersect2;
  48354. position = (_e$intersect2 = e.intersect) === null || _e$intersect2 === void 0 ? void 0 : _e$intersect2.location;
  48355. } else {
  48356. var {
  48357. x,
  48358. y
  48359. } = Potree.Utils.getPointerPosAtHeight(0, e.pointer);
  48360. position = new Vector3(x, y, 0);
  48361. }
  48362. this.updateTitlePos(position);
  48363. this.dispatchEvent({
  48364. type: 'titlePosChanged',
  48365. position,
  48366. root: ((_e$intersect3 = e.intersect) === null || _e$intersect3 === void 0 ? void 0 : _e$intersect3.pointcloud) || ((_e$intersect4 = e.intersect) === null || _e$intersect4 === void 0 ? void 0 : _e$intersect4.object)
  48367. });
  48368. } else if (e.target.name == 'lineDragPoint') {
  48369. this.dragLineLen(e);
  48370. }
  48371. }
  48372. }));
  48373. }
  48374. {
  48375. //和measure不同的是它的边是连在一起的一整条
  48376. this.edge = new Mesh(voidGeometry, new DepthBasicMaterial($.extend({}, depthProps, {
  48377. color: this.color,
  48378. /* opacity: 0.6, */side: 2,
  48379. /* transparent:true, */fadeFar: this.fadeFar
  48380. })));
  48381. //new THREE.MeshBasicMaterial({depthWrite:false, transparent:true, color:this.color || '#fff', opacity:0.5, side:2}))
  48382. this.edge.material.defines.mapOverlay = true;
  48383. this.add(this.edge);
  48384. this.edge.renderOrder = Potree.config.renderOrders.path.edge,
  48385. //和tag的一样,但为何遮不住它?好在一般底下有一层地面能遮住
  48386. this.edge.name = 'pathEdge';
  48387. var addHoverEvent = () => {
  48388. var mouseover = e => {
  48389. if (this.isNew) return;
  48390. this.setSelected('hover');
  48391. this.hoverStates.edge = true;
  48392. if (this.addOrRemovePoint && !this.isNew) {
  48393. CursorDeal.add('pen_addPoint');
  48394. }
  48395. };
  48396. var mouseleave = e => {
  48397. if (this.isNew) return;
  48398. this.setSelected('unhover');
  48399. this.hoverStates.edge = false;
  48400. CursorDeal.remove('pen_addPoint');
  48401. hideFakeMarker();
  48402. };
  48403. this.edge.addEventListener('mouseover', mouseover);
  48404. this.edge.addEventListener('mouseleave', mouseleave);
  48405. this.edge.addEventListener('mousemove', e => {
  48406. if (this.addOrRemovePoint && !this.isNew && !this.hoverStates.marker) {
  48407. var {
  48408. point
  48409. } = this.getPosByIntersect(e, 'onlyPoint');
  48410. showFakeMarker(this, point);
  48411. }
  48412. });
  48413. this.edge.addEventListener('click', e => {
  48414. var now = Date.now();
  48415. if (now - this.lastDropTime < 100 || this.isNew || e.button !== MOUSE.LEFT) return;
  48416. if (this.addOrRemovePoint) {
  48417. var {
  48418. index,
  48419. prevIndex,
  48420. point
  48421. } = this.getPosByIntersect(e);
  48422. viewer.measuringTool.history.beforeChange(this);
  48423. this.addMarker({
  48424. index,
  48425. point,
  48426. dataset_point: this.dataset_points && new Vector3(),
  48427. //初始化
  48428. points_dataset: this.points_datasets[prevIndex] //使用前一个的
  48429. });
  48430. this.updateDatasetBelong(index); //获取dataset_point
  48431. viewer.measuringTool.history.afterChange(this);
  48432. this.updateEdge();
  48433. this.hideArrowUntilUpdate();
  48434. this.dispatchEvent('changed');
  48435. } else {
  48436. this.isNew || viewer.measuringTool.isAdding || this.setSelected('click'); //viewer.focusOnObject(this, 'measure') //正在添加测量线时不要focus其他线(容易误触)
  48437. }
  48438. e.consume(); //防止后续双击
  48439. });
  48440. };
  48441. this.edge.addEventListener('addHoverEvent', addHoverEvent, {
  48442. once: true
  48443. });
  48444. if (!this.isNew) {
  48445. this.edge.dispatchEvent('addHoverEvent');
  48446. }
  48447. }
  48448. {
  48449. this.endCaps = getEndCaps(this); //端点处的半圆
  48450. }
  48451. this.addEventListener('marker_dropped', e => {
  48452. this.updateDatasetBelong(e.index);
  48453. });
  48454. this.setPathWidth(prop.width || 0.2);
  48455. this.setColor(prop.color || '#fff');
  48456. this.setEditEnable(true);
  48457. this.lastDropTime = 0;
  48458. //Potree.Utils.setObjectLayers(this, 'measure' )
  48459. if (!Potree.settings.isOfficial) {
  48460. this.setAddOrRemPoint(true);
  48461. this.addEventListener('createDone', () => {
  48462. this.setAddOrRemPoint(false);
  48463. });
  48464. this.setArrowDisplay(true);
  48465. }
  48466. this.initData(prop);
  48467. }
  48468. updateTitlePos(pos) {
  48469. if (pos) {
  48470. this.fixedTitlePos = pos;
  48471. } else {
  48472. if (!this.fixedTitlePos) {
  48473. //居中
  48474. pos = this.getCenter();
  48475. }
  48476. }
  48477. if (pos) {
  48478. this.titleLabel.parent.position.copy(pos);
  48479. this.titleLabel.updatePose();
  48480. }
  48481. }
  48482. getPosByIntersect(e, type) {
  48483. //intersect落在线上的位置,以及在哪两个点之间
  48484. if (!Potree.settings.pathSmooth) {
  48485. var prevIndex = Math.floor(e.hoveredElement.faceIndex / 2); //端点1(可能是最后一个)
  48486. var nextIndex = this.getIndex(prevIndex, 1); //端点2(可能是第一个)
  48487. var index = prevIndex + 1; //新点在端点1后
  48488. var point = math.getFootPoint(e.hoveredElement.point, this.points[prevIndex], this.points[nextIndex]);
  48489. return {
  48490. index,
  48491. prevIndex,
  48492. point
  48493. };
  48494. } else {
  48495. var prevIndex0 = Math.floor(e.hoveredElement.faceIndex / 2); //所在的mesh片段的端点1
  48496. var nextIndex0 = prevIndex0 + 1; //所在的mesh片段的端点2
  48497. var _point = math.getFootPoint(e.hoveredElement.point, this.geoPoints[prevIndex0], this.geoPoints[nextIndex0]); //新点位置
  48498. if (type == 'onlyPoint') return {
  48499. point: _point
  48500. };
  48501. var _prevIndex, _nextIndex;
  48502. var count = this.points.length - 1;
  48503. for (var i = 0; i < count; i++) {
  48504. if (_prevIndex == void 0 && i / count <= this.UtoTMapArr[prevIndex0] && (i + 1) / count > this.UtoTMapArr[prevIndex0]) {
  48505. _prevIndex = i; //该片段端点1在原先points中哪个点之后(可包含)
  48506. }
  48507. if (_nextIndex == void 0 && i / count <= this.UtoTMapArr[nextIndex0] && (i + 1) / count > this.UtoTMapArr[nextIndex0]) {
  48508. _nextIndex = i; //该片段端点2在原先points中哪个点之后(可包含)
  48509. }
  48510. }
  48511. if (_nextIndex == void 0) {
  48512. //最后一个点
  48513. _nextIndex = count - 1;
  48514. }
  48515. if (_prevIndex != _nextIndex) {
  48516. //端点在不同points区间, 需要判断intersect的究竟在哪个区间
  48517. //console.log('跨点', prevIndex, nextIndex)
  48518. this.geoPoints[_prevIndex];
  48519. var lengths = []; //geo端点间包含points哪些点
  48520. var j = _prevIndex;
  48521. var A = this.geoPoints[prevIndex0];
  48522. var B = this.geoPoints[nextIndex0];
  48523. var APlen = A.distanceTo(_point); // 端点->点击点
  48524. var AB = new Vector3().subVectors(B, A);
  48525. var searchIndex;
  48526. while (j <= _nextIndex) {
  48527. //根据APlen长度算区间
  48528. var len = AB.clone().normalize().dot(new Vector3().subVectors(this.points[j + 1], A)); //在AB的投影长度
  48529. if (len > APlen) {
  48530. searchIndex = j;
  48531. break;
  48532. }
  48533. j++;
  48534. }
  48535. searchIndex == void 0 && (searchIndex = _nextIndex); //最后一个点之后
  48536. _prevIndex = searchIndex;
  48537. }
  48538. _nextIndex = _prevIndex + 1;
  48539. //console.log(prevIndex, nextIndex)
  48540. var _index = _prevIndex + 1; //新点在端点1后
  48541. return {
  48542. index: _index,
  48543. prevIndex: _prevIndex,
  48544. point: _point
  48545. };
  48546. }
  48547. } //如果后续还出现index错误的问题,可以改为绘制时用折线,完成后用曲线。
  48548. createMarkerLabel(text, hasHoverEvent) {
  48549. var label = new TextSprite$2($.extend({}, depthProps, {
  48550. sizeInfo: labelSizeInfo$1,
  48551. name: 'markerTitle',
  48552. text: "",
  48553. fontsize: this.fontsize || 12,
  48554. renderOrder: Potree.config.renderOrders.path.label,
  48555. pickOrder: Potree.config.renderOrders.path.label,
  48556. fontWeight: '',
  48557. //thick
  48558. backgroundColor: {
  48559. r: 255,
  48560. g: 255,
  48561. b: 255,
  48562. a: 0.5
  48563. },
  48564. textColor: {
  48565. r: 0,
  48566. g: 0,
  48567. b: 0,
  48568. a: 1
  48569. },
  48570. fadeFar: this.fadeFar,
  48571. maxLineWidth: 300,
  48572. transform2D: {
  48573. x: 0,
  48574. y: 0.2
  48575. },
  48576. //朝上偏移一些 配合最外层z混合增高
  48577. textAlign: Potree.settings.isOfficial && 'left'
  48578. }));
  48579. if (hasHoverEvent) {
  48580. label.addEventListener('mouseover', () => {
  48581. this.setSelected(true, 'label');
  48582. });
  48583. label.addEventListener('mouseleave', () => {
  48584. this.setSelected(false, 'label');
  48585. });
  48586. label.addEventListener('click', () => {
  48587. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure');
  48588. });
  48589. }
  48590. //label.measure = this
  48591. //label.sprite.material.depthTestWhenPick = true
  48592. //Potree.Utils.setObjectLayers(label, 'measure' )
  48593. this.add(label);
  48594. return label;
  48595. }
  48596. updateMarker(marker, pos) {
  48597. marker.position.copy(pos);
  48598. marker.position.z += 0.01;
  48599. var index = this.markers.indexOf(marker);
  48600. if (this.markerLabels[index]) {
  48601. this.markerLabels[index].position.copy(pos);
  48602. this.markerLabels[index].position.z += 0.3; //混合增高
  48603. this.markerLabels[index].updatePose();
  48604. }
  48605. }
  48606. setPathWidth(w) {
  48607. var v = w / 2;
  48608. if (this.halfPathWidth == v) return;
  48609. this.halfPathWidth = v;
  48610. this.markers.forEach(e => setMarkerScale(e, this.halfPathWidth));
  48611. this.updateEdge();
  48612. this.editEnable || this.updateEndCaps();
  48613. this.updateArrowRepeat();
  48614. viewer.dispatchEvent('content_changed');
  48615. this.hideArrowUntilUpdate();
  48616. }
  48617. setColor(color) {
  48618. if (this.color == color) return;
  48619. this.color = color;
  48620. var c = new Color().set(this.color);
  48621. var hsb = new Color().set(this.color).getHSV();
  48622. var textColor = new Color().setHSV(hsb.h, hsb.s, 100); //make bright full
  48623. this.titleLabel.setTextColor({
  48624. r: textColor.r * 255,
  48625. g: textColor.g * 255,
  48626. b: textColor.b * 255,
  48627. a: 0.95
  48628. });
  48629. this.updateSelectStyle(); //apply color
  48630. viewer.dispatchEvent('content_changed');
  48631. }
  48632. setLineHeight(len) {
  48633. if (len == this.lineHeight) return;
  48634. this.lineHeight = parseFloat(len);
  48635. this.titleLabel.position.z = this.lineHeight;
  48636. this.titleLabel.updatePose();
  48637. LineDraw.updateLine(this.titleLine, [new Vector3(0, 0, 0), new Vector3(0, 0, this.lineHeight)]);
  48638. }
  48639. dragLineLen(e) {
  48640. //拖拽线的顶端修改线长度
  48641. var endPos = this.titleLabel.getWorldPosition(new Vector3());
  48642. var normal = new Vector3(0, 0, 1);
  48643. var projected = endPos.clone().project(e.drag.dragViewport.camera);
  48644. projected.x = e.pointer.x;
  48645. projected.y = e.pointer.y;
  48646. var unprojected = projected.clone().unproject(e.drag.dragViewport.camera);
  48647. var moveVec = new Vector3().subVectors(unprojected, endPos);
  48648. moveVec = moveVec.projectOnVector(normal);
  48649. var newLength = Math.max(0, this.lineHeight + moveVec.dot(normal));
  48650. //console.log(moveVec,newLength)
  48651. this.setLineHeight(newLength);
  48652. this.dispatchEvent('dragLineLen');
  48653. }
  48654. reDraw() {
  48655. this.pauseUpdateEdge = true;
  48656. super.reDraw();
  48657. this.pauseUpdateEdge = false;
  48658. this.updateEdge();
  48659. }
  48660. updateEdge() {
  48661. if (this.pauseUpdateEdge || this.lastUpdatePoints_ && Potree.Common.ifSame(this.lastUpdatePoints_, this.points) && this.halfPathWidth == this.lastHalfPathWidth) return; //没变 不更新
  48662. //this.edge.geometry = MeshDraw.getExtrudeGeo(edgeExtrudePoints, null, {extrudePath: this.points, openEnded:true, shapeDontClose:true/* , dontSmooth:true, steps: this.points.length-1 */})
  48663. //getExtrudeGeo是平滑过的曲线,和设计不一样,且容易翻转,转角有时候细分过少
  48664. //只允许path水平放置
  48665. var geo;
  48666. var points = this.getDifferentPoint(this.points);
  48667. var count = points.length;
  48668. this.edge.geometry.dispose();
  48669. if (count <= 1) {
  48670. geo = voidGeometry;
  48671. this.geoPoints = [];
  48672. this.curve = null;
  48673. } else {
  48674. if (Potree.settings.pathSmooth) {
  48675. //使用曲线
  48676. var curve = this.curve = new CatmullRomCurve3(points, false);
  48677. curve.UtoTMapArr = []; //用于存储 getSpacedPoints得到的点对应points的百分比对应
  48678. var oldCount = count;
  48679. count = Math.max(2, Math.round(this.getTotalDistance() * 200)), points = curve.getSpacedPoints(count - 1); //拆分为更密集的点
  48680. /* //window.arcLengthDivisions && (curve.arcLengthDivisions = arcLengthDivisions) //默认200,但改为1也没变化呀
  48681. let oldCount = count
  48682. //减少点数(拐弯的部分紧凑些,直线部分宽松些):
  48683. let lastVec
  48684. let newPoints = []
  48685. this.UtoTMapArr = []
  48686. let pointIndexs = []//找出新点中对应原先控制点的index,这些点必须加入拐点,否则会出现控制点偏移path(当它所在部分接近直线时)
  48687. for(let n=1;n<oldCount-1;n++){
  48688. pointIndexs.push( curve.UtoTMapArr.findIndex(e=>e>= n / (oldCount-1) ) )
  48689. }
  48690. for(let i=0;i<count;i++){
  48691. let point = points[i];
  48692. let last = points[i-1]
  48693. let next = points[i+1]
  48694. if(i == 0 || i == count-1 ) {
  48695. newPoints.push(point) //直接加入
  48696. this.UtoTMapArr.push(i == 0 ? 0 : 1)
  48697. }
  48698. if(i<count-1){
  48699. let curVec = new THREE.Vector3().subVectors(next,point)
  48700. if(!lastVec) lastVec = curVec
  48701. if(i>1){// 和上一个加入点的vec之间的夹角如果过大就加入
  48702. if(pointIndexs.includes(i) || curVec.angleTo(lastVec) > 0.05){//最小角度
  48703. newPoints.push(point)
  48704. this.UtoTMapArr.push(curve.UtoTMapArr[i])
  48705. lastVec = curVec
  48706. }
  48707. }
  48708. }
  48709. }
  48710. points = newPoints
  48711. */
  48712. var result = MeshDraw.lessCurvePoints(points, oldCount, 0.05, curve.UtoTMapArr);
  48713. this.UtoTMapArr = result.newUtoTMapArr;
  48714. points = result.newPoints;
  48715. count = points.length;
  48716. //delete curve.UtoTMapArr
  48717. }
  48718. var lastSideVec;
  48719. var posArr = [],
  48720. faceArr = [],
  48721. uvArr = [];
  48722. var gatherLen = 0; //累加长度
  48723. this.geoPoints = points;
  48724. //根据点序列计算geometry
  48725. for (var i = 0; i < count; i++) {
  48726. var O = points[i]; //该点
  48727. var A = points[i - 1]; //上一个点
  48728. var B = points[i + 1]; //下一个点
  48729. var p1 = void 0,
  48730. p2 = void 0; //该点两边的折点
  48731. var sideVec = void 0; //该点两边对应的向量
  48732. var uvX = void 0;
  48733. if (i == 0 || i == count - 1) {
  48734. var nor = math.getNormal2d({
  48735. p1: i == 0 ? B : O,
  48736. p2: i == 0 ? O : A
  48737. }) || new Vector3(1, 0, 0);
  48738. sideVec = new Vector3().copy(nor).setZ(0).multiplyScalar(this.halfPathWidth); //垂线
  48739. uvX = i == 0 ? 0 : 1; //percent of length
  48740. } else {
  48741. var OA = new Vector3().subVectors(A, O).setZ(0).normalize(); //只保证俯视角度正确。(如果两点有高度差,该段四个点不会在同一平面,看起来有扭转,有的地方会肥大,但从俯视角度看是正确的。)
  48742. var OB = new Vector3().subVectors(B, O).setZ(0).normalize();
  48743. var angle = math.getAngle(OA, OB, 'z');
  48744. if (math.closeTo(angle, 0, 1e-4) || math.closeTo(angle, Math.PI, 1e-4) || math.closeTo(angle, -Math.PI, 1e-4)) {
  48745. //这时候直接加两个向量算出的平分线不准,故直接找垂线
  48746. var _nor = math.getNormal2d({
  48747. p1: O,
  48748. p2: A
  48749. }) || new Vector3(1, 0, 0);
  48750. sideVec = new Vector3().copy(_nor).setZ(0).multiplyScalar(this.halfPathWidth); //垂线
  48751. //console.log('接近0或180',angle, sideVec)
  48752. } else {
  48753. var midVecLength = this.halfPathWidth / Math.sin(angle / 2);
  48754. sideVec = new Vector3().addVectors(OA, OB).normalize().multiplyScalar(midVecLength); //角平分线 ( 和上一个方向保持在同一侧,故而顺时针和逆时针方向不同 )
  48755. }
  48756. gatherLen += O.distanceTo(A);
  48757. uvX = gatherLen / this.totalLength; //目前为止的长度占比
  48758. }
  48759. var P1 = new Vector3().addVectors(O, sideVec);
  48760. var P2 = new Vector3().subVectors(O, sideVec);
  48761. posArr.push(P1, P2);
  48762. uvArr.push({
  48763. x: uvX,
  48764. y: 0
  48765. }, {
  48766. x: uvX,
  48767. y: 1
  48768. });
  48769. if (i < count - 1) {
  48770. faceArr.push([i * 2, i * 2 + 1, i * 2 + 3], [i * 2, i * 2 + 3, i * 2 + 2]); //每一段两个三角形 013 032
  48771. }
  48772. lastSideVec = sideVec;
  48773. }
  48774. geo = MeshDraw.createGeometry(posArr, faceArr, uvArr);
  48775. this.updateArrowRepeat();
  48776. }
  48777. this.edge.geometry = geo;
  48778. this.lastHalfPathWidth = this.halfPathWidth;
  48779. this.lastUpdatePoints_ = this.points.map(e => e.clone());
  48780. } //不使用curve的曲线是因为那种geo点数较多,且改的话不知道updateArrows怎么改,除非变为贴图,但就和需求中需要调节间距违背。
  48781. update() {
  48782. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  48783. if (options.index == -1) return;
  48784. super.update(options); //updateEdge marker
  48785. this.points.length <= 1 && this.updateEdge(); //补偿上一句
  48786. this.editEnable || this.updateEndCaps();
  48787. {
  48788. var oldVisi = this.titleLabel.parent.visible;
  48789. this.setTitleVisi(this.titleLabel.parent, this.markers.length > 0, 'noPoint');
  48790. if (this.titleLabel.parent.visible && !oldVisi) this.titleLabel.updatePose();
  48791. }
  48792. this.updateTitlePos();
  48793. }
  48794. addMarker() {
  48795. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  48796. var index = o.index == void 0 ? this.points.length : o.index; //要当第几个
  48797. var marker = new Mesh(planeGeo$2, getMarkerMat('default'));
  48798. marker.name = 'marker';
  48799. setMarkerScale(marker, this.halfPathWidth);
  48800. marker.markerSelectStates = {};
  48801. //Potree.Utils.setObjectLayers(marker, 'measure' )
  48802. marker.renderOrder = Potree.config.renderOrders.path.marker;
  48803. marker.addEventListener('mouseover', e => {
  48804. if (this.addOrRemovePoint && !this.isNew) {
  48805. CursorDeal.add('pen_delPoint');
  48806. //hideFakeMarker()
  48807. }
  48808. this.hoverStates.marker = marker;
  48809. } /* ,{importance:1} */);
  48810. marker.addEventListener('mouseleave', e => {
  48811. CursorDeal.remove('pen_delPoint');
  48812. marker == this.hoverStates.marker && (this.hoverStates.marker = null);
  48813. });
  48814. marker.addEventListener('click', e => {
  48815. if (this.isNew || e.button !== MOUSE.LEFT) return;
  48816. if (this.addOrRemovePoint) {
  48817. //点击删除点
  48818. this.removePoint(this.markers.indexOf(marker));
  48819. } else {
  48820. //点击选中点
  48821. this.dispatchEvent({
  48822. type: 'markerSelect',
  48823. marker
  48824. });
  48825. this.setMarkerSelected(marker, 'click');
  48826. setTimeout(() => {
  48827. viewer.addEventListener('global_click', e => {
  48828. var _e$clickElement;
  48829. //点击空白处取消全部
  48830. if (((_e$clickElement = e.clickElement) === null || _e$clickElement === void 0 ? void 0 : _e$clickElement.oriObject) == marker) return;
  48831. this.dispatchEvent({
  48832. type: 'markerSelect',
  48833. marker,
  48834. cancel: true
  48835. });
  48836. this.setMarkerSelected(marker, 'unclick');
  48837. }, {
  48838. once: true
  48839. });
  48840. }, 10);
  48841. }
  48842. e.consume();
  48843. });
  48844. marker.addEventListener('startDragging', e => {
  48845. this.isNew || this.setMarkerSelected(marker, 'click'); //选中
  48846. this.isNew || viewer.measuringTool.history.beforeChange(this);
  48847. this.arrows && Potree.Utils.updateVisible(this.arrows, 'dragging', false);
  48848. //Potree.Common.waitTool.cancel('pathUpdateArrowDelay')
  48849. });
  48850. marker.addEventListener('drop', e => {
  48851. if (!this.isNew && this.arrows) {
  48852. Potree.Utils.updateVisible(this.arrows, 'dragging', true);
  48853. Path$1.updateArrows(true);
  48854. }
  48855. //this.hideArrowUntilUpdate()
  48856. if (e.button != MOUSE.LEFT) return;
  48857. viewer.inputHandler.dispatchEvent({
  48858. type: 'measuring',
  48859. v: false,
  48860. cause: 'stopDragging',
  48861. situation: 'dragging',
  48862. object: this
  48863. });
  48864. this.lastDropTime = Date.now();
  48865. this.isNew || viewer.measuringTool.history.afterChange(this);
  48866. this.setMarkerSelected(marker, 'unclick');
  48867. });
  48868. var label = this.createMarkerLabel('');
  48869. this.markerLabels = [...this.markerLabels.slice(0, index), label, ...this.markerLabels.slice(index, this.points.length)];
  48870. this.setMarkerTitle(index, Potree.settings.isOfficial ? '' : 'point');
  48871. super.addMarker(Object.assign(o, {
  48872. index,
  48873. marker
  48874. }));
  48875. //this.updateEdge()
  48876. return marker;
  48877. }
  48878. updateEndCaps() {
  48879. var len = this.points.length;
  48880. var pts = this.geoPoints.length > 0 ? this.geoPoints : this.points;
  48881. var len2 = pts.length;
  48882. this.endCaps.forEach((e, i) => {
  48883. Potree.Utils.updateVisible(e, 'hasPoints', len > 0);
  48884. if (len) {
  48885. if (len > 1) {
  48886. var dir = i == 0 ? new Vector3().subVectors(pts[1], pts[0]) : new Vector3().subVectors(pts[len2 - 2], pts[len2 - 1]);
  48887. e.quaternion.copy(getMeshQuaInPath(dir));
  48888. } else {
  48889. i == 0 ? e.quaternion.set(0, 0, 0, 1) : e.quaternion.set(0, 0, 1, 0); //两个半圆拼成一个圆点
  48890. }
  48891. e.position.copy(this.points[i == 0 ? 0 : len - 1]);
  48892. var s = this.halfPathWidth * 2.15;
  48893. e.scale.set(s, s, s);
  48894. }
  48895. });
  48896. }
  48897. setEditEnable(state) {
  48898. //是否显示可修改控件
  48899. this.editEnable = !!state;
  48900. this.markers.forEach(e => Potree.Utils.updateVisible(e, 'editEnable', this.editEnable));
  48901. this.endCaps.forEach((e, i) => Potree.Utils.updateVisible(e, 'editEnable', !this.editEnable));
  48902. if (markerMats) {
  48903. //因为marker材质每条path都共用,所以isOfficial时请保证只有一条在编辑
  48904. for (var i in markerMats) {
  48905. markerMats[i].fadeFar = this.fadeFar;
  48906. }
  48907. }
  48908. if (!state) {
  48909. this.updateEndCaps();
  48910. }
  48911. viewer.dispatchEvent('content_changed');
  48912. }
  48913. setAddOrRemPoint(state) {
  48914. //是否可以加减点, 此时不能拖拽marker
  48915. this.addOrRemovePoint = !!state;
  48916. this.updateCursorState();
  48917. }
  48918. updateCursorState() {
  48919. //可能在hover时修改addOrRemovePoint,也可能从marker和edge之间切换, 主要是addOrRemovePoint开关时要记得之前的hover状态
  48920. CursorDeal[this.addOrRemovePoint ? 'add' : 'remove']('pen');
  48921. if (this.addOrRemovePoint && !this.isNew) {
  48922. CursorDeal[this.hoverStates.edge ? 'add' : 'remove']('pen_addPoint');
  48923. CursorDeal[this.hoverStates.marker ? 'add' : 'remove']('pen_delPoint');
  48924. } else {
  48925. CursorDeal.remove('pen_addPoint');
  48926. CursorDeal.remove('pen_delPoint');
  48927. }
  48928. }
  48929. setTitleVisi(label, v) {
  48930. var reason = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
  48931. Potree.Utils.updateVisible(label, 'hideTitle-' + reason, v);
  48932. viewer.dispatchEvent('content_changed');
  48933. }
  48934. setTitle() {
  48935. var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  48936. this.title = title;
  48937. this.titleLabel.setText(title);
  48938. this.setTitleVisi(this.titleLabel.parent, title instanceof Array || title.trim() != '', 'noText');
  48939. viewer.dispatchEvent('content_changed');
  48940. }
  48941. setMarkerTitle(index, title) {
  48942. if (!this.markerLabels[index]) return;
  48943. this.markerLabels[index].originText = title;
  48944. this.markerLabels[index].setText(title);
  48945. this.setTitleVisi(this.markerLabels[index], title instanceof Array || title.trim() != '', 'noText');
  48946. viewer.dispatchEvent('content_changed');
  48947. }
  48948. editStateChange(state) {
  48949. //拖动时被调用
  48950. super.editStateChange(state);
  48951. if (!state) {
  48952. this.editStateTimer = setTimeout(() => {
  48953. if (!this.isEditing) {
  48954. this.dispatchEvent({
  48955. type: 'editStateChange',
  48956. state: false
  48957. });
  48958. }
  48959. }, 100);
  48960. } else {
  48961. if (!this.isEditing) {
  48962. this.dispatchEvent({
  48963. type: 'editStateChange',
  48964. state: true
  48965. });
  48966. clearTimeout(this.editStateTimer);
  48967. }
  48968. }
  48969. this.isEditing = state;
  48970. }
  48971. removePoint(index) {
  48972. if (index == -1) {
  48973. return; //双击会这样,加了迅速删除, 可能因为没来得及删
  48974. }
  48975. viewer.measuringTool.history.beforeChange(this);
  48976. this.removeMarker(index);
  48977. this.hideArrowUntilUpdate();
  48978. viewer.measuringTool.history.afterChange(this);
  48979. this.dispatchEvent('changed');
  48980. if (this.points.length == 0) {
  48981. //viewer.measuringTool.changeToAddState(this)
  48982. viewer.measuringTool.startInsertion({
  48983. resume: true,
  48984. measure: this
  48985. });
  48986. }
  48987. }
  48988. setMarkerSelected(marker, state) {
  48989. state == 'hover' && (marker.markerSelectStates.hover = true);
  48990. state == 'unhover' && (marker.markerSelectStates.hover = false);
  48991. state == 'click' && (marker.markerSelectStates.click = true); //click or drag
  48992. state == 'unclick' && (marker.markerSelectStates.click = false);
  48993. if (marker.markerSelectStates.click) {
  48994. marker.material = getMarkerMat('drag');
  48995. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.path.marker + 1;
  48996. } else if (marker.markerSelectStates.hover) {
  48997. marker.material = getMarkerMat(this.addOrRemovePoint ? 'delete' : 'drag');
  48998. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.path.marker + 1;
  48999. } else {
  49000. marker.material = getMarkerMat('default');
  49001. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.path.marker;
  49002. }
  49003. //marker.selected = absoluteState
  49004. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  49005. viewer.dispatchEvent('content_changed');
  49006. }
  49007. setSelected(state, byList) {
  49008. if (state == 'click' && this.selectStates.click) return this.setSelected('unclick'); //重复点击了
  49009. state == 'hover' && (this.selectStates.hover = true, byList || this.dispatchEvent({
  49010. type: 'highlight',
  49011. state: true
  49012. }), CursorDeal.add('pointer'));
  49013. state == 'unhover' && (this.selectStates.hover = false, byList || this.dispatchEvent({
  49014. type: 'highlight',
  49015. state: false
  49016. }), CursorDeal.remove('pointer'));
  49017. state == 'click' && (this.selectStates.click = true, byList || this.dispatchEvent({
  49018. type: 'chose',
  49019. state: true
  49020. }));
  49021. state == 'unclick' && (this.selectStates.click = false, byList || this.dispatchEvent({
  49022. type: 'chose',
  49023. state: false
  49024. }));
  49025. /* this.arrows?.material.color.set(this.selectStates.click ? '#ffffff' : this.color);
  49026. ([this.edge, this.endCaps[0].children[0]].forEach(e=>{
  49027. e.material.opacity = this.selectStates.click ? 1 : this.selectStates.hover ? 0.8 : 0.6
  49028. e.material.color.set(this.selectStates.click ? '#00C8AF' : this.color)
  49029. })) */
  49030. this.updateSelectStyle();
  49031. state == 'click' && setTimeout(() => {
  49032. viewer.addEventListener('global_click', e => {
  49033. //再点击取消
  49034. this.setSelected('unclick');
  49035. }, {
  49036. once: true
  49037. });
  49038. }, 10);
  49039. viewer.dispatchEvent('content_changed');
  49040. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed');
  49041. }
  49042. updateSelectStyle() {
  49043. //let c = new THREE.Color().set(this.color).getHSL({ h: 0, s: 0, l: 0 })
  49044. var hsv = new Color().set(this.color).getHSV();
  49045. var color, arrowColor;
  49046. if (this.selectStates.click) {
  49047. color = '#00C8AF';
  49048. arrowColor = '#ffffff';
  49049. } else if (this.selectStates.hover) {
  49050. /* color = new THREE.Color().setHSL(c.h, c.s, c.l - 0.1 )
  49051. arrowColor = new THREE.Color().setHSL(c.h, c.s, c.l >= 0.4 ? c.l - 0.3 : c.l + 0.3 ) */
  49052. color = new Color().setHSV(hsv.h, hsv.s, hsv.v - 10);
  49053. arrowColor = new Color().setHSV(hsv.h, hsv.s, hsv.v >= 40 ? hsv.v - 30 : hsv.v + 30);
  49054. } else {
  49055. //arrowColor = new THREE.Color().setHSL(c.h, c.s, c.l >= 0.4 ? c.l - 0.3 : c.l + 0.3 )
  49056. arrowColor = new Color().setHSV(hsv.h, hsv.s, hsv.v >= 40 ? hsv.v - 30 : hsv.v + 30);
  49057. color = this.color;
  49058. }
  49059. if (this.arrows) {
  49060. this.arrows.material.color.set(arrowColor);
  49061. } else {
  49062. this.edge.material.uniforms.mapColor.value.set(arrowColor);
  49063. }
  49064. [this.edge, this.endCaps[0].children[0]].forEach(e => {
  49065. e.material.color.set(color);
  49066. e.material.uniforms.maxClipFactor.value = this.selectStates.click ? 0.4 : this.selectStates.hover ? 0.6 : depthProps.maxClipFactor;
  49067. e.material.uniforms.occlusionDistance.value = this.selectStates.click ? 0.6 : this.selectStates.hover ? 0.7 : depthProps.occlusionDistance;
  49068. });
  49069. }
  49070. removeMarker(index) {
  49071. super.removeMarker(index);
  49072. this.points_datasets.splice(index, 1);
  49073. this.dataset_points && this.dataset_points.splice(index, 1);
  49074. var labelIndex = index;
  49075. if (this.markerLabels[labelIndex]) {
  49076. this.markerLabels[labelIndex].dispose();
  49077. this.markerLabels.splice(labelIndex, 1);
  49078. }
  49079. this.update({
  49080. index: this.getIndex(index, -1)
  49081. });
  49082. this.dispatchEvent({
  49083. type: 'marker_removed',
  49084. measurement: this
  49085. });
  49086. }
  49087. setPosition(index, position) {
  49088. super.setPosition(index, position);
  49089. var event = {
  49090. type: 'marker_moved',
  49091. measure: this,
  49092. index: index,
  49093. position: position.clone()
  49094. };
  49095. this.dispatchEvent(event);
  49096. }
  49097. setFontSize(fontsize) {
  49098. this.fontsize = fontsize;
  49099. this.markerLabels.concat(this.titleLabel).forEach(e => {
  49100. e.fontsize = fontsize;
  49101. e.updateTexture();
  49102. });
  49103. viewer.dispatchEvent('content_changed');
  49104. }
  49105. setFadeFar(far) {
  49106. //消失距离
  49107. if (far == void 0) far = 0; //不设置
  49108. this.traverse(e => {
  49109. var _e$material;
  49110. //if(e.name == 'marker')return //因为marker材质共用的所以不改。因此正式编辑时(有marker时)别设置消失距离。
  49111. if ((_e$material = e.material) !== null && _e$material !== void 0 && (_e$material = _e$material.uniforms) !== null && _e$material !== void 0 && _e$material.fadeFar) {
  49112. e.material.fadeFar = far;
  49113. }
  49114. });
  49115. this.fadeFar = far;
  49116. if (markerMats) {
  49117. //因为marker材质每条path都共用,所以isOfficial时请保证只有一条在编辑
  49118. for (var i in markerMats) {
  49119. markerMats[i].fadeFar = this.fadeFar;
  49120. }
  49121. }
  49122. viewer.dispatchEvent('content_changed');
  49123. }
  49124. dispose() {
  49125. var _this$arrows, _this$arrows2;
  49126. super.dispose();
  49127. this.titleLabel.dispose();
  49128. this.markerLabels.forEach(e => e.dispose());
  49129. (_this$arrows = this.arrows) === null || _this$arrows === void 0 || _this$arrows.dispose();
  49130. (_this$arrows2 = this.arrows) === null || _this$arrows2 === void 0 || _this$arrows2.material.dispose();
  49131. this.edge.geometry.dispose();
  49132. this.edge.material.dispose();
  49133. this.setAddOrRemPoint(false); //cursor recover
  49134. this.dispatchEvent('disposed');
  49135. }
  49136. updateArrowRepeat() {
  49137. if (!this.edge.material.map) return;
  49138. this.edge.material.map.repeat.x = Math.round(this.totalLength / this.halfPathWidth * 0.5) * (this.reverse ? -1 : 1);
  49139. this.edge.material.map.needsUpdate = true;
  49140. this.edge.material.setUV();
  49141. }
  49142. setArrowDisplay(show) {
  49143. if (Potree.settings.pathSmooth) {
  49144. if (show) {
  49145. var map = texLoader$7.load(Potree.resourcePath + '/textures/arrow.png', () => {
  49146. viewer.dispatchEvent('content_changed');
  49147. });
  49148. map.anisotropy = 2;
  49149. map.wrapS = RepeatWrapping;
  49150. map.repeat.set(10, 1.3);
  49151. map.offset.set(0, -0.15);
  49152. this.edge.material.map = map;
  49153. this.updateArrowRepeat();
  49154. } else {
  49155. var _this$edge$material$m;
  49156. (_this$edge$material$m = this.edge.material.map) === null || _this$edge$material$m === void 0 || _this$edge$material$m.dispose();
  49157. this.edge.material.map = null;
  49158. }
  49159. } else {
  49160. if (show) {
  49161. if (!this.arrows) {
  49162. var _map = texLoader$7.load(Potree.resourcePath + '/textures/arrow.png');
  49163. //map.anisotropy = 2
  49164. _map.generateMipmaps = false;
  49165. _map.minFilter = LinearFilter; //防止边缘黑边, 但会造成锯齿
  49166. var material = new DepthBasicMaterial(Object.assign({}, depthProps, {
  49167. map: _map,
  49168. transparent: true,
  49169. side: 2,
  49170. fadeFar: this.fadeFar,
  49171. color: this.selectStates.click ? '#ffffff' : this.color
  49172. }));
  49173. //let material = new THREE.MeshBasicMaterial({map )})
  49174. this.arrows = new InstancedMesh(planeGeo$2, material, arrowCountMax); //会自动向shader添加define和instanceMatrix
  49175. this.arrows.renderOrder = Potree.config.renderOrders.path.edge;
  49176. this.add(this.arrows);
  49177. //Potree.Utils.setObjectLayers(this.arrows, 'measure' )
  49178. }
  49179. this.updateSelectStyle();
  49180. }
  49181. if (this.arrows) {
  49182. Potree.Utils.updateVisible(this.arrows, 'show', show);
  49183. show && Path$1.waitUpdateArrows();
  49184. }
  49185. }
  49186. viewer.dispatchEvent('content_changed');
  49187. }
  49188. setReverse(reverse) {
  49189. if (this.reverse != reverse) {
  49190. this.reverse = reverse;
  49191. if (Potree.settings.pathSmooth) {
  49192. this.updateArrowRepeat();
  49193. } else {
  49194. Path$1.updateArrows(true);
  49195. }
  49196. }
  49197. }
  49198. hideArrowUntilUpdate() {
  49199. this.arrows && Potree.Utils.updateVisible(this.arrows, 'changing', false);
  49200. Path$1.waitUpdateArrows();
  49201. }
  49202. static waitUpdateArrows() {
  49203. if (Potree.settings.pathSmooth) return;
  49204. Potree.Common.waitTool.wait('pathUpdateArrowDelay', () => {
  49205. viewer.scene.measurements.forEach(e => e instanceof Path$1 && e.arrows && Potree.Utils.updateVisible(e.arrows, 'changing', true));
  49206. Path$1.updateArrows(true);
  49207. viewer.dispatchEvent('content_changed');
  49208. }, 300); //为了防止不停点击不停更新,所以隐藏一下不变了再更新
  49209. }
  49210. static updateArrows(force) {
  49211. //console.error('updateArrows?')
  49212. var far = math.linearClamp(Potree.fpsRendered2, [10, 60], [200, 300]); //几乎看不见了
  49213. var paths = viewer.scene.measurements.filter(e => {
  49214. var _e$arrows;
  49215. return e instanceof Path$1 && ((_e$arrows = e.arrows) === null || _e$arrows === void 0 ? void 0 : _e$arrows.visible);
  49216. });
  49217. var waitAdd = [];
  49218. var minDisSq = Infinity;
  49219. var startTime = performance.now();
  49220. var lines = [];
  49221. paths.forEach(path => {
  49222. var len = path.points.length;
  49223. var far_ = path.halfPathWidth * far;
  49224. far_ = path.fadeFar ? Math.min(far_, path.fadeFar * 1.2) : far_;
  49225. var farSquared_ = far_ * far_;
  49226. for (var i = 0; i < len - 1; i++) {
  49227. var thisPoint = path.points[i];
  49228. var nextPoint = path.points[i + 1];
  49229. var line = new Line3(thisPoint, nextPoint);
  49230. var closetPoint = line.closestPointToPoint(viewer.mainViewport.view.position, true, new Vector3()); //过相机到line的垂足,限制在线段内
  49231. var disSq = closetPoint.distanceToSquared(viewer.mainViewport.view.position);
  49232. if (disSq > farSquared_ && lastArrowCount > 0) continue;
  49233. minDisSq = Math.min(minDisSq, disSq);
  49234. lines.push({
  49235. line,
  49236. disSq,
  49237. path
  49238. });
  49239. }
  49240. });
  49241. var spaceDis = MathUtils.clamp(math.toPrecision(Math.pow(minDisSq, 0.1) * 5, 1), 5, 15); //箭头之间的间距,适当调节稀疏
  49242. spaceDis *= math.linearClamp(Potree.fpsRendered2, [10, 60], [3, 1]);
  49243. if ((lastArrowCamPos && math.closeTo(lastArrowCamPos, viewer.mainViewport.view.position, 2) || lines.length == 0) && !force) return; //很远的时候lines空的不更新(不清空)
  49244. lastArrowCamPos = viewer.mainViewport.view.position.clone();
  49245. viewer.scene.measurements.forEach(e => e instanceof Path$1 && e.arrows && (e.arrows.count = 0)); //归零
  49246. lines.sort((a, b) => {
  49247. return a.disSq - b.disSq;
  49248. }); //尽快收集好就近的,使后加的都比waitAdd最后一个大,减少比较
  49249. lines.forEach(info => {
  49250. if (waitAdd[arrowCountMax - 1] && info.disSq > waitAdd[arrowCountMax - 1].disSq) return; //线段最近点已经超过当前list中最远的那个
  49251. info.dir = new Vector3().subVectors(info.line.end, info.line.start).normalize();
  49252. var lineLen = info.line.end.distanceTo(info.line.start);
  49253. var spaceDis_ = info.path.halfPathWidth * spaceDis; //跟随箭头缩放
  49254. var sliceCount = Math.round(lineLen / spaceDis_); //分段
  49255. if (sliceCount < 1) return;
  49256. if (sliceCount == 1) sliceCount = 2; //至少为2
  49257. var arrowCount = sliceCount - 1;
  49258. var sliceLen = lineLen / sliceCount;
  49259. var j = arrowCount;
  49260. var _loop = function _loop() {
  49261. var pos = info.line.start.clone().add(info.dir.clone().multiplyScalar(j * sliceLen));
  49262. var disSq = pos.distanceToSquared(viewer.mainViewport.view.position);
  49263. j--;
  49264. if (waitAdd[arrowCountMax - 1] && disSq > waitAdd[arrowCountMax - 1].disSq) return 1; // continue
  49265. //按从小到大排好。(不知道这种事先排好序的方法 和全部加入最后排序选前面的 相比哪个耗时。 因为冒泡排序更快,但如果总数很多会不会慢?)
  49266. var newItem = {
  49267. pos,
  49268. disSq,
  49269. lineInfo: info
  49270. };
  49271. var index = waitAdd.findIndex(e => e.disSq > disSq);
  49272. if (index == -1) {
  49273. waitAdd.push(newItem);
  49274. } else {
  49275. waitAdd = [...waitAdd.slice(0, index), newItem, ...waitAdd.slice(index, waitAdd.length)];
  49276. }
  49277. waitAdd.length > arrowCountMax && waitAdd.pop();
  49278. };
  49279. while (j > 0) {
  49280. if (_loop()) continue;
  49281. }
  49282. });
  49283. var scaleMap = new Map();
  49284. waitAdd.forEach((e, i) => {
  49285. var scaleQuaMatrix = e.lineInfo.scaleQuaMatrix;
  49286. if (!scaleQuaMatrix) {
  49287. var scaleMatrix = scaleMap.get(e.lineInfo.path);
  49288. if (!scaleMatrix) {
  49289. var s = e.lineInfo.path.halfPathWidth * 1.6;
  49290. scaleMatrix = new Matrix4().scale(new Vector3((e.lineInfo.path.reverse ? -1 : 1) * s, s, s));
  49291. scaleMap.set(e.lineInfo.path, scaleMatrix);
  49292. }
  49293. var qua = getMeshQuaInPath(e.lineInfo.dir); //math.getQuaFromPosAim( new THREE.Vector3, e.lineInfo.dir ).multiply(quaBase)
  49294. var quaMatrix = new Matrix4().makeRotationFromQuaternion(qua);
  49295. scaleQuaMatrix = e.lineInfo.scaleQuaMatrix = new Matrix4().multiplyMatrices(quaMatrix, scaleMatrix);
  49296. }
  49297. var matrix = scaleQuaMatrix.clone().setPosition(e.pos);
  49298. e.lineInfo.path.arrows.count++;
  49299. e.lineInfo.path.arrows.setMatrixAt(e.lineInfo.path.arrows.count - 1, matrix);
  49300. e.lineInfo.path.arrows.instanceMatrix.needsUpdate = true;
  49301. });
  49302. lastArrowCount = waitAdd.length;
  49303. //console.log('updateArrows spaceDis', spaceDis, 'count', waitAdd.length, 'cost', performance.now() - startTime)
  49304. }
  49305. }
  49306. Path$1.prototype.cloneMarker = Measure$1.prototype.cloneMarker;
  49307. Path$1.prototype.updateDatasetBelong = Measure$1.prototype.updateDatasetBelong;
  49308. //Path.prototype.reDraw = Measure.prototype.reDraw
  49309. /*
  49310. 没有intersect的点的dataset_point怎么赋值
  49311. 1 lonlat : 因为说是加在地图上。 但万一用户在添加完path之后才设置经纬度,这个点可能就飘到很远的地方? 由于模型当前的位置都是本地坐标而不是经纬度,所以模型不会跟着一起飘远。
  49312. 2 就近的datasetId : 但如果path全部点都在地图上, 现场只有一个离他远的模型,但它仍被判断在该模型上。之后在路径边加了其他模型。 当它的所属模型被删除后它就像意外消失了……
  49313. 3 本地坐标 : 当模型移动后该点不会跟着移动。 写起来比上一条麻烦点,但逻辑不容易误解。
  49314. 目前用的3
  49315. */
  49316. /*
  49317. const plane = new THREE.Plane(normal, dis);
  49318. viewer.renderer.localClippingEnabled = true;
  49319. material.clippingPlanes = [ localPlane ]
  49320. #include <clipping_planes_pars_fragment>
  49321. #include <clipping_planes_fragment>
  49322. */
  49323. var sid$1 = 0;
  49324. class History extends EventDispatcher {
  49325. constructor(o) {
  49326. super();
  49327. this.undoList = [];
  49328. this.redoList = [];
  49329. this.applyData = o.applyData; //应用数据的方法
  49330. this.getData = o.getData; //获取数据的方法
  49331. this.dataBefore;
  49332. this.sid = sid$1++;
  49333. (o.viewer || viewer).inputHandler.addEventListener('keydown', e => {
  49334. if (e.keyCode == 90 && e.event.ctrlKey) {
  49335. //Z
  49336. this.undo();
  49337. } else if (e.keyCode == 89 && e.event.ctrlKey) {
  49338. //Y
  49339. this.redo();
  49340. }
  49341. });
  49342. }
  49343. undo() {
  49344. //回退
  49345. var length = this.undoList.length;
  49346. if (length > 0) {
  49347. var unExist;
  49348. var last = this.undoList.pop();
  49349. this.applyData && (unExist = !this.applyData(last.before));
  49350. unExist || this.redoList.push(last);
  49351. unExist && this.undo(); //找不到就回退下一个。
  49352. this.dispatchEvent('undo');
  49353. console.log(this.sid, 'undo', this.undoList.length);
  49354. }
  49355. }
  49356. redo() {
  49357. //撤销回退
  49358. var length = this.undoList.length;
  49359. var last = this.redoList.pop();
  49360. if (last) {
  49361. //注意:每行的顺序不能乱
  49362. this.undoList.push(last);
  49363. this.applyData && this.applyData(last.after);
  49364. this.dispatchEvent('redo');
  49365. //console.log('redo',last)
  49366. }
  49367. }
  49368. beforeChange(o) {
  49369. //在变化之前(可能执行好几次直到变化完,但只有第一次有效)。 o的内容完全根据getData怎么定义
  49370. if (!this.dataBefore) {
  49371. var data = this.getData(o);
  49372. data && (this.dataBefore = data);
  49373. }
  49374. }
  49375. afterChange(o) {
  49376. //变化结束,从beforeChange到此算一次操作。
  49377. if (this.dataBefore) {
  49378. this.writeIn({
  49379. before: this.dataBefore,
  49380. after: this.getData(o)
  49381. }); //写入某物体变化前和变化后的状态
  49382. this.dataBefore = null;
  49383. }
  49384. }
  49385. writeIn(data) {
  49386. this.redoList.length = 0; //一旦录入新的操作,就不允许undo了
  49387. //console.log('writeIn', data)
  49388. this.undoList.push(data);
  49389. }
  49390. clear() {
  49391. this.redoList.length = 0;
  49392. this.undoList.length = 0;
  49393. this.dataBefore = null;
  49394. }
  49395. }
  49396. var areaPlaneMats = {};
  49397. class Prism extends Measure$1 {
  49398. constructor(args) {
  49399. args.isPrism = true;
  49400. super(args);
  49401. this.volumeInfo = {};
  49402. this.needsCompute = true;
  49403. /*this.createPrismLines(new THREE.Color('#FFF') )
  49404. this.lineMesh.material.transparent = true
  49405. this.lineMesh.material.opacity = 0.5
  49406. Potree.Utils.setObjectLayers(this.lineMesh, 'measure' ) */
  49407. this.setClipBox();
  49408. this.setTopOrBtm('zMin');
  49409. this.setTopOrBtm('zMax');
  49410. this.setHorizonHeight('btm');
  49411. var update = () => {
  49412. this.setHorizonHeight(this.horizonType, true); //更新
  49413. this.needsCompute = true;
  49414. this.getBound();
  49415. this.dispatchEvent('updated');
  49416. };
  49417. this.addEventListener('marker_dropped' /* 'marker_moved' */, update);
  49418. this.addEventListener('changeByHistory', update);
  49419. this.addEventListener('changed', update);
  49420. /* this.addEventListener('createDone',()=>{
  49421. this.setHorizonHeight()//更新
  49422. this.updateAreaPlane()
  49423. }) */
  49424. this.updateAreaPlane();
  49425. this.getBound();
  49426. this.addEventListener('needsCompute', () => {
  49427. this.needsCompute = true;
  49428. }, 10);
  49429. //Potree.Utils.setObjectLayers(this.lineMesh, 'bothMapAndScene' )
  49430. }
  49431. set needsCompute(state) {
  49432. if (state == 'byVolume') {
  49433. this.needsCompute_ = this.volumeInfo.Vupper == void 0;
  49434. } else {
  49435. this.needsCompute_ = !!state;
  49436. //console.error('needsCompute', state)
  49437. }
  49438. }
  49439. get needsCompute() {
  49440. return this.needsCompute_;
  49441. }
  49442. setHorizonHeight(v) {
  49443. var old = this.horizonZ;
  49444. if (typeof v == 'number') {
  49445. this.horizonType = 'number';
  49446. this.horizonZ = v;
  49447. } else {
  49448. if (v) {
  49449. this.horizonType = v;
  49450. }
  49451. if (!this.horizonType) this.horizonType = 'btm';
  49452. if (this.horizonType == 'number') return;
  49453. var zs = this.points.map(p => p.z).sort((a, b) => a - b);
  49454. this.horizonZ = this.horizonType == 'btm' ? zs[0] : zs[this.points.length - 1];
  49455. }
  49456. //this.horizonZ = THREE.Math.clamp(this.horizonZ, this.zMin, this.zMax )
  49457. if (this.horizonZ != old) {
  49458. this.needsCompute = true;
  49459. this.update(); //update areaPlane and areaLabel pos
  49460. this.dispatchEvent('horizonZChanged');
  49461. }
  49462. //console.log(this.horizonZ)
  49463. }
  49464. setBaseModel(model, modelHaventLoad) {
  49465. //三种状态:使用model、使用基准高度、 什么都没有(不允许计算、不高亮、等待模型上传)
  49466. this.baseModel = model;
  49467. this.modelHaventLoad = modelHaventLoad;
  49468. Potree.Utils.updateVisible(this.areaPlane, 'unuseHorizonH', !model && !modelHaventLoad);
  49469. }
  49470. setClipBox(boxes) {
  49471. //clipBoxes_out
  49472. this.clipBoxes = boxes || [];
  49473. }
  49474. setTopOrBtm(name, v) {
  49475. if (v != void 0) {
  49476. this[name] = v;
  49477. this.updatePrismLines();
  49478. } else {
  49479. this[name] = viewer.bound.boundingBox[name == 'zMin' ? 'min' : 'max'].z;
  49480. }
  49481. this.getBound();
  49482. this.needsCompute = true;
  49483. }
  49484. getBound() {
  49485. var bound = Potree.math.getBound(this.points);
  49486. bound.min.z = this.zMin;
  49487. bound.max.z = this.zMax;
  49488. this.prismBound = bound;
  49489. }
  49490. setVolumeInfo(volumeInfo) {
  49491. this.volumeInfo = volumeInfo;
  49492. this.getVolumeString();
  49493. this.needsCompute = false; //但得到的不一定是对的可能 检查下
  49494. }
  49495. getVolumeString() {
  49496. if (!this.volumeInfo || this.volumeInfo.Vupper == void 0) return;
  49497. this.VupperString = this.getConvertString(this.volumeInfo.Vupper, 'volume', true);
  49498. this.VlowerString = this.getConvertString(this.volumeInfo.Vlower, 'volume', true);
  49499. this.highestString = this.getConvertString(this.volumeInfo.highest, 'distance', true);
  49500. this.lowestString = this.getConvertString(this.volumeInfo.lowest, 'distance', true);
  49501. }
  49502. getConvertString(num, type, restrictUnit) {
  49503. if (!restrictUnit) return super.getConvertString(num, type);
  49504. return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, null, {
  49505. //在pdf里的高度要统一单位
  49506. 'imperial': {
  49507. restrictUnit: 'Foot'
  49508. },
  49509. //ft
  49510. 'metric': {
  49511. restrictUnit: 'Meter'
  49512. }
  49513. });
  49514. }
  49515. setUnitSystem(unitSystem) {
  49516. var old = this.unitSystem;
  49517. super.setUnitSystem(unitSystem);
  49518. if (unitSystem != old) {
  49519. this.getVolumeString();
  49520. }
  49521. }
  49522. getCenter(type) {
  49523. if (type == 'areaPlaneCenter') {
  49524. //areaPlane中心
  49525. return this.areaPlaneCenter;
  49526. }
  49527. return super.getCenter(); //点的中心
  49528. }
  49529. update() {
  49530. super.update.apply(this, arguments);
  49531. this.updatePrismLines();
  49532. }
  49533. getTransformationMatrix(pointcloud) {
  49534. //剪裁矩阵
  49535. var invMatrix = new Matrix4();
  49536. //把当前z移动到-0.5 ~ 0.5所需要的变换
  49537. var minZ = this.zMin; //viewer.bound.boundingBox.min.z
  49538. var maxZ = this.zMax; //viewer.bound.boundingBox.max.z
  49539. var s = 1 / (maxZ - minZ);
  49540. var pos = new Vector3(0, 0, -0.5 - minZ * s),
  49541. scale = new Vector3(1, 1, s);
  49542. invMatrix.compose(pos, new Quaternion(), scale); //先缩放后位移
  49543. return new Matrix4().multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose();
  49544. }
  49545. changeStyleForScreenshot(state) {
  49546. var {
  49547. hideLabel,
  49548. showName
  49549. } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  49550. //截图前变一下外观。根据高度变化颜色
  49551. var config = Potree.settings.prismHeightColor;
  49552. var color; //, lineWidth = this.edges[0].material.lineWidth
  49553. if (this.volumeInfo.Vupper > 0.01 && this.volumeInfo.Vlower > 0.01) {
  49554. color = config.every.color;
  49555. } else if (this.volumeInfo.Vupper > this.volumeInfo.Vlower) {
  49556. for (var i = config.dig.length - 1; i >= 0; i--) {
  49557. if (this.volumeInfo.Vupper >= config.dig[i].min) {
  49558. color = config.dig[i].color;
  49559. break;
  49560. }
  49561. }
  49562. } else {
  49563. for (var _i = config.fill.length - 1; _i >= 0; _i--) {
  49564. if (this.volumeInfo.Vlower >= config.fill[_i].min) {
  49565. color = config.fill[_i].color;
  49566. break;
  49567. }
  49568. }
  49569. }
  49570. color = new Color(color[0] / 255, color[1] / 255, color[2] / 255);
  49571. var name = color.getHexString();
  49572. if (state) {
  49573. Potree.Utils.updateVisible(this.areaPlane, 'screenshot', true, 2, 'add'); //强制显示
  49574. var mat = areaPlaneMats[name];
  49575. if (!mat) {
  49576. mat = new MeshBasicMaterial({
  49577. color,
  49578. transparent: true,
  49579. opacity: 0.6,
  49580. side: DoubleSide
  49581. });
  49582. areaPlaneMats[name] = mat;
  49583. }
  49584. this.oldAreaPlaneMat = this.areaPlane.material;
  49585. this.areaPlane.material = mat;
  49586. if (hideLabel) {
  49587. Potree.Utils.updateVisible(this.areaLabel, 'screenshot-single', false);
  49588. }
  49589. if (showName) {
  49590. this.areaLabel.setText([this.name, this.area.string]);
  49591. /* let btm = this.areaPlaneCenter.clone().setY(this.prismBound.min.y) //置于土方2d块底部
  49592. this.areaLabel.setPos(btm)
  49593. this.areaLabel.sprite.position.y = -0.25 */
  49594. }
  49595. this.markers.forEach(marker => Potree.Utils.updateVisible(marker, 'screenshot-Prism', false));
  49596. this.edges.forEach(edge => Potree.Utils.updateVisible(edge, 'screenshot-Prism', false));
  49597. //Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',false)
  49598. this.styleRecover = () => {
  49599. this.areaPlane.material = this.oldAreaPlaneMat;
  49600. if (hideLabel) {
  49601. Potree.Utils.updateVisible(this.areaLabel, 'screenshot-single', true);
  49602. }
  49603. if (showName) {
  49604. this.areaLabel.setText(this.area.string);
  49605. /* this.areaLabel.setPos(this.areaPlaneCenter)
  49606. this.areaLabel.sprite.position.y = 0 */
  49607. }
  49608. this.markers.forEach(marker => Potree.Utils.updateVisible(marker, 'screenshot-Prism', true));
  49609. this.edges.forEach(edge => Potree.Utils.updateVisible(edge, 'screenshot-Prism', true));
  49610. //Potree.Utils.updateVisible(this.lineMesh,'screenshot-Prism',true)
  49611. this.styleRecover = null;
  49612. };
  49613. } else {
  49614. this.styleRecover && this.styleRecover();
  49615. Potree.Utils.updateVisible(this.areaPlane, 'screenshot', false, 2, 'cancel');
  49616. }
  49617. }
  49618. dispose() {
  49619. super.dispose();
  49620. this.clipBoxes.forEach(e => viewer.scene.removeVolume(e));
  49621. }
  49622. setEditState(state) {
  49623. //编辑页面or截图
  49624. state = !!state;
  49625. this.editing = state;
  49626. this.dontHighlight = !state;
  49627. this.clipBoxes.forEach(box => {
  49628. Potree.Utils.updateVisible(box, 'hidden', state), box.clip = state;
  49629. });
  49630. }
  49631. /* {
  49632. fill: [
  49633. {color: [236, 213, 143, 1], min: 0, max: 5},
  49634. {color: [223, 118, 21, 1], min: 5, max: 10},
  49635. // 没有min表示大于
  49636. {color: [186, 57, 57, 1], min: 10}
  49637. ],
  49638. dig: [
  49639. {color: [144, 193, 190, 1], min: 0, max: 5},
  49640. {color: [76, 155, 211, 1], min: 5, max: 10},
  49641. // 没有min表示大于
  49642. {color: [79, 76, 211, 1], min: 10}
  49643. ],
  49644. // 填挖并存
  49645. every: { color: [49, 200, 181, 1] }
  49646. } */
  49647. }
  49648. class MeasuringTool extends EventDispatcher {
  49649. constructor(viewer) {
  49650. super();
  49651. this.viewer = viewer;
  49652. this.renderer = viewer.renderer;
  49653. this.viewer.addEventListener('start_inserting_measurement', e => {
  49654. this.viewer.dispatchEvent({
  49655. type: 'cancel_insertions'
  49656. });
  49657. });
  49658. this.showLabels = true;
  49659. //this.scene = new THREE.Scene();
  49660. //this.scene.name = 'scene_measurement';
  49661. //this.light = new THREE.PointLight(0xffffff, 1.0);
  49662. //this.scene.add(this.light);
  49663. this.history = new History({
  49664. applyData: data => {
  49665. if (data.measure.parent && data.measure.visible) {
  49666. if (viewer.scene.measurements.indexOf(data.measure) != viewer.scene.measurements.length - 1) {
  49667. //非最新加的
  49668. if ( /* data.points.length < data.measure.minMarkers || */data.isNew) return; //不允许减少点数至minMarkers以下, 也不允许
  49669. }
  49670. data = Potree.Common.CloneObject(data); //避免使用后更改数据又被使用
  49671. data.measure.reDraw();
  49672. data.measure.initData(data);
  49673. data.measure.isNew = data.isNew;
  49674. //console.log('changeByHistory points', data.points.length)
  49675. data.measure.dispatchEvent('changeByHistory');
  49676. /* if(data.measure.isPrism){
  49677. data.measure.needsCompute = data.needsCompute
  49678. } */
  49679. data.measure.facePlane = data.facePlane && data.facePlane.clone();
  49680. data.measure.cannotConfirmNormal = data.cannotConfirmNormal;
  49681. return true;
  49682. }
  49683. },
  49684. getData: measure => {
  49685. if (measure.points.length == 0) return; //没有点的话changeByHistory报错, 得有点可以移动
  49686. var data = {
  49687. measure,
  49688. points: measure.points.map(e => e.clone()),
  49689. dataset_points: measure.dataset_points ? measure.dataset_points.map(e => e && e.clone()) : null,
  49690. points_datasets: measure.points_datasets.slice(),
  49691. datasetId: measure.datasetId,
  49692. isNew: measure.isNew,
  49693. facePlane: measure.facePlane && measure.facePlane.clone(),
  49694. cannotConfirmNormal: measure.cannotConfirmNormal
  49695. };
  49696. /* if(measure.isPrism){ //没用
  49697. data.volumeInfo = measure.volumeInfo
  49698. data.needsCompute = measure.needsCompute
  49699. //但不记录其他信息
  49700. } */
  49701. return data;
  49702. }
  49703. }),
  49704. //this.scene = viewer.overlay//
  49705. this.onRemove = e => {
  49706. e.measurement.dispose(); /* this.scene.remove(e.measurement); */
  49707. };
  49708. this.onAdd = e => {
  49709. viewer.scene.overlayScene.add(e.measurement);
  49710. };
  49711. for (var measurement of viewer.scene.measurements) {
  49712. this.onAdd({
  49713. measurement: measurement
  49714. });
  49715. }
  49716. viewer.addEventListener('camera_changed', this.update.bind(this), {
  49717. importance: 10
  49718. }); //优先级高于sprite
  49719. if (Potree.config.measure.mulLabelHideFaraway) {
  49720. viewer.addEventListener("raycaster", this.beforeDraw.bind(this), {
  49721. importance: 10
  49722. }); //before render
  49723. viewer.addEventListener("render.begin", this.beforeDraw.bind(this), {
  49724. importance: 10
  49725. }); //before render
  49726. viewer.addEventListener("render.begin2", this.beforeDraw.bind(this), {
  49727. importance: 10
  49728. });
  49729. }
  49730. //viewer.addEventListener("update", this.update.bind(this));
  49731. //viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  49732. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  49733. viewer.scene.addEventListener('measurement_added', this.onAdd);
  49734. viewer.scene.addEventListener('measurement_removed', this.onRemove);
  49735. viewer.addEventListener('resize', this.setSize.bind(this));
  49736. }
  49737. onSceneChange(e) {
  49738. if (e.oldScene) {
  49739. e.oldScene.removeEventListener('measurement_added', this.onAdd);
  49740. e.oldScene.removeEventListener('measurement_removed', this.onRemove);
  49741. }
  49742. e.scene.addEventListener('measurement_added', this.onAdd);
  49743. e.scene.addEventListener('measurement_removed', this.onRemove);
  49744. }
  49745. createMeasureFromData(data) {
  49746. //add
  49747. var measure = data.measureType == 'MulDistance Ring' ? new Prism(data) : data.type == 'Path' ? new Path$1(data) : new Measure$1(data);
  49748. if (measure.failBuilded) {
  49749. return;
  49750. }
  49751. viewer.scene.addMeasurement(measure);
  49752. data.type == 'Path' && measure.setEditEnable(false);
  49753. if (measure.guideLine) measure.guideLine.visible = false;
  49754. return measure;
  49755. }
  49756. beforeDraw(e) {
  49757. if (e.viewport.name == 'mapViewport' && !viewer.mapViewer.attachedToViewer) return; //no measures
  49758. viewer.scene.measurements.forEach(measure => {
  49759. if (measure.measureType != 'MulDistance' || (measure.isNew ? measure.points.length < 4 : measure.points.length < 3)) return;
  49760. var lastIndex = measure.points.length - 1;
  49761. for (var index = 0; index <= lastIndex; index++) {
  49762. if (!measure.closed && index == lastIndex) continue;
  49763. var edgeLabel = measure.edgeLabels[index];
  49764. var v = edgeLabel.visiMap.get(e.viewport.camera);
  49765. if (v == void 0) {
  49766. return measure.getEdgeLabelVisi(e.viewport);
  49767. }
  49768. Potree.Utils.updateVisible(edgeLabel, 'tooFar', v === false ? false : true);
  49769. }
  49770. });
  49771. }
  49772. update(e) {
  49773. /* viewer.scene.measurements.forEach(measure=>{
  49774. if(measure.measureType != 'MulDistance' || (measure.isNew ? measure.points.length<4 : measure.points.length<3)) return
  49775. }) */
  49776. if (viewer.inputHandler.measuring && Potree.settings.adsorption) {
  49777. viewer.scene.measurements.forEach(measure => {
  49778. measure.getPointsPos2d(e.viewport, true);
  49779. });
  49780. }
  49781. if (Potree.config.measure.mulLabelHideFaraway) {
  49782. if (e.changeInfo.projectionChanged || e.viewport.camera.type == 'PerspectiveCamera' && e.changeInfo.positionChanged) {
  49783. //for MulDistance
  49784. viewer.scene.measurements.forEach(measure => {
  49785. if (measure.measureType != 'MulDistance' || (measure.isNew ? measure.points.length < 4 : measure.points.length < 3)) return;
  49786. measure.getEdgeLabelVisi(e.viewport);
  49787. return;
  49788. var lastIndex = measure.points.length - 1;
  49789. for (var index = 0; index <= lastIndex; index++) {
  49790. if (!measure.closed && index == lastIndex) continue;
  49791. var nextIndex = index + 1 > lastIndex ? 0 : index + 1;
  49792. var previousIndex = index === 0 ? lastIndex : index - 1;
  49793. var point = measure.points[index];
  49794. var nextPoint = measure.points[nextIndex];
  49795. var previousPoint = measure.points[previousIndex];
  49796. var point2d = new Vector2().copy(pos2ds[index]);
  49797. var nextPoint2d = new Vector2().copy(pos2ds[nextIndex]);
  49798. if (measure.showDistances || measure.labelText) {
  49799. // edge labels
  49800. var edgeLabel = measure.edgeLabels[index];
  49801. if (edgeLabel.visible) {
  49802. measure.setEdgeLabelPos(edgeLabel, point, nextPoint);
  49803. }
  49804. }
  49805. }
  49806. });
  49807. }
  49808. }
  49809. return;
  49810. var camera = this.viewer.scene.getActiveCamera();
  49811. var domElement = this.renderer.domElement;
  49812. var measurements = this.viewer.scene.measurements;
  49813. // make size independant of distance
  49814. var mainLabels = [],
  49815. subLabels = [];
  49816. for (var measure of measurements) {
  49817. measure.lengthUnit = this.viewer.lengthUnit;
  49818. measure.lengthUnitDisplay = this.viewer.lengthUnitDisplay;
  49819. //measure.update();
  49820. updateAzimuth(this.viewer, measure);
  49821. /* [...measure.markers, ...measure.edgeLabels, measure.areaLabel].forEach(e=>{
  49822. e && e.update()
  49823. }); */
  49824. // labels
  49825. /* let labels = measure.edgeLabels.concat(measure.angleLabels);
  49826. for(let label of labels){
  49827. label.update()
  49828. if(label.elem.hasClass('sub')){
  49829. subLabels.push(label)
  49830. }else{
  49831. mainLabels.push(label)
  49832. }
  49833. }
  49834. // coordinate labels
  49835. for (let j = 0; j < measure.coordinateLabels.length; j++) {
  49836. let label = measure.coordinateLabels[j];
  49837. label.update()
  49838. mainLabels.push(label)
  49839. }
  49840. if(measure.showArea){ // area label
  49841. let label = measure.areaLabel;
  49842. label.update()
  49843. mainLabels.push(label)
  49844. } */
  49845. /* if(measure.showCircle){ // radius label
  49846. let label = measure.circleRadiusLabel;
  49847. let distance = label.position.distanceTo(camera.position);
  49848. let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  49849. let scale = (70 / pr);
  49850. label.scale.set(scale, scale, scale);
  49851. } */
  49852. if (!this.showLabels) {
  49853. var labels = [...measure.sphereLabels, ...measure.angleLabels, measure.circleRadiusLabel];
  49854. for (var label of labels) {
  49855. label.visible = false;
  49856. }
  49857. }
  49858. }
  49859. //this.updateLabelZIndex([{labels:subLabels},{labels:mainLabels}])
  49860. }
  49861. setSize(e) {//e.resolution
  49862. /* if(Measure.lineMats){
  49863. for(var m in Measure.lineMats){
  49864. Measure.lineMats[m].resolution.set(e.canvasWidth, e.canvasHeight);
  49865. }
  49866. }
  49867. if(Measure.sphereMats){
  49868. for(var s in Measure.sphereMats){
  49869. Measure.sphereMats[s].uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
  49870. }
  49871. }
  49872. for (let measure of this.viewer.scene.measurements) {
  49873. measure.edgeLabels.concat(measure.areaLabel).forEach(label=>{
  49874. label.sprite.material.uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
  49875. })
  49876. } */
  49877. }
  49878. updateLabelZIndex(group) {
  49879. //[{labels:[]},{}] 顺序按照z-index低到高
  49880. group.forEach((e, i) => {
  49881. e.base = group[i - 1] ? group[i - 1].base + group[i - 1].labels.length : 0;
  49882. var labels = e.labels.sort((a, b) => {
  49883. return b.pos2d.z - a.pos2d.z;
  49884. });
  49885. labels.forEach((label, index) => {
  49886. $(label.elem).css('z-index', e.base + index);
  49887. });
  49888. });
  49889. }
  49890. changeEditMode(mode) {
  49891. viewer.dispatchEvent({
  49892. type: "CursorChange",
  49893. action: "remove",
  49894. name: "addPoint"
  49895. });
  49896. viewer.dispatchEvent({
  49897. type: "CursorChange",
  49898. action: "remove",
  49899. name: "delPoint"
  49900. });
  49901. if (mode) {
  49902. if (mode == 'addPoint') {
  49903. viewer.dispatchEvent({
  49904. type: "CursorChange",
  49905. action: "add",
  49906. name: "addPoint"
  49907. });
  49908. } else {
  49909. viewer.dispatchEvent({
  49910. type: "CursorChange",
  49911. action: "add",
  49912. name: "delPoint"
  49913. });
  49914. }
  49915. }
  49916. this.editMode = mode;
  49917. }
  49918. editStateChange(e) {
  49919. //console.log("editStateChange" , e.state)
  49920. var state = e.state;
  49921. if (!state) {
  49922. state = viewer.scene.measurements.some(e => e.isEditing);
  49923. }
  49924. if (state) {
  49925. viewer.dispatchEvent({
  49926. type: "measureMovePoint"
  49927. }); //重新激活reticule状态
  49928. } else {
  49929. viewer.dispatchEvent({
  49930. type: "endMeasureMove"
  49931. });
  49932. }
  49933. //this.editing =
  49934. }
  49935. startInsertion() {
  49936. var _this = this;
  49937. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  49938. var callback = arguments.length > 1 ? arguments[1] : undefined;
  49939. var cancelFun = arguments.length > 2 ? arguments[2] : undefined;
  49940. var measure;
  49941. var domElement = this.viewer.renderer.domElement;
  49942. if (args.resume) {
  49943. measure = args.measure;
  49944. args.minMarkers = measure.minMarkers;
  49945. } else {
  49946. measure = args.measureType == 'MulDistance Ring' ? new Prism(args) : args.type == 'Path' ? new Path$1(args) : new Measure$1(args);
  49947. viewer.scene.overlayScene.add(measure);
  49948. }
  49949. measure.isNew = true;
  49950. this.viewer.dispatchEvent({
  49951. type: 'start_inserting_measurement',
  49952. measure: measure
  49953. });
  49954. measure.addEventListener('editStateChange', this.editStateChange.bind(this));
  49955. measure.editStateChange(true);
  49956. var timer;
  49957. this.isAdding = true;
  49958. var endDragFun = e => {
  49959. var length = measure.points.length;
  49960. if (e.button == MOUSE.LEFT || e.isTouch) {
  49961. if (length >= measure.maxMarkers) {
  49962. _end({
  49963. finish: true
  49964. });
  49965. } else {
  49966. this.history.beforeChange(measure);
  49967. var marker = measure.cloneMarker(length - 1, length);
  49968. if (args.isRect && measure.markers.length == 3) {
  49969. //marker全可见
  49970. measure.cloneMarker(0, 3);
  49971. } else {
  49972. Potree.Utils.updateVisible(measure.markers[length], 'adding', false);
  49973. measure instanceof Path$1 || (measure.edges[length].visible = false);
  49974. }
  49975. measure instanceof Path$1 || (measure.edges[length - 1].visible = true);
  49976. Potree.Utils.updateVisible(measure.markers[length - 1], 'adding', true);
  49977. marker.isDragging = true;
  49978. this.history.afterChange(measure);
  49979. measure.continueDrag(marker, e);
  49980. }
  49981. } else if (e.button === MOUSE.RIGHT) {
  49982. //触屏怎么取消?
  49983. if (e.pressDistance < Potree.config.clickMaxDragDis) {
  49984. //非拖拽的话
  49985. var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d.slice(0, measure.point2dInfo.points2d.length - 1)); //检测除了最后一个点的相交情况
  49986. if (!isIntersectSelf) _end(e);else measure.continueDrag(null, e);
  49987. } else measure.continueDrag(null, e);
  49988. }
  49989. };
  49990. var _end = function end() {
  49991. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  49992. //确定、结束
  49993. if (!measure.isNew) return;
  49994. if (args.minMarkers != void 0) {
  49995. if (!e.finish && measure.markers.length <= args.minMarkers) {
  49996. //右键 当个数不够时取消
  49997. //this.viewer.scene.removeMeasurement(measure)
  49998. //重新开始画
  49999. if (measure.markers.length > 0) {
  50000. measure.markers[0].removeEventListener('mousedown', _end);
  50001. measure.reDraw();
  50002. _this.viewer.addEventListener('global_click', click, {
  50003. importance: 10
  50004. });
  50005. measure.editStateChange(true);
  50006. }
  50007. return;
  50008. /* if(!Potree.settings.isOfficial) this.viewer.scene.removeMeasurement(measure)
  50009. else if(e.drag){ //正式版本不允许右键退出, 继续
  50010. continueDrag(e.drag.object)
  50011. measure.editStateChange(true)
  50012. return
  50013. } */
  50014. }
  50015. }
  50016. var lastMarker = measure.markers[measure.markers.length - 1];
  50017. if ( /* !e.finish&& */measure.markers.length > args.minMarkers) {
  50018. measure.removeMarker(measure.points.length - 1);
  50019. measure.markers[0].removeEventListener('mouseover', mouseover);
  50020. measure.markers[0].removeEventListener('mouseleave', mouseleave);
  50021. measure.markers[0].removeEventListener('click' /* 'mousedown' */, Exit);
  50022. if (e.byClickMarker && measure.markers.length > args.minMarkers) {
  50023. //通过点击第一个marker而结束的话,会多一个marker。但点击marker后可能会因为和它坐标一致而没有添加成功,就不删,根据添加的时间来判断。
  50024. var delta = Date.now() - lastMarker.createTime;
  50025. //console.log('delta',delta)
  50026. if (delta < 10) {
  50027. //刚生成的,说明点击后新增了一个marker
  50028. measure.removeMarker(measure.points.length - 1);
  50029. }
  50030. }
  50031. } else {
  50032. //仅两个点的
  50033. _this.history.beforeChange(measure);
  50034. _this.history.afterChange(measure);
  50035. }
  50036. measure.isNew = false;
  50037. var length = measure.points.length;
  50038. if (length) {
  50039. Potree.Utils.updateVisible(measure.markers[length - 1], 'adding', true);
  50040. if (!(measure instanceof Path$1)) {
  50041. measure.edges[length - 1].visible = !!measure.closed;
  50042. measure.edges.forEach(edge => {
  50043. edge.dispatchEvent('addHoverEvent');
  50044. });
  50045. } else {
  50046. measure.edge.dispatchEvent('addHoverEvent');
  50047. }
  50048. measure.markers.forEach(marker => {
  50049. marker.dispatchEvent('addHoverEvent');
  50050. });
  50051. measure.update(); //update last edgeLabel
  50052. }
  50053. clearTimeout(timer);
  50054. _this.viewer.removeEventListener('cancel_insertions', Exit);
  50055. //pressExit && this.viewer.inputHandler.removeEventListener('keydown', pressExit);
  50056. _this.viewer.removeEventListener('global_click', click);
  50057. _this.viewer.removeEventListener('global_mousemove', ifAtWrongPlace);
  50058. viewer.dispatchEvent({
  50059. type: "CursorChange",
  50060. action: "remove",
  50061. name: "polygon_AtWrongPlace"
  50062. });
  50063. viewer.inputHandler.dispatchEvent({
  50064. type: 'measuring',
  50065. v: false,
  50066. cause: 'stopInsertion',
  50067. situation: 'adding',
  50068. object: measure
  50069. });
  50070. //var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d.slice(0,measure.point2dInfo.points2d.length-1))//检测除了最后一个点的相交情况
  50071. var isIntersectSelf = measure.atPlane && measure.closed && !measure.isRect && measure.point2dInfo && measure.intersectSelf(measure.point2dInfo.points2d);
  50072. if (isIntersectSelf) return cancelFun && cancelFun(); //请求删除,不重建
  50073. e.remove || callback && callback();
  50074. /* this.viewer.dispatchEvent({
  50075. type: 'finish_inserting_measurement',
  50076. measure: measure
  50077. }); */
  50078. _this.isAdding = false;
  50079. measure.dispatchEvent('createDone');
  50080. };
  50081. measure.addEventListener('finish', _end); //完成
  50082. var Exit = e => {
  50083. //强制退出
  50084. if (e.measure && e.measure != measure || !viewer.scene.measurements.includes(measure) || !measure.isNew) {
  50085. return; //若指定了退出的measure但和该measure不一致,就返回
  50086. }
  50087. measure.editStateChange(false);
  50088. measure.cannotConfirmNormal = false; //一些dropMarker中的句子
  50089. measure.guideLine && (measure.guideLine.visible = false);
  50090. /*
  50091. if(this.viewer.inputHandler.drag && !e.remove ){//还未触发drop的话
  50092. this.viewer.inputHandler.drag.object.dispatchEvent({ //这句会导致又增一个marker
  50093. type: 'drop',
  50094. drag: this.viewer.inputHandler.drag,
  50095. viewer: this.viewer,
  50096. pressDistance:0,
  50097. button : THREE.MOUSE.RIGHT
  50098. });
  50099. } else {*/ //未结束时添加新的measure时会触发
  50100. _end({
  50101. finish: true,
  50102. remove: e.remove,
  50103. byClickMarker: e.type == 'click'
  50104. });
  50105. //}
  50106. this.viewer.inputHandler.drag && (this.viewer.inputHandler.drag.object = null);
  50107. };
  50108. this.viewer.addEventListener('cancel_insertions', Exit);
  50109. /*let pressExit
  50110. if(!Potree.settings.isOfficial){
  50111. pressExit = (e)=>{
  50112. if(e.keyCode == 27){//Esc
  50113. //Exit()
  50114. //怎么模拟右键???//现由前端发出
  50115. }
  50116. }
  50117. this.viewer.inputHandler.addEventListener('keydown', pressExit)
  50118. } */
  50119. var mouseover = e => {
  50120. measure.setMarkerSelected(e.object, 'hover', 'single');
  50121. };
  50122. var mouseleave = e => {
  50123. measure.setMarkerSelected(e.object, 'unhover', 'single');
  50124. };
  50125. var click = e => {
  50126. //一旦点击就立刻增加两marker
  50127. if (ifAtWrongPlace(e)) return;
  50128. if (e.clickElement) return; //如点击label时focusOnObject
  50129. if (e.button === MOUSE.RIGHT) return;
  50130. //console.log('measure clicked33', !!e.intersectPoint)
  50131. var I = e.intersect && (e.intersect.orthoIntersect || e.intersect.location);
  50132. if (!I) {
  50133. if (measure.zPlaneWhenNoIntersect != void 0) {
  50134. var {
  50135. x,
  50136. y
  50137. } = Potree.Utils.getPointerPosAtHeight(measure.zPlaneWhenNoIntersect, e.pointer);
  50138. I = new Vector3(x, y, measure.zPlaneWhenNoIntersect);
  50139. } else {
  50140. return measure.dispatchEvent('intersectNoPointcloud');
  50141. }
  50142. }
  50143. var atMap = e.drag.dragViewport.name == 'mapViewport';
  50144. //在地图上测量的首个点按楼层高度(暂时先只按mainViewport相机高度吧,但navvis是按楼层,画在楼层的地面上,可能因为平面图显示的是楼层近地面),
  50145. if (atMap) {
  50146. I = I.clone().setZ(viewer.mainViewport.camera.position.z);
  50147. }
  50148. var marker = measure.addMarker({
  50149. point: I
  50150. });
  50151. marker.isDragging = true;
  50152. this.viewer.inputHandler.startDragging(marker, {
  50153. endDragFun,
  50154. notPressMouse: true
  50155. }); //notPressMouse代表不是通过按下鼠标来拖拽
  50156. e.drag = this.viewer.inputHandler.drag;
  50157. /* e.drag.endDragFun = endDragFun
  50158. e.drag.notPressMouse = true */
  50159. //if(!measure.dragMarker(e) || !measure.dropMarker(e))return
  50160. measure.dragMarker(e);
  50161. measure.dropMarker(e);
  50162. if (measure.maxMarkers > 1) {
  50163. Potree.Utils.updateVisible(measure.markers[1], 'adding', false);
  50164. measure instanceof Path$1 || (measure.edges[1].visible = false);
  50165. }
  50166. if (measure.closed && !measure.isRect) {
  50167. measure.markers[0].addEventListener('mouseover', mouseover);
  50168. measure.markers[0].addEventListener('mouseleave', mouseleave);
  50169. measure.markers[0].addEventListener('click' /* 'mousedown' */, Exit); //点击到第一个marker就结束
  50170. }
  50171. this.viewer.removeEventListener('global_click', click); ///* global_drop */
  50172. //console.log('measure clicked')
  50173. e.consume && e.consume();
  50174. return {
  50175. stopContinue: true
  50176. }; //防止继续执行别的侦听,如flytopano
  50177. };
  50178. //点击第n下拥有n+1个marker, n>0
  50179. viewer.inputHandler.dispatchEvent({
  50180. type: 'measuring',
  50181. v: true,
  50182. cause: 'startInsertion',
  50183. situation: 'adding',
  50184. object: measure
  50185. });
  50186. this.viewer.addEventListener('global_click', click, {
  50187. importance: 10
  50188. }); //add importance
  50189. var ifAtWrongPlace = e => {
  50190. if (measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport') {
  50191. if (e.isTouch) {
  50192. viewer.dispatchEvent({
  50193. type: 'reticule_forbit',
  50194. v: true
  50195. });
  50196. } else {
  50197. viewer.dispatchEvent({
  50198. type: "CursorChange",
  50199. action: "add",
  50200. name: "polygon_AtWrongPlace"
  50201. });
  50202. }
  50203. return true;
  50204. } else {
  50205. if (e.isTouch) {
  50206. viewer.dispatchEvent({
  50207. type: 'reticule_forbit',
  50208. v: false
  50209. });
  50210. } else {
  50211. viewer.dispatchEvent({
  50212. type: "CursorChange",
  50213. action: "remove",
  50214. name: "polygon_AtWrongPlace"
  50215. });
  50216. }
  50217. }
  50218. };
  50219. if (measure.unableDragAtMap) {
  50220. this.viewer.addEventListener('global_mousemove', ifAtWrongPlace);
  50221. }
  50222. var changeByHistory = e => {
  50223. if (!measure.isNew) return;
  50224. var marker = measure.markers[measure.points.length - 1];
  50225. this.viewer.inputHandler.startDragging(marker, {
  50226. endDragFun,
  50227. notPressMouse: true
  50228. });
  50229. Potree.Utils.updateVisible(marker, 'adding', false);
  50230. var I = viewer.inputHandler.intersect && (viewer.inputHandler.intersect.orthoIntersect || viewer.inputHandler.intersect.location);
  50231. if (I) {
  50232. measure.dragChange(I.clone(), measure.points.length - 1); //使最后一个点在鼠标处
  50233. }
  50234. args.isRect || measure instanceof Path$1 || (measure.edges[measure.points.length - 1].visible = false);
  50235. //measure.continueDrag(measure.markers[measure.points.length-1], o )
  50236. };
  50237. measure.addEventListener('changeByHistory', changeByHistory);
  50238. args.resume || this.viewer.scene.addMeasurement(measure);
  50239. return measure;
  50240. }
  50241. render() {
  50242. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  50243. //废弃
  50244. if (this.scene.children.filter(e => e.visible).length == 0) return;
  50245. var renderer = o.renderer || this.viewer.renderer;
  50246. Potree.Utils.setCameraLayers(o.camera, ['sceneObjects']);
  50247. /* if(o.screenshot && this.viewer.fxaaPass.enabled){ //抗锯齿
  50248. this.viewer.ssaaRenderPass.sampleLevel = 4
  50249. this.viewer.composer.render(this.scene, o.camera );
  50250. }else{ */
  50251. viewer.dispatchEvent({
  50252. type: "render.begin2",
  50253. name: 'measure',
  50254. viewport: o.viewport,
  50255. renderer: o.renderer
  50256. });
  50257. renderer.render(this.scene, o.camera);
  50258. //}
  50259. }
  50260. }
  50261. ;
  50262. function updateAzimuth(viewer, measure) {
  50263. if (!measure.showAzimuth) return;
  50264. var azimuth = measure.azimuth;
  50265. var isOkay = measure.points.length === 2;
  50266. azimuth.node.visible = isOkay;
  50267. if (!azimuth.node.visible) {
  50268. return;
  50269. }
  50270. var camera = viewer.scene.getActiveCamera();
  50271. var renderAreaSize = viewer.renderer.getSize(new Vector2());
  50272. var width = renderAreaSize.width;
  50273. var height = renderAreaSize.height;
  50274. var [p0, p1] = measure.points;
  50275. var r = p0.position.distanceTo(p1.position);
  50276. var northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
  50277. var northPos = p0.position.clone().add(northVec);
  50278. azimuth.center.position.copy(p0.position);
  50279. azimuth.center.scale.set(2, 2, 2);
  50280. azimuth.center.visible = false;
  50281. // azimuth.target.visible = false;
  50282. {
  50283. // north
  50284. azimuth.north.position.copy(northPos);
  50285. azimuth.north.scale.set(2, 2, 2);
  50286. var _distance = azimuth.north.position.distanceTo(camera.position);
  50287. var _pr = Utils.projectedRadius(1, camera, _distance, width, height);
  50288. var _scale = 5 / _pr;
  50289. azimuth.north.scale.set(_scale, _scale, _scale);
  50290. }
  50291. {
  50292. // target
  50293. azimuth.target.position.copy(p1.position);
  50294. azimuth.target.position.z = azimuth.north.position.z;
  50295. var _distance2 = azimuth.target.position.distanceTo(camera.position);
  50296. var _pr2 = Utils.projectedRadius(1, camera, _distance2, width, height);
  50297. var _scale2 = 5 / _pr2;
  50298. azimuth.target.scale.set(_scale2, _scale2, _scale2);
  50299. }
  50300. azimuth.circle.position.copy(p0.position);
  50301. azimuth.circle.scale.set(r, r, r);
  50302. azimuth.circle.material.resolution.set(width, height);
  50303. // to target
  50304. azimuth.centerToTarget.geometry.setPositions([0, 0, 0, ...p1.position.clone().sub(p0.position).toArray()]);
  50305. azimuth.centerToTarget.position.copy(p0.position);
  50306. azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
  50307. azimuth.centerToTarget.geometry.computeBoundingSphere();
  50308. azimuth.centerToTarget.computeLineDistances();
  50309. azimuth.centerToTarget.material.resolution.set(width, height);
  50310. // to target ground
  50311. azimuth.centerToTargetground.geometry.setPositions([0, 0, 0, p1.position.x - p0.position.x, p1.position.y - p0.position.y, 0]);
  50312. azimuth.centerToTargetground.position.copy(p0.position);
  50313. azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
  50314. azimuth.centerToTargetground.geometry.computeBoundingSphere();
  50315. azimuth.centerToTargetground.computeLineDistances();
  50316. azimuth.centerToTargetground.material.resolution.set(width, height);
  50317. // to north
  50318. azimuth.centerToNorth.geometry.setPositions([0, 0, 0, northPos.x - p0.position.x, northPos.y - p0.position.y, 0]);
  50319. azimuth.centerToNorth.position.copy(p0.position);
  50320. azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
  50321. azimuth.centerToNorth.geometry.computeBoundingSphere();
  50322. azimuth.centerToNorth.computeLineDistances();
  50323. azimuth.centerToNorth.material.resolution.set(width, height);
  50324. // label
  50325. var radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
  50326. var degrees = MathUtils.radToDeg(radians);
  50327. if (degrees < 0) {
  50328. degrees = 360 + degrees;
  50329. }
  50330. var txtDegrees = "".concat(degrees.toFixed(2), "\xB0");
  50331. var labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
  50332. if (labelDir.length() > 0) {
  50333. labelDir.z = 0;
  50334. labelDir.normalize();
  50335. var labelVec = labelDir.clone().multiplyScalar(r);
  50336. var labelPos = p0.position.clone().add(labelVec);
  50337. azimuth.label.position.copy(labelPos);
  50338. }
  50339. azimuth.label.setText(txtDegrees);
  50340. var distance = azimuth.label.position.distanceTo(camera.position);
  50341. var pr = Utils.projectedRadius(1, camera, distance, width, height);
  50342. var scale = 70 / pr;
  50343. azimuth.label.scale.set(scale, scale, scale);
  50344. }
  50345. class ProfileTool extends EventDispatcher$1 {
  50346. constructor(viewer) {
  50347. super();
  50348. this.viewer = viewer;
  50349. this.renderer = viewer.renderer;
  50350. this.addEventListener('start_inserting_profile', e => {
  50351. this.viewer.dispatchEvent({
  50352. type: 'cancel_insertions'
  50353. });
  50354. });
  50355. this.scene = new Scene();
  50356. this.scene.name = 'scene_profile';
  50357. this.light = new PointLight(0xffffff, 1.0);
  50358. this.scene.add(this.light);
  50359. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  50360. this.onRemove = e => this.scene.remove(e.profile);
  50361. this.onAdd = e => this.scene.add(e.profile);
  50362. for (var profile of viewer.scene.profiles) {
  50363. this.onAdd({
  50364. profile: profile
  50365. });
  50366. }
  50367. viewer.addEventListener("update", this.update.bind(this));
  50368. viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  50369. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  50370. viewer.scene.addEventListener('profile_added', this.onAdd);
  50371. viewer.scene.addEventListener('profile_removed', this.onRemove);
  50372. }
  50373. onSceneChange(e) {
  50374. if (e.oldScene) {
  50375. e.oldScene.removeEventListeners('profile_added', this.onAdd);
  50376. e.oldScene.removeEventListeners('profile_removed', this.onRemove);
  50377. }
  50378. e.scene.addEventListener('profile_added', this.onAdd);
  50379. e.scene.addEventListener('profile_removed', this.onRemove);
  50380. }
  50381. startInsertion() {
  50382. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  50383. var domElement = this.viewer.renderer.domElement;
  50384. var profile = new Profile();
  50385. profile.name = args.name || 'Profile';
  50386. this.dispatchEvent({
  50387. type: 'start_inserting_profile',
  50388. profile: profile
  50389. });
  50390. this.scene.add(profile);
  50391. var cancel = {
  50392. callback: null
  50393. };
  50394. var insertionCallback = e => {
  50395. if (e.button === MOUSE.LEFT) {
  50396. if (profile.points.length <= 1) {
  50397. var camera = this.viewer.scene.getActiveCamera();
  50398. var distance = camera.position.distanceTo(profile.points[0]);
  50399. var clientSize = this.viewer.renderer.getSize(new Vector2());
  50400. var pr = Utils.projectedRadius(1, camera, distance, clientSize.width, clientSize.height);
  50401. var width = 10 / pr;
  50402. profile.setWidth(width);
  50403. }
  50404. profile.addMarker(profile.points[profile.points.length - 1].clone());
  50405. this.viewer.inputHandler.startDragging(profile.spheres[profile.spheres.length - 1]);
  50406. } else if (e.button === MOUSE.RIGHT) {
  50407. cancel.callback();
  50408. }
  50409. };
  50410. cancel.callback = e => {
  50411. profile.removeMarker(profile.points.length - 1);
  50412. domElement.removeEventListener('mouseup', insertionCallback, false);
  50413. this.viewer.removeEventListener('cancel_insertions', cancel.callback);
  50414. };
  50415. this.viewer.addEventListener('cancel_insertions', cancel.callback);
  50416. domElement.addEventListener('mouseup', insertionCallback, false);
  50417. profile.addMarker(new Vector3(0, 0, 0));
  50418. this.viewer.inputHandler.startDragging(profile.spheres[profile.spheres.length - 1]);
  50419. this.viewer.scene.addProfile(profile);
  50420. return profile;
  50421. }
  50422. update() {
  50423. var camera = this.viewer.scene.getActiveCamera();
  50424. var profiles = this.viewer.scene.profiles;
  50425. var renderAreaSize = this.viewer.renderer.getSize(new Vector2());
  50426. var clientWidth = renderAreaSize.width;
  50427. var clientHeight = renderAreaSize.height;
  50428. this.light.position.copy(camera.position);
  50429. // make size independant of distance
  50430. for (var profile of profiles) {
  50431. for (var sphere of profile.spheres) {
  50432. var distance = camera.position.distanceTo(sphere.getWorldPosition(new Vector3()));
  50433. var pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
  50434. var scale = 15 / pr;
  50435. sphere.scale.set(scale, scale, scale);
  50436. }
  50437. }
  50438. }
  50439. render() {
  50440. this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  50441. }
  50442. }
  50443. class ScreenBoxSelectTool extends EventDispatcher$1 {
  50444. constructor(viewer) {
  50445. super();
  50446. this.viewer = viewer;
  50447. this.scene = new Scene();
  50448. viewer.addEventListener("update", this.update.bind(this));
  50449. viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
  50450. viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
  50451. }
  50452. onSceneChange(scene) {
  50453. console.log("scene changed");
  50454. }
  50455. startInsertion() {
  50456. var domElement = this.viewer.renderer.domElement;
  50457. var volume = new BoxVolume();
  50458. volume.position.set(12345, 12345, 12345);
  50459. volume.showVolumeLabel = false;
  50460. volume.visible = false;
  50461. volume.update();
  50462. this.viewer.scene.addVolume(volume);
  50463. this.importance = 10;
  50464. var selectionBox = $("<div style=\"position: absolute; border: 2px solid white; pointer-events: none; border-style:dashed\"></div>");
  50465. $(domElement.parentElement).append(selectionBox);
  50466. selectionBox.css("right", "10px");
  50467. selectionBox.css("bottom", "10px");
  50468. var drag = e => {
  50469. volume.visible = true;
  50470. var mStart = e.drag.start;
  50471. var mEnd = e.drag.end;
  50472. var box2D = new Box2();
  50473. box2D.expandByPoint(mStart);
  50474. box2D.expandByPoint(mEnd);
  50475. selectionBox.css("left", "".concat(box2D.min.x, "px"));
  50476. selectionBox.css("top", "".concat(box2D.min.y, "px"));
  50477. selectionBox.css("width", "".concat(box2D.max.x - box2D.min.x, "px"));
  50478. selectionBox.css("height", "".concat(box2D.max.y - box2D.min.y, "px"));
  50479. var camera = e.viewer.scene.getActiveCamera();
  50480. var size = e.viewer.renderer.getSize(new Vector2());
  50481. var frustumSize = new Vector2(camera.right - camera.left, camera.top - camera.bottom);
  50482. var screenCentroid = new Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5);
  50483. var ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height);
  50484. var diff = new Vector2().subVectors(e.drag.end, e.drag.start);
  50485. diff.divide(size).multiply(frustumSize);
  50486. volume.position.copy(ray.origin);
  50487. volume.up.copy(camera.up);
  50488. volume.rotation.copy(camera.rotation);
  50489. volume.scale.set(diff.x, diff.y, 1000 * 100);
  50490. e.consume();
  50491. };
  50492. var drop = e => {
  50493. this.importance = 0;
  50494. $(selectionBox).remove();
  50495. this.viewer.inputHandler.deselectAll();
  50496. this.viewer.inputHandler.toggleSelection(volume);
  50497. var camera = e.viewer.scene.getActiveCamera();
  50498. var size = e.viewer.renderer.getSize(new Vector2());
  50499. var screenCentroid = new Vector2().addVectors(e.drag.end, e.drag.start).multiplyScalar(0.5);
  50500. var ray = Utils.mouseToRay(screenCentroid, camera, size.width, size.height);
  50501. var line = new Line3(ray.origin, new Vector3().addVectors(ray.origin, ray.direction));
  50502. this.removeEventListener("drag", drag);
  50503. this.removeEventListener("drop", drop);
  50504. var allPointsNear = [];
  50505. var allPointsFar = [];
  50506. // TODO support more than one point cloud
  50507. for (var pointcloud of this.viewer.scene.pointclouds) {
  50508. if (!pointcloud.visible) {
  50509. continue;
  50510. }
  50511. var volCam = camera.clone();
  50512. volCam.left = -volume.scale.x / 2;
  50513. volCam.right = +volume.scale.x / 2;
  50514. volCam.top = +volume.scale.y / 2;
  50515. volCam.bottom = -volume.scale.y / 2;
  50516. volCam.near = -volume.scale.z / 2;
  50517. volCam.far = +volume.scale.z / 2;
  50518. volCam.rotation.copy(volume.rotation);
  50519. volCam.position.copy(volume.position);
  50520. volCam.updateMatrix();
  50521. volCam.updateMatrixWorld();
  50522. volCam.updateProjectionMatrix();
  50523. volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert();
  50524. var _ray = new Ray(volCam.getWorldPosition(new Vector3()), volCam.getWorldDirection(new Vector3()));
  50525. var rayInverse = new Ray(_ray.origin.clone().add(_ray.direction.clone().multiplyScalar(volume.scale.z)), _ray.direction.clone().multiplyScalar(-1));
  50526. var pickerSettings = {
  50527. width: 8,
  50528. height: 8,
  50529. pickWindowSize: 8,
  50530. all: true,
  50531. pickClipped: true,
  50532. pointSizeType: PointSizeType.FIXED,
  50533. pointSize: 1
  50534. };
  50535. var pointsNear = pointcloud.pick(viewer, volCam, _ray, pickerSettings);
  50536. volCam.rotateX(Math.PI);
  50537. volCam.updateMatrix();
  50538. volCam.updateMatrixWorld();
  50539. volCam.updateProjectionMatrix();
  50540. volCam.matrixWorldInverse.copy(volCam.matrixWorld).invert();
  50541. var pointsFar = pointcloud.pick(viewer, volCam, rayInverse, pickerSettings);
  50542. allPointsNear.push(...pointsNear);
  50543. allPointsFar.push(...pointsFar);
  50544. }
  50545. if (allPointsNear.length > 0 && allPointsFar.length > 0) {
  50546. var viewLine = new Line3(ray.origin, new Vector3().addVectors(ray.origin, ray.direction));
  50547. var closestOnLine = allPointsNear.map(p => viewLine.closestPointToPoint(p.position, false, new Vector3()));
  50548. var closest = closestOnLine.sort((a, b) => ray.origin.distanceTo(a) - ray.origin.distanceTo(b))[0];
  50549. var farthestOnLine = allPointsFar.map(p => viewLine.closestPointToPoint(p.position, false, new Vector3()));
  50550. var farthest = farthestOnLine.sort((a, b) => ray.origin.distanceTo(b) - ray.origin.distanceTo(a))[0];
  50551. var distance = closest.distanceTo(farthest);
  50552. var centroid = new Vector3().addVectors(closest, farthest).multiplyScalar(0.5);
  50553. volume.scale.z = distance * 1.1;
  50554. volume.position.copy(centroid);
  50555. }
  50556. volume.clip = true;
  50557. };
  50558. this.addEventListener("drag", drag);
  50559. this.addEventListener("drop", drop);
  50560. viewer.inputHandler.addInputListener(this);
  50561. return volume;
  50562. }
  50563. update(e) {
  50564. //console.log(e.delta)
  50565. }
  50566. render() {
  50567. this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  50568. }
  50569. }
  50570. class SpotLightHelper$1 extends Object3D {
  50571. constructor(light, color) {
  50572. super();
  50573. this.light = light;
  50574. this.color = color;
  50575. //this.up.set(0, 0, 1);
  50576. this.updateMatrix();
  50577. this.updateMatrixWorld();
  50578. {
  50579. // SPHERE
  50580. var sg = new SphereGeometry(1, 32, 32);
  50581. var sm = new MeshNormalMaterial();
  50582. this.sphere = new Mesh(sg, sm);
  50583. this.sphere.scale.set(0.5, 0.5, 0.5);
  50584. this.add(this.sphere);
  50585. }
  50586. {
  50587. // LINES
  50588. var positions = new Float32Array([+0, +0, +0, +0, +0, -1, +0, +0, +0, -1, -1, -1, +0, +0, +0, +1, -1, -1, +0, +0, +0, +1, +1, -1, +0, +0, +0, -1, +1, -1, -1, -1, -1, +1, -1, -1, +1, -1, -1, +1, +1, -1, +1, +1, -1, -1, +1, -1, -1, +1, -1, -1, -1, -1]);
  50589. var geometry = new BufferGeometry();
  50590. geometry.setAttribute("position", new BufferAttribute(positions, 3));
  50591. var material = new LineBasicMaterial();
  50592. this.frustum = new LineSegments(geometry, material);
  50593. this.add(this.frustum);
  50594. }
  50595. this.update();
  50596. }
  50597. update() {
  50598. this.light.updateMatrix();
  50599. this.light.updateMatrixWorld();
  50600. var position = this.light.position;
  50601. var target = new Vector3().addVectors(this.light.position, this.light.getWorldDirection(new Vector3()).multiplyScalar(-1));
  50602. var quat = new Quaternion().setFromRotationMatrix(new Matrix4().lookAt(position, target, new Vector3(0, 0, 1)));
  50603. this.setRotationFromQuaternion(quat);
  50604. this.position.copy(position);
  50605. var coneLength = this.light.distance > 0 ? this.light.distance : 1000;
  50606. var coneWidth = coneLength * Math.tan(this.light.angle * 0.5);
  50607. this.frustum.scale.set(coneWidth, coneWidth, coneLength);
  50608. }
  50609. }
  50610. //问题:如何转换到世界坐标?(缩放方向有bug。)
  50611. //add-------------------------------------
  50612. var OpaWhenNotSelect = 0.6;
  50613. var ScaleRatio = 3;
  50614. var OutlineColor = 0x666666;
  50615. //----------------------------------------
  50616. var hideFocusHandles = true; //add
  50617. class TransformationTool extends EventDispatcher {
  50618. constructor(viewer) {
  50619. super();
  50620. this.viewer = viewer;
  50621. this.modesEnabled = {}; //add
  50622. this.style = 'singleMode'; //建mesh时按照singleModes建的
  50623. this.scene = new Scene();
  50624. this.selection = [];
  50625. this.pivot = new Vector3();
  50626. this.dragging = false;
  50627. this.showPickVolumes = false;
  50628. this.viewer.inputHandler.registerInteractiveScene(this.scene);
  50629. this.viewer.inputHandler.addEventListener('selection_changed', e => {
  50630. /* for(let selected of this.selection){ //若不删除,应该会穿过选中的物体选到别的而不是取消选择
  50631. this.viewer.inputHandler.blacklist.delete(selected);
  50632. } */
  50633. this.selection = e.selection;
  50634. /* for(let selected of this.selection){
  50635. this.viewer.inputHandler.blacklist.add(selected);
  50636. } */
  50637. });
  50638. this.viewer.addEventListener('global_touchstart', e => {
  50639. //add
  50640. this.update();
  50641. });
  50642. this.viewer.addEventListener('global_mousemove', e => {
  50643. //add
  50644. this.onPointerMove();
  50645. });
  50646. var red = Potree.config.axis.x.color;
  50647. var green = Potree.config.axis.y.color;
  50648. var blue = Potree.config.axis.z.color;
  50649. var white = Potree.config.axis.xyz.color;
  50650. this.activeHandle = null;
  50651. this.scaleHandles = {
  50652. "scale.x+": {
  50653. name: "scale.x+",
  50654. node: new Object3D(),
  50655. color: red,
  50656. alignment: [+1, +0, +0]
  50657. },
  50658. "scale.x-": {
  50659. name: "scale.x-",
  50660. node: new Object3D(),
  50661. color: red,
  50662. alignment: [-1, +0, +0]
  50663. },
  50664. "scale.y+": {
  50665. name: "scale.y+",
  50666. node: new Object3D(),
  50667. color: green,
  50668. alignment: [+0, +1, +0]
  50669. },
  50670. "scale.y-": {
  50671. name: "scale.y-",
  50672. node: new Object3D(),
  50673. color: green,
  50674. alignment: [+0, -1, +0]
  50675. },
  50676. "scale.z+": {
  50677. name: "scale.z+",
  50678. node: new Object3D(),
  50679. color: blue,
  50680. alignment: [+0, +0, +1]
  50681. },
  50682. "scale.z-": {
  50683. name: "scale.z-",
  50684. node: new Object3D(),
  50685. color: blue,
  50686. alignment: [+0, +0, -1]
  50687. },
  50688. "lines": {
  50689. name: 'lines',
  50690. node: new Object3D(),
  50691. dontScale: true
  50692. } //add
  50693. };
  50694. this.focusHandles = {
  50695. "focus.x+": {
  50696. name: "focus.x+",
  50697. node: new Object3D(),
  50698. color: red,
  50699. alignment: [+1, +0, +0]
  50700. },
  50701. "focus.x-": {
  50702. name: "focus.x-",
  50703. node: new Object3D(),
  50704. color: red,
  50705. alignment: [-1, +0, +0]
  50706. },
  50707. "focus.y+": {
  50708. name: "focus.y+",
  50709. node: new Object3D(),
  50710. color: green,
  50711. alignment: [+0, +1, +0]
  50712. },
  50713. "focus.y-": {
  50714. name: "focus.y-",
  50715. node: new Object3D(),
  50716. color: green,
  50717. alignment: [+0, -1, +0]
  50718. },
  50719. "focus.z+": {
  50720. name: "focus.z+",
  50721. node: new Object3D(),
  50722. color: blue,
  50723. alignment: [+0, +0, +1]
  50724. },
  50725. "focus.z-": {
  50726. name: "focus.z-",
  50727. node: new Object3D(),
  50728. color: blue,
  50729. alignment: [+0, +0, -1]
  50730. }
  50731. };
  50732. this.translationHandles = {
  50733. "translation.x": {
  50734. name: "translation.x",
  50735. node: new Object3D(),
  50736. color: red,
  50737. alignment: [1, 0, 0]
  50738. },
  50739. "translation.y": {
  50740. name: "translation.y",
  50741. node: new Object3D(),
  50742. color: green,
  50743. alignment: [0, 1, 0]
  50744. },
  50745. "translation.z": {
  50746. name: "translation.z",
  50747. node: new Object3D(),
  50748. color: blue,
  50749. alignment: [0, 0, 1]
  50750. },
  50751. //add
  50752. 'translation.xyz': {
  50753. name: "translation.xyz",
  50754. node: new Object3D(),
  50755. color: white,
  50756. alignment: [0, 0, 0],
  50757. alignment2: [1, 1, 1]
  50758. },
  50759. 'translation.plane.xy': {
  50760. name: "translation.plane.xy",
  50761. node: new Object3D(),
  50762. color: blue,
  50763. alignment: [0, 0, 1],
  50764. alignment2: [1, 1, 0]
  50765. },
  50766. 'translation.plane.yz': {
  50767. name: "translation.plane.yz",
  50768. node: new Object3D(),
  50769. color: red,
  50770. alignment: [1, 0, 0],
  50771. alignment2: [0, 1, 1]
  50772. },
  50773. 'translation.plane.xz': {
  50774. name: "translation.plane.xz",
  50775. node: new Object3D(),
  50776. color: green,
  50777. alignment: [0, 1, 0],
  50778. alignment2: [1, 0, 1]
  50779. }
  50780. };
  50781. this.rotationHandles = {
  50782. "rotation.x": {
  50783. name: "rotation.x",
  50784. node: new Object3D(),
  50785. color: red,
  50786. alignment: [1, 0, 0]
  50787. },
  50788. "rotation.y": {
  50789. name: "rotation.y",
  50790. node: new Object3D(),
  50791. color: green,
  50792. alignment: [0, 1, 0]
  50793. },
  50794. "rotation.z": {
  50795. name: "rotation.z",
  50796. node: new Object3D(),
  50797. color: blue,
  50798. alignment: [0, 0, 1]
  50799. }
  50800. };
  50801. this.handles = Object.assign({}, this.scaleHandles, hideFocusHandles ? {} : this.focusHandles, this.translationHandles, this.rotationHandles);
  50802. this.pickVolumes = [];
  50803. this.initializeScaleHandles();
  50804. this.initializeFocusHandles();
  50805. this.initializeTranslationHandles();
  50806. this.initializeRotationHandles();
  50807. var boxFrameGeometry = new Geometry();
  50808. {
  50809. // bottom
  50810. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  50811. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  50812. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  50813. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  50814. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  50815. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  50816. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  50817. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  50818. // top
  50819. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  50820. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  50821. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  50822. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  50823. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  50824. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  50825. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  50826. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  50827. // sides
  50828. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, 0.5));
  50829. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, 0.5));
  50830. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, 0.5));
  50831. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, 0.5));
  50832. boxFrameGeometry.vertices.push(new Vector3(0.5, -0.5, -0.5));
  50833. boxFrameGeometry.vertices.push(new Vector3(0.5, 0.5, -0.5));
  50834. boxFrameGeometry.vertices.push(new Vector3(-0.5, -0.5, -0.5));
  50835. boxFrameGeometry.vertices.push(new Vector3(-0.5, 0.5, -0.5));
  50836. }
  50837. this.frame = new LineSegments(boxFrameGeometry, new LineBasicMaterial({
  50838. color: 0xffff00
  50839. }));
  50840. this.scene.add(this.frame);
  50841. //------------------add-----------------------
  50842. this.setModeEnable(['scale', 'translation', 'rotation']);
  50843. Potree.Utils.setObjectLayers(this.scene, 'transformationTool');
  50844. this.scene.traverse(e => {
  50845. e.pickDontCheckDis = true; //pick时不需要识别是否在点云之上
  50846. });
  50847. {
  50848. var exist = object => {
  50849. //是否没被删除(暂时不考虑换了parent)
  50850. while (object.parent) {
  50851. object = object.parent;
  50852. }
  50853. if (object instanceof Scene) {
  50854. return true;
  50855. }
  50856. };
  50857. this.history = new History({
  50858. //也可以写到全局,但需要加个判断物品是否存在的函数
  50859. applyData: data => {
  50860. if (exist(data.object)) {
  50861. //viewer.scene.volumes.includes(data.box) //或许还要识别是否matrixAuto
  50862. data.matrix.decompose(data.object.position, data.object.quaternion, data.object.scale);
  50863. this.dispatchEvent('changeByHistory');
  50864. viewer.dispatchEvent('content_changed');
  50865. return true;
  50866. }
  50867. },
  50868. getData: data => {
  50869. return data;
  50870. }
  50871. });
  50872. this.addEventListener('transformed', e => {
  50873. var object = viewer.transformationTool.selection[0];
  50874. this.history.beforeChange({
  50875. object,
  50876. matrix: e.matrixBefore.clone()
  50877. });
  50878. this.viewer.dispatchEvent('content_changed');
  50879. });
  50880. this.addEventListener('stopDrag', e => {
  50881. var object = viewer.transformationTool.selection[0];
  50882. object && this.history.afterChange({
  50883. object,
  50884. matrix: object.matrix.clone()
  50885. });
  50886. });
  50887. /* viewer.inputHandler.addEventListener('keydown', (e)=>{
  50888. if(e.keyCode == 90 && e.event.ctrlKey){//Z
  50889. this.history.undo()
  50890. }else if(e.keyCode == 89 && e.event.ctrlKey){//Y
  50891. this.history.redo()
  50892. }
  50893. }) */
  50894. }
  50895. }
  50896. setModeEnable() {
  50897. var enableModes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  50898. //xzw add
  50899. var length = 0;
  50900. ['translation', 'scale', 'rotation'].forEach(mode => {
  50901. var handels = this[mode + 'Handles'];
  50902. var enable = enableModes.includes(mode);
  50903. for (var o in handels) {
  50904. Potree.Utils.updateVisible(handels[o].node, 'modeForce', !!enable);
  50905. }
  50906. this.modesEnabled[mode] = !!enable;
  50907. enable && length++;
  50908. });
  50909. if (this.style == 'singleMode' && length > 1) {
  50910. this.changeStyle('mixedModes');
  50911. } else if (this.style == 'mixedModes' && length == 1) {
  50912. this.changeStyle('singleMode');
  50913. }
  50914. }
  50915. changeStyle(style) {
  50916. // 切换单个mode & 多个mode混合 风格(因多个混合比较拥挤,需要做调整)
  50917. var s1 = style == 'singleMode' ? 30 : 25;
  50918. var s2 = style == 'singleMode' ? 15 : 10;
  50919. ['x', 'y', 'z'].forEach(axis => {
  50920. this.translationHandles['translation.' + axis].node.children.forEach(mesh => {
  50921. if (mesh.name.includes('arrow')) {
  50922. Potree.Utils.updateVisible(mesh, 'modeStyle', style == 'singleMode');
  50923. } else if (mesh.name.includes('handle')) {
  50924. mesh.material.lineWidth = style == 'singleMode' ? 5 : 7;
  50925. }
  50926. });
  50927. this.rotationHandles['rotation.' + axis].translateNode.scale.set(s1, s1, s1);
  50928. });
  50929. ['xy', 'yz', 'xz'].forEach(axis => {
  50930. var handle = this.translationHandles['translation.plane.' + axis];
  50931. handle.node.children[0].scale.set(s2, s2, s2);
  50932. handle.node.children[0].position.fromArray(handle.alignment2).multiplyScalar(s2 * 1.5);
  50933. });
  50934. Potree.Utils.updateVisible(this.scaleHandles['lines'].node, 'modeStyle', style == 'singleMode');
  50935. this.style = style;
  50936. }
  50937. initializeTranslationHandles() {
  50938. var _this = this;
  50939. //大改
  50940. var boxGeometry = new BoxGeometry(1, 1, 1);
  50941. var length = 100,
  50942. arrowRadius = 4,
  50943. arrowHeight = 10;
  50944. var arrowGeometry = new CylinderBufferGeometry(0, arrowRadius, arrowHeight, 12, 1, false); //add 箭头朝(0,1,0)
  50945. var arrowInitialQua = new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); //先将qua旋转到朝向0,0,-1, 因为一般quaternion不设置时默认表示朝向0,0,-1,
  50946. var octahedronGeometry = new OctahedronBufferGeometry(5, 0);
  50947. var planeGeometry = new PlaneBufferGeometry(1, 1);
  50948. var _loop = function _loop(handleName) {
  50949. var handle = _this.handles[handleName];
  50950. var node = handle.node;
  50951. _this.scene.add(node);
  50952. node.name = handleName; //add
  50953. var alignment = new Vector3(...handle.alignment);
  50954. var geometry,
  50955. mesh,
  50956. pickVolume,
  50957. meshScale,
  50958. pickScale,
  50959. rotation,
  50960. position,
  50961. lookAtPoint,
  50962. hasPick = true,
  50963. meshPickable = false,
  50964. renderOrder;
  50965. var matProp = {
  50966. color: handle.color,
  50967. opacity: OpaWhenNotSelect,
  50968. transparent: true,
  50969. side: handleName.includes('plane') ? DoubleSide : FrontSide
  50970. };
  50971. var material = new MeshBasicMaterial(matProp);
  50972. var pickMaterial = new MeshNormalMaterial({
  50973. opacity: 0.2,
  50974. transparent: true,
  50975. visible: _this.showPickVolumes
  50976. });
  50977. if (handleName.includes('xyz')) {
  50978. geometry = octahedronGeometry;
  50979. meshPickable = true;
  50980. renderOrder = 12;
  50981. } else if (handleName.includes('plane')) {
  50982. geometry = planeGeometry;
  50983. meshPickable = true;
  50984. position = new Vector3(...handle.alignment2);
  50985. lookAtPoint = alignment;
  50986. if (handleName.includes('xy')) {} else if (handleName.includes('yz')) {} else if (handleName.includes('xz')) {}
  50987. } else {
  50988. geometry = boxGeometry;
  50989. var point = new Vector3(0, 0, length / 2); //new THREE.Vector3().copy(alignment).multiplyScalar(length/2)
  50990. mesh = LineDraw.createFatLine([point, point.clone().negate()], {
  50991. lineWidth: 6,
  50992. mat: new LineDraw.createFatLineMat(matProp)
  50993. });
  50994. lookAtPoint = alignment;
  50995. renderOrder = 10;
  50996. pickScale = new Vector3(4, 4, length + arrowHeight * 2); //pickScale = new THREE.Vector3(4, 4, 1.2)
  50997. {
  50998. var arrow = new Mesh(arrowGeometry, material);
  50999. arrow.name = "".concat(handleName, ".arrow");
  51000. arrow.renderOrder = 11;
  51001. arrow.position.set(...handle.alignment).multiplyScalar(length / 2 + arrowHeight / 2);
  51002. arrow.lookAt(0, 0, 0);
  51003. node.add(arrow);
  51004. var arrow2 = arrow.clone();
  51005. arrow2.position.negate();
  51006. arrow2.lookAt(0, 0, 0);
  51007. node.add(arrow2);
  51008. arrow.quaternion.multiply(arrowInitialQua); //乘上初始旋转
  51009. arrow2.quaternion.multiply(arrowInitialQua);
  51010. }
  51011. }
  51012. mesh || (mesh = new Mesh(geometry, material));
  51013. mesh.name = "".concat(handleName, ".handle");
  51014. node.add(mesh);
  51015. renderOrder && (mesh.renderOrder = renderOrder);
  51016. meshScale && mesh.scale.copy(meshScale);
  51017. rotation && mesh.rotation.copy(rotation);
  51018. lookAtPoint && mesh.lookAt(lookAtPoint);
  51019. position && mesh.position.copy(position);
  51020. if (!meshPickable && hasPick) {
  51021. pickVolume = new Mesh(geometry, pickMaterial);
  51022. pickScale && pickVolume.scale.copy(pickScale);
  51023. } else if (hasPick && meshPickable) {
  51024. pickVolume = mesh;
  51025. }
  51026. if (pickVolume) {
  51027. if (mesh != pickVolume) {
  51028. mesh.add(pickVolume);
  51029. pickVolume.name = "".concat(handleName, ".pick_volume");
  51030. } else {
  51031. pickVolume.name += ' & pick_volume';
  51032. }
  51033. pickVolume.handle = handleName;
  51034. _this.pickVolumes.push(pickVolume);
  51035. }
  51036. node.setOpacity = target => {
  51037. if (handleName.includes('plane')) {
  51038. var more = 1.5; //减掉更多,使min更低,max还是1
  51039. target = 1 - (1 - target) * more;
  51040. }
  51041. var opacity = {
  51042. x: material.opacity
  51043. };
  51044. var t = new TWEEN.Tween(opacity).to({
  51045. x: target
  51046. }, 0);
  51047. t.onUpdate(() => {
  51048. mesh.visible = opacity.x > 0;
  51049. pickVolume && (pickVolume.visible = opacity.x > 0);
  51050. material.opacity = opacity.x;
  51051. mesh.material.opacity = opacity.x;
  51052. //outlineMaterial.opacity = opacity.x;
  51053. pickMaterial.opacity = opacity.x * 0.5;
  51054. });
  51055. t.start();
  51056. };
  51057. pickVolume.addEventListener("drag", e => {
  51058. _this.dragTranslationHandle(e);
  51059. });
  51060. pickVolume.addEventListener("drop", e => {
  51061. _this.dropTranslationHandle(e);
  51062. });
  51063. };
  51064. for (var handleName of Object.keys(this.translationHandles)) {
  51065. _loop(handleName);
  51066. }
  51067. }
  51068. initializeScaleHandles() {
  51069. var _this2 = this;
  51070. var sgSphere = new SphereGeometry(1, 32, 32);
  51071. var sgLowPolySphere = new SphereGeometry(1, 16, 16);
  51072. var _loop2 = function _loop2() {
  51073. var handle = _this2.scaleHandles[handleName];
  51074. var node = handle.node;
  51075. node.name = handleName; //add
  51076. _this2.scene.add(node);
  51077. if (handleName == 'lines') {
  51078. //add
  51079. ['x', 'y', 'z'].forEach(axis => {
  51080. var handle1_ = _this2.scaleHandles['scale.' + axis + '+'];
  51081. var handle2_ = _this2.scaleHandles['scale.' + axis + '-'];
  51082. var line = LineDraw.createFatLine([new Vector3().fromArray(handle1_.alignment).multiplyScalar(0.5), new Vector3().fromArray(handle2_.alignment).multiplyScalar(0.5)], {
  51083. color: handle1_.color,
  51084. lineWidth: 4
  51085. } // , dontAlwaysSeen:true
  51086. );
  51087. node.add(line);
  51088. });
  51089. node.setOpacity = opacity => {
  51090. opacity *= 0.6;
  51091. node.children.forEach(e => e.material.opacity = opacity);
  51092. };
  51093. return 1; // continue
  51094. }
  51095. node.position.set(...handle.alignment).multiplyScalar(0.5);
  51096. var material = new MeshBasicMaterial({
  51097. color: handle.color,
  51098. side: DoubleSide,
  51099. //xzw add
  51100. opacity: OpaWhenNotSelect,
  51101. transparent: true
  51102. });
  51103. var outlineMaterial = new MeshBasicMaterial({
  51104. color: OutlineColor,
  51105. side: BackSide,
  51106. opacity: OpaWhenNotSelect,
  51107. transparent: true
  51108. });
  51109. var pickMaterial = new MeshNormalMaterial({
  51110. opacity: 0.2,
  51111. transparent: true,
  51112. side: DoubleSide,
  51113. //xzw add for orthoCam, 缩小画面时因球体放大导致到相机背面去了而看不到球体正面
  51114. visible: _this2.showPickVolumes
  51115. });
  51116. var sphere = new Mesh(sgSphere, material);
  51117. sphere.scale.set(5, 5, 5);
  51118. sphere.name = "".concat(handleName, ".handle");
  51119. node.add(sphere);
  51120. sphere.renderOrder = 10;
  51121. /* let outline = new THREE.Mesh(sgSphere, outlineMaterial);
  51122. outline.scale.set(1.1, 1.1, 1.1);
  51123. outline.name = `${handleName}.outline`;
  51124. sphere.add(outline); */
  51125. var pickSphere = new Mesh(sgLowPolySphere, pickMaterial);
  51126. pickSphere.name = "".concat(handleName, ".pick_volume");
  51127. pickSphere.scale.set(1.5, 1.5, 1.5);
  51128. sphere.add(pickSphere);
  51129. pickSphere.handle = handleName;
  51130. _this2.pickVolumes.push(pickSphere);
  51131. node.setOpacity = target => {
  51132. var opacity = {
  51133. x: material.opacity
  51134. };
  51135. var t = new TWEEN.Tween(opacity).to({
  51136. x: target
  51137. }, 0); //xzw改 原100毫秒,因为太慢容易选错
  51138. t.onUpdate(() => {
  51139. sphere.visible = opacity.x > 0;
  51140. pickSphere.visible = opacity.x > 0;
  51141. material.opacity = opacity.x;
  51142. outlineMaterial.opacity = opacity.x;
  51143. pickSphere.material.opacity = opacity.x * 0.5;
  51144. });
  51145. t.start();
  51146. };
  51147. pickSphere.addEventListener("drag", e => _this2.dragScaleHandle(e));
  51148. pickSphere.addEventListener("drop", e => _this2.dropScaleHandle(e));
  51149. pickSphere.addEventListener("mouseover", e => {
  51150. //node.setOpacity(1);
  51151. });
  51152. pickSphere.addEventListener("click", e => {
  51153. //e.consume();
  51154. });
  51155. pickSphere.addEventListener("mouseleave", e => {
  51156. //node.setOpacity(OpaWhenNotSelect);
  51157. });
  51158. };
  51159. for (var handleName of Object.keys(this.scaleHandles)) {
  51160. if (_loop2()) continue;
  51161. }
  51162. }
  51163. initializeRotationHandles() {
  51164. var _this3 = this;
  51165. var boldAdjust = 2.3;
  51166. var torusGeometry = new TorusGeometry(1.3, boldAdjust * 0.015, 8, 64, Math.PI / 2);
  51167. //let outlineGeometry = new THREE.TorusGeometry(1, boldAdjust * 0.018, 8, 64, Math.PI / 2);
  51168. var pickGeometry = new TorusGeometry(1.3, boldAdjust * 0.06, 6, 4, Math.PI / 2);
  51169. var _loop3 = function _loop3() {
  51170. var handle = _this3.handles[handleName];
  51171. var node = handle.node;
  51172. _this3.scene.add(node);
  51173. node.name = handleName; //add
  51174. var material = new MeshBasicMaterial({
  51175. color: handle.color,
  51176. opacity: OpaWhenNotSelect,
  51177. transparent: true
  51178. });
  51179. /* let outlineMaterial = new THREE.MeshBasicMaterial({
  51180. color: OutlineColor,
  51181. side: THREE.BackSide,
  51182. opacity: OpaWhenNotSelect,
  51183. transparent: true
  51184. }); */
  51185. var pickMaterial = new MeshNormalMaterial({
  51186. opacity: 0.2,
  51187. transparent: true,
  51188. visible: _this3.showPickVolumes
  51189. });
  51190. var box = new Mesh(torusGeometry, material);
  51191. box.name = "".concat(handleName, ".handle");
  51192. box.scale.set(30, 30, 30);
  51193. box.lookAt(new Vector3(...handle.alignment));
  51194. node.add(box);
  51195. handle.translateNode = box;
  51196. /* let outline = new THREE.Mesh(outlineGeometry, outlineMaterial);
  51197. outline.name = `${handleName}.outline`;
  51198. outline.scale.set(1, 1, 1);
  51199. outline.renderOrder = 0;
  51200. box.add(outline);
  51201. */
  51202. var pickVolume = new Mesh(pickGeometry, pickMaterial);
  51203. pickVolume.name = "".concat(handleName, ".pick_volume");
  51204. pickVolume.scale.set(1, 1, 1);
  51205. pickVolume.handle = handleName;
  51206. box.add(pickVolume);
  51207. _this3.pickVolumes.push(pickVolume);
  51208. node.setOpacity = target => {
  51209. var opacity = {
  51210. x: material.opacity
  51211. };
  51212. var t = new TWEEN.Tween(opacity).to({
  51213. x: target
  51214. }, 0);
  51215. t.onUpdate(() => {
  51216. box.visible = opacity.x > 0;
  51217. pickVolume.visible = opacity.x > 0;
  51218. material.opacity = opacity.x;
  51219. //outlineMaterial.opacity = opacity.x;
  51220. pickMaterial.opacity = opacity.x * 0.5;
  51221. });
  51222. t.start();
  51223. };
  51224. //pickVolume.addEventListener("mouseover", (e) => {
  51225. // //let a = this.viewer.scene.getActiveCamera().getWorldDirection(new THREE.Vector3()).dot(pickVolume.getWorldDirection(new THREE.Vector3()));
  51226. // console.log(pickVolume.getWorldDirection(new THREE.Vector3()));
  51227. //});
  51228. pickVolume.addEventListener("drag", e => {
  51229. _this3.dragRotationHandle(e);
  51230. });
  51231. pickVolume.addEventListener("drop", e => {
  51232. _this3.dropRotationHandle(e);
  51233. });
  51234. };
  51235. for (var handleName of Object.keys(this.rotationHandles)) {
  51236. _loop3();
  51237. }
  51238. }
  51239. initializeFocusHandles() {
  51240. var _this4 = this;
  51241. if (hideFocusHandles) return; //add
  51242. //let sgBox = new THREE.BoxGeometry(1, 1, 1);
  51243. var sgPlane = new PlaneGeometry(4, 4, 1, 1);
  51244. var sgLowPolySphere = new SphereGeometry(1, 16, 16);
  51245. var texture = new TextureLoader().load("".concat(exports.resourcePath, "/icons/eye_2.png"));
  51246. var _loop4 = function _loop4() {
  51247. var handle = _this4.focusHandles[handleName];
  51248. var node = handle.node;
  51249. _this4.scene.add(node);
  51250. var align = handle.alignment;
  51251. node.name = handleName; //add
  51252. //node.lookAt(new THREE.Vector3().addVectors(node.position, new THREE.Vector3(...align)));
  51253. node.lookAt(new Vector3(...align));
  51254. var off = 0.8;
  51255. if (align[0] === 1) {
  51256. node.position.set(1, off, -off).multiplyScalar(0.5);
  51257. node.rotation.z = Math.PI / 2;
  51258. } else if (align[0] === -1) {
  51259. node.position.set(-1, -off, -off).multiplyScalar(0.5);
  51260. node.rotation.z = Math.PI / 2;
  51261. } else if (align[1] === 1) {
  51262. node.position.set(-off, 1, -off).multiplyScalar(0.5);
  51263. node.rotation.set(Math.PI / 2, Math.PI, 0.0);
  51264. } else if (align[1] === -1) {
  51265. node.position.set(off, -1, -off).multiplyScalar(0.5);
  51266. node.rotation.set(Math.PI / 2, 0.0, 0.0);
  51267. } else if (align[2] === 1) {
  51268. node.position.set(off, off, 1).multiplyScalar(0.5);
  51269. } else if (align[2] === -1) {
  51270. node.position.set(-off, off, -1).multiplyScalar(0.5);
  51271. }
  51272. var material = new MeshBasicMaterial({
  51273. color: handle.color,
  51274. opacity: 0,
  51275. transparent: true,
  51276. map: texture
  51277. });
  51278. //let outlineMaterial = new THREE.MeshBasicMaterial({
  51279. // color: 0x000000,
  51280. // side: THREE.BackSide,
  51281. // opacity: 0,
  51282. // transparent: true});
  51283. var pickMaterial = new MeshNormalMaterial({
  51284. //opacity: 0,
  51285. transparent: true,
  51286. visible: _this4.showPickVolumes
  51287. });
  51288. var box = new Mesh(sgPlane, material);
  51289. box.name = "".concat(handleName, ".handle");
  51290. box.scale.set(1.5, 1.5, 1.5);
  51291. box.position.set(0, 0, 0);
  51292. box.visible = false;
  51293. node.add(box);
  51294. //handle.focusNode = box;
  51295. //let outline = new THREE.Mesh(sgPlane, outlineMaterial);
  51296. //outline.scale.set(1.4, 1.4, 1.4);
  51297. //outline.name = `${handleName}.outline`;
  51298. //box.add(outline);
  51299. var pickSphere = new Mesh(sgLowPolySphere, pickMaterial);
  51300. pickSphere.name = "".concat(handleName, ".pick_volume");
  51301. pickSphere.scale.set(2, 2, 2);
  51302. box.add(pickSphere);
  51303. pickSphere.handle = handleName;
  51304. _this4.pickVolumes.push(pickSphere);
  51305. node.setOpacity = target => {
  51306. var opacity = {
  51307. x: material.opacity
  51308. };
  51309. var t = new TWEEN.Tween(opacity).to({
  51310. x: target
  51311. }, 0);
  51312. t.onUpdate(() => {
  51313. pickSphere.visible = opacity.x > 0;
  51314. box.visible = opacity.x > 0;
  51315. material.opacity = opacity.x;
  51316. //outlineMaterial.opacity = opacity.x;
  51317. pickSphere.material.opacity = opacity.x * 0.5;
  51318. });
  51319. t.start();
  51320. };
  51321. //pickSphere.addEventListener("drag", e => {});
  51322. pickSphere.addEventListener("mouseup", e => {
  51323. //e.consume();
  51324. });
  51325. pickSphere.addEventListener("mousedown", e => {
  51326. //e.consume();
  51327. });
  51328. pickSphere.addEventListener("click", e => {
  51329. //e.consume();
  51330. var selected = _this4.selection[0];
  51331. var maxScale = Math.max(...selected.scale.toArray());
  51332. var minScale = Math.min(...selected.scale.toArray());
  51333. var handleLength = Math.abs(selected.scale.dot(new Vector3(...handle.alignment)));
  51334. var alignment = new Vector3(...handle.alignment).multiplyScalar(2 * maxScale / handleLength);
  51335. alignment.applyMatrix4(selected.matrixWorld);
  51336. var newCamPos = alignment;
  51337. var newCamTarget = selected.getWorldPosition(new Vector3());
  51338. Utils.moveTo(_this4.viewer.scene, newCamPos, newCamTarget);
  51339. });
  51340. pickSphere.addEventListener("mouseover", e => {
  51341. //box.setOpacity(1);
  51342. });
  51343. pickSphere.addEventListener("mouseleave", e => {
  51344. //box.setOpacity(OpaWhenNotSelect);
  51345. });
  51346. };
  51347. for (var handleName of Object.keys(this.focusHandles)) {
  51348. _loop4();
  51349. }
  51350. }
  51351. dragRotationHandle(e) {
  51352. var drag = e.drag;
  51353. var handle = this.activeHandle;
  51354. var camera = this.viewer.mainViewport.camera; //this.viewer.scene.getActiveCamera();
  51355. if (!handle || !handle.name.includes('rotation')) {
  51356. return;
  51357. }
  51358. ;
  51359. var localNormal = new Vector3(...handle.alignment);
  51360. var n = new Vector3();
  51361. n.copy(new Vector4(...localNormal.toArray(), 0).applyMatrix4(handle.node.matrixWorld));
  51362. n.normalize();
  51363. if (!drag.intersectionStart) {
  51364. //this.viewer.scene.scene.remove(this.debug);
  51365. //this.debug = new THREE.Object3D();
  51366. //this.viewer.scene.scene.add(this.debug);
  51367. //Utils.debugSphere(this.debug, drag.location, 3, 0xaaaaaa);
  51368. //let debugEnd = drag.location.clone().add(n.clone().multiplyScalar(20));
  51369. //Utils.debugLine(this.debug, drag.location, debugEnd, 0xff0000);
  51370. drag.intersectionStart = drag.location;
  51371. drag.objectStart = drag.object.getWorldPosition(new Vector3());
  51372. drag.handle = handle;
  51373. var plane = new Plane().setFromNormalAndCoplanarPoint(n, drag.intersectionStart);
  51374. drag.dragPlane = plane;
  51375. drag.pivot = drag.intersectionStart;
  51376. } else {
  51377. handle = drag.handle;
  51378. }
  51379. if (!drag.dragPlane) return; //xzw add 因有时候没有
  51380. this.dragging = true;
  51381. var pointer = this.viewer.inputHandler.pointer;
  51382. var domElement = this.viewer.renderer.domElement;
  51383. var ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  51384. var I = ray.intersectPlane(drag.dragPlane, new Vector3());
  51385. if (I) {
  51386. var center = this.scene.getWorldPosition(new Vector3()); //bounding中心
  51387. var from = drag.pivot;
  51388. var to = I;
  51389. var v1 = from.clone().sub(center).normalize();
  51390. var v2 = to.clone().sub(center).normalize();
  51391. var angle = Math.acos(v1.dot(v2));
  51392. var sign = Math.sign(v1.cross(v2).dot(n));
  51393. angle = angle * sign;
  51394. if (Number.isNaN(angle)) {
  51395. return;
  51396. }
  51397. var matrixBefore = this.selection[0].matrix.clone();
  51398. var normal = new Vector3(...handle.alignment);
  51399. for (var selection of this.selection) {
  51400. //直接修改matrix,使整体绕boundingBox中心旋转。 xzw
  51401. var quaternion = selection.quaternion.clone();
  51402. var diffQua = new Quaternion().setFromAxisAngle(normal, angle); //变化量,参考 selection.rotateOnAxis(normal, angle);
  51403. var moveToZero = new Matrix4().setPosition(center.clone().negate()); //先将boundingBox中心(整体)移动到原点
  51404. var rotM = new Matrix4().makeRotationFromQuaternion(quaternion.clone().inverse().premultiply(diffQua).premultiply(quaternion)); //再旋转。根据selection.rotateOnAxis,应该是旧的qua 右乘 diffQua,所以先用invert消掉旧的qua
  51405. var moveBack = new Matrix4().setPosition(center.clone()); //移动回去,使boundingBox中心位置还原
  51406. selection.matrix.premultiply(moveToZero).premultiply(rotM).premultiply(moveBack);
  51407. selection.matrix.decompose(selection.position, selection.quaternion, selection.scale); //记录 (scale基本不变)
  51408. selection.updateMatrixWorld(); //xzw add 保险起见立即update
  51409. selection.dispatchEvent({
  51410. type: "orientation_changed",
  51411. object: selection
  51412. });
  51413. selection.dispatchEvent({
  51414. //当boundingBox中心不在原点时
  51415. type: "position_changed",
  51416. object: selection
  51417. });
  51418. }
  51419. this.dispatchEvent({
  51420. type: 'transformed',
  51421. changeType: ['orientation'],
  51422. matrixBefore
  51423. }); //add
  51424. drag.pivot = I;
  51425. }
  51426. }
  51427. dropRotationHandle(e) {
  51428. this.dragging = false;
  51429. this.setActiveHandle(null);
  51430. this.dispatchEvent({
  51431. type: 'stopDrag',
  51432. handle: 'rotation'
  51433. }); //add
  51434. }
  51435. dragTranslationHandle(e) {
  51436. //---大改,参考transformControls,为了加上xyz xy yz xz 这四个方向的变换。 (但感觉好像plane上有丢丢延迟?是因为drag延迟还是worldmatrix没更新)
  51437. var drag = e.drag;
  51438. var handle = this.activeHandle;
  51439. var camera = this.viewer.mainViewport.camera; //this.viewer.scene.getActiveCamera();
  51440. if (handle && handle.name.includes('translation') && this.selection[0]) {
  51441. var posWorld = this.scene.getWorldPosition(new Vector3()); //bounding中心
  51442. if (!drag.intersectionStart) {
  51443. drag.intersectionStart = drag.location;
  51444. drag.worldPositionStart = this.selection[0].getWorldPosition(new Vector3());
  51445. drag.objectQua = this.selection[0].quaternion.clone(); //不考虑父级
  51446. drag.objectQuaInv = drag.objectQua.clone().invert();
  51447. this.dragging = true;
  51448. }
  51449. if (drag.intersectionStart) {
  51450. var pointer = this.viewer.inputHandler.pointer;
  51451. var ray = Utils.mouseToRay(pointer, camera);
  51452. //方向滑动所在面
  51453. var normal;
  51454. var axisName = handle.name.split('.').pop();
  51455. if (axisName == 'xyz') {
  51456. // 平行于屏幕滑动
  51457. normal = viewer.mainViewport.view.direction;
  51458. } else {
  51459. var alignVector = new Vector3();
  51460. normal = new Vector3();
  51461. var unitX = new Vector3(1, 0, 0).applyQuaternion(drag.objectQua);
  51462. var unitY = new Vector3(0, 1, 0).applyQuaternion(drag.objectQua);
  51463. var unitZ = new Vector3(0, 0, 1).applyQuaternion(drag.objectQua);
  51464. switch (axisName) {
  51465. case 'x':
  51466. alignVector.copy(viewer.mainViewport.view.direction).cross(unitX);
  51467. normal.copy(unitX).cross(alignVector);
  51468. break;
  51469. case 'y':
  51470. alignVector.copy(viewer.mainViewport.view.direction).cross(unitY);
  51471. normal.copy(unitY).cross(alignVector);
  51472. break;
  51473. case 'z':
  51474. alignVector.copy(viewer.mainViewport.view.direction).cross(unitZ);
  51475. normal.copy(unitZ).cross(alignVector);
  51476. break;
  51477. case 'xy':
  51478. normal.copy(unitZ);
  51479. break;
  51480. case 'yz':
  51481. normal.copy(unitX);
  51482. break;
  51483. case 'xz':
  51484. normal.copy(unitY);
  51485. break;
  51486. } //参考transformControls.使跟手
  51487. }
  51488. drag.dragPlane = new Plane().setFromNormalAndCoplanarPoint(normal, posWorld /* drag.worldPositionStart */); //过center的与视线垂直的平面
  51489. var I = ray.intersectPlane(drag.dragPlane, new Vector3());
  51490. if (I) {
  51491. var offset = new Vector3().subVectors(I, drag.worldPositionStart);
  51492. //let offset = new THREE.Vector3().subVectors(iOnLine, drag.worldPositionStart);
  51493. if (!drag.pointStart) {
  51494. drag.pointStart = offset;
  51495. } else {
  51496. drag.pointEnd = offset;
  51497. var diff = new Vector3().subVectors(drag.pointEnd, drag.pointStart);
  51498. diff.applyQuaternion(drag.objectQuaInv); // 得到在该物体local空间上的offset
  51499. if (!handle.name.includes('x')) diff.x = 0;
  51500. if (!handle.name.includes('y')) diff.y = 0;
  51501. if (!handle.name.includes('z')) diff.z = 0;
  51502. //恢复为world offset
  51503. diff.applyQuaternion(drag.objectQua);
  51504. //-------------
  51505. var matrixBefore = this.selection[0].matrix.clone();
  51506. this.selection[0].position.copy(diff).add(drag.worldPositionStart);
  51507. for (var selection of this.selection) {
  51508. selection.updateMatrixWorld(); //xzw add 保险起见立即update
  51509. selection.dispatchEvent({
  51510. type: "position_changed",
  51511. object: selection
  51512. });
  51513. }
  51514. this.dispatchEvent({
  51515. type: 'transformed',
  51516. changeType: ['position'],
  51517. matrixBefore
  51518. }); //add
  51519. }
  51520. }
  51521. }
  51522. }
  51523. }
  51524. dropTranslationHandle(e) {
  51525. this.dragging = false;
  51526. this.setActiveHandle(null);
  51527. this.dispatchEvent({
  51528. type: 'stopDrag',
  51529. handle: 'translation'
  51530. }); //add
  51531. }
  51532. dropScaleHandle(e) {
  51533. this.dragging = false;
  51534. this.setActiveHandle(null);
  51535. this.dispatchEvent({
  51536. type: 'stopDrag',
  51537. handle: 'scale'
  51538. }); //add
  51539. }
  51540. dragScaleHandle(e) {
  51541. var drag = e.drag;
  51542. var handle = this.activeHandle;
  51543. if (!handle || !handle.name.includes('scale')) return;
  51544. var camera = this.viewer.mainViewport.camera; //this.viewer.scene.getActiveCamera();
  51545. if (!drag.intersectionStart) {
  51546. drag.intersectionStart = drag.location;
  51547. drag.objectStart = drag.object.getWorldPosition(new Vector3());
  51548. drag.handle = handle;
  51549. var start = drag.intersectionStart;
  51550. var dir = new Vector4(...handle.alignment, 0).applyMatrix4(this.scene.matrixWorld);
  51551. var end = new Vector3().addVectors(start, dir);
  51552. var line = new Line3(start.clone(), end.clone());
  51553. drag.line = line;
  51554. var normal;
  51555. if (camera.type == 'OrthographicCamera') {
  51556. //xzw add
  51557. normal = new Vector3(0, 0, -1).applyQuaternion(camera.quaternion);
  51558. } else {
  51559. var camOnLine = line.closestPointToPoint(camera.position, false, new Vector3());
  51560. normal = new Vector3().subVectors(camera.position, camOnLine);
  51561. }
  51562. var plane = new Plane().setFromNormalAndCoplanarPoint(normal, drag.intersectionStart); //过轴线的一个能铺满屏幕的平面
  51563. drag.dragPlane = plane;
  51564. drag.pivot = drag.intersectionStart;
  51565. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  51566. } else {
  51567. handle = drag.handle;
  51568. }
  51569. this.dragging = true;
  51570. if (drag.dragPlane) {
  51571. //xzw add 因有时候没有
  51572. var pointer = this.viewer.inputHandler.pointer;
  51573. var domElement = this.viewer.renderer.domElement;
  51574. var ray = Utils.mouseToRay(pointer, camera, domElement.clientWidth, domElement.clientHeight);
  51575. var I = ray.intersectPlane(drag.dragPlane, new Vector3());
  51576. if (I) {
  51577. var iOnLine = drag.line.closestPointToPoint(I, false, new Vector3());
  51578. var direction = handle.alignment.reduce((a, v) => a + v, 0);
  51579. var toObjectSpace = this.selection[0].matrixWorld.clone().invert();
  51580. var iOnLineOS = iOnLine.clone().applyMatrix4(toObjectSpace);
  51581. var pivotOS = drag.pivot.clone().applyMatrix4(toObjectSpace);
  51582. var diffOS = new Vector3().subVectors(iOnLineOS, pivotOS);
  51583. var dragDirectionOS = diffOS.clone().normalize();
  51584. if (iOnLine.distanceTo(drag.pivot) === 0) {
  51585. dragDirectionOS.set(0, 0, 0);
  51586. }
  51587. var dragDirection = dragDirectionOS.dot(new Vector3(...handle.alignment));
  51588. var alignment = new Vector3(...handle.alignment);
  51589. var diff = new Vector3().subVectors(iOnLine, drag.pivot);
  51590. var diffScale = alignment.clone().multiplyScalar(diff.length() * direction * dragDirection);
  51591. //let diffPosition = diff.clone().multiplyScalar(0.5); //这个仅当bound包含原点才准确。
  51592. var matrixBefore = this.selection[0].matrix.clone();
  51593. for (var selection of this.selection) {
  51594. //xzw 改:否则不跟手
  51595. var {
  51596. min,
  51597. max
  51598. } = selection.boundingBox;
  51599. var fixPoint = alignment.x != 0 ? (alignment.x > 0 ? min : max).clone().setY(0).setZ(0) :
  51600. //要保证另一边不能移动
  51601. alignment.y != 0 ? (alignment.y > 0 ? min : max).clone().setX(0).setZ(0) : (alignment.z > 0 ? min : max).clone().setX(0).setY(0);
  51602. var fixPointBefore = fixPoint.clone().applyMatrix4(selection.matrixWorld);
  51603. var size = selection.boundingBox.getSize(new Vector3());
  51604. var diffScale_ = diffScale.clone().divide(size);
  51605. size.x == 0 && (diffScale_.x = 0); //add 若为0,不改此轴大小
  51606. size.y == 0 && (diffScale_.y = 0);
  51607. size.z == 0 && (diffScale_.z = 0);
  51608. selection.scale.add(diffScale_);
  51609. selection.scale.max(new Vector3(0.1, 0.1, 0.1));
  51610. //selection.position.add(diffPosition);
  51611. selection.updateMatrixWorld();
  51612. var fixPointAfter = fixPoint.clone().applyMatrix4(this.selection[0].matrixWorld);
  51613. selection.position.sub(new Vector3().subVectors(fixPointAfter, fixPointBefore)); //保证另一边不能移动所需要的位移
  51614. selection.updateMatrixWorld(); //xzw add 保险起见立即update
  51615. selection.dispatchEvent({
  51616. type: "position_changed",
  51617. object: selection
  51618. });
  51619. selection.dispatchEvent({
  51620. type: "scale_changed",
  51621. object: selection
  51622. });
  51623. }
  51624. this.dispatchEvent({
  51625. type: 'transformed',
  51626. changeType: ['position', 'scale'],
  51627. matrixBefore
  51628. }); //add
  51629. drag.pivot.copy(iOnLine);
  51630. //Utils.debugSphere(viewer.scene.scene, drag.pivot, 0.05);
  51631. }
  51632. }
  51633. }
  51634. setActiveHandle(handle) {
  51635. if (this.dragging) {
  51636. return;
  51637. }
  51638. if (this.activeHandle === handle) {
  51639. return;
  51640. }
  51641. this.activeHandle = handle;
  51642. if (handle === null) {
  51643. for (var handleName of Object.keys(this.handles)) {
  51644. var _handle = this.handles[handleName];
  51645. _handle.node.setOpacity(0);
  51646. }
  51647. }
  51648. viewer.dispatchEvent({
  51649. type: 'CursorChange',
  51650. action: this.activeHandle ? 'add' : 'remove',
  51651. name: 'hoverTranHandle'
  51652. });
  51653. if (!hideFocusHandles) {
  51654. for (var _handleName of Object.keys(this.focusHandles)) {
  51655. var _handle2 = this.focusHandles[_handleName];
  51656. if (this.activeHandle === _handle2) {
  51657. _handle2.node.setOpacity(1.0);
  51658. } else {
  51659. _handle2.node.setOpacity(OpaWhenNotSelect);
  51660. }
  51661. }
  51662. }
  51663. for (var _handleName2 of Object.keys(this.translationHandles)) {
  51664. var _handle3 = this.translationHandles[_handleName2];
  51665. if (this.activeHandle === _handle3) {
  51666. _handle3.node.setOpacity(1.0);
  51667. } else {
  51668. _handle3.node.setOpacity(OpaWhenNotSelect);
  51669. }
  51670. }
  51671. for (var _handleName3 of Object.keys(this.rotationHandles)) {
  51672. var _handle4 = this.rotationHandles[_handleName3];
  51673. //if(this.activeHandle === handle){
  51674. // handle.node.setOpacity(1.0);
  51675. //}else{
  51676. // handle.node.setOpacity(OpaWhenNotSelect)
  51677. //}
  51678. _handle4.node.setOpacity(OpaWhenNotSelect);
  51679. }
  51680. for (var _handleName4 of Object.keys(this.scaleHandles)) {
  51681. var _handle5 = this.scaleHandles[_handleName4];
  51682. if (this.activeHandle === _handle5) {
  51683. _handle5.node.setOpacity(1.0);
  51684. if (!hideFocusHandles) {
  51685. var relatedFocusHandle = this.focusHandles[_handle5.name.replace("scale", "focus")];
  51686. var relatedFocusNode = relatedFocusHandle.node;
  51687. relatedFocusNode.setOpacity(OpaWhenNotSelect);
  51688. }
  51689. for (var translationHandleName of Object.keys(this.translationHandles)) {
  51690. var translationHandle = this.translationHandles[translationHandleName];
  51691. translationHandle.node.setOpacity(OpaWhenNotSelect);
  51692. }
  51693. //let relatedTranslationHandle = this.translationHandles[
  51694. // handle.name.replace("scale", "translation").replace(/[+-]/g, "")];
  51695. //let relatedTranslationNode = relatedTranslationHandle.node;
  51696. //relatedTranslationNode.setOpacity(OpaWhenNotSelect);
  51697. } else {
  51698. _handle5.node.setOpacity(OpaWhenNotSelect);
  51699. }
  51700. }
  51701. if (handle) {
  51702. handle.node.setOpacity(1.0);
  51703. }
  51704. viewer.dispatchEvent('content_changed');
  51705. }
  51706. update() {
  51707. if (this.selection.length === 1) {
  51708. this.scene.visible = true;
  51709. this.scene.updateMatrix();
  51710. this.scene.updateMatrixWorld();
  51711. var selected = this.selection[0];
  51712. //selected.updateMatrixWorld();//add 否则scale的sphere抖动
  51713. var world = selected.matrixWorld;
  51714. var camera = this.viewer.mainViewport.camera; //this.viewer.scene.getActiveCamera();
  51715. var domElement = this.viewer.renderer.domElement;
  51716. var center = selected.boundingBox.getCenter(new Vector3()).clone().applyMatrix4(selected.matrixWorld);
  51717. var scale = selected.boundingBox.getSize(new Vector3()).multiply(selected.scale);
  51718. scale.max(new Vector3(.1, .1, .1)); //xzw add 如果是plane,没有厚度,会导致该tool消失
  51719. this.scene.scale.copy(scale);
  51720. this.scene.position.copy(center);
  51721. this.scene.rotation.copy(selected.rotation); //这里只考虑当前子级的scale rotation
  51722. //如果是世界坐标 (缩放方向有bug。)
  51723. /*
  51724. let boundingBox = selected.boundingBox.clone().applyMatrix4(selected.matrixWorld);
  51725. let center = boundingBox.getCenter(new THREE.Vector3())
  51726. this.scene.position.copy(center);
  51727. this.scene.scale.copy(boundingBox.getSize(new THREE.Vector3()));
  51728. */
  51729. this.scene.updateMatrixWorld();
  51730. {
  51731. // adjust rotation handles
  51732. if (!this.dragging) {
  51733. if (this.modesEnabled.rotation || this.modesEnabled.translation) {
  51734. var tWorld = this.scene.matrixWorld;
  51735. var tObject = tWorld.clone().invert();
  51736. var camObjectPos = camera.getWorldPosition(new Vector3()).applyMatrix4(tObject);
  51737. if (this.modesEnabled.translation) {
  51738. //add
  51739. ['xy', 'yz', 'xz'].forEach(axis => {
  51740. var handle = this.translationHandles["translation.plane." + axis];
  51741. var pos = handle.node.children[0].position;
  51742. camObjectPos.x && (pos.x = Math.sign(camObjectPos.x) * Math.abs(pos.x));
  51743. camObjectPos.y && (pos.y = Math.sign(camObjectPos.y) * Math.abs(pos.y));
  51744. camObjectPos.z && (pos.z = Math.sign(camObjectPos.z) * Math.abs(pos.z));
  51745. });
  51746. }
  51747. if (this.modesEnabled.rotation) {
  51748. var above = camObjectPos.z > 0;
  51749. var below = !above;
  51750. var PI_HALF = Math.PI / 2;
  51751. var x = this.rotationHandles["rotation.x"].node.rotation;
  51752. var y = this.rotationHandles["rotation.y"].node.rotation;
  51753. var z = this.rotationHandles["rotation.z"].node.rotation;
  51754. x.order = "ZYX";
  51755. y.order = "ZYX";
  51756. if (above) {
  51757. if (camObjectPos.x > 0 && camObjectPos.y > 0) {
  51758. x.x = 1 * PI_HALF;
  51759. y.y = 3 * PI_HALF;
  51760. z.z = 0 * PI_HALF;
  51761. } else if (camObjectPos.x < 0 && camObjectPos.y > 0) {
  51762. x.x = 1 * PI_HALF;
  51763. y.y = 2 * PI_HALF;
  51764. z.z = 1 * PI_HALF;
  51765. } else if (camObjectPos.x < 0 && camObjectPos.y < 0) {
  51766. x.x = 2 * PI_HALF;
  51767. y.y = 2 * PI_HALF;
  51768. z.z = 2 * PI_HALF;
  51769. } else if (camObjectPos.x > 0 && camObjectPos.y < 0) {
  51770. x.x = 2 * PI_HALF;
  51771. y.y = 3 * PI_HALF;
  51772. z.z = 3 * PI_HALF;
  51773. }
  51774. } else if (below) {
  51775. if (camObjectPos.x > 0 && camObjectPos.y > 0) {
  51776. x.x = 0 * PI_HALF;
  51777. y.y = 0 * PI_HALF;
  51778. z.z = 0 * PI_HALF;
  51779. } else if (camObjectPos.x < 0 && camObjectPos.y > 0) {
  51780. x.x = 0 * PI_HALF;
  51781. y.y = 1 * PI_HALF;
  51782. z.z = 1 * PI_HALF;
  51783. } else if (camObjectPos.x < 0 && camObjectPos.y < 0) {
  51784. x.x = 3 * PI_HALF;
  51785. y.y = 1 * PI_HALF;
  51786. z.z = 2 * PI_HALF;
  51787. } else if (camObjectPos.x > 0 && camObjectPos.y < 0) {
  51788. x.x = 3 * PI_HALF;
  51789. y.y = 0 * PI_HALF;
  51790. z.z = 3 * PI_HALF;
  51791. }
  51792. }
  51793. }
  51794. }
  51795. }
  51796. // adjust scale of components
  51797. for (var handleName of Object.keys(this.handles)) {
  51798. var handle = this.handles[handleName];
  51799. var node = handle.node;
  51800. //xzw add:---- -当该轴正对相机时隐藏。(主要针对ortho类型camera。
  51801. if (!Potree.Utils.getObjVisiByReason(node, 'modeForce')) continue;
  51802. var alignment = handle.alignment;
  51803. if (alignment && (!handleName.includes('rotation') || camera.type == 'OrthographicCamera')) {
  51804. //旋转的话正常都应该显示
  51805. var normal = void 0;
  51806. var dir = new Vector3(...alignment).applyQuaternion(this.scene.quaternion);
  51807. if (camera.type == 'OrthographicCamera') {
  51808. normal = new Vector3(0, 0, -1).applyQuaternion(camera.quaternion);
  51809. } else {
  51810. normal = new Vector3().subVectors(center, camera.position).normalize();
  51811. }
  51812. var ifOnLine = void 0;
  51813. if (handleName.includes('rotation') || handleName.includes('plane')) {
  51814. // 旋转轴和视线垂直时隐藏
  51815. ifOnLine = Math.abs(dir.dot(normal)) < 0.1;
  51816. } else {
  51817. ifOnLine = Math.abs(dir.dot(normal)) > 0.995;
  51818. }
  51819. Potree.Utils.updateVisible(node, 'faceToCamHide', !ifOnLine);
  51820. } else {
  51821. Potree.Utils.updateVisible(node, 'faceToCamHide', true);
  51822. }
  51823. if (!node.visible) continue;
  51824. //------------------------------------------------------------------------
  51825. if (handle.dontScale) continue; //add
  51826. var handlePos = node.getWorldPosition(new Vector3());
  51827. var distance = handlePos.distanceTo(camera.position);
  51828. var pr = Utils.projectedRadius(1, camera, distance, domElement.clientWidth, domElement.clientHeight);
  51829. var ws = node.parent.getWorldScale(new Vector3());
  51830. var s = ScaleRatio / pr;
  51831. var _scale = new Vector3(s, s, s).divide(ws);
  51832. var rot = new Matrix4().makeRotationFromEuler(node.rotation); //需要使用到旋转,所以我把设置scale的移到旋转后了,否则在视图上下旋转的分界线处rotateHandel会被拉长从而闪烁。
  51833. var rotInv = rot.clone().invert();
  51834. _scale.applyMatrix4(rotInv);
  51835. _scale.x = Math.abs(_scale.x);
  51836. _scale.y = Math.abs(_scale.y);
  51837. _scale.z = Math.abs(_scale.z);
  51838. node.scale.copy(_scale);
  51839. }
  51840. }
  51841. } else {
  51842. this.scene.visible = false;
  51843. }
  51844. }
  51845. onPointerMove() {
  51846. var pointer = this.viewer.inputHandler.pointer;
  51847. var camera = this.viewer.mainViewport.camera;
  51848. if (this.selection.length === 1 && !this.dragging) {
  51849. //xzw 添加dragging条件
  51850. var ray = Utils.mouseToRay(pointer, camera);
  51851. var raycaster = new Raycaster(ray.origin, ray.direction);
  51852. raycaster.layers.enableAll(); //add
  51853. var pickVolumes = this.pickVolumes.filter(v => {
  51854. var mode = v.handle.split('.')[0];
  51855. if (!this.modesEnabled[mode]) return;
  51856. return v.parent.parent.visible; //可能被隐藏该轴
  51857. });
  51858. var intersects = raycaster.intersectObjects(pickVolumes, true);
  51859. intersects = intersects.sort(function (a, b) {
  51860. var order2 = b.object.renderOrder || 0;
  51861. var order1 = a.object.renderOrder || 0;
  51862. return order2 - order1;
  51863. }); // 降序
  51864. if (intersects.length > 0) {
  51865. var I = intersects[0];
  51866. var handleName = I.object.handle;
  51867. //console.log(handleName)
  51868. this.setActiveHandle(this.handles[handleName]);
  51869. } else {
  51870. this.setActiveHandle(null);
  51871. }
  51872. }
  51873. }
  51874. }
  51875. ;
  51876. /*
  51877. note:
  51878. transformationTool.scene会跟随选中物体,其scale就是boundingbox的大小。因此transformationTool.frame这个框也会跟着缩放
  51879. */
  51880. var boxOpacity = {
  51881. hovered: 0.1,
  51882. selected: 0.2
  51883. };
  51884. var LineOpacity = {
  51885. default: 0.6,
  51886. selected: 1
  51887. };
  51888. var colors = {
  51889. 2: 0x2ee4ce,
  51890. //0x00ff80, //可见
  51891. 3: 0xffc23b,
  51892. //0xff3158, //不可见
  51893. 4: 0xffffff //
  51894. };
  51895. class Volume$1 extends Object3D {
  51896. constructor() {
  51897. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  51898. super();
  51899. if (this.constructor.name === "Volume") {
  51900. console.warn("Can't create object of class Volume directly. Use classes BoxVolume or SphereVolume instead.");
  51901. }
  51902. this._clip = args.clip || false;
  51903. this._visible = true;
  51904. //this.showVolumeLabel = true;
  51905. this._modifiable = args.modifiable || true;
  51906. if (!args.noPointerEvent) {
  51907. // event listeners
  51908. this.addEventListener('select', e => {
  51909. //console.log('select')
  51910. this.setSelected(true);
  51911. });
  51912. this.addEventListener('deselect', e => {
  51913. //console.log('deselect')
  51914. this.setSelected(false);
  51915. });
  51916. this.addEventListener('mouseover', e => {
  51917. this.hovered = true;
  51918. this.update();
  51919. });
  51920. this.addEventListener('mouseleave', e => {
  51921. this.hovered = false;
  51922. this.update();
  51923. });
  51924. }
  51925. }
  51926. setSelected(state) {
  51927. //add
  51928. this.selected = !!state;
  51929. this.update();
  51930. }
  51931. get visible() {
  51932. return this._visible;
  51933. }
  51934. set visible(value) {
  51935. if (this._visible !== value) {
  51936. this._visible = value;
  51937. this.dispatchEvent({
  51938. type: "visibility_changed",
  51939. object: this
  51940. });
  51941. }
  51942. }
  51943. getVolume() {
  51944. console.warn("override this in subclass");
  51945. }
  51946. update() {}
  51947. raycast(raycaster, intersects) {}
  51948. get clip() {
  51949. return this._clip;
  51950. }
  51951. set clip(value) {
  51952. if (this._clip !== value) {
  51953. this._clip = value;
  51954. this.update();
  51955. this.dispatchEvent({
  51956. type: "clip_changed",
  51957. object: this
  51958. });
  51959. }
  51960. }
  51961. get modifieable() {
  51962. return this._modifiable;
  51963. }
  51964. set modifieable(value) {
  51965. this._modifiable = value;
  51966. this.update();
  51967. }
  51968. }
  51969. ;
  51970. class BoxVolume$1 extends Volume$1 {
  51971. constructor() {
  51972. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  51973. super(args);
  51974. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  51975. this.name = 'box_' + this.constructor.counter;
  51976. this.clipTask = args.clipTask || Potree.ClipTask.SHOW_INSIDE; //add
  51977. this.showBox = true;
  51978. var boxGeometry = new BoxGeometry(1, 1, 1);
  51979. boxGeometry.computeBoundingBox();
  51980. var boxFrameGeometry = new Geometry();
  51981. var Vector3$1 = Vector3;
  51982. {
  51983. boxFrameGeometry.vertices.push(
  51984. // bottom
  51985. new Vector3$1(-0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, -0.5, 0.5),
  51986. // top
  51987. new Vector3$1(-0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5), new Vector3$1(-0.5, 0.5, 0.5),
  51988. // sides
  51989. new Vector3$1(-0.5, -0.5, 0.5), new Vector3$1(-0.5, 0.5, 0.5), new Vector3$1(0.5, -0.5, 0.5), new Vector3$1(0.5, 0.5, 0.5), new Vector3$1(0.5, -0.5, -0.5), new Vector3$1(0.5, 0.5, -0.5), new Vector3$1(-0.5, -0.5, -0.5), new Vector3$1(-0.5, 0.5, -0.5));
  51990. }
  51991. this.material = new DepthBasicMaterial({
  51992. color: colors[this.clipTask],
  51993. side: DoubleSide,
  51994. transparent: true,
  51995. opacity: boxOpacity.hovered,
  51996. depthTest: true,
  51997. depthWrite: false,
  51998. useDepth: true,
  51999. clipDistance: 2,
  52000. //消失距离
  52001. occlusionDistance: 0.1,
  52002. //变为backColor距离
  52003. maxClipFactor: 0.9
  52004. });
  52005. this.box = new Mesh(boxGeometry, this.material);
  52006. this.box.geometry.computeBoundingBox();
  52007. this.boundingBox = this.box.geometry.boundingBox;
  52008. this.add(this.box);
  52009. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: colors[this.clipTask], opacity:LineOpacity.default/* 0xff2050 */}));
  52010. this.frame = LineDraw.createFatLine(boxFrameGeometry.vertices, {
  52011. color: colors[this.clipTask],
  52012. opacity: LineOpacity.default,
  52013. lineWidth: 1,
  52014. dontAlwaysSeen: true,
  52015. autoDepthTest: true
  52016. });
  52017. // this.frame.mode = THREE.Lines;
  52018. this.add(this.frame);
  52019. this.update();
  52020. }
  52021. update() {
  52022. this.boundingBox = this.box.geometry.boundingBox;
  52023. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  52024. Potree.Utils.updateVisible(this.box, 'selected', (this.selected || this.hovered) && this.showBox);
  52025. this.box.material.opacity = this.selected ? boxOpacity.selected : boxOpacity.hovered;
  52026. this.box.material.color.set(colors[this.clipTask]);
  52027. this.frame.material.color.set(colors[this.clipTask]);
  52028. this.frame.material.opacity = this.selected ? LineOpacity.selected : LineOpacity.default;
  52029. this.frame.material.lineWidth = this.selected ? 2 : 1;
  52030. }
  52031. raycast(raycaster, intersects) {
  52032. var is = [];
  52033. this.box.raycast(raycaster, is);
  52034. if (is.length > 0) {
  52035. var I = is[0];
  52036. intersects.push({
  52037. distance: I.distance,
  52038. object: this,
  52039. point: I.point.clone()
  52040. });
  52041. }
  52042. }
  52043. getVolume() {
  52044. return Math.abs(this.scale.x * this.scale.y * this.scale.z);
  52045. }
  52046. }
  52047. ;
  52048. class SphereVolume$2 extends Volume$1 {
  52049. constructor() {
  52050. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  52051. super(args);
  52052. this.constructor.counter = this.constructor.counter === undefined ? 0 : this.constructor.counter + 1;
  52053. this.name = 'sphere_' + this.constructor.counter;
  52054. var sphereGeometry = new SphereGeometry(1, 32, 32);
  52055. sphereGeometry.computeBoundingBox();
  52056. this.material = new MeshBasicMaterial({
  52057. color: 0x00ff00,
  52058. transparent: true,
  52059. opacity: 0.3,
  52060. depthTest: true,
  52061. depthWrite: false
  52062. });
  52063. this.sphere = new Mesh(sphereGeometry, this.material);
  52064. this.sphere.visible = false;
  52065. this.sphere.geometry.computeBoundingBox();
  52066. this.boundingBox = this.sphere.geometry.boundingBox;
  52067. this.add(this.sphere);
  52068. this.label.visible = false;
  52069. var frameGeometry = new Geometry();
  52070. {
  52071. var steps = 64;
  52072. var uSegments = 8;
  52073. var vSegments = 5;
  52074. var r = 1;
  52075. for (var uSegment = 0; uSegment < uSegments; uSegment++) {
  52076. var alpha = uSegment / uSegments * Math.PI * 2;
  52077. var dirx = Math.cos(alpha);
  52078. var diry = Math.sin(alpha);
  52079. for (var i = 0; i <= steps; i++) {
  52080. var v = i / steps * Math.PI * 2;
  52081. var vNext = v + 2 * Math.PI / steps;
  52082. var height = Math.sin(v);
  52083. var xyAmount = Math.cos(v);
  52084. var heightNext = Math.sin(vNext);
  52085. var xyAmountNext = Math.cos(vNext);
  52086. var vertex = new Vector3(dirx * xyAmount, diry * xyAmount, height);
  52087. frameGeometry.vertices.push(vertex);
  52088. var vertexNext = new Vector3(dirx * xyAmountNext, diry * xyAmountNext, heightNext);
  52089. frameGeometry.vertices.push(vertexNext);
  52090. }
  52091. }
  52092. // creates rings at poles, just because it's easier to implement
  52093. for (var vSegment = 0; vSegment <= vSegments + 1; vSegment++) {
  52094. //let height = (vSegment / (vSegments + 1)) * 2 - 1; // -1 to 1
  52095. var uh = vSegment / (vSegments + 1); // -1 to 1
  52096. uh = (1 - uh) * (-Math.PI / 2) + uh * (Math.PI / 2);
  52097. var _height = Math.sin(uh);
  52098. console.log(uh, _height);
  52099. for (var _i = 0; _i <= steps; _i++) {
  52100. var u = _i / steps * Math.PI * 2;
  52101. var uNext = u + 2 * Math.PI / steps;
  52102. var _dirx = Math.cos(u);
  52103. var _diry = Math.sin(u);
  52104. var dirxNext = Math.cos(uNext);
  52105. var diryNext = Math.sin(uNext);
  52106. var _xyAmount = Math.sqrt(1 - _height * _height);
  52107. var _vertex = new Vector3(_dirx * _xyAmount, _diry * _xyAmount, _height);
  52108. frameGeometry.vertices.push(_vertex);
  52109. var _vertexNext = new Vector3(dirxNext * _xyAmount, diryNext * _xyAmount, _height);
  52110. frameGeometry.vertices.push(_vertexNext);
  52111. }
  52112. }
  52113. }
  52114. this.frame = new LineSegments(frameGeometry, new LineBasicMaterial({
  52115. color: 0x000000
  52116. }));
  52117. this.add(this.frame);
  52118. var frameMaterial = new MeshBasicMaterial({
  52119. wireframe: true,
  52120. color: 0x000000
  52121. });
  52122. this.frame = new Mesh(sphereGeometry, frameMaterial);
  52123. //this.add(this.frame);
  52124. //this.frame = new THREE.LineSegments(boxFrameGeometry, new THREE.LineBasicMaterial({color: 0x000000}));
  52125. // this.frame.mode = THREE.Lines;
  52126. //this.add(this.frame);
  52127. this.update();
  52128. }
  52129. update() {
  52130. this.boundingBox = this.sphere.geometry.boundingBox;
  52131. this.boundingSphere = this.boundingBox.getBoundingSphere(new Sphere());
  52132. //if (this._clip) {
  52133. // this.sphere.visible = false;
  52134. // this.label.visible = false;
  52135. //} else {
  52136. // this.sphere.visible = true;
  52137. // this.label.visible = this.showVolumeLabel;
  52138. //}
  52139. }
  52140. raycast(raycaster, intersects) {
  52141. var is = [];
  52142. this.sphere.raycast(raycaster, is);
  52143. if (is.length > 0) {
  52144. var I = is[0];
  52145. intersects.push({
  52146. distance: I.distance,
  52147. object: this,
  52148. point: I.point.clone()
  52149. });
  52150. }
  52151. }
  52152. // see https://en.wikipedia.org/wiki/Ellipsoid#Volume
  52153. getVolume() {
  52154. return 4 / 3 * Math.PI * this.scale.x * this.scale.y * this.scale.z;
  52155. }
  52156. }
  52157. ;
  52158. //2022.11.11 copyfrom : https://unpkg.com/three@0.146.0/examples/jsm/loaders/DRACOLoader.js
  52159. var _taskCache = new WeakMap();
  52160. class DRACOLoader extends Loader {
  52161. constructor(manager) {
  52162. super(manager);
  52163. this.decoderPath = '';
  52164. this.decoderConfig = {
  52165. TOTAL_MEMORY: Potree.settings.TOTAL_MEMORY
  52166. };
  52167. this.decoderBinary = null;
  52168. this.decoderPending = null;
  52169. this.workerLimit = 4;
  52170. this.workerPool = [];
  52171. this.workerNextTaskID = 1;
  52172. this.workerSourceURL = '';
  52173. this.defaultAttributeIDs = {
  52174. position: 'POSITION',
  52175. normal: 'NORMAL',
  52176. color: 'COLOR',
  52177. uv: 'TEX_COORD'
  52178. };
  52179. this.defaultAttributeTypes = {
  52180. position: 'Float32Array',
  52181. normal: 'Float32Array',
  52182. color: 'Float32Array',
  52183. uv: 'Float32Array'
  52184. };
  52185. }
  52186. setDecoderPath(path) {
  52187. this.decoderPath = path;
  52188. return this;
  52189. }
  52190. setDecoderConfig(config) {
  52191. this.decoderConfig = config;
  52192. return this;
  52193. }
  52194. setWorkerLimit(workerLimit) {
  52195. this.workerLimit = workerLimit;
  52196. return this;
  52197. }
  52198. load(url, onLoad, onProgress, onError) {
  52199. var loader = new FileLoader(this.manager);
  52200. loader.setPath(this.path);
  52201. loader.setResponseType('arraybuffer');
  52202. loader.setRequestHeader(this.requestHeader);
  52203. loader.setWithCredentials(this.withCredentials);
  52204. loader.load(url, buffer => {
  52205. this.decodeDracoFile(buffer, onLoad).catch(onError);
  52206. }, onProgress, onError);
  52207. }
  52208. decodeDracoFile(buffer, callback, attributeIDs, attributeTypes) {
  52209. var taskConfig = {
  52210. attributeIDs: attributeIDs || this.defaultAttributeIDs,
  52211. attributeTypes: attributeTypes || this.defaultAttributeTypes,
  52212. useUniqueIDs: !!attributeIDs
  52213. };
  52214. return this.decodeGeometry(buffer, taskConfig).then(callback);
  52215. }
  52216. decodeGeometry(buffer, taskConfig) {
  52217. var taskKey = JSON.stringify(taskConfig);
  52218. // Check for an existing task using this buffer. A transferred buffer cannot be transferred
  52219. // again from this thread.
  52220. if (_taskCache.has(buffer)) {
  52221. var cachedTask = _taskCache.get(buffer);
  52222. if (cachedTask.key === taskKey) {
  52223. return cachedTask.promise;
  52224. } else if (buffer.byteLength === 0) {
  52225. // Technically, it would be possible to wait for the previous task to complete,
  52226. // transfer the buffer back, and decode again with the second configuration. That
  52227. // is complex, and I don't know of any reason to decode a Draco buffer twice in
  52228. // different ways, so this is left unimplemented.
  52229. throw new Error('THREE.DRACOLoader: Unable to re-decode a buffer with different ' + 'settings. Buffer has already been transferred.');
  52230. }
  52231. }
  52232. //
  52233. var worker;
  52234. var taskID = this.workerNextTaskID++;
  52235. var taskCost = buffer.byteLength;
  52236. // Obtain a worker and assign a task, and construct a geometry instance
  52237. // when the task completes.
  52238. var geometryPending = this._getWorker(taskID, taskCost).then(_worker => {
  52239. worker = _worker;
  52240. return new Promise((resolve, reject) => {
  52241. worker._callbacks[taskID] = {
  52242. resolve,
  52243. reject
  52244. };
  52245. worker.postMessage({
  52246. type: 'decode',
  52247. id: taskID,
  52248. taskConfig,
  52249. buffer
  52250. }, [buffer]);
  52251. // this.debug();
  52252. });
  52253. }).then(message => this._createGeometry(message.geometry));
  52254. // Remove task from the task list.
  52255. // Note: replaced '.finally()' with '.catch().then()' block - iOS 11 support (#19416)
  52256. geometryPending.catch(() => true).then(() => {
  52257. if (worker && taskID) {
  52258. this._releaseTask(worker, taskID);
  52259. // this.debug();
  52260. }
  52261. });
  52262. // Cache the task result.
  52263. _taskCache.set(buffer, {
  52264. key: taskKey,
  52265. promise: geometryPending
  52266. });
  52267. return geometryPending;
  52268. }
  52269. _createGeometry(geometryData) {
  52270. var geometry = new BufferGeometry();
  52271. if (geometryData.index) {
  52272. geometry.setIndex(new BufferAttribute(geometryData.index.array, 1));
  52273. }
  52274. for (var i = 0; i < geometryData.attributes.length; i++) {
  52275. var attribute = geometryData.attributes[i];
  52276. var name = attribute.name;
  52277. var array = attribute.array;
  52278. var itemSize = attribute.itemSize;
  52279. geometry.setAttribute(name, new BufferAttribute(array, itemSize));
  52280. }
  52281. return geometry;
  52282. }
  52283. _loadLibrary(url, responseType) {
  52284. var loader = new FileLoader(this.manager);
  52285. loader.setPath(this.decoderPath);
  52286. loader.setResponseType(responseType);
  52287. loader.setWithCredentials(this.withCredentials);
  52288. return new Promise((resolve, reject) => {
  52289. loader.load(url, resolve, undefined, reject);
  52290. });
  52291. }
  52292. preload() {
  52293. this._initDecoder();
  52294. return this;
  52295. }
  52296. _initDecoder() {
  52297. if (this.decoderPending) return this.decoderPending;
  52298. var useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js';
  52299. var librariesPending = [];
  52300. if (useJS) {
  52301. librariesPending.push(this._loadLibrary('draco_decoder.js', 'text'));
  52302. } else {
  52303. librariesPending.push(this._loadLibrary('draco_wasm_wrapper.js', 'text'));
  52304. librariesPending.push(this._loadLibrary('draco_decoder.wasm', 'arraybuffer'));
  52305. }
  52306. this.decoderPending = Promise.all(librariesPending).then(libraries => {
  52307. var jsContent = libraries[0];
  52308. if (!useJS) {
  52309. this.decoderConfig.wasmBinary = libraries[1];
  52310. }
  52311. var fn = DRACOWorker.toString();
  52312. var body = ['/* draco decoder */', jsContent, '', '/* worker */', fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))].join('\n');
  52313. this.workerSourceURL = URL.createObjectURL(new Blob([body]));
  52314. });
  52315. return this.decoderPending;
  52316. }
  52317. _getWorker(taskID, taskCost) {
  52318. return this._initDecoder().then(() => {
  52319. if (this.workerPool.length < this.workerLimit) {
  52320. var _worker2 = new Worker(this.workerSourceURL);
  52321. _worker2._callbacks = {};
  52322. _worker2._taskCosts = {};
  52323. _worker2._taskLoad = 0;
  52324. _worker2.postMessage({
  52325. type: 'init',
  52326. decoderConfig: this.decoderConfig
  52327. });
  52328. _worker2.onmessage = function (e) {
  52329. var message = e.data;
  52330. switch (message.type) {
  52331. case 'decode':
  52332. _worker2._callbacks[message.id].resolve(message);
  52333. break;
  52334. case 'error':
  52335. _worker2._callbacks[message.id].reject(message);
  52336. break;
  52337. default:
  52338. console.error('THREE.DRACOLoader: Unexpected message, "' + message.type + '"');
  52339. }
  52340. };
  52341. this.workerPool.push(_worker2);
  52342. } else {
  52343. this.workerPool.sort(function (a, b) {
  52344. return a._taskLoad > b._taskLoad ? -1 : 1;
  52345. });
  52346. }
  52347. var worker = this.workerPool[this.workerPool.length - 1];
  52348. worker._taskCosts[taskID] = taskCost;
  52349. worker._taskLoad += taskCost;
  52350. return worker;
  52351. });
  52352. }
  52353. _releaseTask(worker, taskID) {
  52354. worker._taskLoad -= worker._taskCosts[taskID];
  52355. delete worker._callbacks[taskID];
  52356. delete worker._taskCosts[taskID];
  52357. }
  52358. debug() {
  52359. console.log('Task load: ', this.workerPool.map(worker => worker._taskLoad));
  52360. }
  52361. dispose() {
  52362. for (var i = 0; i < this.workerPool.length; ++i) {
  52363. this.workerPool[i].terminate();
  52364. }
  52365. this.workerPool.length = 0;
  52366. return this;
  52367. }
  52368. }
  52369. /* WEB WORKER */
  52370. function DRACOWorker() {
  52371. var decoderConfig;
  52372. var decoderPending;
  52373. onmessage = function onmessage(e) {
  52374. var message = e.data;
  52375. switch (message.type) {
  52376. case 'init':
  52377. decoderConfig = message.decoderConfig;
  52378. decoderPending = new Promise(function (resolve /*, reject*/) {
  52379. decoderConfig.onModuleLoaded = function (draco) {
  52380. // Module is Promise-like. Wrap before resolving to avoid loop.
  52381. resolve({
  52382. draco: draco
  52383. });
  52384. };
  52385. DracoDecoderModule(decoderConfig); // eslint-disable-line no-undef
  52386. });
  52387. break;
  52388. case 'decode':
  52389. var buffer = message.buffer;
  52390. var taskConfig = message.taskConfig;
  52391. decoderPending.then(module => {
  52392. var draco = module.draco;
  52393. var decoder = new draco.Decoder();
  52394. var decoderBuffer = new draco.DecoderBuffer();
  52395. decoderBuffer.Init(new Int8Array(buffer), buffer.byteLength);
  52396. try {
  52397. var geometry = decodeGeometry(draco, decoder, decoderBuffer, taskConfig);
  52398. var buffers = geometry.attributes.map(attr => attr.array.buffer);
  52399. if (geometry.index) buffers.push(geometry.index.array.buffer);
  52400. self.postMessage({
  52401. type: 'decode',
  52402. id: message.id,
  52403. geometry
  52404. }, buffers);
  52405. } catch (error) {
  52406. console.error(error);
  52407. self.postMessage({
  52408. type: 'error',
  52409. id: message.id,
  52410. error: error.message
  52411. });
  52412. } finally {
  52413. draco.destroy(decoderBuffer);
  52414. draco.destroy(decoder);
  52415. }
  52416. });
  52417. break;
  52418. }
  52419. };
  52420. function decodeGeometry(draco, decoder, decoderBuffer, taskConfig) {
  52421. var attributeIDs = taskConfig.attributeIDs;
  52422. var attributeTypes = taskConfig.attributeTypes;
  52423. var dracoGeometry;
  52424. var decodingStatus;
  52425. var geometryType = decoder.GetEncodedGeometryType(decoderBuffer);
  52426. if (geometryType === draco.TRIANGULAR_MESH) {
  52427. dracoGeometry = new draco.Mesh();
  52428. decodingStatus = decoder.DecodeBufferToMesh(decoderBuffer, dracoGeometry);
  52429. } else if (geometryType === draco.POINT_CLOUD) {
  52430. dracoGeometry = new draco.PointCloud();
  52431. decodingStatus = decoder.DecodeBufferToPointCloud(decoderBuffer, dracoGeometry);
  52432. } else {
  52433. throw new Error('THREE.DRACOLoader: Unexpected geometry type.');
  52434. }
  52435. if (!decodingStatus.ok() || dracoGeometry.ptr === 0) {
  52436. throw new Error('THREE.DRACOLoader: Decoding failed: ' + decodingStatus.error_msg());
  52437. }
  52438. var geometry = {
  52439. index: null,
  52440. attributes: []
  52441. };
  52442. // Gather all vertex attributes.
  52443. for (var attributeName in attributeIDs) {
  52444. var attributeType = self[attributeTypes[attributeName]];
  52445. var attribute = void 0;
  52446. var attributeID = void 0;
  52447. // A Draco file may be created with default vertex attributes, whose attribute IDs
  52448. // are mapped 1:1 from their semantic name (POSITION, NORMAL, ...). Alternatively,
  52449. // a Draco file may contain a custom set of attributes, identified by known unique
  52450. // IDs. glTF files always do the latter, and `.drc` files typically do the former.
  52451. if (taskConfig.useUniqueIDs) {
  52452. attributeID = attributeIDs[attributeName];
  52453. attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeID);
  52454. } else {
  52455. attributeID = decoder.GetAttributeId(dracoGeometry, draco[attributeIDs[attributeName]]);
  52456. if (attributeID === -1) continue;
  52457. attribute = decoder.GetAttribute(dracoGeometry, attributeID);
  52458. }
  52459. geometry.attributes.push(decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute));
  52460. }
  52461. // Add index.
  52462. if (geometryType === draco.TRIANGULAR_MESH) {
  52463. geometry.index = decodeIndex(draco, decoder, dracoGeometry);
  52464. }
  52465. draco.destroy(dracoGeometry);
  52466. return geometry;
  52467. }
  52468. function decodeIndex(draco, decoder, dracoGeometry) {
  52469. var numFaces = dracoGeometry.num_faces();
  52470. var numIndices = numFaces * 3;
  52471. var byteLength = numIndices * 4;
  52472. var ptr = draco._malloc(byteLength);
  52473. decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
  52474. var index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice();
  52475. draco._free(ptr);
  52476. return {
  52477. array: index,
  52478. itemSize: 1
  52479. };
  52480. }
  52481. function decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute) {
  52482. var numComponents = attribute.num_components();
  52483. var numPoints = dracoGeometry.num_points();
  52484. var numValues = numPoints * numComponents;
  52485. var byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
  52486. var dataType = getDracoDataType(draco, attributeType);
  52487. var ptr = draco._malloc(byteLength);
  52488. decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr);
  52489. var array = new attributeType(draco.HEAPF32.buffer, ptr, numValues).slice();
  52490. draco._free(ptr);
  52491. return {
  52492. name: attributeName,
  52493. array: array,
  52494. itemSize: numComponents
  52495. };
  52496. }
  52497. function getDracoDataType(draco, attributeType) {
  52498. switch (attributeType) {
  52499. case Float32Array:
  52500. return draco.DT_FLOAT32;
  52501. case Int8Array:
  52502. return draco.DT_INT8;
  52503. case Int16Array:
  52504. return draco.DT_INT16;
  52505. case Int32Array:
  52506. return draco.DT_INT32;
  52507. case Uint8Array:
  52508. return draco.DT_UINT8;
  52509. case Uint16Array:
  52510. return draco.DT_UINT16;
  52511. case Uint32Array:
  52512. return draco.DT_UINT32;
  52513. }
  52514. }
  52515. }
  52516. /**
  52517. * @author Deepkolos / https://github.com/deepkolos
  52518. */
  52519. //用于KTX2Loader
  52520. class WorkerPool$1 {
  52521. constructor() {
  52522. var pool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;
  52523. this.pool = pool;
  52524. this.queue = [];
  52525. this.workers = [];
  52526. this.workersResolve = [];
  52527. this.workerStatus = 0;
  52528. }
  52529. _initWorker(workerId) {
  52530. if (!this.workers[workerId]) {
  52531. var worker = this.workerCreator();
  52532. worker.addEventListener('message', this._onMessage.bind(this, workerId));
  52533. this.workers[workerId] = worker;
  52534. }
  52535. }
  52536. _getIdleWorker() {
  52537. for (var i = 0; i < this.pool; i++) if (!(this.workerStatus & 1 << i)) return i;
  52538. return -1;
  52539. }
  52540. _onMessage(workerId, msg) {
  52541. var resolve = this.workersResolve[workerId];
  52542. resolve && resolve(msg);
  52543. if (this.queue.length) {
  52544. var {
  52545. resolve: _resolve,
  52546. msg: _msg,
  52547. transfer
  52548. } = this.queue.shift();
  52549. this.workersResolve[workerId] = _resolve;
  52550. this.workers[workerId].postMessage(_msg, transfer);
  52551. } else {
  52552. this.workerStatus ^= 1 << workerId;
  52553. }
  52554. }
  52555. setWorkerCreator(workerCreator) {
  52556. this.workerCreator = workerCreator;
  52557. }
  52558. setWorkerLimit(pool) {
  52559. this.pool = pool;
  52560. }
  52561. postMessage(msg, transfer) {
  52562. return new Promise(resolve => {
  52563. var workerId = this._getIdleWorker();
  52564. if (workerId !== -1) {
  52565. this._initWorker(workerId);
  52566. this.workerStatus |= 1 << workerId;
  52567. this.workersResolve[workerId] = resolve;
  52568. this.workers[workerId].postMessage(msg, transfer);
  52569. } else {
  52570. this.queue.push({
  52571. resolve,
  52572. msg,
  52573. transfer
  52574. });
  52575. }
  52576. });
  52577. }
  52578. dispose() {
  52579. this.workers.forEach(worker => worker.terminate());
  52580. this.workersResolve.length = 0;
  52581. this.workers.length = 0;
  52582. this.queue.length = 0;
  52583. this.workerStatus = 0;
  52584. }
  52585. }
  52586. var t = 0,
  52587. e$1 = 1,
  52588. n$1 = 2,
  52589. i$2 = 3,
  52590. s = 0,
  52591. a$1 = 0,
  52592. r = 2,
  52593. o$1 = 0,
  52594. l$1 = 1,
  52595. f = 160,
  52596. U$1 = 161,
  52597. c$1 = 162,
  52598. h$2 = 163,
  52599. _$1 = 0,
  52600. p = 1,
  52601. g = 0,
  52602. y = 1,
  52603. x$2 = 2,
  52604. u$2 = 3,
  52605. b$1 = 4,
  52606. d = 5,
  52607. m = 6,
  52608. w$1 = 7,
  52609. D = 8,
  52610. B = 9,
  52611. L = 10,
  52612. A = 11,
  52613. k = 12,
  52614. v = 13,
  52615. S$1 = 14,
  52616. I = 15,
  52617. O = 16,
  52618. T$1 = 17,
  52619. V = 18,
  52620. E = 0,
  52621. F = 1,
  52622. P = 2,
  52623. C = 3,
  52624. z = 4,
  52625. M$1 = 5,
  52626. W = 6,
  52627. N = 7,
  52628. H = 8,
  52629. K = 9,
  52630. X = 10,
  52631. j = 11,
  52632. R = 0,
  52633. Y = 1,
  52634. q = 2,
  52635. G = 13,
  52636. J = 14,
  52637. Q = 15,
  52638. Z = 128,
  52639. $$1 = 64,
  52640. tt = 32,
  52641. et = 16,
  52642. nt = 0,
  52643. it = 1,
  52644. st = 2,
  52645. at = 3,
  52646. rt = 4,
  52647. ot = 5,
  52648. lt = 6,
  52649. ft = 7,
  52650. Ut = 8,
  52651. ct = 9,
  52652. ht = 10,
  52653. _t = 13,
  52654. pt = 14,
  52655. gt = 15,
  52656. yt = 16,
  52657. xt = 17,
  52658. ut = 20,
  52659. bt = 21,
  52660. dt = 22,
  52661. mt = 23,
  52662. wt = 24,
  52663. Dt = 27,
  52664. Bt = 28,
  52665. Lt = 29,
  52666. At = 30,
  52667. kt = 31,
  52668. vt = 34,
  52669. St = 35,
  52670. It = 36,
  52671. Ot = 37,
  52672. Tt = 38,
  52673. Vt = 41,
  52674. Et = 42,
  52675. Ft = 43,
  52676. Pt = 44,
  52677. Ct = 45,
  52678. zt = 48,
  52679. Mt = 49,
  52680. Wt = 50,
  52681. Nt = 58,
  52682. Ht = 59,
  52683. Kt = 62,
  52684. Xt = 63,
  52685. jt = 64,
  52686. Rt = 65,
  52687. Yt = 68,
  52688. qt = 69,
  52689. Gt = 70,
  52690. Jt = 71,
  52691. Qt = 74,
  52692. Zt = 75,
  52693. $t = 76,
  52694. te = 77,
  52695. ee = 78,
  52696. ne = 81,
  52697. ie = 82,
  52698. se = 83,
  52699. ae = 84,
  52700. re = 85,
  52701. oe = 88,
  52702. le = 89,
  52703. fe = 90,
  52704. Ue = 91,
  52705. ce = 92,
  52706. he = 95,
  52707. _e = 96,
  52708. pe = 97,
  52709. ge = 98,
  52710. ye = 99,
  52711. xe = 100,
  52712. ue = 101,
  52713. be = 102,
  52714. de = 103,
  52715. me = 104,
  52716. we = 105,
  52717. De = 106,
  52718. Be = 107,
  52719. Le = 108,
  52720. Ae = 109,
  52721. ke = 110,
  52722. ve = 111,
  52723. Se = 112,
  52724. Ie = 113,
  52725. Oe = 114,
  52726. Te = 115,
  52727. Ve = 116,
  52728. Ee = 117,
  52729. Fe = 118,
  52730. Pe = 119,
  52731. Ce = 120,
  52732. ze = 121,
  52733. Me = 122,
  52734. We = 123,
  52735. Ne = 124,
  52736. He = 125,
  52737. Ke = 126,
  52738. Xe = 127,
  52739. je = 128,
  52740. Re = 129,
  52741. Ye = 130,
  52742. qe = 131,
  52743. Ge = 132,
  52744. Je = 133,
  52745. Qe = 134,
  52746. Ze = 135,
  52747. $e = 136,
  52748. tn = 137,
  52749. en = 138,
  52750. nn = 139,
  52751. sn = 140,
  52752. an = 141,
  52753. rn = 142,
  52754. on = 143,
  52755. ln = 144,
  52756. fn = 145,
  52757. Un = 146,
  52758. cn = 147,
  52759. hn = 148,
  52760. _n = 149,
  52761. pn = 150,
  52762. gn = 151,
  52763. yn = 152,
  52764. xn = 153,
  52765. un = 154,
  52766. bn = 155,
  52767. dn = 156,
  52768. mn = 157,
  52769. wn = 158,
  52770. Dn = 159,
  52771. Bn = 160,
  52772. Ln = 161,
  52773. An = 162,
  52774. kn = 163,
  52775. vn = 164,
  52776. Sn = 165,
  52777. In = 166,
  52778. On = 167,
  52779. Tn = 168,
  52780. Vn = 169,
  52781. En = 170,
  52782. Fn = 171,
  52783. Pn = 172,
  52784. Cn = 173,
  52785. zn = 174,
  52786. Mn = 175,
  52787. Wn = 176,
  52788. Nn = 177,
  52789. Hn = 178,
  52790. Kn = 179,
  52791. Xn = 180,
  52792. jn = 181,
  52793. Rn = 182,
  52794. Yn = 183,
  52795. qn = 184,
  52796. Gn = 1000156007,
  52797. Jn = 1000156008,
  52798. Qn = 1000156009,
  52799. Zn = 1000156010,
  52800. $n = 1000156011,
  52801. ti = 1000156017,
  52802. ei = 1000156018,
  52803. ni = 1000156019,
  52804. ii = 1000156020,
  52805. si = 1000156021,
  52806. ai = 1000054e3,
  52807. ri = 1000054001,
  52808. oi = 1000054002,
  52809. li = 1000054003,
  52810. fi = 1000054004,
  52811. Ui = 1000054005,
  52812. ci = 1000054006,
  52813. hi = 1000054007,
  52814. _i = 1000066e3,
  52815. pi = 1000066001,
  52816. gi = 1000066002,
  52817. yi = 1000066003,
  52818. xi = 1000066004,
  52819. ui = 1000066005,
  52820. bi = 1000066006,
  52821. di = 1000066007,
  52822. mi = 1000066008,
  52823. wi = 1000066009,
  52824. Di = 1000066010,
  52825. Bi = 1000066011,
  52826. Li = 1000066012,
  52827. Ai = 1000066013,
  52828. ki = 100034e4,
  52829. vi = 1000340001;
  52830. class Si {
  52831. constructor() {
  52832. 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 = [{
  52833. vendorId: 0,
  52834. descriptorType: 0,
  52835. descriptorBlockSize: 0,
  52836. versionNumber: 2,
  52837. colorModel: 0,
  52838. colorPrimaries: 1,
  52839. transferFunction: 2,
  52840. flags: 0,
  52841. texelBlockDimension: [0, 0, 0, 0],
  52842. bytesPlane: [0, 0, 0, 0, 0, 0, 0, 0],
  52843. samples: []
  52844. }], this.keyValue = {}, this.globalData = null;
  52845. }
  52846. }
  52847. class Ii {
  52848. constructor(t, e, n, i) {
  52849. this._dataView = new DataView(t.buffer, t.byteOffset + e, n), this._littleEndian = i, this._offset = 0;
  52850. }
  52851. _nextUint8() {
  52852. var t = this._dataView.getUint8(this._offset);
  52853. return this._offset += 1, t;
  52854. }
  52855. _nextUint16() {
  52856. var t = this._dataView.getUint16(this._offset, this._littleEndian);
  52857. return this._offset += 2, t;
  52858. }
  52859. _nextUint32() {
  52860. var t = this._dataView.getUint32(this._offset, this._littleEndian);
  52861. return this._offset += 4, t;
  52862. }
  52863. _nextUint64() {
  52864. var t = this._dataView.getUint32(this._offset, this._littleEndian) + 2 ** 32 * this._dataView.getUint32(this._offset + 4, this._littleEndian);
  52865. return this._offset += 8, t;
  52866. }
  52867. _nextInt32() {
  52868. var t = this._dataView.getInt32(this._offset, this._littleEndian);
  52869. return this._offset += 4, t;
  52870. }
  52871. _skip(t) {
  52872. return this._offset += t, this;
  52873. }
  52874. _scan(t) {
  52875. var e = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  52876. var n = this._offset;
  52877. var i = 0;
  52878. for (; this._dataView.getUint8(this._offset) !== e && i < t;) i++, this._offset++;
  52879. return i < t && this._offset++, new Uint8Array(this._dataView.buffer, this._dataView.byteOffset + n, i);
  52880. }
  52881. }
  52882. var Oi = new Uint8Array([0]),
  52883. Ti = [171, 75, 84, 88, 32, 50, 48, 187, 13, 10, 26, 10];
  52884. function Vi(t) {
  52885. return "undefined" != typeof TextEncoder ? new TextEncoder().encode(t) : Buffer.from(t);
  52886. }
  52887. function Ei(t) {
  52888. return "undefined" != typeof TextDecoder ? new TextDecoder().decode(t) : Buffer.from(t).toString("utf8");
  52889. }
  52890. function Fi(t) {
  52891. var e = 0;
  52892. for (var _n2 of t) e += _n2.byteLength;
  52893. var n = new Uint8Array(e);
  52894. var i = 0;
  52895. for (var _e2 of t) n.set(new Uint8Array(_e2), i), i += _e2.byteLength;
  52896. return n;
  52897. }
  52898. function Pi(t) {
  52899. var e = new Uint8Array(t.buffer, t.byteOffset, Ti.length);
  52900. 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.");
  52901. var n = new Si(),
  52902. i = 17 * Uint32Array.BYTES_PER_ELEMENT,
  52903. s = new Ii(t, Ti.length, i, !0);
  52904. 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();
  52905. var a = s._nextUint32();
  52906. n.supercompressionScheme = s._nextUint32();
  52907. var r = s._nextUint32(),
  52908. o = s._nextUint32(),
  52909. l = s._nextUint32(),
  52910. f = s._nextUint32(),
  52911. U = s._nextUint64(),
  52912. c = s._nextUint64(),
  52913. h = new Ii(t, Ti.length + i, 3 * a * 8, !0);
  52914. for (var _e3 = 0; _e3 < a; _e3++) n.levels.push({
  52915. levelData: new Uint8Array(t.buffer, t.byteOffset + h._nextUint64(), h._nextUint64()),
  52916. uncompressedByteLength: h._nextUint64()
  52917. });
  52918. var _ = new Ii(t, r, o, !0),
  52919. p = {
  52920. vendorId: _._skip(4)._nextUint16(),
  52921. descriptorType: _._nextUint16(),
  52922. versionNumber: _._nextUint16(),
  52923. descriptorBlockSize: _._nextUint16(),
  52924. colorModel: _._nextUint8(),
  52925. colorPrimaries: _._nextUint8(),
  52926. transferFunction: _._nextUint8(),
  52927. flags: _._nextUint8(),
  52928. texelBlockDimension: [_._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8()],
  52929. bytesPlane: [_._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8()],
  52930. samples: []
  52931. },
  52932. g = (p.descriptorBlockSize / 4 - 6) / 4;
  52933. for (var _t2 = 0; _t2 < g; _t2++) {
  52934. var _e4 = {
  52935. bitOffset: _._nextUint16(),
  52936. bitLength: _._nextUint8(),
  52937. channelType: _._nextUint8(),
  52938. samplePosition: [_._nextUint8(), _._nextUint8(), _._nextUint8(), _._nextUint8()],
  52939. sampleLower: -Infinity,
  52940. sampleUpper: Infinity
  52941. };
  52942. 64 & _e4.channelType ? (_e4.sampleLower = _._nextInt32(), _e4.sampleUpper = _._nextInt32()) : (_e4.sampleLower = _._nextUint32(), _e4.sampleUpper = _._nextUint32()), p.samples[_t2] = _e4;
  52943. }
  52944. n.dataFormatDescriptor.length = 0, n.dataFormatDescriptor.push(p);
  52945. var y = new Ii(t, l, f, !0);
  52946. for (; y._offset < f;) {
  52947. var _t3 = y._nextUint32(),
  52948. _e5 = y._scan(_t3),
  52949. _i2 = Ei(_e5),
  52950. _s = y._scan(_t3 - _e5.byteLength);
  52951. n.keyValue[_i2] = _i2.match(/^ktx/i) ? Ei(_s) : _s, y._offset % 4 && y._skip(4 - y._offset % 4);
  52952. }
  52953. if (c <= 0) return n;
  52954. var x = new Ii(t, U, c, !0),
  52955. u = x._nextUint16(),
  52956. b = x._nextUint16(),
  52957. d = x._nextUint32(),
  52958. m = x._nextUint32(),
  52959. w = x._nextUint32(),
  52960. D = x._nextUint32(),
  52961. B = [];
  52962. for (var _t4 = 0; _t4 < a; _t4++) B.push({
  52963. imageFlags: x._nextUint32(),
  52964. rgbSliceByteOffset: x._nextUint32(),
  52965. rgbSliceByteLength: x._nextUint32(),
  52966. alphaSliceByteOffset: x._nextUint32(),
  52967. alphaSliceByteLength: x._nextUint32()
  52968. });
  52969. var L = U + x._offset,
  52970. A = L + d,
  52971. k = A + m,
  52972. v = k + w,
  52973. S = new Uint8Array(t.buffer, t.byteOffset + L, d),
  52974. I = new Uint8Array(t.buffer, t.byteOffset + A, m),
  52975. O = new Uint8Array(t.buffer, t.byteOffset + k, w),
  52976. T = new Uint8Array(t.buffer, t.byteOffset + v, D);
  52977. return n.globalData = {
  52978. endpointCount: u,
  52979. selectorCount: b,
  52980. imageDescs: B,
  52981. endpointsData: S,
  52982. selectorsData: I,
  52983. tablesData: O,
  52984. extendedData: T
  52985. }, n;
  52986. }
  52987. function Ci() {
  52988. return (Ci = Object.assign || function (t) {
  52989. for (var e = 1; e < arguments.length; e++) {
  52990. var n = arguments[e];
  52991. for (var i in n) Object.prototype.hasOwnProperty.call(n, i) && (t[i] = n[i]);
  52992. }
  52993. return t;
  52994. }).apply(this, arguments);
  52995. }
  52996. var zi = {
  52997. keepWriter: !1
  52998. };
  52999. function Mi(t) {
  53000. var e = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  53001. e = Ci({}, zi, e);
  53002. var n = new ArrayBuffer(0);
  53003. if (t.globalData) {
  53004. var _e6 = new ArrayBuffer(20 + 5 * t.globalData.imageDescs.length * 4),
  53005. _i3 = new DataView(_e6);
  53006. _i3.setUint16(0, t.globalData.endpointCount, !0), _i3.setUint16(2, t.globalData.selectorCount, !0), _i3.setUint32(4, t.globalData.endpointsData.byteLength, !0), _i3.setUint32(8, t.globalData.selectorsData.byteLength, !0), _i3.setUint32(12, t.globalData.tablesData.byteLength, !0), _i3.setUint32(16, t.globalData.extendedData.byteLength, !0);
  53007. for (var _e7 = 0; _e7 < t.globalData.imageDescs.length; _e7++) {
  53008. var _n3 = t.globalData.imageDescs[_e7];
  53009. _i3.setUint32(20 + 5 * _e7 * 4 + 0, _n3.imageFlags, !0), _i3.setUint32(20 + 5 * _e7 * 4 + 4, _n3.rgbSliceByteOffset, !0), _i3.setUint32(20 + 5 * _e7 * 4 + 8, _n3.rgbSliceByteLength, !0), _i3.setUint32(20 + 5 * _e7 * 4 + 12, _n3.alphaSliceByteOffset, !0), _i3.setUint32(20 + 5 * _e7 * 4 + 16, _n3.alphaSliceByteLength, !0);
  53010. }
  53011. n = Fi([_e6, t.globalData.endpointsData, t.globalData.selectorsData, t.globalData.tablesData, t.globalData.extendedData]);
  53012. }
  53013. var i = [];
  53014. var s = t.keyValue;
  53015. e.keepWriter || (s = Ci({}, t.keyValue, {
  53016. KTXwriter: "KTX-Parse v0.3.1"
  53017. }));
  53018. for (var _t5 in s) {
  53019. var _e8 = s[_t5],
  53020. _n4 = Vi(_t5),
  53021. _a = "string" == typeof _e8 ? Vi(_e8) : _e8,
  53022. _r = _n4.byteLength + 1 + _a.byteLength + 1,
  53023. _o = _r % 4 ? 4 - _r % 4 : 0;
  53024. i.push(Fi([new Uint32Array([_r]), _n4, Oi, _a, Oi, new Uint8Array(_o).fill(0)]));
  53025. }
  53026. var a = Fi(i);
  53027. if (1 !== t.dataFormatDescriptor.length || 0 !== t.dataFormatDescriptor[0].descriptorType) throw new Error("Only BASICFORMAT Data Format Descriptor output supported.");
  53028. var r = t.dataFormatDescriptor[0],
  53029. o = new ArrayBuffer(28 + 16 * r.samples.length),
  53030. l = new DataView(o),
  53031. f = 24 + 16 * r.samples.length;
  53032. 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`.");
  53033. l.setUint8(16, r.texelBlockDimension[0]), l.setUint8(17, r.texelBlockDimension[1]), l.setUint8(18, r.texelBlockDimension[2]), l.setUint8(19, r.texelBlockDimension[3]);
  53034. for (var _t6 = 0; _t6 < 8; _t6++) l.setUint8(20 + _t6, r.bytesPlane[_t6]);
  53035. for (var _t7 = 0; _t7 < r.samples.length; _t7++) {
  53036. var _e9 = r.samples[_t7],
  53037. _n5 = 28 + 16 * _t7;
  53038. if (_e9.channelID) throw new Error("channelID has been renamed to channelType.");
  53039. l.setUint16(_n5 + 0, _e9.bitOffset, !0), l.setUint8(_n5 + 2, _e9.bitLength), l.setUint8(_n5 + 3, _e9.channelType), l.setUint8(_n5 + 4, _e9.samplePosition[0]), l.setUint8(_n5 + 5, _e9.samplePosition[1]), l.setUint8(_n5 + 6, _e9.samplePosition[2]), l.setUint8(_n5 + 7, _e9.samplePosition[3]), 64 & _e9.channelType ? (l.setInt32(_n5 + 8, _e9.sampleLower, !0), l.setInt32(_n5 + 12, _e9.sampleUpper, !0)) : (l.setUint32(_n5 + 8, _e9.sampleLower, !0), l.setUint32(_n5 + 12, _e9.sampleUpper, !0));
  53040. }
  53041. var U = Ti.length + 68 + 3 * t.levels.length * 8,
  53042. c = U + o.byteLength;
  53043. var h = n.byteLength > 0 ? c + a.byteLength : 0;
  53044. h % 8 && (h += 8 - h % 8);
  53045. var _ = [],
  53046. p = new DataView(new ArrayBuffer(3 * t.levels.length * 8));
  53047. var g = (h || c + a.byteLength) + n.byteLength;
  53048. for (var _e10 = 0; _e10 < t.levels.length; _e10++) {
  53049. var _n6 = t.levels[_e10];
  53050. _.push(_n6.levelData), p.setBigUint64(24 * _e10 + 0, BigInt(g), !0), p.setBigUint64(24 * _e10 + 8, BigInt(_n6.levelData.byteLength), !0), p.setBigUint64(24 * _e10 + 16, BigInt(_n6.uncompressedByteLength), !0), g += _n6.levelData.byteLength;
  53051. }
  53052. var y = new ArrayBuffer(68),
  53053. x = new DataView(y);
  53054. 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, ..._]));
  53055. }
  53056. /**
  53057. * @author Don McCurdy / https://www.donmccurdy.com
  53058. */
  53059. var init, instance, heap;
  53060. var importObject = {
  53061. env: {
  53062. emscripten_notify_memory_growth: function emscripten_notify_memory_growth(index) {
  53063. heap = new Uint8Array(instance.exports.memory.buffer);
  53064. }
  53065. }
  53066. };
  53067. /**
  53068. * ZSTD (Zstandard) decoder.
  53069. *
  53070. * Compiled from https://github.com/facebook/zstd/tree/dev/contrib/single_file_libs, with the
  53071. * following steps:
  53072. *
  53073. * ```
  53074. * ./combine.sh -r ../../lib -o zstddeclib.c zstddeclib-in.c
  53075. * 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
  53076. * base64 zstddec.wasm > zstddec.txt
  53077. * ```
  53078. *
  53079. * The base64 string written to `zstddec.txt` is embedded as the `wasm` variable at the bottom
  53080. * of this file. The rest of this file is written by hand, in order to avoid an additional JS
  53081. * wrapper generated by Emscripten.
  53082. */
  53083. class ZSTDDecoder {
  53084. init() {
  53085. if (!init) {
  53086. init = fetch('data:application/wasm;base64,' + wasm).then(response => response.arrayBuffer()).then(arrayBuffer => WebAssembly.instantiate(arrayBuffer, importObject)).then(result => {
  53087. instance = result.instance;
  53088. importObject.env.emscripten_notify_memory_growth(0); // initialize heap.
  53089. });
  53090. }
  53091. return init;
  53092. }
  53093. decode(array) {
  53094. var uncompressedSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  53095. // Write compressed data into WASM memory.
  53096. var compressedSize = array.byteLength;
  53097. var compressedPtr = instance.exports.malloc(compressedSize);
  53098. heap.set(array, compressedPtr);
  53099. // Decompress into WASM memory.
  53100. uncompressedSize = uncompressedSize || Number(instance.exports.ZSTD_findDecompressedSize(compressedPtr, compressedSize));
  53101. var uncompressedPtr = instance.exports.malloc(uncompressedSize);
  53102. var actualSize = instance.exports.ZSTD_decompress(uncompressedPtr, uncompressedSize, compressedPtr, compressedSize);
  53103. // Read decompressed data and free WASM memory.
  53104. var dec = heap.slice(uncompressedPtr, uncompressedPtr + actualSize);
  53105. instance.exports.free(compressedPtr);
  53106. instance.exports.free(uncompressedPtr);
  53107. return dec;
  53108. }
  53109. }
  53110. /**
  53111. * BSD License
  53112. *
  53113. * For Zstandard software
  53114. *
  53115. * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. All rights reserved.
  53116. *
  53117. * Redistribution and use in source and binary forms, with or without modification,
  53118. * are permitted provided that the following conditions are met:
  53119. *
  53120. * * Redistributions of source code must retain the above copyright notice, this
  53121. * list of conditions and the following disclaimer.
  53122. *
  53123. * * Redistributions in binary form must reproduce the above copyright notice,
  53124. * this list of conditions and the following disclaimer in the documentation
  53125. * and/or other materials provided with the distribution.
  53126. *
  53127. * * Neither the name Facebook nor the names of its contributors may be used to
  53128. * endorse or promote products derived from this software without specific
  53129. * prior written permission.
  53130. *
  53131. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  53132. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  53133. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  53134. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  53135. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  53136. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  53137. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  53138. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  53139. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  53140. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  53141. */
  53142. var 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';
  53143. /**
  53144. * Loader for KTX 2.0 GPU Texture containers.
  53145. *
  53146. * KTX 2.0 is a container format for various GPU texture formats. The loader
  53147. * supports Basis Universal GPU textures, which can be quickly transcoded to
  53148. * a wide variety of GPU texture compression formats, as well as some
  53149. * uncompressed DataTexture and Data3DTexture formats.
  53150. *
  53151. * References:
  53152. * - KTX: http://github.khronos.org/KTX-Specification/
  53153. * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor
  53154. */
  53155. var _taskCache$1 = new WeakMap();
  53156. var _activeLoaders = 0;
  53157. var _zstd;
  53158. class KTX2Loader extends Loader {
  53159. constructor(manager) {
  53160. super(manager);
  53161. this.transcoderPath = '';
  53162. this.transcoderBinary = null;
  53163. this.transcoderPending = null;
  53164. this.workerPool = new WorkerPool$1();
  53165. this.workerSourceURL = '';
  53166. this.workerConfig = null;
  53167. if (typeof MSC_TRANSCODER !== 'undefined') {
  53168. console.warn('THREE.KTX2Loader: Please update to latest "basis_transcoder".' + ' "msc_basis_transcoder" is no longer supported in three.js r125+.');
  53169. }
  53170. }
  53171. setTranscoderPath(path) {
  53172. this.transcoderPath = path;
  53173. return this;
  53174. }
  53175. setWorkerLimit(num) {
  53176. this.workerPool.setWorkerLimit(num);
  53177. return this;
  53178. }
  53179. detectSupport(renderer) {
  53180. this.workerConfig = {
  53181. astcSupported: renderer.extensions.has('WEBGL_compressed_texture_astc'),
  53182. etc1Supported: renderer.extensions.has('WEBGL_compressed_texture_etc1'),
  53183. etc2Supported: renderer.extensions.has('WEBGL_compressed_texture_etc'),
  53184. dxtSupported: renderer.extensions.has('WEBGL_compressed_texture_s3tc'),
  53185. bptcSupported: renderer.extensions.has('EXT_texture_compression_bptc'),
  53186. pvrtcSupported: renderer.extensions.has('WEBGL_compressed_texture_pvrtc') || renderer.extensions.has('WEBKIT_WEBGL_compressed_texture_pvrtc')
  53187. };
  53188. if (renderer.capabilities.isWebGL2) {
  53189. // https://github.com/mrdoob/three.js/pull/22928
  53190. this.workerConfig.etc1Supported = false;
  53191. }
  53192. return this;
  53193. }
  53194. init() {
  53195. if (!this.transcoderPending) {
  53196. // Load transcoder wrapper.
  53197. var jsLoader = new FileLoader(this.manager);
  53198. jsLoader.setPath(this.transcoderPath);
  53199. jsLoader.setWithCredentials(this.withCredentials);
  53200. var jsContent = jsLoader.loadAsync('basis_transcoder.js');
  53201. // Load transcoder WASM binary.
  53202. var binaryLoader = new FileLoader(this.manager);
  53203. binaryLoader.setPath(this.transcoderPath);
  53204. binaryLoader.setResponseType('arraybuffer');
  53205. binaryLoader.setWithCredentials(this.withCredentials);
  53206. var binaryContent = binaryLoader.loadAsync('basis_transcoder.wasm');
  53207. this.transcoderPending = Promise.all([jsContent, binaryContent]).then(_ref => {
  53208. var [jsContent, binaryContent] = _ref;
  53209. var fn = KTX2Loader.BasisWorker.toString();
  53210. var body = ['/* constants */', 'let _EngineFormat = ' + JSON.stringify(KTX2Loader.EngineFormat), 'let _TranscoderFormat = ' + JSON.stringify(KTX2Loader.TranscoderFormat), 'let _BasisFormat = ' + JSON.stringify(KTX2Loader.BasisFormat), '/* basis_transcoder.js */', jsContent, '/* worker */', fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))].join('\n');
  53211. this.workerSourceURL = URL.createObjectURL(new Blob([body]));
  53212. this.transcoderBinary = binaryContent;
  53213. this.workerPool.setWorkerCreator(() => {
  53214. var worker = new Worker(this.workerSourceURL);
  53215. var transcoderBinary = this.transcoderBinary.slice(0);
  53216. worker.postMessage({
  53217. type: 'init',
  53218. config: this.workerConfig,
  53219. transcoderBinary
  53220. }, [transcoderBinary]);
  53221. return worker;
  53222. });
  53223. });
  53224. if (_activeLoaders > 0) {
  53225. // Each instance loads a transcoder and allocates workers, increasing network and memory cost.
  53226. console.warn('THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.' + ' Use a single KTX2Loader instance, or call .dispose() on old instances.');
  53227. }
  53228. _activeLoaders++;
  53229. }
  53230. return this.transcoderPending;
  53231. }
  53232. load(url, onLoad, onProgress, onError) {
  53233. if (this.workerConfig === null) {
  53234. throw new Error('THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.');
  53235. }
  53236. var loader = new FileLoader(this.manager);
  53237. loader.setResponseType('arraybuffer');
  53238. loader.setWithCredentials(this.withCredentials);
  53239. loader.load(url, buffer => {
  53240. // Check for an existing task using this buffer. A transferred buffer cannot be transferred
  53241. // again from this thread.
  53242. if (_taskCache$1.has(buffer)) {
  53243. var cachedTask = _taskCache$1.get(buffer);
  53244. return cachedTask.promise.then(onLoad).catch(onError);
  53245. }
  53246. this._createTexture(buffer).then(texture => onLoad ? onLoad(texture) : null).catch(onError);
  53247. }, onProgress, onError);
  53248. }
  53249. _createTextureFrom(transcodeResult, container) {
  53250. var {
  53251. mipmaps,
  53252. width,
  53253. height,
  53254. format,
  53255. type,
  53256. error,
  53257. dfdTransferFn,
  53258. dfdFlags
  53259. } = transcodeResult;
  53260. if (type === 'error') return Promise.reject(error);
  53261. var texture = container.layerCount > 1 ? new CompressedArrayTexture(mipmaps, width, height, container.layerCount, format, UnsignedByteType) : new CompressedTexture(mipmaps, width, height, format, UnsignedByteType);
  53262. texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
  53263. texture.magFilter = LinearFilter;
  53264. texture.generateMipmaps = false;
  53265. texture.needsUpdate = true;
  53266. texture.encoding = dfdTransferFn === x$2 ? sRGBEncoding : LinearEncoding;
  53267. texture.premultiplyAlpha = !!(dfdFlags & p);
  53268. return texture;
  53269. }
  53270. /**
  53271. * @param {ArrayBuffer} buffer
  53272. * @param {object?} config
  53273. * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
  53274. */
  53275. async _createTexture(buffer) {
  53276. var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  53277. var container = Pi(new Uint8Array(buffer));
  53278. if (container.vkFormat !== nt) {
  53279. return createDataTexture(container);
  53280. }
  53281. //
  53282. var taskConfig = config;
  53283. var texturePending = this.init().then(() => {
  53284. return this.workerPool.postMessage({
  53285. type: 'transcode',
  53286. buffer,
  53287. taskConfig: taskConfig
  53288. }, [buffer]);
  53289. }).then(e => this._createTextureFrom(e.data, container));
  53290. // Cache the task result.
  53291. _taskCache$1.set(buffer, {
  53292. promise: texturePending
  53293. });
  53294. return texturePending;
  53295. }
  53296. dispose() {
  53297. this.workerPool.dispose();
  53298. if (this.workerSourceURL) URL.revokeObjectURL(this.workerSourceURL);
  53299. _activeLoaders--;
  53300. return this;
  53301. }
  53302. }
  53303. /* CONSTANTS */
  53304. KTX2Loader.BasisFormat = {
  53305. ETC1S: 0,
  53306. UASTC_4x4: 1
  53307. };
  53308. KTX2Loader.TranscoderFormat = {
  53309. ETC1: 0,
  53310. ETC2: 1,
  53311. BC1: 2,
  53312. BC3: 3,
  53313. BC4: 4,
  53314. BC5: 5,
  53315. BC7_M6_OPAQUE_ONLY: 6,
  53316. BC7_M5: 7,
  53317. PVRTC1_4_RGB: 8,
  53318. PVRTC1_4_RGBA: 9,
  53319. ASTC_4x4: 10,
  53320. ATC_RGB: 11,
  53321. ATC_RGBA_INTERPOLATED_ALPHA: 12,
  53322. RGBA32: 13,
  53323. RGB565: 14,
  53324. BGR565: 15,
  53325. RGBA4444: 16
  53326. };
  53327. KTX2Loader.EngineFormat = {
  53328. RGBAFormat: RGBAFormat,
  53329. RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
  53330. RGBA_BPTC_Format: RGBA_BPTC_Format,
  53331. RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
  53332. RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
  53333. RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format$1,
  53334. RGB_ETC1_Format: RGB_ETC1_Format,
  53335. RGB_ETC2_Format: RGB_ETC2_Format,
  53336. RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
  53337. RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format
  53338. };
  53339. /* WEB WORKER */
  53340. KTX2Loader.BasisWorker = function () {
  53341. var config;
  53342. var transcoderPending;
  53343. var BasisModule;
  53344. var EngineFormat = _EngineFormat; // eslint-disable-line no-undef
  53345. var TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
  53346. var BasisFormat = _BasisFormat; // eslint-disable-line no-undef
  53347. self.addEventListener('message', function (e) {
  53348. var message = e.data;
  53349. switch (message.type) {
  53350. case 'init':
  53351. config = message.config;
  53352. init(message.transcoderBinary);
  53353. break;
  53354. case 'transcode':
  53355. transcoderPending.then(() => {
  53356. try {
  53357. var {
  53358. width,
  53359. height,
  53360. hasAlpha,
  53361. mipmaps,
  53362. format,
  53363. dfdTransferFn,
  53364. dfdFlags
  53365. } = transcode(message.buffer);
  53366. var buffers = [];
  53367. for (var i = 0; i < mipmaps.length; ++i) {
  53368. buffers.push(mipmaps[i].data.buffer);
  53369. }
  53370. self.postMessage({
  53371. type: 'transcode',
  53372. id: message.id,
  53373. width,
  53374. height,
  53375. hasAlpha,
  53376. mipmaps,
  53377. format,
  53378. dfdTransferFn,
  53379. dfdFlags
  53380. }, buffers);
  53381. } catch (error) {
  53382. console.error(error);
  53383. self.postMessage({
  53384. type: 'error',
  53385. id: message.id,
  53386. error: error.message
  53387. });
  53388. }
  53389. });
  53390. break;
  53391. }
  53392. });
  53393. function init(wasmBinary) {
  53394. transcoderPending = new Promise(resolve => {
  53395. BasisModule = {
  53396. wasmBinary,
  53397. onRuntimeInitialized: resolve
  53398. };
  53399. BASIS(BasisModule); // eslint-disable-line no-undef
  53400. }).then(() => {
  53401. BasisModule.initializeBasis();
  53402. if (BasisModule.KTX2File === undefined) {
  53403. console.warn('THREE.KTX2Loader: Please update Basis Universal transcoder.');
  53404. }
  53405. });
  53406. }
  53407. function transcode(buffer) {
  53408. var ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
  53409. function cleanup() {
  53410. ktx2File.close();
  53411. ktx2File.delete();
  53412. }
  53413. if (!ktx2File.isValid()) {
  53414. cleanup();
  53415. throw new Error('THREE.KTX2Loader: Invalid or unsupported .ktx2 file');
  53416. }
  53417. var basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
  53418. var width = ktx2File.getWidth();
  53419. var height = ktx2File.getHeight();
  53420. var layers = ktx2File.getLayers() || 1;
  53421. var levels = ktx2File.getLevels();
  53422. var hasAlpha = ktx2File.getHasAlpha();
  53423. var dfdTransferFn = ktx2File.getDFDTransferFunc();
  53424. var dfdFlags = ktx2File.getDFDFlags();
  53425. var {
  53426. transcoderFormat,
  53427. engineFormat
  53428. } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
  53429. if (!width || !height || !levels) {
  53430. cleanup();
  53431. throw new Error('THREE.KTX2Loader: Invalid texture');
  53432. }
  53433. if (!ktx2File.startTranscoding()) {
  53434. cleanup();
  53435. throw new Error('THREE.KTX2Loader: .startTranscoding failed');
  53436. }
  53437. var mipmaps = [];
  53438. for (var mip = 0; mip < levels; mip++) {
  53439. var layerMips = [];
  53440. var mipWidth = void 0,
  53441. mipHeight = void 0;
  53442. for (var layer = 0; layer < layers; layer++) {
  53443. var levelInfo = ktx2File.getImageLevelInfo(mip, layer, 0);
  53444. mipWidth = levelInfo.origWidth;
  53445. mipHeight = levelInfo.origHeight;
  53446. var dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, layer, 0, transcoderFormat));
  53447. var status = ktx2File.transcodeImage(dst, mip, layer, 0, transcoderFormat, 0, -1, -1);
  53448. if (!status) {
  53449. cleanup();
  53450. throw new Error('THREE.KTX2Loader: .transcodeImage failed.');
  53451. }
  53452. layerMips.push(dst);
  53453. }
  53454. mipmaps.push({
  53455. data: concat(layerMips),
  53456. width: mipWidth,
  53457. height: mipHeight
  53458. });
  53459. }
  53460. cleanup();
  53461. return {
  53462. width,
  53463. height,
  53464. hasAlpha,
  53465. mipmaps,
  53466. format: engineFormat,
  53467. dfdTransferFn,
  53468. dfdFlags
  53469. };
  53470. }
  53471. //
  53472. // Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
  53473. // device capabilities, and texture dimensions. The list below ranks the formats separately
  53474. // for ETC1S and UASTC.
  53475. //
  53476. // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
  53477. // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
  53478. // chooses RGBA32 only as a last resort and does not expose that option to the caller.
  53479. var FORMAT_OPTIONS = [{
  53480. if: 'astcSupported',
  53481. basisFormat: [BasisFormat.UASTC_4x4],
  53482. transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
  53483. engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
  53484. priorityETC1S: Infinity,
  53485. priorityUASTC: 1,
  53486. needsPowerOfTwo: false
  53487. }, {
  53488. if: 'bptcSupported',
  53489. basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
  53490. transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
  53491. engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
  53492. priorityETC1S: 3,
  53493. priorityUASTC: 2,
  53494. needsPowerOfTwo: false
  53495. }, {
  53496. if: 'dxtSupported',
  53497. basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
  53498. transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
  53499. engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
  53500. priorityETC1S: 4,
  53501. priorityUASTC: 5,
  53502. needsPowerOfTwo: false
  53503. }, {
  53504. if: 'etc2Supported',
  53505. basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
  53506. transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
  53507. engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
  53508. priorityETC1S: 1,
  53509. priorityUASTC: 3,
  53510. needsPowerOfTwo: false
  53511. }, {
  53512. if: 'etc1Supported',
  53513. basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
  53514. transcoderFormat: [TranscoderFormat.ETC1],
  53515. engineFormat: [EngineFormat.RGB_ETC1_Format],
  53516. priorityETC1S: 2,
  53517. priorityUASTC: 4,
  53518. needsPowerOfTwo: false
  53519. }, {
  53520. if: 'pvrtcSupported',
  53521. basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
  53522. transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
  53523. engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
  53524. priorityETC1S: 5,
  53525. priorityUASTC: 6,
  53526. needsPowerOfTwo: true
  53527. }];
  53528. var ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
  53529. return a.priorityETC1S - b.priorityETC1S;
  53530. });
  53531. var UASTC_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
  53532. return a.priorityUASTC - b.priorityUASTC;
  53533. });
  53534. function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
  53535. var transcoderFormat;
  53536. var engineFormat;
  53537. var options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
  53538. for (var i = 0; i < options.length; i++) {
  53539. var opt = options[i];
  53540. if (!config[opt.if]) continue;
  53541. if (!opt.basisFormat.includes(basisFormat)) continue;
  53542. if (hasAlpha && opt.transcoderFormat.length < 2) continue;
  53543. if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height))) continue;
  53544. transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
  53545. engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
  53546. return {
  53547. transcoderFormat,
  53548. engineFormat
  53549. };
  53550. }
  53551. console.warn('THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.');
  53552. transcoderFormat = TranscoderFormat.RGBA32;
  53553. engineFormat = EngineFormat.RGBAFormat;
  53554. return {
  53555. transcoderFormat,
  53556. engineFormat
  53557. };
  53558. }
  53559. function isPowerOfTwo(value) {
  53560. if (value <= 2) return true;
  53561. return (value & value - 1) === 0 && value !== 0;
  53562. }
  53563. /** Concatenates N byte arrays. */
  53564. function concat(arrays) {
  53565. var totalByteLength = 0;
  53566. for (var array of arrays) {
  53567. totalByteLength += array.byteLength;
  53568. }
  53569. var result = new Uint8Array(totalByteLength);
  53570. var byteOffset = 0;
  53571. for (var _array of arrays) {
  53572. result.set(_array, byteOffset);
  53573. byteOffset += _array.byteLength;
  53574. }
  53575. return result;
  53576. }
  53577. };
  53578. //
  53579. // DataTexture and Data3DTexture parsing.
  53580. var FORMAT_MAP = {
  53581. [Ae]: RGBAFormat,
  53582. [pe]: RGBAFormat,
  53583. [Ot]: RGBAFormat,
  53584. [Ft]: RGBAFormat,
  53585. [de]: RGFormat,
  53586. [se]: RGFormat,
  53587. [yt]: RGFormat,
  53588. [dt]: RGFormat,
  53589. [xe]: RedFormat,
  53590. [$t]: RedFormat,
  53591. [gt]: RedFormat,
  53592. [ct]: RedFormat
  53593. };
  53594. var TYPE_MAP = {
  53595. [Ae]: FloatType,
  53596. [pe]: HalfFloatType,
  53597. [Ot]: UnsignedByteType,
  53598. [Ft]: UnsignedByteType,
  53599. [de]: FloatType,
  53600. [se]: HalfFloatType,
  53601. [yt]: UnsignedByteType,
  53602. [dt]: UnsignedByteType,
  53603. [xe]: FloatType,
  53604. [$t]: HalfFloatType,
  53605. [gt]: UnsignedByteType,
  53606. [ct]: UnsignedByteType
  53607. };
  53608. var ENCODING_MAP = {
  53609. [Ft]: sRGBEncoding,
  53610. [dt]: sRGBEncoding,
  53611. [gt]: sRGBEncoding
  53612. };
  53613. async function createDataTexture(container) {
  53614. var {
  53615. vkFormat,
  53616. pixelWidth,
  53617. pixelHeight,
  53618. pixelDepth
  53619. } = container;
  53620. if (FORMAT_MAP[vkFormat] === undefined) {
  53621. throw new Error('THREE.KTX2Loader: Unsupported vkFormat.');
  53622. }
  53623. var level = container.levels[0];
  53624. var levelData;
  53625. var view;
  53626. if (container.supercompressionScheme === t) {
  53627. levelData = level.levelData;
  53628. } else if (container.supercompressionScheme === n$1) {
  53629. if (!_zstd) {
  53630. _zstd = new Promise(async resolve => {
  53631. var zstd = new ZSTDDecoder();
  53632. await zstd.init();
  53633. resolve(zstd);
  53634. });
  53635. }
  53636. levelData = (await _zstd).decode(level.levelData, level.uncompressedByteLength);
  53637. } else {
  53638. throw new Error('THREE.KTX2Loader: Unsupported supercompressionScheme.');
  53639. }
  53640. if (TYPE_MAP[vkFormat] === FloatType) {
  53641. view = new Float32Array(levelData.buffer, levelData.byteOffset, levelData.byteLength / Float32Array.BYTES_PER_ELEMENT);
  53642. } else if (TYPE_MAP[vkFormat] === HalfFloatType) {
  53643. view = new Uint16Array(levelData.buffer, levelData.byteOffset, levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT);
  53644. } else {
  53645. view = levelData;
  53646. }
  53647. //
  53648. var texture = pixelDepth === 0 ? new DataTexture(view, pixelWidth, pixelHeight) : new Data3DTexture(view, pixelWidth, pixelHeight, pixelDepth);
  53649. texture.type = TYPE_MAP[vkFormat];
  53650. texture.format = FORMAT_MAP[vkFormat];
  53651. texture.encoding = ENCODING_MAP[vkFormat] || LinearEncoding;
  53652. texture.needsUpdate = true;
  53653. //
  53654. return Promise.resolve(texture);
  53655. }
  53656. // This file is part of meshoptimizer library and is distributed under the terms of MIT License.
  53657. // Copyright (C) 2016-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
  53658. var MeshoptDecoder = function () {
  53659. "use strict";
  53660. // Built with clang version 11.0.0 (https://github.com/llvm/llvm-project.git 0160ad802e899c2922bc9b29564080c22eb0908c)
  53661. // Built from meshoptimizer 0.14
  53662. 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";
  53663. 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";
  53664. // Uses bulk-memory and simd extensions
  53665. 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]);
  53666. // Used to unpack wasm
  53667. 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]);
  53668. if (typeof WebAssembly !== 'object') {
  53669. // This module requires WebAssembly to function
  53670. return {
  53671. supported: false
  53672. };
  53673. }
  53674. var wasm = wasm_base;
  53675. if (WebAssembly.validate(detector)) {
  53676. wasm = wasm_simd;
  53677. console.log("Warning: meshopt_decoder is using experimental SIMD support");
  53678. }
  53679. var instance;
  53680. var promise = WebAssembly.instantiate(unpack(wasm), {}).then(function (result) {
  53681. instance = result.instance;
  53682. instance.exports.__wasm_call_ctors();
  53683. });
  53684. function unpack(data) {
  53685. var result = new Uint8Array(data.length);
  53686. for (var i = 0; i < data.length; ++i) {
  53687. var ch = data.charCodeAt(i);
  53688. result[i] = ch > 96 ? ch - 71 : ch > 64 ? ch - 65 : ch > 47 ? ch + 4 : ch > 46 ? 63 : 62;
  53689. }
  53690. var write = 0;
  53691. for (var i = 0; i < data.length; ++i) {
  53692. result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
  53693. }
  53694. return result.buffer.slice(0, write);
  53695. }
  53696. function decode(fun, target, count, size, source, filter) {
  53697. var sbrk = instance.exports.sbrk;
  53698. var count4 = count + 3 & ~3; // pad for SIMD filter
  53699. var tp = sbrk(count4 * size);
  53700. var sp = sbrk(source.length);
  53701. var heap = new Uint8Array(instance.exports.memory.buffer);
  53702. heap.set(source, sp);
  53703. var res = fun(tp, count, size, sp, source.length);
  53704. if (res == 0 && filter) {
  53705. filter(tp, count4, size);
  53706. }
  53707. target.set(heap.subarray(tp, tp + count * size));
  53708. sbrk(tp - sbrk(0));
  53709. if (res != 0) {
  53710. throw new Error("Malformed buffer data: " + res);
  53711. }
  53712. }
  53713. ;
  53714. var filters = {
  53715. // legacy index-based enums for glTF
  53716. 0: "",
  53717. 1: "meshopt_decodeFilterOct",
  53718. 2: "meshopt_decodeFilterQuat",
  53719. 3: "meshopt_decodeFilterExp",
  53720. // string-based enums for glTF
  53721. NONE: "",
  53722. OCTAHEDRAL: "meshopt_decodeFilterOct",
  53723. QUATERNION: "meshopt_decodeFilterQuat",
  53724. EXPONENTIAL: "meshopt_decodeFilterExp"
  53725. };
  53726. var decoders = {
  53727. // legacy index-based enums for glTF
  53728. 0: "meshopt_decodeVertexBuffer",
  53729. 1: "meshopt_decodeIndexBuffer",
  53730. 2: "meshopt_decodeIndexSequence",
  53731. // string-based enums for glTF
  53732. ATTRIBUTES: "meshopt_decodeVertexBuffer",
  53733. TRIANGLES: "meshopt_decodeIndexBuffer",
  53734. INDICES: "meshopt_decodeIndexSequence"
  53735. };
  53736. return {
  53737. ready: promise,
  53738. supported: true,
  53739. decodeVertexBuffer: function decodeVertexBuffer(target, count, size, source, filter) {
  53740. decode(instance.exports.meshopt_decodeVertexBuffer, target, count, size, source, instance.exports[filters[filter]]);
  53741. },
  53742. decodeIndexBuffer: function decodeIndexBuffer(target, count, size, source) {
  53743. decode(instance.exports.meshopt_decodeIndexBuffer, target, count, size, source);
  53744. },
  53745. decodeIndexSequence: function decodeIndexSequence(target, count, size, source) {
  53746. decode(instance.exports.meshopt_decodeIndexSequence, target, count, size, source);
  53747. },
  53748. decodeGltfBuffer: function decodeGltfBuffer(target, count, size, source, mode, filter) {
  53749. decode(instance.exports[decoders[mode]], target, count, size, source, instance.exports[filters[filter]]);
  53750. }
  53751. };
  53752. }();
  53753. var DDSLoader = function DDSLoader(manager) {
  53754. CompressedTextureLoader.call(this, manager);
  53755. };
  53756. DDSLoader.prototype = Object.assign(Object.create(CompressedTextureLoader.prototype), {
  53757. constructor: DDSLoader,
  53758. parse: function parse(buffer, loadMipmaps) {
  53759. var dds = {
  53760. mipmaps: [],
  53761. width: 0,
  53762. height: 0,
  53763. format: null,
  53764. mipmapCount: 1
  53765. };
  53766. // Adapted from @toji's DDS utils
  53767. // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js
  53768. // All values and structures referenced from:
  53769. // http://msdn.microsoft.com/en-us/library/bb943991.aspx/
  53770. var DDS_MAGIC = 0x20534444;
  53771. // var DDSD_CAPS = 0x1;
  53772. // var DDSD_HEIGHT = 0x2;
  53773. // var DDSD_WIDTH = 0x4;
  53774. // var DDSD_PITCH = 0x8;
  53775. // var DDSD_PIXELFORMAT = 0x1000;
  53776. var DDSD_MIPMAPCOUNT = 0x20000;
  53777. // var DDSD_LINEARSIZE = 0x80000;
  53778. // var DDSD_DEPTH = 0x800000;
  53779. // var DDSCAPS_COMPLEX = 0x8;
  53780. // var DDSCAPS_MIPMAP = 0x400000;
  53781. // var DDSCAPS_TEXTURE = 0x1000;
  53782. var DDSCAPS2_CUBEMAP = 0x200;
  53783. var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400;
  53784. var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800;
  53785. var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000;
  53786. var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000;
  53787. var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000;
  53788. var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000;
  53789. // var DDSCAPS2_VOLUME = 0x200000;
  53790. // var DDPF_ALPHAPIXELS = 0x1;
  53791. // var DDPF_ALPHA = 0x2;
  53792. var DDPF_FOURCC = 0x4;
  53793. // var DDPF_RGB = 0x40;
  53794. // var DDPF_YUV = 0x200;
  53795. // var DDPF_LUMINANCE = 0x20000;
  53796. function fourCCToInt32(value) {
  53797. return value.charCodeAt(0) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) << 16) + (value.charCodeAt(3) << 24);
  53798. }
  53799. function int32ToFourCC(value) {
  53800. return String.fromCharCode(value & 0xff, value >> 8 & 0xff, value >> 16 & 0xff, value >> 24 & 0xff);
  53801. }
  53802. function loadARGBMip(buffer, dataOffset, width, height) {
  53803. var dataLength = width * height * 4;
  53804. var srcBuffer = new Uint8Array(buffer, dataOffset, dataLength);
  53805. var byteArray = new Uint8Array(dataLength);
  53806. var dst = 0;
  53807. var src = 0;
  53808. for (var y = 0; y < height; y++) {
  53809. for (var x = 0; x < width; x++) {
  53810. var b = srcBuffer[src];
  53811. src++;
  53812. var g = srcBuffer[src];
  53813. src++;
  53814. var r = srcBuffer[src];
  53815. src++;
  53816. var a = srcBuffer[src];
  53817. src++;
  53818. byteArray[dst] = r;
  53819. dst++; //r
  53820. byteArray[dst] = g;
  53821. dst++; //g
  53822. byteArray[dst] = b;
  53823. dst++; //b
  53824. byteArray[dst] = a;
  53825. dst++; //a
  53826. }
  53827. }
  53828. return byteArray;
  53829. }
  53830. var FOURCC_DXT1 = fourCCToInt32('DXT1');
  53831. var FOURCC_DXT3 = fourCCToInt32('DXT3');
  53832. var FOURCC_DXT5 = fourCCToInt32('DXT5');
  53833. var FOURCC_ETC1 = fourCCToInt32('ETC1');
  53834. var headerLengthInt = 31; // The header length in 32 bit ints
  53835. // Offsets into the header array
  53836. var off_magic = 0;
  53837. var off_size = 1;
  53838. var off_flags = 2;
  53839. var off_height = 3;
  53840. var off_width = 4;
  53841. var off_mipmapCount = 7;
  53842. var off_pfFlags = 20;
  53843. var off_pfFourCC = 21;
  53844. var off_RGBBitCount = 22;
  53845. var off_RBitMask = 23;
  53846. var off_GBitMask = 24;
  53847. var off_BBitMask = 25;
  53848. var off_ABitMask = 26;
  53849. // var off_caps = 27;
  53850. var off_caps2 = 28;
  53851. // var off_caps3 = 29;
  53852. // var off_caps4 = 30;
  53853. // Parse header
  53854. var header = new Int32Array(buffer, 0, headerLengthInt);
  53855. if (header[off_magic] !== DDS_MAGIC) {
  53856. console.error('THREE.DDSLoader.parse: Invalid magic number in DDS header.');
  53857. return dds;
  53858. }
  53859. if (!header[off_pfFlags] & DDPF_FOURCC) {
  53860. console.error('THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.');
  53861. return dds;
  53862. }
  53863. var blockBytes;
  53864. var fourCC = header[off_pfFourCC];
  53865. var isRGBAUncompressed = false;
  53866. switch (fourCC) {
  53867. case FOURCC_DXT1:
  53868. blockBytes = 8;
  53869. dds.format = RGB_S3TC_DXT1_Format;
  53870. break;
  53871. case FOURCC_DXT3:
  53872. blockBytes = 16;
  53873. dds.format = RGBA_S3TC_DXT3_Format;
  53874. break;
  53875. case FOURCC_DXT5:
  53876. blockBytes = 16;
  53877. dds.format = RGBA_S3TC_DXT5_Format$1;
  53878. break;
  53879. case FOURCC_ETC1:
  53880. blockBytes = 8;
  53881. dds.format = RGB_ETC1_Format;
  53882. break;
  53883. default:
  53884. if (header[off_RGBBitCount] === 32 && header[off_RBitMask] & 0xff0000 && header[off_GBitMask] & 0xff00 && header[off_BBitMask] & 0xff && header[off_ABitMask] & 0xff000000) {
  53885. isRGBAUncompressed = true;
  53886. blockBytes = 64;
  53887. dds.format = RGBAFormat;
  53888. } else {
  53889. console.error('THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC(fourCC));
  53890. return dds;
  53891. }
  53892. }
  53893. dds.mipmapCount = 1;
  53894. if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
  53895. dds.mipmapCount = Math.max(1, header[off_mipmapCount]);
  53896. }
  53897. var caps2 = header[off_caps2];
  53898. dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false;
  53899. if (dds.isCubemap && (!(caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) || !(caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) || !(caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ))) {
  53900. console.error('THREE.DDSLoader.parse: Incomplete cubemap faces');
  53901. return dds;
  53902. }
  53903. dds.width = header[off_width];
  53904. dds.height = header[off_height];
  53905. var dataOffset = header[off_size] + 4;
  53906. // Extract mipmaps buffers
  53907. var faces = dds.isCubemap ? 6 : 1;
  53908. for (var face = 0; face < faces; face++) {
  53909. var width = dds.width;
  53910. var height = dds.height;
  53911. for (var i = 0; i < dds.mipmapCount; i++) {
  53912. if (isRGBAUncompressed) {
  53913. var byteArray = loadARGBMip(buffer, dataOffset, width, height);
  53914. var dataLength = byteArray.length;
  53915. } else {
  53916. var dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
  53917. var byteArray = new Uint8Array(buffer, dataOffset, dataLength);
  53918. }
  53919. var mipmap = {
  53920. 'data': byteArray,
  53921. 'width': width,
  53922. 'height': height
  53923. };
  53924. dds.mipmaps.push(mipmap);
  53925. dataOffset += dataLength;
  53926. width = Math.max(width >> 1, 1);
  53927. height = Math.max(height >> 1, 1);
  53928. }
  53929. }
  53930. return dds;
  53931. }
  53932. });
  53933. //import BasicMaterial from '../../../src/custom/materials/BasicMaterial.js'
  53934. //xzw add:----
  53935. var unknownExtensions = {};
  53936. var GLTFLoader = function () {
  53937. function GLTFLoader(manager, renderer, urlPrefix) {
  53938. Loader.call(this, manager);
  53939. //xzw add:
  53940. this.dracoLoader = new DRACOLoader();
  53941. this.ktx2Loader = new KTX2Loader();
  53942. this.meshoptDecoder = MeshoptDecoder;
  53943. this.ddsLoader = new DDSLoader(); //这个没测过
  53944. //路径相对于index.html
  53945. this.dracoLoader.setDecoderPath(urlPrefix + 'three.js/loaders/draco/' /*or 'https://unpkg.com/three@0.144.0/examples/js/libs/draco/gltf/' 版本可升级 */); //这两个路径可以自己改。在laser的环境也要放一份这个路径
  53946. this.ktx2Loader.setTranscoderPath(urlPrefix + 'three.js/loaders/basis/' /*or 'https://unpkg.com/three@0.144.0/examples/js/libs/basis/' 版本可升级 */).detectSupport(renderer);
  53947. /*
  53948. this.dracoLoader = null;
  53949. this.ddsLoader = null;
  53950. this.ktx2Loader = null;
  53951. this.meshoptDecoder = null;
  53952. */
  53953. this.pluginCallbacks = [];
  53954. this.register(function (parser) {
  53955. return new GLTFMaterialsClearcoatExtension(parser);
  53956. });
  53957. this.register(function (parser) {
  53958. return new GLTFTextureBasisUExtension(parser);
  53959. });
  53960. this.register(function (parser) {
  53961. return new GLTFTextureWebPExtension(parser);
  53962. });
  53963. this.register(function (parser) {
  53964. return new GLTFMaterialsTransmissionExtension(parser);
  53965. });
  53966. this.register(function (parser) {
  53967. return new GLTFLightsExtension(parser);
  53968. });
  53969. this.register(function (parser) {
  53970. return new GLTFMeshoptCompression(parser);
  53971. });
  53972. }
  53973. GLTFLoader.prototype = Object.assign(Object.create(Loader.prototype), {
  53974. constructor: GLTFLoader,
  53975. load: function load(url, onLoad, onProgress, onError) {
  53976. var scope = this;
  53977. var resourcePath;
  53978. if (this.resourcePath !== '') {
  53979. resourcePath = this.resourcePath;
  53980. } else if (this.path !== '') {
  53981. resourcePath = this.path;
  53982. } else {
  53983. resourcePath = LoaderUtils.extractUrlBase(url);
  53984. }
  53985. // Tells the LoadingManager to track an extra item, which resolves after
  53986. // the model is fully loaded. This means the count of items loaded will
  53987. // be incorrect, but ensures manager.onLoad() does not fire early.
  53988. this.manager.itemStart(url);
  53989. var _onError = function _onError(e) {
  53990. if (onError) {
  53991. onError(e);
  53992. } else {
  53993. console.error(e);
  53994. }
  53995. scope.manager.itemError(url);
  53996. scope.manager.itemEnd(url);
  53997. };
  53998. var loader = new FileLoader(this.manager);
  53999. loader.setPath(this.path);
  54000. loader.setResponseType('arraybuffer');
  54001. loader.setRequestHeader(this.requestHeader);
  54002. loader.setWithCredentials(this.withCredentials);
  54003. loader.load(url, function (data) {
  54004. try {
  54005. scope.parse(data, resourcePath, function (gltf) {
  54006. onLoad(gltf);
  54007. scope.manager.itemEnd(url);
  54008. }, _onError);
  54009. } catch (e) {
  54010. _onError(e);
  54011. }
  54012. }, onProgress, _onError);
  54013. },
  54014. setDRACOLoader: function setDRACOLoader(dracoLoader) {
  54015. this.dracoLoader = dracoLoader;
  54016. return this;
  54017. },
  54018. setDDSLoader: function setDDSLoader(ddsLoader) {
  54019. this.ddsLoader = ddsLoader;
  54020. return this;
  54021. },
  54022. setKTX2Loader: function setKTX2Loader(ktx2Loader) {
  54023. this.ktx2Loader = ktx2Loader;
  54024. return this;
  54025. },
  54026. setMeshoptDecoder: function setMeshoptDecoder(meshoptDecoder) {
  54027. this.meshoptDecoder = meshoptDecoder;
  54028. return this;
  54029. },
  54030. register: function register(callback) {
  54031. if (this.pluginCallbacks.indexOf(callback) === -1) {
  54032. this.pluginCallbacks.push(callback);
  54033. }
  54034. return this;
  54035. },
  54036. unregister: function unregister(callback) {
  54037. if (this.pluginCallbacks.indexOf(callback) !== -1) {
  54038. this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback), 1);
  54039. }
  54040. return this;
  54041. },
  54042. parse: function parse(data, path, onLoad, onError) {
  54043. var content;
  54044. var extensions = {};
  54045. var plugins = {};
  54046. if (typeof data === 'string') {
  54047. content = data;
  54048. } else {
  54049. var magic = LoaderUtils.decodeText(new Uint8Array(data, 0, 4));
  54050. if (magic === BINARY_EXTENSION_HEADER_MAGIC) {
  54051. try {
  54052. extensions[EXTENSIONS.KHR_BINARY_GLTF] = new GLTFBinaryExtension(data);
  54053. } catch (error) {
  54054. if (onError) onError(error);
  54055. return;
  54056. }
  54057. content = extensions[EXTENSIONS.KHR_BINARY_GLTF].content;
  54058. } else {
  54059. content = LoaderUtils.decodeText(new Uint8Array(data));
  54060. }
  54061. }
  54062. var json = JSON.parse(content);
  54063. if (json.asset === undefined || json.asset.version[0] < 2) {
  54064. if (onError) onError(new Error('THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.'));
  54065. return;
  54066. }
  54067. var parser = new GLTFParser(json, {
  54068. path: path || this.resourcePath || '',
  54069. crossOrigin: this.crossOrigin,
  54070. manager: this.manager,
  54071. ktx2Loader: this.ktx2Loader,
  54072. meshoptDecoder: this.meshoptDecoder
  54073. });
  54074. parser.fileLoader.setRequestHeader(this.requestHeader);
  54075. for (var i = 0; i < this.pluginCallbacks.length; i++) {
  54076. var plugin = this.pluginCallbacks[i](parser);
  54077. plugins[plugin.name] = plugin;
  54078. // Workaround to avoid determining as unknown extension
  54079. // in addUnknownExtensionsToUserData().
  54080. // Remove this workaround if we move all the existing
  54081. // extension handlers to plugin system
  54082. extensions[plugin.name] = true;
  54083. }
  54084. if (json.extensionsUsed) {
  54085. for (var i = 0; i < json.extensionsUsed.length; ++i) {
  54086. var extensionName = json.extensionsUsed[i];
  54087. var extensionsRequired = json.extensionsRequired || [];
  54088. switch (extensionName) {
  54089. case EXTENSIONS.KHR_MATERIALS_UNLIT:
  54090. extensions[extensionName] = new GLTFMaterialsUnlitExtension();
  54091. break;
  54092. case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
  54093. extensions[extensionName] = new GLTFMaterialsPbrSpecularGlossinessExtension();
  54094. break;
  54095. case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
  54096. extensions[extensionName] = new GLTFDracoMeshCompressionExtension(json, this.dracoLoader);
  54097. break;
  54098. case EXTENSIONS.MSFT_TEXTURE_DDS:
  54099. extensions[extensionName] = new GLTFTextureDDSExtension(this.ddsLoader);
  54100. break;
  54101. case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
  54102. extensions[extensionName] = new GLTFTextureTransformExtension();
  54103. break;
  54104. case EXTENSIONS.KHR_MESH_QUANTIZATION:
  54105. extensions[extensionName] = new GLTFMeshQuantizationExtension();
  54106. break;
  54107. default:
  54108. if (extensionsRequired.indexOf(extensionName) >= 0 && plugins[extensionName] === undefined) {
  54109. if (!unknownExtensions[extensionName]) {
  54110. console.warn('GLTFLoader: Unknown extension "' + extensionName + '".', '使用默认的KHR_materials_unlit材质');
  54111. unknownExtensions[extensionName] = 1;
  54112. }
  54113. //xzw add: 默认 不加的话都是白色的
  54114. json.extensionsRequired = 'KHR_materials_unlit';
  54115. var materials = [];
  54116. var _i = 0;
  54117. while (_i < json.materials.length) {
  54118. materials.push({
  54119. extensions: {
  54120. KHR_materials_unlit: {}
  54121. },
  54122. pbrMetallicRoughness: {
  54123. baseColorFactor: [1, 1, 1, 1],
  54124. baseColorTexture: {
  54125. index: _i,
  54126. texCoord: 0
  54127. },
  54128. metallicFactor: 0,
  54129. roughnessFactor: 0.5
  54130. }
  54131. });
  54132. _i++;
  54133. }
  54134. json.materials = materials;
  54135. extensions[json.extensionsRequired] = new GLTFMaterialsUnlitExtension();
  54136. }
  54137. /*
  54138. 如原先:
  54139. json.materials = KHR_techniques_webgl:{
  54140. technique: 0,
  54141. values:{u_diffuse:{index: 0,texCoord: 0}}
  54142. }
  54143. */
  54144. }
  54145. }
  54146. }
  54147. parser.setExtensions(extensions);
  54148. parser.setPlugins(plugins);
  54149. parser.parse(onLoad, onError);
  54150. }
  54151. });
  54152. /* GLTFREGISTRY */
  54153. function GLTFRegistry() {
  54154. var objects = {};
  54155. return {
  54156. get: function get(key) {
  54157. return objects[key];
  54158. },
  54159. add: function add(key, object) {
  54160. objects[key] = object;
  54161. },
  54162. remove: function remove(key) {
  54163. delete objects[key];
  54164. },
  54165. removeAll: function removeAll() {
  54166. objects = {};
  54167. }
  54168. };
  54169. }
  54170. /*********************************/
  54171. /********** EXTENSIONS ***********/
  54172. /*********************************/
  54173. var EXTENSIONS = {
  54174. KHR_BINARY_GLTF: 'KHR_binary_glTF',
  54175. KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
  54176. KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
  54177. KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
  54178. KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
  54179. KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
  54180. KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
  54181. KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
  54182. KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
  54183. KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
  54184. EXT_TEXTURE_WEBP: 'EXT_texture_webp',
  54185. EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
  54186. MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
  54187. };
  54188. /**
  54189. * DDS Texture Extension
  54190. *
  54191. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds
  54192. *
  54193. */
  54194. function GLTFTextureDDSExtension(ddsLoader) {
  54195. if (!ddsLoader) {
  54196. throw new Error('THREE.GLTFLoader: Attempting to load .dds texture without importing DDSLoader');
  54197. }
  54198. this.name = EXTENSIONS.MSFT_TEXTURE_DDS;
  54199. this.ddsLoader = ddsLoader;
  54200. }
  54201. /**
  54202. * Punctual Lights Extension
  54203. *
  54204. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
  54205. */
  54206. function GLTFLightsExtension(parser) {
  54207. this.parser = parser;
  54208. this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
  54209. // Object3D instance caches
  54210. this.cache = {
  54211. refs: {},
  54212. uses: {}
  54213. };
  54214. }
  54215. GLTFLightsExtension.prototype._markDefs = function () {
  54216. var parser = this.parser;
  54217. var nodeDefs = this.parser.json.nodes || [];
  54218. for (var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex++) {
  54219. var nodeDef = nodeDefs[nodeIndex];
  54220. if (nodeDef.extensions && nodeDef.extensions[this.name] && nodeDef.extensions[this.name].light !== undefined) {
  54221. parser._addNodeRef(this.cache, nodeDef.extensions[this.name].light);
  54222. }
  54223. }
  54224. };
  54225. GLTFLightsExtension.prototype._loadLight = function (lightIndex) {
  54226. var parser = this.parser;
  54227. var cacheKey = 'light:' + lightIndex;
  54228. var dependency = parser.cache.get(cacheKey);
  54229. if (dependency) return dependency;
  54230. var json = parser.json;
  54231. var extensions = json.extensions && json.extensions[this.name] || {};
  54232. var lightDefs = extensions.lights || [];
  54233. var lightDef = lightDefs[lightIndex];
  54234. var lightNode;
  54235. var color = new Color(0xffffff);
  54236. if (lightDef.color !== undefined) color.fromArray(lightDef.color);
  54237. var range = lightDef.range !== undefined ? lightDef.range : 0;
  54238. switch (lightDef.type) {
  54239. case 'directional':
  54240. lightNode = new DirectionalLight(color);
  54241. lightNode.target.position.set(0, 0, -1);
  54242. lightNode.add(lightNode.target);
  54243. break;
  54244. case 'point':
  54245. lightNode = new PointLight(color);
  54246. lightNode.distance = range;
  54247. break;
  54248. case 'spot':
  54249. lightNode = new SpotLight(color);
  54250. lightNode.distance = range;
  54251. // Handle spotlight properties.
  54252. lightDef.spot = lightDef.spot || {};
  54253. lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
  54254. lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
  54255. lightNode.angle = lightDef.spot.outerConeAngle;
  54256. lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
  54257. lightNode.target.position.set(0, 0, -1);
  54258. lightNode.add(lightNode.target);
  54259. break;
  54260. default:
  54261. throw new Error('THREE.GLTFLoader: Unexpected light type: ' + lightDef.type);
  54262. }
  54263. // Some lights (e.g. spot) default to a position other than the origin. Reset the position
  54264. // here, because node-level parsing will only override position if explicitly specified.
  54265. lightNode.position.set(0, 0, 0);
  54266. lightNode.decay = 2;
  54267. if (lightDef.intensity !== undefined) lightNode.intensity = lightDef.intensity;
  54268. lightNode.name = parser.createUniqueName(lightDef.name || 'light_' + lightIndex);
  54269. dependency = Promise.resolve(lightNode);
  54270. parser.cache.add(cacheKey, dependency);
  54271. return dependency;
  54272. };
  54273. GLTFLightsExtension.prototype.createNodeAttachment = function (nodeIndex) {
  54274. var self = this;
  54275. var parser = this.parser;
  54276. var json = parser.json;
  54277. var nodeDef = json.nodes[nodeIndex];
  54278. var lightDef = nodeDef.extensions && nodeDef.extensions[this.name] || {};
  54279. var lightIndex = lightDef.light;
  54280. if (lightIndex === undefined) return null;
  54281. return this._loadLight(lightIndex).then(function (light) {
  54282. return parser._getNodeRef(self.cache, lightIndex, light);
  54283. });
  54284. };
  54285. /**
  54286. * Unlit Materials Extension
  54287. *
  54288. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit
  54289. */
  54290. function GLTFMaterialsUnlitExtension() {
  54291. this.name = EXTENSIONS.KHR_MATERIALS_UNLIT;
  54292. }
  54293. GLTFMaterialsUnlitExtension.prototype.getMaterialType = function () {
  54294. return MeshBasicMaterial;
  54295. };
  54296. GLTFMaterialsUnlitExtension.prototype.extendParams = function (materialParams, materialDef, parser) {
  54297. var pending = [];
  54298. materialParams.color = new Color(1.0, 1.0, 1.0);
  54299. materialParams.opacity = 1.0;
  54300. var metallicRoughness = materialDef.pbrMetallicRoughness;
  54301. if (metallicRoughness) {
  54302. if (Array.isArray(metallicRoughness.baseColorFactor)) {
  54303. var array = metallicRoughness.baseColorFactor;
  54304. materialParams.color.fromArray(array);
  54305. materialParams.opacity = array[3];
  54306. }
  54307. if (metallicRoughness.baseColorTexture !== undefined) {
  54308. pending.push(parser.assignTexture(materialParams, 'map', metallicRoughness.baseColorTexture));
  54309. }
  54310. }
  54311. return Promise.all(pending);
  54312. };
  54313. /**
  54314. * Clearcoat Materials Extension
  54315. *
  54316. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
  54317. */
  54318. function GLTFMaterialsClearcoatExtension(parser) {
  54319. this.parser = parser;
  54320. this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;
  54321. }
  54322. GLTFMaterialsClearcoatExtension.prototype.getMaterialType = function (materialIndex) {
  54323. var parser = this.parser;
  54324. var materialDef = parser.json.materials[materialIndex];
  54325. if (!materialDef.extensions || !materialDef.extensions[this.name]) return null;
  54326. return MeshPhysicalMaterial;
  54327. };
  54328. GLTFMaterialsClearcoatExtension.prototype.extendMaterialParams = function (materialIndex, materialParams) {
  54329. var parser = this.parser;
  54330. var materialDef = parser.json.materials[materialIndex];
  54331. if (!materialDef.extensions || !materialDef.extensions[this.name]) {
  54332. return Promise.resolve();
  54333. }
  54334. var pending = [];
  54335. var extension = materialDef.extensions[this.name];
  54336. if (extension.clearcoatFactor !== undefined) {
  54337. materialParams.clearcoat = extension.clearcoatFactor;
  54338. }
  54339. if (extension.clearcoatTexture !== undefined) {
  54340. pending.push(parser.assignTexture(materialParams, 'clearcoatMap', extension.clearcoatTexture));
  54341. }
  54342. if (extension.clearcoatRoughnessFactor !== undefined) {
  54343. materialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;
  54344. }
  54345. if (extension.clearcoatRoughnessTexture !== undefined) {
  54346. pending.push(parser.assignTexture(materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture));
  54347. }
  54348. if (extension.clearcoatNormalTexture !== undefined) {
  54349. pending.push(parser.assignTexture(materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture));
  54350. if (extension.clearcoatNormalTexture.scale !== undefined) {
  54351. var scale = extension.clearcoatNormalTexture.scale;
  54352. materialParams.clearcoatNormalScale = new Vector2(scale, scale);
  54353. }
  54354. }
  54355. return Promise.all(pending);
  54356. };
  54357. /**
  54358. * Transmission Materials Extension
  54359. *
  54360. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
  54361. * Draft: https://github.com/KhronosGroup/glTF/pull/1698
  54362. */
  54363. function GLTFMaterialsTransmissionExtension(parser) {
  54364. this.parser = parser;
  54365. this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;
  54366. }
  54367. GLTFMaterialsTransmissionExtension.prototype.getMaterialType = function (materialIndex) {
  54368. var parser = this.parser;
  54369. var materialDef = parser.json.materials[materialIndex];
  54370. if (!materialDef.extensions || !materialDef.extensions[this.name]) return null;
  54371. return MeshPhysicalMaterial;
  54372. };
  54373. GLTFMaterialsTransmissionExtension.prototype.extendMaterialParams = function (materialIndex, materialParams) {
  54374. var parser = this.parser;
  54375. var materialDef = parser.json.materials[materialIndex];
  54376. if (!materialDef.extensions || !materialDef.extensions[this.name]) {
  54377. return Promise.resolve();
  54378. }
  54379. var pending = [];
  54380. var extension = materialDef.extensions[this.name];
  54381. if (extension.transmissionFactor !== undefined) {
  54382. materialParams.transmission = extension.transmissionFactor;
  54383. }
  54384. if (extension.transmissionTexture !== undefined) {
  54385. pending.push(parser.assignTexture(materialParams, 'transmissionMap', extension.transmissionTexture));
  54386. }
  54387. return Promise.all(pending);
  54388. };
  54389. /**
  54390. * BasisU Texture Extension
  54391. *
  54392. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu
  54393. */
  54394. function GLTFTextureBasisUExtension(parser) {
  54395. this.parser = parser;
  54396. this.name = EXTENSIONS.KHR_TEXTURE_BASISU;
  54397. }
  54398. GLTFTextureBasisUExtension.prototype.loadTexture = function (textureIndex) {
  54399. var parser = this.parser;
  54400. var json = parser.json;
  54401. var textureDef = json.textures[textureIndex];
  54402. if (!textureDef.extensions || !textureDef.extensions[this.name]) {
  54403. return null;
  54404. }
  54405. var extension = textureDef.extensions[this.name];
  54406. var source = json.images[extension.source];
  54407. var loader = parser.options.ktx2Loader;
  54408. if (!loader) {
  54409. if (json.extensionsRequired && json.extensionsRequired.indexOf(this.name) >= 0) {
  54410. throw new Error('THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures');
  54411. } else {
  54412. // Assumes that the extension is optional and that a fallback texture is present
  54413. return null;
  54414. }
  54415. }
  54416. return parser.loadTextureImage(textureIndex, source, loader);
  54417. };
  54418. /**
  54419. * WebP Texture Extension
  54420. *
  54421. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp
  54422. */
  54423. function GLTFTextureWebPExtension(parser) {
  54424. this.parser = parser;
  54425. this.name = EXTENSIONS.EXT_TEXTURE_WEBP;
  54426. this.isSupported = null;
  54427. }
  54428. GLTFTextureWebPExtension.prototype.loadTexture = function (textureIndex) {
  54429. var name = this.name;
  54430. var parser = this.parser;
  54431. var json = parser.json;
  54432. var textureDef = json.textures[textureIndex];
  54433. if (!textureDef.extensions || !textureDef.extensions[name]) {
  54434. return null;
  54435. }
  54436. var extension = textureDef.extensions[name];
  54437. var source = json.images[extension.source];
  54438. var loader = source.uri ? parser.options.manager.getHandler(source.uri) : parser.textureLoader;
  54439. return this.detectSupport().then(function (isSupported) {
  54440. if (isSupported) return parser.loadTextureImage(textureIndex, source, loader);
  54441. if (json.extensionsRequired && json.extensionsRequired.indexOf(name) >= 0) {
  54442. throw new Error('THREE.GLTFLoader: WebP required by asset but unsupported.');
  54443. }
  54444. // Fall back to PNG or JPEG.
  54445. return parser.loadTexture(textureIndex);
  54446. });
  54447. };
  54448. GLTFTextureWebPExtension.prototype.detectSupport = function () {
  54449. if (!this.isSupported) {
  54450. this.isSupported = new Promise(function (resolve) {
  54451. var image = new Image();
  54452. // Lossy test image. Support for lossy images doesn't guarantee support for all
  54453. // WebP images, unfortunately.
  54454. image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
  54455. image.onload = image.onerror = function () {
  54456. resolve(image.height === 1);
  54457. };
  54458. });
  54459. }
  54460. return this.isSupported;
  54461. };
  54462. /**
  54463. * meshopt BufferView Compression Extension
  54464. *
  54465. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression
  54466. */
  54467. function GLTFMeshoptCompression(parser) {
  54468. this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION;
  54469. this.parser = parser;
  54470. }
  54471. GLTFMeshoptCompression.prototype.loadBufferView = function (index) {
  54472. var json = this.parser.json;
  54473. var bufferView = json.bufferViews[index];
  54474. if (bufferView.extensions && bufferView.extensions[this.name]) {
  54475. var extensionDef = bufferView.extensions[this.name];
  54476. var buffer = this.parser.getDependency('buffer', extensionDef.buffer);
  54477. var decoder = this.parser.options.meshoptDecoder;
  54478. if (!decoder || !decoder.supported) {
  54479. if (json.extensionsRequired && json.extensionsRequired.indexOf(this.name) >= 0) {
  54480. throw new Error('THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files');
  54481. } else {
  54482. // Assumes that the extension is optional and that fallback buffer data is present
  54483. return null;
  54484. }
  54485. }
  54486. return Promise.all([buffer, decoder.ready]).then(function (res) {
  54487. var byteOffset = extensionDef.byteOffset || 0;
  54488. var byteLength = extensionDef.byteLength || 0;
  54489. var count = extensionDef.count;
  54490. var stride = extensionDef.byteStride;
  54491. var result = new ArrayBuffer(count * stride);
  54492. var source = new Uint8Array(res[0], byteOffset, byteLength);
  54493. decoder.decodeGltfBuffer(new Uint8Array(result), count, stride, source, extensionDef.mode, extensionDef.filter);
  54494. return result;
  54495. });
  54496. } else {
  54497. return null;
  54498. }
  54499. };
  54500. /* BINARY EXTENSION */
  54501. var BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
  54502. var BINARY_EXTENSION_HEADER_LENGTH = 12;
  54503. var BINARY_EXTENSION_CHUNK_TYPES = {
  54504. JSON: 0x4E4F534A,
  54505. BIN: 0x004E4942
  54506. };
  54507. function GLTFBinaryExtension(data) {
  54508. this.name = EXTENSIONS.KHR_BINARY_GLTF;
  54509. this.content = null;
  54510. this.body = null;
  54511. var headerView = new DataView(data, 0, BINARY_EXTENSION_HEADER_LENGTH);
  54512. this.header = {
  54513. magic: LoaderUtils.decodeText(new Uint8Array(data.slice(0, 4))),
  54514. version: headerView.getUint32(4, true),
  54515. length: headerView.getUint32(8, true)
  54516. };
  54517. if (this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC) {
  54518. throw new Error('THREE.GLTFLoader: Unsupported glTF-Binary header.');
  54519. } else if (this.header.version < 2.0) {
  54520. throw new Error('THREE.GLTFLoader: Legacy binary file detected.');
  54521. }
  54522. var chunkView = new DataView(data, BINARY_EXTENSION_HEADER_LENGTH);
  54523. var chunkIndex = 0;
  54524. while (chunkIndex < chunkView.byteLength) {
  54525. var chunkLength = chunkView.getUint32(chunkIndex, true);
  54526. chunkIndex += 4;
  54527. var chunkType = chunkView.getUint32(chunkIndex, true);
  54528. chunkIndex += 4;
  54529. if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON) {
  54530. var contentArray = new Uint8Array(data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength);
  54531. this.content = LoaderUtils.decodeText(contentArray);
  54532. } else if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN) {
  54533. var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
  54534. this.body = data.slice(byteOffset, byteOffset + chunkLength);
  54535. }
  54536. // Clients must ignore chunks with unknown types.
  54537. chunkIndex += chunkLength;
  54538. }
  54539. if (this.content === null) {
  54540. throw new Error('THREE.GLTFLoader: JSON content not found.');
  54541. }
  54542. }
  54543. /**
  54544. * DRACO Mesh Compression Extension
  54545. *
  54546. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
  54547. */
  54548. //GLTFDracoMeshCompressionExtension由124版本的改为146版本的,因为dracoLoader报错了
  54549. class GLTFDracoMeshCompressionExtension {
  54550. constructor(json, dracoLoader) {
  54551. if (!dracoLoader) {
  54552. throw new Error('THREE.GLTFLoader: No DRACOLoader instance provided.');
  54553. }
  54554. this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
  54555. this.json = json;
  54556. this.dracoLoader = dracoLoader;
  54557. this.dracoLoader.preload();
  54558. }
  54559. decodePrimitive(primitive, parser) {
  54560. var json = this.json;
  54561. var dracoLoader = this.dracoLoader;
  54562. var bufferViewIndex = primitive.extensions[this.name].bufferView;
  54563. var gltfAttributeMap = primitive.extensions[this.name].attributes;
  54564. var threeAttributeMap = {};
  54565. var attributeNormalizedMap = {};
  54566. var attributeTypeMap = {};
  54567. for (var attributeName in gltfAttributeMap) {
  54568. var threeAttributeName = ATTRIBUTES[attributeName] || attributeName.toLowerCase();
  54569. threeAttributeMap[threeAttributeName] = gltfAttributeMap[attributeName];
  54570. }
  54571. for (var _attributeName in primitive.attributes) {
  54572. var _threeAttributeName = ATTRIBUTES[_attributeName] || _attributeName.toLowerCase();
  54573. if (gltfAttributeMap[_attributeName] !== undefined) {
  54574. var accessorDef = json.accessors[primitive.attributes[_attributeName]];
  54575. var componentType = WEBGL_COMPONENT_TYPES[accessorDef.componentType];
  54576. attributeTypeMap[_threeAttributeName] = componentType.name;
  54577. attributeNormalizedMap[_threeAttributeName] = accessorDef.normalized === true;
  54578. }
  54579. }
  54580. return parser.getDependency('bufferView', bufferViewIndex).then(function (bufferView) {
  54581. return new Promise(function (resolve) {
  54582. dracoLoader.decodeDracoFile(bufferView, function (geometry) {
  54583. for (var _attributeName2 in geometry.attributes) {
  54584. var attribute = geometry.attributes[_attributeName2];
  54585. var normalized = attributeNormalizedMap[_attributeName2];
  54586. if (normalized !== undefined) attribute.normalized = normalized;
  54587. }
  54588. resolve(geometry);
  54589. }, threeAttributeMap, attributeTypeMap);
  54590. });
  54591. });
  54592. }
  54593. }
  54594. /**
  54595. * Texture Transform Extension
  54596. *
  54597. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform
  54598. */
  54599. function GLTFTextureTransformExtension() {
  54600. this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
  54601. }
  54602. GLTFTextureTransformExtension.prototype.extendTexture = function (texture, transform) {
  54603. texture = texture.clone();
  54604. if (transform.offset !== undefined) {
  54605. texture.offset.fromArray(transform.offset);
  54606. }
  54607. if (transform.rotation !== undefined) {
  54608. texture.rotation = transform.rotation;
  54609. }
  54610. if (transform.scale !== undefined) {
  54611. texture.repeat.fromArray(transform.scale);
  54612. }
  54613. if (transform.texCoord !== undefined) {
  54614. console.warn('THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.');
  54615. }
  54616. texture.needsUpdate = true;
  54617. return texture;
  54618. };
  54619. /**
  54620. * Specular-Glossiness Extension
  54621. *
  54622. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
  54623. */
  54624. /**
  54625. * A sub class of StandardMaterial with some of the functionality
  54626. * changed via the `onBeforeCompile` callback
  54627. * @pailhead
  54628. */
  54629. function GLTFMeshStandardSGMaterial(params) {
  54630. MeshStandardMaterial.call(this);
  54631. this.isGLTFSpecularGlossinessMaterial = true;
  54632. //various chunks that need replacing
  54633. var specularMapParsFragmentChunk = ['#ifdef USE_SPECULARMAP', ' uniform sampler2D specularMap;', '#endif'].join('\n');
  54634. var glossinessMapParsFragmentChunk = ['#ifdef USE_GLOSSINESSMAP', ' uniform sampler2D glossinessMap;', '#endif'].join('\n');
  54635. var specularMapFragmentChunk = ['vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', ' texelSpecular = sRGBToLinear( texelSpecular );', ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', ' specularFactor *= texelSpecular.rgb;', '#endif'].join('\n');
  54636. var glossinessMapFragmentChunk = ['float glossinessFactor = glossiness;', '#ifdef USE_GLOSSINESSMAP', ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );', ' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture', ' glossinessFactor *= texelGlossiness.a;', '#endif'].join('\n');
  54637. var lightPhysicalFragmentChunk = ['PhysicalMaterial material;', 'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );', 'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );', 'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );', 'material.specularRoughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.', 'material.specularRoughness += geometryRoughness;', 'material.specularRoughness = min( material.specularRoughness, 1.0 );', 'material.specularColor = specularFactor;'].join('\n');
  54638. var uniforms = {
  54639. specular: {
  54640. value: new Color().setHex(0xffffff)
  54641. },
  54642. glossiness: {
  54643. value: 1
  54644. },
  54645. specularMap: {
  54646. value: null
  54647. },
  54648. glossinessMap: {
  54649. value: null
  54650. }
  54651. };
  54652. this._extraUniforms = uniforms;
  54653. this.onBeforeCompile = function (shader) {
  54654. for (var uniformName in uniforms) {
  54655. shader.uniforms[uniformName] = uniforms[uniformName];
  54656. }
  54657. shader.fragmentShader = shader.fragmentShader.replace('uniform float roughness;', 'uniform vec3 specular;').replace('uniform float metalness;', 'uniform float glossiness;').replace('#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk).replace('#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk).replace('#include <roughnessmap_fragment>', specularMapFragmentChunk).replace('#include <metalnessmap_fragment>', glossinessMapFragmentChunk).replace('#include <lights_physical_fragment>', lightPhysicalFragmentChunk);
  54658. };
  54659. Object.defineProperties(this, {
  54660. specular: {
  54661. get: function get() {
  54662. return uniforms.specular.value;
  54663. },
  54664. set: function set(v) {
  54665. uniforms.specular.value = v;
  54666. }
  54667. },
  54668. specularMap: {
  54669. get: function get() {
  54670. return uniforms.specularMap.value;
  54671. },
  54672. set: function set(v) {
  54673. uniforms.specularMap.value = v;
  54674. if (v) {
  54675. this.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps
  54676. } else {
  54677. delete this.defines.USE_SPECULARMAP;
  54678. }
  54679. }
  54680. },
  54681. glossiness: {
  54682. get: function get() {
  54683. return uniforms.glossiness.value;
  54684. },
  54685. set: function set(v) {
  54686. uniforms.glossiness.value = v;
  54687. }
  54688. },
  54689. glossinessMap: {
  54690. get: function get() {
  54691. return uniforms.glossinessMap.value;
  54692. },
  54693. set: function set(v) {
  54694. uniforms.glossinessMap.value = v;
  54695. if (v) {
  54696. this.defines.USE_GLOSSINESSMAP = '';
  54697. this.defines.USE_UV = '';
  54698. } else {
  54699. delete this.defines.USE_GLOSSINESSMAP;
  54700. delete this.defines.USE_UV;
  54701. }
  54702. }
  54703. }
  54704. });
  54705. delete this.metalness;
  54706. delete this.roughness;
  54707. delete this.metalnessMap;
  54708. delete this.roughnessMap;
  54709. this.setValues(params);
  54710. }
  54711. GLTFMeshStandardSGMaterial.prototype = Object.create(MeshStandardMaterial.prototype);
  54712. GLTFMeshStandardSGMaterial.prototype.constructor = GLTFMeshStandardSGMaterial;
  54713. GLTFMeshStandardSGMaterial.prototype.copy = function (source) {
  54714. MeshStandardMaterial.prototype.copy.call(this, source);
  54715. this.specularMap = source.specularMap;
  54716. this.specular.copy(source.specular);
  54717. this.glossinessMap = source.glossinessMap;
  54718. this.glossiness = source.glossiness;
  54719. delete this.metalness;
  54720. delete this.roughness;
  54721. delete this.metalnessMap;
  54722. delete this.roughnessMap;
  54723. return this;
  54724. };
  54725. function GLTFMaterialsPbrSpecularGlossinessExtension() {
  54726. return {
  54727. name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,
  54728. specularGlossinessParams: ['color', 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalMapType', 'displacementMap', 'displacementScale', 'displacementBias', 'specularMap', 'specular', 'glossinessMap', 'glossiness', 'alphaMap', 'envMap', 'envMapIntensity', 'refractionRatio'],
  54729. getMaterialType: function getMaterialType() {
  54730. return GLTFMeshStandardSGMaterial;
  54731. },
  54732. extendParams: function extendParams(materialParams, materialDef, parser) {
  54733. var pbrSpecularGlossiness = materialDef.extensions[this.name];
  54734. materialParams.color = new Color(1.0, 1.0, 1.0);
  54735. materialParams.opacity = 1.0;
  54736. var pending = [];
  54737. if (Array.isArray(pbrSpecularGlossiness.diffuseFactor)) {
  54738. var array = pbrSpecularGlossiness.diffuseFactor;
  54739. materialParams.color.fromArray(array);
  54740. materialParams.opacity = array[3];
  54741. }
  54742. if (pbrSpecularGlossiness.diffuseTexture !== undefined) {
  54743. pending.push(parser.assignTexture(materialParams, 'map', pbrSpecularGlossiness.diffuseTexture));
  54744. }
  54745. materialParams.emissive = new Color(0.0, 0.0, 0.0);
  54746. materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
  54747. materialParams.specular = new Color(1.0, 1.0, 1.0);
  54748. if (Array.isArray(pbrSpecularGlossiness.specularFactor)) {
  54749. materialParams.specular.fromArray(pbrSpecularGlossiness.specularFactor);
  54750. }
  54751. if (pbrSpecularGlossiness.specularGlossinessTexture !== undefined) {
  54752. var specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
  54753. pending.push(parser.assignTexture(materialParams, 'glossinessMap', specGlossMapDef));
  54754. pending.push(parser.assignTexture(materialParams, 'specularMap', specGlossMapDef));
  54755. }
  54756. return Promise.all(pending);
  54757. },
  54758. createMaterial: function createMaterial(materialParams) {
  54759. var material = new GLTFMeshStandardSGMaterial(materialParams);
  54760. material.fog = true;
  54761. material.color = materialParams.color;
  54762. material.map = materialParams.map === undefined ? null : materialParams.map;
  54763. material.lightMap = null;
  54764. material.lightMapIntensity = 1.0;
  54765. material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;
  54766. material.aoMapIntensity = 1.0;
  54767. material.emissive = materialParams.emissive;
  54768. material.emissiveIntensity = 1.0;
  54769. material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;
  54770. material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;
  54771. material.bumpScale = 1;
  54772. material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;
  54773. material.normalMapType = TangentSpaceNormalMap;
  54774. if (materialParams.normalScale) material.normalScale = materialParams.normalScale;
  54775. material.displacementMap = null;
  54776. material.displacementScale = 1;
  54777. material.displacementBias = 0;
  54778. material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;
  54779. material.specular = materialParams.specular;
  54780. material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;
  54781. material.glossiness = materialParams.glossiness;
  54782. material.alphaMap = null;
  54783. material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
  54784. material.envMapIntensity = 1.0;
  54785. material.refractionRatio = 0.98;
  54786. return material;
  54787. }
  54788. };
  54789. }
  54790. /**
  54791. * Mesh Quantization Extension
  54792. *
  54793. * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization
  54794. */
  54795. function GLTFMeshQuantizationExtension() {
  54796. this.name = EXTENSIONS.KHR_MESH_QUANTIZATION;
  54797. }
  54798. /*********************************/
  54799. /********** INTERPOLATION ********/
  54800. /*********************************/
  54801. // Spline Interpolation
  54802. // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
  54803. function GLTFCubicSplineInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  54804. Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  54805. }
  54806. GLTFCubicSplineInterpolant.prototype = Object.create(Interpolant.prototype);
  54807. GLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;
  54808. GLTFCubicSplineInterpolant.prototype.copySampleValue_ = function (index) {
  54809. // Copies a sample value to the result buffer. See description of glTF
  54810. // CUBICSPLINE values layout in interpolate_() function below.
  54811. var result = this.resultBuffer,
  54812. values = this.sampleValues,
  54813. valueSize = this.valueSize,
  54814. offset = index * valueSize * 3 + valueSize;
  54815. for (var i = 0; i !== valueSize; i++) {
  54816. result[i] = values[offset + i];
  54817. }
  54818. return result;
  54819. };
  54820. GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
  54821. GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
  54822. GLTFCubicSplineInterpolant.prototype.interpolate_ = function (i1, t0, t, t1) {
  54823. var result = this.resultBuffer;
  54824. var values = this.sampleValues;
  54825. var stride = this.valueSize;
  54826. var stride2 = stride * 2;
  54827. var stride3 = stride * 3;
  54828. var td = t1 - t0;
  54829. var p = (t - t0) / td;
  54830. var pp = p * p;
  54831. var ppp = pp * p;
  54832. var offset1 = i1 * stride3;
  54833. var offset0 = offset1 - stride3;
  54834. var s2 = -2 * ppp + 3 * pp;
  54835. var s3 = ppp - pp;
  54836. var s0 = 1 - s2;
  54837. var s1 = s3 - pp + p;
  54838. // Layout of keyframe output values for CUBICSPLINE animations:
  54839. // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
  54840. for (var i = 0; i !== stride; i++) {
  54841. var p0 = values[offset0 + i + stride]; // splineVertex_k
  54842. var m0 = values[offset0 + i + stride2] * td; // outTangent_k * (t_k+1 - t_k)
  54843. var p1 = values[offset1 + i + stride]; // splineVertex_k+1
  54844. var m1 = values[offset1 + i] * td; // inTangent_k+1 * (t_k+1 - t_k)
  54845. result[i] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
  54846. }
  54847. return result;
  54848. };
  54849. /*********************************/
  54850. /********** INTERNALS ************/
  54851. /*********************************/
  54852. /* CONSTANTS */
  54853. var WEBGL_CONSTANTS = {
  54854. FLOAT: 5126,
  54855. //FLOAT_MAT2: 35674,
  54856. FLOAT_MAT3: 35675,
  54857. FLOAT_MAT4: 35676,
  54858. FLOAT_VEC2: 35664,
  54859. FLOAT_VEC3: 35665,
  54860. FLOAT_VEC4: 35666,
  54861. LINEAR: 9729,
  54862. REPEAT: 10497,
  54863. SAMPLER_2D: 35678,
  54864. POINTS: 0,
  54865. LINES: 1,
  54866. LINE_LOOP: 2,
  54867. LINE_STRIP: 3,
  54868. TRIANGLES: 4,
  54869. TRIANGLE_STRIP: 5,
  54870. TRIANGLE_FAN: 6,
  54871. UNSIGNED_BYTE: 5121,
  54872. UNSIGNED_SHORT: 5123
  54873. };
  54874. var WEBGL_COMPONENT_TYPES = {
  54875. 5120: Int8Array,
  54876. 5121: Uint8Array,
  54877. 5122: Int16Array,
  54878. 5123: Uint16Array,
  54879. 5125: Uint32Array,
  54880. 5126: Float32Array
  54881. };
  54882. var WEBGL_FILTERS = {
  54883. 9728: NearestFilter,
  54884. 9729: LinearFilter,
  54885. 9984: NearestMipmapNearestFilter,
  54886. 9985: LinearMipmapNearestFilter,
  54887. 9986: NearestMipmapLinearFilter,
  54888. 9987: LinearMipmapLinearFilter
  54889. };
  54890. var WEBGL_WRAPPINGS = {
  54891. 33071: ClampToEdgeWrapping,
  54892. 33648: MirroredRepeatWrapping,
  54893. 10497: RepeatWrapping
  54894. };
  54895. var WEBGL_TYPE_SIZES = {
  54896. 'SCALAR': 1,
  54897. 'VEC2': 2,
  54898. 'VEC3': 3,
  54899. 'VEC4': 4,
  54900. 'MAT2': 4,
  54901. 'MAT3': 9,
  54902. 'MAT4': 16
  54903. };
  54904. var ATTRIBUTES = {
  54905. POSITION: 'position',
  54906. NORMAL: 'normal',
  54907. TANGENT: 'tangent',
  54908. TEXCOORD_0: 'uv',
  54909. TEXCOORD_1: 'uv2',
  54910. COLOR_0: 'color',
  54911. WEIGHTS_0: 'skinWeight',
  54912. JOINTS_0: 'skinIndex'
  54913. };
  54914. var PATH_PROPERTIES = {
  54915. scale: 'scale',
  54916. translation: 'position',
  54917. rotation: 'quaternion',
  54918. weights: 'morphTargetInfluences'
  54919. };
  54920. var INTERPOLATION = {
  54921. CUBICSPLINE: undefined,
  54922. // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
  54923. // keyframe track will be initialized with a default interpolation type, then modified.
  54924. LINEAR: InterpolateLinear,
  54925. STEP: InterpolateDiscrete
  54926. };
  54927. var ALPHA_MODES = {
  54928. OPAQUE: 'OPAQUE',
  54929. MASK: 'MASK',
  54930. BLEND: 'BLEND'
  54931. };
  54932. /* UTILITY FUNCTIONS */
  54933. function resolveURL(url, path) {
  54934. // Invalid URL
  54935. if (typeof url !== 'string' || url === '') return '';
  54936. // Host Relative URL
  54937. if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
  54938. path = path.replace(/(^https?:\/\/[^\/]+).*/i, '$1');
  54939. }
  54940. // Absolute URL http://,https://,//
  54941. if (/^(https?:)?\/\//i.test(url)) return url;
  54942. // Data URI
  54943. if (/^data:.*,.*$/i.test(url)) return url;
  54944. // Blob URL
  54945. if (/^blob:.*$/i.test(url)) return url;
  54946. // Relative URL
  54947. return path + url;
  54948. }
  54949. /**
  54950. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
  54951. */
  54952. function createDefaultMaterial(cache) {
  54953. if (cache['DefaultMaterial'] === undefined) {
  54954. cache['DefaultMaterial'] = new MeshStandardMaterial({
  54955. color: 0xFFFFFF,
  54956. emissive: 0x000000,
  54957. metalness: 1,
  54958. roughness: 1,
  54959. transparent: false,
  54960. depthTest: true,
  54961. side: FrontSide
  54962. });
  54963. }
  54964. return cache['DefaultMaterial'];
  54965. }
  54966. function addUnknownExtensionsToUserData(knownExtensions, object, objectDef) {
  54967. // Add unknown glTF extensions to an object's userData.
  54968. for (var name in objectDef.extensions) {
  54969. if (knownExtensions[name] === undefined) {
  54970. object.userData.gltfExtensions = object.userData.gltfExtensions || {};
  54971. object.userData.gltfExtensions[name] = objectDef.extensions[name];
  54972. }
  54973. }
  54974. }
  54975. /**
  54976. * @param {Object3D|Material|BufferGeometry} object
  54977. * @param {GLTF.definition} gltfDef
  54978. */
  54979. function assignExtrasToUserData(object, gltfDef) {
  54980. if (gltfDef.extras !== undefined) {
  54981. if (typeof gltfDef.extras === 'object') {
  54982. Object.assign(object.userData, gltfDef.extras);
  54983. } else {
  54984. console.warn('THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras);
  54985. }
  54986. }
  54987. }
  54988. /**
  54989. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
  54990. *
  54991. * @param {BufferGeometry} geometry
  54992. * @param {Array<GLTF.Target>} targets
  54993. * @param {GLTFParser} parser
  54994. * @return {Promise<BufferGeometry>}
  54995. */
  54996. function addMorphTargets(geometry, targets, parser) {
  54997. var hasMorphPosition = false;
  54998. var hasMorphNormal = false;
  54999. for (var i = 0, il = targets.length; i < il; i++) {
  55000. var target = targets[i];
  55001. if (target.POSITION !== undefined) hasMorphPosition = true;
  55002. if (target.NORMAL !== undefined) hasMorphNormal = true;
  55003. if (hasMorphPosition && hasMorphNormal) break;
  55004. }
  55005. if (!hasMorphPosition && !hasMorphNormal) return Promise.resolve(geometry);
  55006. var pendingPositionAccessors = [];
  55007. var pendingNormalAccessors = [];
  55008. for (var i = 0, il = targets.length; i < il; i++) {
  55009. var target = targets[i];
  55010. if (hasMorphPosition) {
  55011. var pendingAccessor = target.POSITION !== undefined ? parser.getDependency('accessor', target.POSITION) : geometry.attributes.position;
  55012. pendingPositionAccessors.push(pendingAccessor);
  55013. }
  55014. if (hasMorphNormal) {
  55015. var pendingAccessor = target.NORMAL !== undefined ? parser.getDependency('accessor', target.NORMAL) : geometry.attributes.normal;
  55016. pendingNormalAccessors.push(pendingAccessor);
  55017. }
  55018. }
  55019. return Promise.all([Promise.all(pendingPositionAccessors), Promise.all(pendingNormalAccessors)]).then(function (accessors) {
  55020. var morphPositions = accessors[0];
  55021. var morphNormals = accessors[1];
  55022. if (hasMorphPosition) geometry.morphAttributes.position = morphPositions;
  55023. if (hasMorphNormal) geometry.morphAttributes.normal = morphNormals;
  55024. geometry.morphTargetsRelative = true;
  55025. return geometry;
  55026. });
  55027. }
  55028. /**
  55029. * @param {Mesh} mesh
  55030. * @param {GLTF.Mesh} meshDef
  55031. */
  55032. function updateMorphTargets(mesh, meshDef) {
  55033. mesh.updateMorphTargets();
  55034. if (meshDef.weights !== undefined) {
  55035. for (var i = 0, il = meshDef.weights.length; i < il; i++) {
  55036. mesh.morphTargetInfluences[i] = meshDef.weights[i];
  55037. }
  55038. }
  55039. // .extras has user-defined data, so check that .extras.targetNames is an array.
  55040. if (meshDef.extras && Array.isArray(meshDef.extras.targetNames)) {
  55041. var targetNames = meshDef.extras.targetNames;
  55042. if (mesh.morphTargetInfluences.length === targetNames.length) {
  55043. mesh.morphTargetDictionary = {};
  55044. for (var i = 0, il = targetNames.length; i < il; i++) {
  55045. mesh.morphTargetDictionary[targetNames[i]] = i;
  55046. }
  55047. } else {
  55048. console.warn('THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.');
  55049. }
  55050. }
  55051. }
  55052. function createPrimitiveKey(primitiveDef) {
  55053. var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION];
  55054. var geometryKey;
  55055. if (dracoExtension) {
  55056. geometryKey = 'draco:' + dracoExtension.bufferView + ':' + dracoExtension.indices + ':' + createAttributesKey(dracoExtension.attributes);
  55057. } else {
  55058. geometryKey = primitiveDef.indices + ':' + createAttributesKey(primitiveDef.attributes) + ':' + primitiveDef.mode;
  55059. }
  55060. return geometryKey;
  55061. }
  55062. function createAttributesKey(attributes) {
  55063. var attributesKey = '';
  55064. var keys = Object.keys(attributes).sort();
  55065. for (var i = 0, il = keys.length; i < il; i++) {
  55066. attributesKey += keys[i] + ':' + attributes[keys[i]] + ';';
  55067. }
  55068. return attributesKey;
  55069. }
  55070. /* GLTF PARSER */
  55071. function GLTFParser(json, options) {
  55072. this.json = json || {};
  55073. this.extensions = {};
  55074. this.plugins = {};
  55075. this.options = options || {};
  55076. // loader object cache
  55077. this.cache = new GLTFRegistry();
  55078. // associations between Three.js objects and glTF elements
  55079. this.associations = new Map();
  55080. // BufferGeometry caching
  55081. this.primitiveCache = {};
  55082. // Object3D instance caches
  55083. this.meshCache = {
  55084. refs: {},
  55085. uses: {}
  55086. };
  55087. this.cameraCache = {
  55088. refs: {},
  55089. uses: {}
  55090. };
  55091. this.lightCache = {
  55092. refs: {},
  55093. uses: {}
  55094. };
  55095. // Track node names, to ensure no duplicates
  55096. this.nodeNamesUsed = {};
  55097. // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
  55098. // expensive work of uploading a texture to the GPU off the main thread.
  55099. if (typeof createImageBitmap !== 'undefined' && /Firefox/.test(navigator.userAgent) === false) {
  55100. this.textureLoader = new ImageBitmapLoader(this.options.manager);
  55101. } else {
  55102. this.textureLoader = new TextureLoader(this.options.manager);
  55103. }
  55104. this.textureLoader.setCrossOrigin(this.options.crossOrigin);
  55105. this.fileLoader = new FileLoader(this.options.manager);
  55106. this.fileLoader.setResponseType('arraybuffer');
  55107. if (this.options.crossOrigin === 'use-credentials') {
  55108. this.fileLoader.setWithCredentials(true);
  55109. }
  55110. }
  55111. GLTFParser.prototype.setExtensions = function (extensions) {
  55112. this.extensions = extensions;
  55113. };
  55114. GLTFParser.prototype.setPlugins = function (plugins) {
  55115. this.plugins = plugins;
  55116. };
  55117. GLTFParser.prototype.parse = function (onLoad, onError) {
  55118. var parser = this;
  55119. var json = this.json;
  55120. var extensions = this.extensions;
  55121. // Clear the loader cache
  55122. this.cache.removeAll();
  55123. // Mark the special nodes/meshes in json for efficient parse
  55124. this._invokeAll(function (ext) {
  55125. return ext._markDefs && ext._markDefs();
  55126. });
  55127. Promise.all([this.getDependencies('scene'), this.getDependencies('animation'), this.getDependencies('camera')]).then(function (dependencies) {
  55128. var result = {
  55129. scene: dependencies[0][json.scene || 0],
  55130. scenes: dependencies[0],
  55131. animations: dependencies[1],
  55132. cameras: dependencies[2],
  55133. asset: json.asset,
  55134. parser: parser,
  55135. userData: {}
  55136. };
  55137. addUnknownExtensionsToUserData(extensions, result, json);
  55138. assignExtrasToUserData(result, json);
  55139. onLoad(result);
  55140. }).catch(onError);
  55141. };
  55142. /**
  55143. * Marks the special nodes/meshes in json for efficient parse.
  55144. */
  55145. GLTFParser.prototype._markDefs = function () {
  55146. var nodeDefs = this.json.nodes || [];
  55147. var skinDefs = this.json.skins || [];
  55148. var meshDefs = this.json.meshes || [];
  55149. // Nothing in the node definition indicates whether it is a Bone or an
  55150. // Object3D. Use the skins' joint references to mark bones.
  55151. for (var skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex++) {
  55152. var joints = skinDefs[skinIndex].joints;
  55153. for (var i = 0, il = joints.length; i < il; i++) {
  55154. nodeDefs[joints[i]].isBone = true;
  55155. }
  55156. }
  55157. // Iterate over all nodes, marking references to shared resources,
  55158. // as well as skeleton joints.
  55159. for (var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex++) {
  55160. var nodeDef = nodeDefs[nodeIndex];
  55161. if (nodeDef.mesh !== undefined) {
  55162. this._addNodeRef(this.meshCache, nodeDef.mesh);
  55163. // Nothing in the mesh definition indicates whether it is
  55164. // a SkinnedMesh or Mesh. Use the node's mesh reference
  55165. // to mark SkinnedMesh if node has skin.
  55166. if (nodeDef.skin !== undefined) {
  55167. meshDefs[nodeDef.mesh].isSkinnedMesh = true;
  55168. }
  55169. }
  55170. if (nodeDef.camera !== undefined) {
  55171. this._addNodeRef(this.cameraCache, nodeDef.camera);
  55172. }
  55173. }
  55174. };
  55175. /**
  55176. * Counts references to shared node / Object3D resources. These resources
  55177. * can be reused, or "instantiated", at multiple nodes in the scene
  55178. * hierarchy. Mesh, Camera, and Light instances are instantiated and must
  55179. * be marked. Non-scenegraph resources (like Materials, Geometries, and
  55180. * Textures) can be reused directly and are not marked here.
  55181. *
  55182. * Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
  55183. */
  55184. GLTFParser.prototype._addNodeRef = function (cache, index) {
  55185. if (index === undefined) return;
  55186. if (cache.refs[index] === undefined) {
  55187. cache.refs[index] = cache.uses[index] = 0;
  55188. }
  55189. cache.refs[index]++;
  55190. };
  55191. /** Returns a reference to a shared resource, cloning it if necessary. */
  55192. GLTFParser.prototype._getNodeRef = function (cache, index, object) {
  55193. if (cache.refs[index] <= 1) return object;
  55194. var ref = object.clone();
  55195. ref.name += '_instance_' + cache.uses[index]++;
  55196. return ref;
  55197. };
  55198. GLTFParser.prototype._invokeOne = function (func) {
  55199. var extensions = Object.values(this.plugins);
  55200. extensions.push(this);
  55201. for (var i = 0; i < extensions.length; i++) {
  55202. var result = func(extensions[i]);
  55203. if (result) return result;
  55204. }
  55205. };
  55206. GLTFParser.prototype._invokeAll = function (func) {
  55207. var extensions = Object.values(this.plugins);
  55208. extensions.unshift(this);
  55209. var pending = [];
  55210. for (var i = 0; i < extensions.length; i++) {
  55211. var result = func(extensions[i]);
  55212. if (result) pending.push(result);
  55213. }
  55214. return pending;
  55215. };
  55216. /**
  55217. * Requests the specified dependency asynchronously, with caching.
  55218. * @param {string} type
  55219. * @param {number} index
  55220. * @return {Promise<Object3D|Material|THREE.Texture|AnimationClip|ArrayBuffer|Object>}
  55221. */
  55222. GLTFParser.prototype.getDependency = function (type, index) {
  55223. var cacheKey = type + ':' + index;
  55224. var dependency = this.cache.get(cacheKey);
  55225. if (!dependency) {
  55226. switch (type) {
  55227. case 'scene':
  55228. dependency = this.loadScene(index);
  55229. break;
  55230. case 'node':
  55231. dependency = this.loadNode(index);
  55232. break;
  55233. case 'mesh':
  55234. dependency = this._invokeOne(function (ext) {
  55235. return ext.loadMesh && ext.loadMesh(index);
  55236. });
  55237. break;
  55238. case 'accessor':
  55239. dependency = this.loadAccessor(index);
  55240. break;
  55241. case 'bufferView':
  55242. dependency = this._invokeOne(function (ext) {
  55243. return ext.loadBufferView && ext.loadBufferView(index);
  55244. });
  55245. break;
  55246. case 'buffer':
  55247. dependency = this.loadBuffer(index);
  55248. break;
  55249. case 'material':
  55250. dependency = this._invokeOne(function (ext) {
  55251. return ext.loadMaterial && ext.loadMaterial(index);
  55252. });
  55253. break;
  55254. case 'texture':
  55255. dependency = this._invokeOne(function (ext) {
  55256. return ext.loadTexture && ext.loadTexture(index);
  55257. });
  55258. break;
  55259. case 'skin':
  55260. dependency = this.loadSkin(index);
  55261. break;
  55262. case 'animation':
  55263. dependency = this.loadAnimation(index);
  55264. break;
  55265. case 'camera':
  55266. dependency = this.loadCamera(index);
  55267. break;
  55268. default:
  55269. throw new Error('Unknown type: ' + type);
  55270. }
  55271. this.cache.add(cacheKey, dependency);
  55272. }
  55273. return dependency;
  55274. };
  55275. /**
  55276. * Requests all dependencies of the specified type asynchronously, with caching.
  55277. * @param {string} type
  55278. * @return {Promise<Array<Object>>}
  55279. */
  55280. GLTFParser.prototype.getDependencies = function (type) {
  55281. var dependencies = this.cache.get(type);
  55282. if (!dependencies) {
  55283. var parser = this;
  55284. var defs = this.json[type + (type === 'mesh' ? 'es' : 's')] || [];
  55285. dependencies = Promise.all(defs.map(function (def, index) {
  55286. return parser.getDependency(type, index);
  55287. }));
  55288. this.cache.add(type, dependencies);
  55289. }
  55290. return dependencies;
  55291. };
  55292. /**
  55293. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
  55294. * @param {number} bufferIndex
  55295. * @return {Promise<ArrayBuffer>}
  55296. */
  55297. GLTFParser.prototype.loadBuffer = function (bufferIndex) {
  55298. var bufferDef = this.json.buffers[bufferIndex];
  55299. var loader = this.fileLoader;
  55300. if (bufferDef.type && bufferDef.type !== 'arraybuffer') {
  55301. throw new Error('THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.');
  55302. }
  55303. // If present, GLB container is required to be the first buffer.
  55304. if (bufferDef.uri === undefined && bufferIndex === 0) {
  55305. return Promise.resolve(this.extensions[EXTENSIONS.KHR_BINARY_GLTF].body);
  55306. }
  55307. var options = this.options;
  55308. return new Promise(function (resolve, reject) {
  55309. loader.load(resolveURL(bufferDef.uri, options.path), resolve, undefined, function () {
  55310. reject(new Error('THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".'));
  55311. });
  55312. });
  55313. };
  55314. /**
  55315. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
  55316. * @param {number} bufferViewIndex
  55317. * @return {Promise<ArrayBuffer>}
  55318. */
  55319. GLTFParser.prototype.loadBufferView = function (bufferViewIndex) {
  55320. var bufferViewDef = this.json.bufferViews[bufferViewIndex];
  55321. return this.getDependency('buffer', bufferViewDef.buffer).then(function (buffer) {
  55322. var byteLength = bufferViewDef.byteLength || 0;
  55323. var byteOffset = bufferViewDef.byteOffset || 0;
  55324. return buffer.slice(byteOffset, byteOffset + byteLength);
  55325. });
  55326. };
  55327. /**
  55328. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors
  55329. * @param {number} accessorIndex
  55330. * @return {Promise<BufferAttribute|InterleavedBufferAttribute>}
  55331. */
  55332. GLTFParser.prototype.loadAccessor = function (accessorIndex) {
  55333. var parser = this;
  55334. var json = this.json;
  55335. var accessorDef = this.json.accessors[accessorIndex];
  55336. if (accessorDef.bufferView === undefined && accessorDef.sparse === undefined) {
  55337. // Ignore empty accessors, which may be used to declare runtime
  55338. // information about attributes coming from another source (e.g. Draco
  55339. // compression extension).
  55340. return Promise.resolve(null);
  55341. }
  55342. var pendingBufferViews = [];
  55343. if (accessorDef.bufferView !== undefined) {
  55344. pendingBufferViews.push(this.getDependency('bufferView', accessorDef.bufferView));
  55345. } else {
  55346. pendingBufferViews.push(null);
  55347. }
  55348. if (accessorDef.sparse !== undefined) {
  55349. pendingBufferViews.push(this.getDependency('bufferView', accessorDef.sparse.indices.bufferView));
  55350. pendingBufferViews.push(this.getDependency('bufferView', accessorDef.sparse.values.bufferView));
  55351. }
  55352. return Promise.all(pendingBufferViews).then(function (bufferViews) {
  55353. var bufferView = bufferViews[0];
  55354. var itemSize = WEBGL_TYPE_SIZES[accessorDef.type];
  55355. var TypedArray = WEBGL_COMPONENT_TYPES[accessorDef.componentType];
  55356. // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
  55357. var elementBytes = TypedArray.BYTES_PER_ELEMENT;
  55358. var itemBytes = elementBytes * itemSize;
  55359. var byteOffset = accessorDef.byteOffset || 0;
  55360. var byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[accessorDef.bufferView].byteStride : undefined;
  55361. var normalized = accessorDef.normalized === true;
  55362. var array, bufferAttribute;
  55363. // The buffer is not interleaved if the stride is the item size in bytes.
  55364. if (byteStride && byteStride !== itemBytes) {
  55365. // Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer
  55366. // This makes sure that IBA.count reflects accessor.count properly
  55367. var ibSlice = Math.floor(byteOffset / byteStride);
  55368. var ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;
  55369. var ib = parser.cache.get(ibCacheKey);
  55370. if (!ib) {
  55371. array = new TypedArray(bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes);
  55372. // Integer parameters to IB/IBA are in array elements, not bytes.
  55373. ib = new InterleavedBuffer(array, byteStride / elementBytes);
  55374. parser.cache.add(ibCacheKey, ib);
  55375. }
  55376. bufferAttribute = new InterleavedBufferAttribute(ib, itemSize, byteOffset % byteStride / elementBytes, normalized);
  55377. } else {
  55378. if (bufferView === null) {
  55379. array = new TypedArray(accessorDef.count * itemSize);
  55380. } else {
  55381. array = new TypedArray(bufferView, byteOffset, accessorDef.count * itemSize);
  55382. }
  55383. bufferAttribute = new BufferAttribute(array, itemSize, normalized);
  55384. }
  55385. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors
  55386. if (accessorDef.sparse !== undefined) {
  55387. var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
  55388. var TypedArrayIndices = WEBGL_COMPONENT_TYPES[accessorDef.sparse.indices.componentType];
  55389. var byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
  55390. var byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
  55391. var sparseIndices = new TypedArrayIndices(bufferViews[1], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices);
  55392. var sparseValues = new TypedArray(bufferViews[2], byteOffsetValues, accessorDef.sparse.count * itemSize);
  55393. if (bufferView !== null) {
  55394. // Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.
  55395. bufferAttribute = new BufferAttribute(bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized);
  55396. }
  55397. for (var i = 0, il = sparseIndices.length; i < il; i++) {
  55398. var index = sparseIndices[i];
  55399. bufferAttribute.setX(index, sparseValues[i * itemSize]);
  55400. if (itemSize >= 2) bufferAttribute.setY(index, sparseValues[i * itemSize + 1]);
  55401. if (itemSize >= 3) bufferAttribute.setZ(index, sparseValues[i * itemSize + 2]);
  55402. if (itemSize >= 4) bufferAttribute.setW(index, sparseValues[i * itemSize + 3]);
  55403. if (itemSize >= 5) throw new Error('THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.');
  55404. }
  55405. }
  55406. return bufferAttribute;
  55407. });
  55408. };
  55409. /**
  55410. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
  55411. * @param {number} textureIndex
  55412. * @return {Promise<THREE.Texture>}
  55413. */
  55414. GLTFParser.prototype.loadTexture = function (textureIndex) {
  55415. var parser = this;
  55416. var json = this.json;
  55417. var options = this.options;
  55418. var textureDef = json.textures[textureIndex];
  55419. var textureExtensions = textureDef.extensions || {};
  55420. var source;
  55421. if (textureExtensions[EXTENSIONS.MSFT_TEXTURE_DDS]) {
  55422. source = json.images[textureExtensions[EXTENSIONS.MSFT_TEXTURE_DDS].source];
  55423. } else {
  55424. source = json.images[textureDef.source];
  55425. }
  55426. var loader;
  55427. if (source.uri) {
  55428. loader = options.manager.getHandler(source.uri);
  55429. }
  55430. if (!loader) {
  55431. loader = textureExtensions[EXTENSIONS.MSFT_TEXTURE_DDS] ? parser.extensions[EXTENSIONS.MSFT_TEXTURE_DDS].ddsLoader : this.textureLoader;
  55432. }
  55433. return this.loadTextureImage(textureIndex, source, loader);
  55434. };
  55435. GLTFParser.prototype.loadTextureImage = function (textureIndex, source, loader) {
  55436. var parser = this;
  55437. var json = this.json;
  55438. var options = this.options;
  55439. var textureDef = json.textures[textureIndex];
  55440. var URL = self.URL || self.webkitURL;
  55441. var sourceURI = source.uri;
  55442. var isObjectURL = false;
  55443. var hasAlpha = true;
  55444. if (source.mimeType === 'image/jpeg') hasAlpha = false;
  55445. if (source.bufferView !== undefined) {
  55446. // Load binary image data from bufferView, if provided.
  55447. sourceURI = parser.getDependency('bufferView', source.bufferView).then(function (bufferView) {
  55448. if (source.mimeType === 'image/png') {
  55449. // Inspect the PNG 'IHDR' chunk to determine whether the image could have an
  55450. // alpha channel. This check is conservative — the image could have an alpha
  55451. // channel with all values == 1, and the indexed type (colorType == 3) only
  55452. // sometimes contains alpha.
  55453. //
  55454. // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header
  55455. var colorType = new DataView(bufferView, 25, 1).getUint8(0, false);
  55456. hasAlpha = colorType === 6 || colorType === 4 || colorType === 3;
  55457. }
  55458. isObjectURL = true;
  55459. var blob = new Blob([bufferView], {
  55460. type: source.mimeType
  55461. });
  55462. sourceURI = URL.createObjectURL(blob);
  55463. return sourceURI;
  55464. });
  55465. }
  55466. return Promise.resolve(sourceURI).then(function (sourceURI) {
  55467. return new Promise(function (resolve, reject) {
  55468. var onLoad = resolve;
  55469. if (loader.isImageBitmapLoader === true) {
  55470. onLoad = function onLoad(imageBitmap) {
  55471. resolve(new CanvasTexture(imageBitmap));
  55472. };
  55473. }
  55474. loader.load(resolveURL(sourceURI, options.path), onLoad, undefined, reject);
  55475. });
  55476. }).then(function (texture) {
  55477. // Clean up resources and configure Texture.
  55478. if (isObjectURL === true) {
  55479. URL.revokeObjectURL(sourceURI);
  55480. }
  55481. texture.flipY = false;
  55482. if (textureDef.name) texture.name = textureDef.name;
  55483. // When there is definitely no alpha channel in the texture, set RGBFormat to save space.
  55484. if (!hasAlpha) texture.format = RGBFormat;
  55485. var samplers = json.samplers || {};
  55486. var sampler = samplers[textureDef.sampler] || {};
  55487. texture.encoding = THREE.LinearEncoding; //add
  55488. Potree.Utils.makeTexDontResize(texture); //add
  55489. /* //xzw 删除设置,因为已经makeTexDontResize
  55490. texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;
  55491. texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;
  55492. texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;
  55493. texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;
  55494. */
  55495. parser.associations.set(texture, {
  55496. type: 'textures',
  55497. index: textureIndex
  55498. });
  55499. return texture;
  55500. });
  55501. };
  55502. /**
  55503. * Asynchronously assigns a texture to the given material parameters.
  55504. * @param {Object} materialParams
  55505. * @param {string} mapName
  55506. * @param {Object} mapDef
  55507. * @return {Promise}
  55508. */
  55509. GLTFParser.prototype.assignTexture = function (materialParams, mapName, mapDef) {
  55510. var parser = this;
  55511. return this.getDependency('texture', mapDef.index).then(function (texture) {
  55512. // Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
  55513. // However, we will copy UV set 0 to UV set 1 on demand for aoMap
  55514. if (mapDef.texCoord !== undefined && mapDef.texCoord != 0 && !(mapName === 'aoMap' && mapDef.texCoord == 1)) {
  55515. console.warn('THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.');
  55516. }
  55517. if (parser.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM]) {
  55518. var transform = mapDef.extensions !== undefined ? mapDef.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM] : undefined;
  55519. if (transform) {
  55520. var gltfReference = parser.associations.get(texture);
  55521. texture = parser.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM].extendTexture(texture, transform);
  55522. parser.associations.set(texture, gltfReference);
  55523. }
  55524. }
  55525. materialParams[mapName] = texture;
  55526. });
  55527. };
  55528. /**
  55529. * Assigns final material to a Mesh, Line, or Points instance. The instance
  55530. * already has a material (generated from the glTF material options alone)
  55531. * but reuse of the same glTF material may require multiple threejs materials
  55532. * to accomodate different primitive types, defines, etc. New materials will
  55533. * be created if necessary, and reused from a cache.
  55534. * @param {Object3D} mesh Mesh, Line, or Points instance.
  55535. */
  55536. GLTFParser.prototype.assignFinalMaterial = function (mesh) {
  55537. var geometry = mesh.geometry;
  55538. var material = mesh.material;
  55539. var useVertexTangents = geometry.attributes.tangent !== undefined;
  55540. var useVertexColors = geometry.attributes.color !== undefined;
  55541. var useFlatShading = geometry.attributes.normal === undefined;
  55542. var useSkinning = mesh.isSkinnedMesh === true;
  55543. var useMorphTargets = Object.keys(geometry.morphAttributes).length > 0;
  55544. var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;
  55545. if (mesh.isPoints) {
  55546. var cacheKey = 'PointsMaterial:' + material.uuid;
  55547. var pointsMaterial = this.cache.get(cacheKey);
  55548. if (!pointsMaterial) {
  55549. pointsMaterial = new PointsMaterial();
  55550. Material.prototype.copy.call(pointsMaterial, material);
  55551. pointsMaterial.color.copy(material.color);
  55552. pointsMaterial.map = material.map;
  55553. pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
  55554. this.cache.add(cacheKey, pointsMaterial);
  55555. }
  55556. material = pointsMaterial;
  55557. } else if (mesh.isLine) {
  55558. var cacheKey = 'LineBasicMaterial:' + material.uuid;
  55559. var lineMaterial = this.cache.get(cacheKey);
  55560. if (!lineMaterial) {
  55561. lineMaterial = new LineBasicMaterial();
  55562. Material.prototype.copy.call(lineMaterial, material);
  55563. lineMaterial.color.copy(material.color);
  55564. this.cache.add(cacheKey, lineMaterial);
  55565. }
  55566. material = lineMaterial;
  55567. }
  55568. // Clone the material if it will be modified
  55569. if (useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets) {
  55570. var cacheKey = 'ClonedMaterial:' + material.uuid + ':';
  55571. if (material.isGLTFSpecularGlossinessMaterial) cacheKey += 'specular-glossiness:';
  55572. if (useSkinning) cacheKey += 'skinning:';
  55573. if (useVertexTangents) cacheKey += 'vertex-tangents:';
  55574. if (useVertexColors) cacheKey += 'vertex-colors:';
  55575. if (useFlatShading) cacheKey += 'flat-shading:';
  55576. if (useMorphTargets) cacheKey += 'morph-targets:';
  55577. if (useMorphNormals) cacheKey += 'morph-normals:';
  55578. var cachedMaterial = this.cache.get(cacheKey);
  55579. if (!cachedMaterial) {
  55580. cachedMaterial = material.clone();
  55581. if (useSkinning) cachedMaterial.skinning = true;
  55582. if (useVertexTangents) cachedMaterial.vertexTangents = true;
  55583. if (useVertexColors) cachedMaterial.vertexColors = true;
  55584. if (useFlatShading) cachedMaterial.flatShading = true;
  55585. if (useMorphTargets) cachedMaterial.morphTargets = true;
  55586. if (useMorphNormals) cachedMaterial.morphNormals = true;
  55587. this.cache.add(cacheKey, cachedMaterial);
  55588. this.associations.set(cachedMaterial, this.associations.get(material));
  55589. }
  55590. material = cachedMaterial;
  55591. }
  55592. // workarounds for mesh and geometry
  55593. if (material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined) {
  55594. geometry.setAttribute('uv2', geometry.attributes.uv);
  55595. }
  55596. // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
  55597. if (material.normalScale && !useVertexTangents) {
  55598. material.normalScale.y = -material.normalScale.y;
  55599. }
  55600. if (material.clearcoatNormalScale && !useVertexTangents) {
  55601. material.clearcoatNormalScale.y = -material.clearcoatNormalScale.y;
  55602. }
  55603. mesh.material = material;
  55604. };
  55605. GLTFParser.prototype.getMaterialType = function /* materialIndex */
  55606. () {
  55607. return MeshStandardMaterial;
  55608. };
  55609. /**
  55610. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
  55611. * @param {number} materialIndex
  55612. * @return {Promise<Material>}
  55613. */
  55614. GLTFParser.prototype.loadMaterial = function (materialIndex) {
  55615. var parser = this;
  55616. var json = this.json;
  55617. var extensions = this.extensions;
  55618. var materialDef = json.materials[materialIndex];
  55619. var materialType;
  55620. var materialParams = {};
  55621. var materialExtensions = materialDef.extensions || {};
  55622. var pending = [];
  55623. if (materialExtensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS]) {
  55624. var sgExtension = extensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS];
  55625. materialType = /* BasicMaterial// */sgExtension.getMaterialType(); //xzw 改
  55626. pending.push(sgExtension.extendParams(materialParams, materialDef, parser));
  55627. } else if (materialExtensions[EXTENSIONS.KHR_MATERIALS_UNLIT]) {
  55628. var kmuExtension = extensions[EXTENSIONS.KHR_MATERIALS_UNLIT];
  55629. materialType = /* BasicMaterial// */kmuExtension.getMaterialType(); //xzw 改
  55630. pending.push(kmuExtension.extendParams(materialParams, materialDef, parser));
  55631. } else {
  55632. // Specification:
  55633. // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
  55634. var metallicRoughness = materialDef.pbrMetallicRoughness || {};
  55635. materialParams.color = new Color(1.0, 1.0, 1.0);
  55636. materialParams.opacity = 1.0;
  55637. if (Array.isArray(metallicRoughness.baseColorFactor)) {
  55638. var array = metallicRoughness.baseColorFactor;
  55639. materialParams.color.fromArray(array);
  55640. materialParams.opacity = array[3];
  55641. }
  55642. if (metallicRoughness.baseColorTexture !== undefined) {
  55643. pending.push(parser.assignTexture(materialParams, 'map', metallicRoughness.baseColorTexture));
  55644. }
  55645. materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
  55646. materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
  55647. if (metallicRoughness.metallicRoughnessTexture !== undefined) {
  55648. pending.push(parser.assignTexture(materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture));
  55649. pending.push(parser.assignTexture(materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture));
  55650. }
  55651. materialType = this._invokeOne(function (ext) {
  55652. return ext.getMaterialType && ext.getMaterialType(materialIndex);
  55653. });
  55654. pending.push(Promise.all(this._invokeAll(function (ext) {
  55655. return ext.extendMaterialParams && ext.extendMaterialParams(materialIndex, materialParams);
  55656. })));
  55657. }
  55658. if (materialDef.doubleSided === true) {
  55659. materialParams.side = DoubleSide;
  55660. }
  55661. var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
  55662. if (alphaMode === ALPHA_MODES.BLEND) {
  55663. materialParams.transparent = true;
  55664. // See: https://github.com/mrdoob/three.js/issues/17706
  55665. materialParams.depthWrite = false;
  55666. } else {
  55667. materialParams.transparent = false;
  55668. if (alphaMode === ALPHA_MODES.MASK) {
  55669. materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
  55670. }
  55671. }
  55672. if (materialDef.normalTexture !== undefined && materialType !== MeshBasicMaterial) {
  55673. pending.push(parser.assignTexture(materialParams, 'normalMap', materialDef.normalTexture));
  55674. materialParams.normalScale = new Vector2(1, 1);
  55675. if (materialDef.normalTexture.scale !== undefined) {
  55676. materialParams.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
  55677. }
  55678. }
  55679. if (materialDef.occlusionTexture !== undefined && materialType !== MeshBasicMaterial) {
  55680. pending.push(parser.assignTexture(materialParams, 'aoMap', materialDef.occlusionTexture));
  55681. if (materialDef.occlusionTexture.strength !== undefined) {
  55682. materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
  55683. }
  55684. }
  55685. if (materialDef.emissiveFactor !== undefined && materialType !== MeshBasicMaterial) {
  55686. materialParams.emissive = new Color().fromArray(materialDef.emissiveFactor);
  55687. }
  55688. if (materialDef.emissiveTexture !== undefined && materialType !== MeshBasicMaterial) {
  55689. pending.push(parser.assignTexture(materialParams, 'emissiveMap', materialDef.emissiveTexture));
  55690. }
  55691. return Promise.all(pending).then(function () {
  55692. var material;
  55693. if (materialType === GLTFMeshStandardSGMaterial) {
  55694. material = extensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS].createMaterial(materialParams);
  55695. } else {
  55696. material = new materialType(materialParams);
  55697. }
  55698. if (materialDef.name) material.name = materialDef.name;
  55699. /* // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
  55700. if ( material.map ) material.map.encoding = sRGBEncoding; //xzw delete, sRGB会造成颜色偏深。新版本的loader也没加srgb
  55701. if ( material.emissiveMap ) material.emissiveMap.encoding = sRGBEncoding; */
  55702. assignExtrasToUserData(material, materialDef);
  55703. parser.associations.set(material, {
  55704. type: 'materials',
  55705. index: materialIndex
  55706. });
  55707. if (materialDef.extensions) addUnknownExtensionsToUserData(extensions, material, materialDef);
  55708. return material;
  55709. });
  55710. };
  55711. /** When Object3D instances are targeted by animation, they need unique names. */
  55712. GLTFParser.prototype.createUniqueName = function (originalName) {
  55713. var sanitizedName = PropertyBinding.sanitizeNodeName(originalName || '');
  55714. var name = sanitizedName;
  55715. for (var i = 1; this.nodeNamesUsed[name]; ++i) {
  55716. name = sanitizedName + '_' + i;
  55717. }
  55718. this.nodeNamesUsed[name] = true;
  55719. return name;
  55720. };
  55721. /**
  55722. * @param {BufferGeometry} geometry
  55723. * @param {GLTF.Primitive} primitiveDef
  55724. * @param {GLTFParser} parser
  55725. */
  55726. function computeBounds(geometry, primitiveDef, parser) {
  55727. var attributes = primitiveDef.attributes;
  55728. var box = new Box3();
  55729. if (attributes.POSITION !== undefined) {
  55730. var accessor = parser.json.accessors[attributes.POSITION];
  55731. var min = accessor.min;
  55732. var max = accessor.max;
  55733. // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
  55734. if (min !== undefined && max !== undefined) {
  55735. box.set(new Vector3(min[0], min[1], min[2]), new Vector3(max[0], max[1], max[2]));
  55736. } else {
  55737. console.warn('THREE.GLTFLoader: Missing min/max properties for accessor POSITION.');
  55738. return;
  55739. }
  55740. } else {
  55741. return;
  55742. }
  55743. var targets = primitiveDef.targets;
  55744. if (targets !== undefined) {
  55745. var maxDisplacement = new Vector3();
  55746. var vector = new Vector3();
  55747. for (var i = 0, il = targets.length; i < il; i++) {
  55748. var target = targets[i];
  55749. if (target.POSITION !== undefined) {
  55750. var accessor = parser.json.accessors[target.POSITION];
  55751. var min = accessor.min;
  55752. var max = accessor.max;
  55753. // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
  55754. if (min !== undefined && max !== undefined) {
  55755. // we need to get max of absolute components because target weight is [-1,1]
  55756. vector.setX(Math.max(Math.abs(min[0]), Math.abs(max[0])));
  55757. vector.setY(Math.max(Math.abs(min[1]), Math.abs(max[1])));
  55758. vector.setZ(Math.max(Math.abs(min[2]), Math.abs(max[2])));
  55759. // Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
  55760. // to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
  55761. // are used to implement key-frame animations and as such only two are active at a time - this results in very large
  55762. // boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.
  55763. maxDisplacement.max(vector);
  55764. } else {
  55765. console.warn('THREE.GLTFLoader: Missing min/max properties for accessor POSITION.');
  55766. }
  55767. }
  55768. }
  55769. // As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.
  55770. box.expandByVector(maxDisplacement);
  55771. }
  55772. geometry.boundingBox = box;
  55773. var sphere = new Sphere();
  55774. box.getCenter(sphere.center);
  55775. sphere.radius = box.min.distanceTo(box.max) / 2;
  55776. geometry.boundingSphere = sphere;
  55777. }
  55778. /**
  55779. * @param {BufferGeometry} geometry
  55780. * @param {GLTF.Primitive} primitiveDef
  55781. * @param {GLTFParser} parser
  55782. * @return {Promise<BufferGeometry>}
  55783. */
  55784. function addPrimitiveAttributes(geometry, primitiveDef, parser) {
  55785. var attributes = primitiveDef.attributes;
  55786. var pending = [];
  55787. function assignAttributeAccessor(accessorIndex, attributeName) {
  55788. return parser.getDependency('accessor', accessorIndex).then(function (accessor) {
  55789. geometry.setAttribute(attributeName, accessor);
  55790. });
  55791. }
  55792. for (var gltfAttributeName in attributes) {
  55793. var threeAttributeName = ATTRIBUTES[gltfAttributeName] || gltfAttributeName.toLowerCase();
  55794. // Skip attributes already provided by e.g. Draco extension.
  55795. if (threeAttributeName in geometry.attributes) continue;
  55796. pending.push(assignAttributeAccessor(attributes[gltfAttributeName], threeAttributeName));
  55797. }
  55798. if (primitiveDef.indices !== undefined && !geometry.index) {
  55799. var accessor = parser.getDependency('accessor', primitiveDef.indices).then(function (accessor) {
  55800. geometry.setIndex(accessor);
  55801. });
  55802. pending.push(accessor);
  55803. }
  55804. assignExtrasToUserData(geometry, primitiveDef);
  55805. computeBounds(geometry, primitiveDef, parser);
  55806. return Promise.all(pending).then(function () {
  55807. return primitiveDef.targets !== undefined ? addMorphTargets(geometry, primitiveDef.targets, parser) : geometry;
  55808. });
  55809. }
  55810. /**
  55811. * @param {BufferGeometry} geometry
  55812. * @param {Number} drawMode
  55813. * @return {BufferGeometry}
  55814. */
  55815. function toTrianglesDrawMode(geometry, drawMode) {
  55816. var index = geometry.getIndex();
  55817. // generate index if not present
  55818. if (index === null) {
  55819. var indices = [];
  55820. var position = geometry.getAttribute('position');
  55821. if (position !== undefined) {
  55822. for (var i = 0; i < position.count; i++) {
  55823. indices.push(i);
  55824. }
  55825. geometry.setIndex(indices);
  55826. index = geometry.getIndex();
  55827. } else {
  55828. console.error('THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.');
  55829. return geometry;
  55830. }
  55831. }
  55832. //
  55833. var numberOfTriangles = index.count - 2;
  55834. var newIndices = [];
  55835. if (drawMode === TriangleFanDrawMode) {
  55836. // gl.TRIANGLE_FAN
  55837. for (var i = 1; i <= numberOfTriangles; i++) {
  55838. newIndices.push(index.getX(0));
  55839. newIndices.push(index.getX(i));
  55840. newIndices.push(index.getX(i + 1));
  55841. }
  55842. } else {
  55843. // gl.TRIANGLE_STRIP
  55844. for (var i = 0; i < numberOfTriangles; i++) {
  55845. if (i % 2 === 0) {
  55846. newIndices.push(index.getX(i));
  55847. newIndices.push(index.getX(i + 1));
  55848. newIndices.push(index.getX(i + 2));
  55849. } else {
  55850. newIndices.push(index.getX(i + 2));
  55851. newIndices.push(index.getX(i + 1));
  55852. newIndices.push(index.getX(i));
  55853. }
  55854. }
  55855. }
  55856. if (newIndices.length / 3 !== numberOfTriangles) {
  55857. console.error('THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.');
  55858. }
  55859. // build final geometry
  55860. var newGeometry = geometry.clone();
  55861. newGeometry.setIndex(newIndices);
  55862. return newGeometry;
  55863. }
  55864. /**
  55865. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
  55866. *
  55867. * Creates BufferGeometries from primitives.
  55868. *
  55869. * @param {Array<GLTF.Primitive>} primitives
  55870. * @return {Promise<Array<BufferGeometry>>}
  55871. */
  55872. GLTFParser.prototype.loadGeometries = function (primitives) {
  55873. var parser = this;
  55874. var extensions = this.extensions;
  55875. var cache = this.primitiveCache;
  55876. function createDracoPrimitive(primitive) {
  55877. return extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(primitive, parser).then(function (geometry) {
  55878. return addPrimitiveAttributes(geometry, primitive, parser);
  55879. });
  55880. }
  55881. var pending = [];
  55882. for (var i = 0, il = primitives.length; i < il; i++) {
  55883. var primitive = primitives[i];
  55884. var cacheKey = createPrimitiveKey(primitive);
  55885. // See if we've already created this geometry
  55886. var cached = cache[cacheKey];
  55887. if (cached) {
  55888. // Use the cached geometry if it exists
  55889. pending.push(cached.promise);
  55890. } else {
  55891. var geometryPromise;
  55892. if (primitive.extensions && primitive.extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION]) {
  55893. // Use DRACO geometry if available
  55894. geometryPromise = createDracoPrimitive(primitive);
  55895. } else {
  55896. // Otherwise create a new geometry
  55897. geometryPromise = addPrimitiveAttributes(new BufferGeometry(), primitive, parser);
  55898. }
  55899. // Cache this geometry
  55900. cache[cacheKey] = {
  55901. primitive: primitive,
  55902. promise: geometryPromise
  55903. };
  55904. pending.push(geometryPromise);
  55905. }
  55906. }
  55907. return Promise.all(pending);
  55908. };
  55909. /**
  55910. * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
  55911. * @param {number} meshIndex
  55912. * @return {Promise<Group|Mesh|SkinnedMesh>}
  55913. */
  55914. GLTFParser.prototype.loadMesh = function (meshIndex) {
  55915. var parser = this;
  55916. var json = this.json;
  55917. var extensions = this.extensions;
  55918. var meshDef = json.meshes[meshIndex];
  55919. var primitives = meshDef.primitives;
  55920. var pending = [];
  55921. for (var i = 0, il = primitives.length; i < il; i++) {
  55922. var material = primitives[i].material === undefined ? createDefaultMaterial(this.cache) : this.getDependency('material', primitives[i].material);
  55923. pending.push(material);
  55924. }
  55925. pending.push(parser.loadGeometries(primitives));
  55926. return Promise.all(pending).then(function (results) {
  55927. var materials = results.slice(0, results.length - 1);
  55928. var geometries = results[results.length - 1];
  55929. var meshes = [];
  55930. for (var i = 0, il = geometries.length; i < il; i++) {
  55931. var geometry = geometries[i];
  55932. var primitive = primitives[i];
  55933. // 1. create Mesh
  55934. var mesh;
  55935. var material = materials[i];
  55936. if (primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN || primitive.mode === undefined) {
  55937. // .isSkinnedMesh isn't in glTF spec. See ._markDefs()
  55938. mesh = meshDef.isSkinnedMesh === true ? new SkinnedMesh(geometry, material) : new Mesh(geometry, material);
  55939. if (mesh.isSkinnedMesh === true && !mesh.geometry.attributes.skinWeight.normalized) {
  55940. // we normalize floating point skin weight array to fix malformed assets (see #15319)
  55941. // it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
  55942. mesh.normalizeSkinWeights();
  55943. }
  55944. if (primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP) {
  55945. mesh.geometry = toTrianglesDrawMode(mesh.geometry, TriangleStripDrawMode);
  55946. } else if (primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN) {
  55947. mesh.geometry = toTrianglesDrawMode(mesh.geometry, TriangleFanDrawMode);
  55948. }
  55949. } else if (primitive.mode === WEBGL_CONSTANTS.LINES) {
  55950. mesh = new LineSegments(geometry, material);
  55951. } else if (primitive.mode === WEBGL_CONSTANTS.LINE_STRIP) {
  55952. mesh = new Line(geometry, material);
  55953. } else if (primitive.mode === WEBGL_CONSTANTS.LINE_LOOP) {
  55954. mesh = new LineLoop(geometry, material);
  55955. } else if (primitive.mode === WEBGL_CONSTANTS.POINTS) {
  55956. mesh = new Points(geometry, material);
  55957. } else {
  55958. throw new Error('THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode);
  55959. }
  55960. if (Object.keys(mesh.geometry.morphAttributes).length > 0) {
  55961. updateMorphTargets(mesh, meshDef);
  55962. }
  55963. mesh.name = parser.createUniqueName(meshDef.name || 'mesh_' + meshIndex);
  55964. assignExtrasToUserData(mesh, meshDef);
  55965. if (primitive.extensions) addUnknownExtensionsToUserData(extensions, mesh, primitive);
  55966. parser.assignFinalMaterial(mesh);
  55967. meshes.push(mesh);
  55968. }
  55969. if (meshes.length === 1) {
  55970. return meshes[0];
  55971. }
  55972. var group = new Group();
  55973. for (var i = 0, il = meshes.length; i < il; i++) {
  55974. group.add(meshes[i]);
  55975. }
  55976. return group;
  55977. });
  55978. };
  55979. /**
  55980. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
  55981. * @param {number} cameraIndex
  55982. * @return {Promise<THREE.Camera>}
  55983. */
  55984. GLTFParser.prototype.loadCamera = function (cameraIndex) {
  55985. var camera;
  55986. var cameraDef = this.json.cameras[cameraIndex];
  55987. var params = cameraDef[cameraDef.type];
  55988. if (!params) {
  55989. console.warn('THREE.GLTFLoader: Missing camera parameters.');
  55990. return;
  55991. }
  55992. if (cameraDef.type === 'perspective') {
  55993. camera = new PerspectiveCamera(MathUtils.radToDeg(params.yfov), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6);
  55994. } else if (cameraDef.type === 'orthographic') {
  55995. camera = new OrthographicCamera(-params.xmag, params.xmag, params.ymag, -params.ymag, params.znear, params.zfar);
  55996. }
  55997. if (cameraDef.name) camera.name = this.createUniqueName(cameraDef.name);
  55998. assignExtrasToUserData(camera, cameraDef);
  55999. return Promise.resolve(camera);
  56000. };
  56001. /**
  56002. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
  56003. * @param {number} skinIndex
  56004. * @return {Promise<Object>}
  56005. */
  56006. GLTFParser.prototype.loadSkin = function (skinIndex) {
  56007. var skinDef = this.json.skins[skinIndex];
  56008. var skinEntry = {
  56009. joints: skinDef.joints
  56010. };
  56011. if (skinDef.inverseBindMatrices === undefined) {
  56012. return Promise.resolve(skinEntry);
  56013. }
  56014. return this.getDependency('accessor', skinDef.inverseBindMatrices).then(function (accessor) {
  56015. skinEntry.inverseBindMatrices = accessor;
  56016. return skinEntry;
  56017. });
  56018. };
  56019. /**
  56020. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations
  56021. * @param {number} animationIndex
  56022. * @return {Promise<AnimationClip>}
  56023. */
  56024. GLTFParser.prototype.loadAnimation = function (animationIndex) {
  56025. var json = this.json;
  56026. var animationDef = json.animations[animationIndex];
  56027. var pendingNodes = [];
  56028. var pendingInputAccessors = [];
  56029. var pendingOutputAccessors = [];
  56030. var pendingSamplers = [];
  56031. var pendingTargets = [];
  56032. for (var i = 0, il = animationDef.channels.length; i < il; i++) {
  56033. var channel = animationDef.channels[i];
  56034. var sampler = animationDef.samplers[channel.sampler];
  56035. var target = channel.target;
  56036. var name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.
  56037. var input = animationDef.parameters !== undefined ? animationDef.parameters[sampler.input] : sampler.input;
  56038. var output = animationDef.parameters !== undefined ? animationDef.parameters[sampler.output] : sampler.output;
  56039. pendingNodes.push(this.getDependency('node', name));
  56040. pendingInputAccessors.push(this.getDependency('accessor', input));
  56041. pendingOutputAccessors.push(this.getDependency('accessor', output));
  56042. pendingSamplers.push(sampler);
  56043. pendingTargets.push(target);
  56044. }
  56045. return Promise.all([Promise.all(pendingNodes), Promise.all(pendingInputAccessors), Promise.all(pendingOutputAccessors), Promise.all(pendingSamplers), Promise.all(pendingTargets)]).then(function (dependencies) {
  56046. var nodes = dependencies[0];
  56047. var inputAccessors = dependencies[1];
  56048. var outputAccessors = dependencies[2];
  56049. var samplers = dependencies[3];
  56050. var targets = dependencies[4];
  56051. var tracks = [];
  56052. for (var i = 0, il = nodes.length; i < il; i++) {
  56053. var node = nodes[i];
  56054. var inputAccessor = inputAccessors[i];
  56055. var outputAccessor = outputAccessors[i];
  56056. var sampler = samplers[i];
  56057. var target = targets[i];
  56058. if (node === undefined) continue;
  56059. node.updateMatrix();
  56060. node.matrixAutoUpdate = true;
  56061. var TypedKeyframeTrack;
  56062. switch (PATH_PROPERTIES[target.path]) {
  56063. case PATH_PROPERTIES.weights:
  56064. TypedKeyframeTrack = NumberKeyframeTrack;
  56065. break;
  56066. case PATH_PROPERTIES.rotation:
  56067. TypedKeyframeTrack = QuaternionKeyframeTrack;
  56068. break;
  56069. case PATH_PROPERTIES.position:
  56070. case PATH_PROPERTIES.scale:
  56071. default:
  56072. TypedKeyframeTrack = VectorKeyframeTrack;
  56073. break;
  56074. }
  56075. var targetName = node.name ? node.name : node.uuid;
  56076. var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[sampler.interpolation] : InterpolateLinear;
  56077. var targetNames = [];
  56078. if (PATH_PROPERTIES[target.path] === PATH_PROPERTIES.weights) {
  56079. // Node may be a Group (glTF mesh with several primitives) or a Mesh.
  56080. node.traverse(function (object) {
  56081. if (object.isMesh === true && object.morphTargetInfluences) {
  56082. targetNames.push(object.name ? object.name : object.uuid);
  56083. }
  56084. });
  56085. } else {
  56086. targetNames.push(targetName);
  56087. }
  56088. var outputArray = outputAccessor.array;
  56089. if (outputAccessor.normalized) {
  56090. var scale;
  56091. if (outputArray.constructor === Int8Array) {
  56092. scale = 1 / 127;
  56093. } else if (outputArray.constructor === Uint8Array) {
  56094. scale = 1 / 255;
  56095. } else if (outputArray.constructor == Int16Array) {
  56096. scale = 1 / 32767;
  56097. } else if (outputArray.constructor === Uint16Array) {
  56098. scale = 1 / 65535;
  56099. } else {
  56100. throw new Error('THREE.GLTFLoader: Unsupported output accessor component type.');
  56101. }
  56102. var scaled = new Float32Array(outputArray.length);
  56103. for (var j = 0, jl = outputArray.length; j < jl; j++) {
  56104. scaled[j] = outputArray[j] * scale;
  56105. }
  56106. outputArray = scaled;
  56107. }
  56108. for (var j = 0, jl = targetNames.length; j < jl; j++) {
  56109. var track = new TypedKeyframeTrack(targetNames[j] + '.' + PATH_PROPERTIES[target.path], inputAccessor.array, outputArray, interpolation);
  56110. // Override interpolation with custom factory method.
  56111. if (sampler.interpolation === 'CUBICSPLINE') {
  56112. track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline(result) {
  56113. // A CUBICSPLINE keyframe in glTF has three output values for each input value,
  56114. // representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
  56115. // must be divided by three to get the interpolant's sampleSize argument.
  56116. return new GLTFCubicSplineInterpolant(this.times, this.values, this.getValueSize() / 3, result);
  56117. };
  56118. // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
  56119. track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
  56120. }
  56121. tracks.push(track);
  56122. }
  56123. }
  56124. var name = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
  56125. return new AnimationClip(name, undefined, tracks);
  56126. });
  56127. };
  56128. /**
  56129. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy
  56130. * @param {number} nodeIndex
  56131. * @return {Promise<Object3D>}
  56132. */
  56133. GLTFParser.prototype.loadNode = function (nodeIndex) {
  56134. var json = this.json;
  56135. var extensions = this.extensions;
  56136. var parser = this;
  56137. var nodeDef = json.nodes[nodeIndex];
  56138. // reserve node's name before its dependencies, so the root has the intended name.
  56139. var nodeName = nodeDef.name ? parser.createUniqueName(nodeDef.name) : '';
  56140. return function () {
  56141. var pending = [];
  56142. if (nodeDef.mesh !== undefined) {
  56143. pending.push(parser.getDependency('mesh', nodeDef.mesh).then(function (mesh) {
  56144. var node = parser._getNodeRef(parser.meshCache, nodeDef.mesh, mesh);
  56145. // if weights are provided on the node, override weights on the mesh.
  56146. if (nodeDef.weights !== undefined) {
  56147. node.traverse(function (o) {
  56148. if (!o.isMesh) return;
  56149. for (var i = 0, il = nodeDef.weights.length; i < il; i++) {
  56150. o.morphTargetInfluences[i] = nodeDef.weights[i];
  56151. }
  56152. });
  56153. }
  56154. return node;
  56155. }));
  56156. }
  56157. if (nodeDef.camera !== undefined) {
  56158. pending.push(parser.getDependency('camera', nodeDef.camera).then(function (camera) {
  56159. return parser._getNodeRef(parser.cameraCache, nodeDef.camera, camera);
  56160. }));
  56161. }
  56162. parser._invokeAll(function (ext) {
  56163. return ext.createNodeAttachment && ext.createNodeAttachment(nodeIndex);
  56164. }).forEach(function (promise) {
  56165. pending.push(promise);
  56166. });
  56167. return Promise.all(pending);
  56168. }().then(function (objects) {
  56169. var node;
  56170. // .isBone isn't in glTF spec. See ._markDefs
  56171. if (nodeDef.isBone === true) {
  56172. node = new Bone();
  56173. } else if (objects.length > 1) {
  56174. node = new Group();
  56175. } else if (objects.length === 1) {
  56176. node = objects[0];
  56177. } else {
  56178. node = new Object3D();
  56179. }
  56180. if (node !== objects[0]) {
  56181. for (var i = 0, il = objects.length; i < il; i++) {
  56182. node.add(objects[i]);
  56183. }
  56184. }
  56185. if (nodeDef.name) {
  56186. node.userData.name = nodeDef.name;
  56187. node.name = nodeName;
  56188. }
  56189. assignExtrasToUserData(node, nodeDef);
  56190. if (nodeDef.extensions) addUnknownExtensionsToUserData(extensions, node, nodeDef);
  56191. if (nodeDef.matrix !== undefined) {
  56192. var matrix = new Matrix4();
  56193. matrix.fromArray(nodeDef.matrix);
  56194. node.applyMatrix4(matrix);
  56195. } else {
  56196. if (nodeDef.translation !== undefined) {
  56197. node.position.fromArray(nodeDef.translation);
  56198. }
  56199. if (nodeDef.rotation !== undefined) {
  56200. node.quaternion.fromArray(nodeDef.rotation);
  56201. }
  56202. if (nodeDef.scale !== undefined) {
  56203. node.scale.fromArray(nodeDef.scale);
  56204. }
  56205. }
  56206. parser.associations.set(node, {
  56207. type: 'nodes',
  56208. index: nodeIndex
  56209. });
  56210. return node;
  56211. });
  56212. };
  56213. /**
  56214. * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
  56215. * @param {number} sceneIndex
  56216. * @return {Promise<Group>}
  56217. */
  56218. GLTFParser.prototype.loadScene = function () {
  56219. // scene node hierachy builder
  56220. function buildNodeHierachy(nodeId, parentObject, json, parser) {
  56221. var nodeDef = json.nodes[nodeId];
  56222. return parser.getDependency('node', nodeId).then(function (node) {
  56223. if (nodeDef.skin === undefined) return node;
  56224. // build skeleton here as well
  56225. var skinEntry;
  56226. return parser.getDependency('skin', nodeDef.skin).then(function (skin) {
  56227. skinEntry = skin;
  56228. var pendingJoints = [];
  56229. for (var i = 0, il = skinEntry.joints.length; i < il; i++) {
  56230. pendingJoints.push(parser.getDependency('node', skinEntry.joints[i]));
  56231. }
  56232. return Promise.all(pendingJoints);
  56233. }).then(function (jointNodes) {
  56234. node.traverse(function (mesh) {
  56235. if (!mesh.isMesh) return;
  56236. var bones = [];
  56237. var boneInverses = [];
  56238. for (var j = 0, jl = jointNodes.length; j < jl; j++) {
  56239. var jointNode = jointNodes[j];
  56240. if (jointNode) {
  56241. bones.push(jointNode);
  56242. var mat = new Matrix4();
  56243. if (skinEntry.inverseBindMatrices !== undefined) {
  56244. mat.fromArray(skinEntry.inverseBindMatrices.array, j * 16);
  56245. }
  56246. boneInverses.push(mat);
  56247. } else {
  56248. console.warn('THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[j]);
  56249. }
  56250. }
  56251. mesh.bind(new Skeleton(bones, boneInverses), mesh.matrixWorld);
  56252. });
  56253. return node;
  56254. });
  56255. }).then(function (node) {
  56256. // build node hierachy
  56257. parentObject.add(node);
  56258. var pending = [];
  56259. if (nodeDef.children) {
  56260. var children = nodeDef.children;
  56261. for (var i = 0, il = children.length; i < il; i++) {
  56262. var child = children[i];
  56263. pending.push(buildNodeHierachy(child, node, json, parser));
  56264. }
  56265. }
  56266. return Promise.all(pending);
  56267. });
  56268. }
  56269. return function loadScene(sceneIndex) {
  56270. var json = this.json;
  56271. var extensions = this.extensions;
  56272. var sceneDef = this.json.scenes[sceneIndex];
  56273. var parser = this;
  56274. // Loader returns Group, not Scene.
  56275. // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172
  56276. var scene = new Group();
  56277. if (sceneDef.name) scene.name = parser.createUniqueName(sceneDef.name);
  56278. assignExtrasToUserData(scene, sceneDef);
  56279. if (sceneDef.extensions) addUnknownExtensionsToUserData(extensions, scene, sceneDef);
  56280. var nodeIds = sceneDef.nodes || [];
  56281. var pending = [];
  56282. for (var i = 0, il = nodeIds.length; i < il; i++) {
  56283. pending.push(buildNodeHierachy(nodeIds[i], scene, json, parser));
  56284. }
  56285. return Promise.all(pending).then(function () {
  56286. return scene;
  56287. });
  56288. };
  56289. }();
  56290. return GLTFLoader;
  56291. }();
  56292. var globalThis=window;//add 有的app没有globalThis. 2023.1
  56293. var rtcCenterGlobal=false;//默认false,也就是scale.z要乘以-1
  56294. /*! *****************************************************************************
  56295. github: https://github.com/nytimes/three-loader-3dtiles
  56296. Copyright (c) Microsoft Corporation.
  56297. Permission to use, copy, modify, and/or distribute this software for any
  56298. purpose with or without fee is hereby granted.
  56299. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  56300. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  56301. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  56302. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  56303. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  56304. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  56305. PERFORMANCE OF THIS SOFTWARE.
  56306. ***************************************************************************** */var visiGeoCount=0;var maxVertexVisi=5e6;var maxTexVisi=500;var maxDepth=100;function getGpuMemoryUsage(){var win=arguments.length>0&&arguments[0]!==undefined?arguments[0]:window;//总的
  56307. var c=0;viewer.setAllTilesets(model=>{var tileset3D=model.runtime.getTileset();c+=tileset3D.gpuMemoryUsageInBytes;//不会因为tileset或tile隐藏而降低,除非释放了资源
  56308. });if(win.parent!=win){//还有父级页面。 暂时只有子级需要考虑父级,假设父级在前台时子级已经销毁
  56309. c+=getGpuMemoryUsage(win.parent);}viewer.tiles3dMemoryUsage=c;return c;}function updateQuality(){var maximumMemory=Potree.settings.tiles3DMaxMemory*1024*1024;var memory=getGpuMemoryUsage();var r=memory/maximumMemory;viewer.setAllTilesets(model=>{var tileset=model.runtime.getTileset();var e=tileset.options.maximumScreenSpaceError*THREE.Math.clamp(r,0.9,1.1);e=THREE.Math.clamp(e,tileset.options.initialMaxSSE,1000);tileset.options.maximumScreenSpaceError=e;});}function changeModelPointCount(tile,type){var posCount,texArea;if(type=='add'){var _o=viewer.getObjectPointCount(tile.tileContent);posCount=_o.posCount,texArea=_o.texArea;tile.posCount=posCount,tile.texArea=texArea;}else {posCount=-tile.posCount,texArea=-tile.texArea;}viewer.memoryModelCountInfo.tilePosCount+=posCount;viewer.memoryModelCountInfo.tileTexArea+=texArea;}function __awaiter(thisArg,_arguments,P,generator){function adopt(value){return value instanceof P?value:new P(function(resolve){resolve(value);});}return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value));}catch(e){reject(e);}}function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e);}}function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);}step((generator=generator.apply(thisArg,_arguments||[])).next());});}function assert$7(condition,message){if(!condition){throw new Error(message||'loader assertion failed.');}}var isBrowser$2=Boolean(typeof process!=='object'||String(process)!=='[object process]'||process.browser);var matches$1=typeof process!=='undefined'&&process.version&&/v([0-9]*)/.exec(process.version);matches$1&&parseFloat(matches$1[1])||0;var VERSION$8="3.1.4";function assert$6(condition,message){if(!condition){throw new Error(message||'loaders.gl assertion failed.');}}var globals$1={self:typeof self!=='undefined'&&self,window:typeof window!=='undefined'&&window,global:typeof global!=='undefined'&&global,document:typeof document!=='undefined'&&document};var global_=globals$1.global||globals$1.self||globals$1.window||{};var isBrowser$1=typeof process!=='object'||String(process)!=='[object process]'||process.browser;var isWorker=typeof importScripts==='function';var isMobile=typeof window!=='undefined'&&typeof window.orientation!=='undefined';var matches=typeof process!=='undefined'&&process.version&&/v([0-9]*)/.exec(process.version);matches&&parseFloat(matches[1])||0;function _defineProperty$1(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else {obj[key]=value;}return obj;}class WorkerJob{constructor(jobName,workerThread){_defineProperty$1(this,"name",void 0);_defineProperty$1(this,"workerThread",void 0);_defineProperty$1(this,"isRunning",void 0);_defineProperty$1(this,"result",void 0);_defineProperty$1(this,"_resolve",void 0);_defineProperty$1(this,"_reject",void 0);this.name=jobName;this.workerThread=workerThread;this.isRunning=true;this._resolve=()=>{};this._reject=()=>{};this.result=new Promise((resolve,reject)=>{this._resolve=resolve;this._reject=reject;});}postMessage(type,payload){this.workerThread.postMessage({source:'loaders.gl',type,payload});}done(value){assert$6(this.isRunning);this.isRunning=false;this._resolve(value);}error(error){assert$6(this.isRunning);this.isRunning=false;this._reject(error);}}var workerURLCache=new Map();function getLoadableWorkerURL(props){assert$6(props.source&&!props.url||!props.source&&props.url);var workerURL=workerURLCache.get(props.source||props.url);if(!workerURL){if(props.url){workerURL=getLoadableWorkerURLFromURL(props.url);workerURLCache.set(props.url,workerURL);}if(props.source){workerURL=getLoadableWorkerURLFromSource(props.source);workerURLCache.set(props.source,workerURL);}}assert$6(workerURL);return workerURL;}function getLoadableWorkerURLFromURL(url){if(!url.startsWith('http')){return url;}var workerSource=buildScriptSource(url);return getLoadableWorkerURLFromSource(workerSource);}function getLoadableWorkerURLFromSource(workerSource){var blob=new Blob([workerSource],{type:'application/javascript'});return URL.createObjectURL(blob);}function buildScriptSource(workerUrl){return "try {\n importScripts('".concat(workerUrl,"');\n} catch (error) {\n console.error(error);\n throw error;\n}");}function getTransferList(object){var recursive=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;var transfers=arguments.length>2?arguments[2]:undefined;var transfersSet=transfers||new Set();if(!object);else if(isTransferable(object)){transfersSet.add(object);}else if(isTransferable(object.buffer)){transfersSet.add(object.buffer);}else if(ArrayBuffer.isView(object));else if(recursive&&typeof object==='object'){for(var key in object){getTransferList(object[key],recursive,transfersSet);}}return transfers===undefined?Array.from(transfersSet):[];}function isTransferable(object){if(!object){return false;}if(object instanceof ArrayBuffer){return true;}if(typeof MessagePort!=='undefined'&&object instanceof MessagePort){return true;}if(typeof ImageBitmap!=='undefined'&&object instanceof ImageBitmap){return true;}if(typeof OffscreenCanvas!=='undefined'&&object instanceof OffscreenCanvas){return true;}return false;}var NOOP=()=>{};class WorkerThread{static isSupported(){return typeof Worker!=='undefined';}constructor(props){_defineProperty$1(this,"name",void 0);_defineProperty$1(this,"source",void 0);_defineProperty$1(this,"url",void 0);_defineProperty$1(this,"terminated",false);_defineProperty$1(this,"worker",void 0);_defineProperty$1(this,"onMessage",void 0);_defineProperty$1(this,"onError",void 0);_defineProperty$1(this,"_loadableURL",'');var{name,source,url}=props;assert$6(source||url);this.name=name;this.source=source;this.url=url;this.onMessage=NOOP;this.onError=error=>console.log(error);this.worker=this._createBrowserWorker();}destroy(){this.onMessage=NOOP;this.onError=NOOP;this.worker.terminate();this.terminated=true;}get isRunning(){return Boolean(this.onMessage);}postMessage(data,transferList){transferList=transferList||getTransferList(data);this.worker.postMessage(data,transferList);}_getErrorFromErrorEvent(event){var message='Failed to load ';message+="worker ".concat(this.name," from ").concat(this.url,". ");if(event.message){message+="".concat(event.message," in ");}if(event.lineno){message+=":".concat(event.lineno,":").concat(event.colno);}return new Error(message);}_createBrowserWorker(){this._loadableURL=getLoadableWorkerURL({source:this.source,url:this.url});var worker=new Worker(this._loadableURL,{name:this.name});worker.onmessage=event=>{if(!event.data){this.onError(new Error('No data received'));}else {this.onMessage(event.data);}};worker.onerror=error=>{this.onError(this._getErrorFromErrorEvent(error));this.terminated=true;};worker.onmessageerror=event=>console.error(event);return worker;}}class WorkerPool$2{constructor(props){_defineProperty$1(this,"name",'unnamed');_defineProperty$1(this,"source",void 0);_defineProperty$1(this,"url",void 0);_defineProperty$1(this,"maxConcurrency",1);_defineProperty$1(this,"maxMobileConcurrency",1);_defineProperty$1(this,"onDebug",()=>{});_defineProperty$1(this,"reuseWorkers",true);_defineProperty$1(this,"props",{});_defineProperty$1(this,"jobQueue",[]);_defineProperty$1(this,"idleQueue",[]);_defineProperty$1(this,"count",0);_defineProperty$1(this,"isDestroyed",false);this.source=props.source;this.url=props.url;this.setProps(props);}destroy(){this.idleQueue.forEach(worker=>worker.destroy());this.isDestroyed=true;}setProps(props){this.props=_objectSpread2(_objectSpread2({},this.props),props);if(props.name!==undefined){this.name=props.name;}if(props.maxConcurrency!==undefined){this.maxConcurrency=props.maxConcurrency;}if(props.maxMobileConcurrency!==undefined){this.maxMobileConcurrency=props.maxMobileConcurrency;}if(props.reuseWorkers!==undefined){this.reuseWorkers=props.reuseWorkers;}if(props.onDebug!==undefined){this.onDebug=props.onDebug;}}async startJob(name){var onMessage=arguments.length>1&&arguments[1]!==undefined?arguments[1]:(job,type,data)=>job.done(data);var onError=arguments.length>2&&arguments[2]!==undefined?arguments[2]:(job,error)=>job.error(error);var startPromise=new Promise(onStart=>{this.jobQueue.push({name,onMessage,onError,onStart});return this;});this._startQueuedJob();return await startPromise;}async _startQueuedJob(){if(!this.jobQueue.length){return;}var workerThread=this._getAvailableWorker();if(!workerThread){return;}var queuedJob=this.jobQueue.shift();if(queuedJob){this.onDebug({message:'Starting job',name:queuedJob.name,workerThread,backlog:this.jobQueue.length});var job=new WorkerJob(queuedJob.name,workerThread);workerThread.onMessage=data=>queuedJob.onMessage(job,data.type,data.payload);workerThread.onError=error=>queuedJob.onError(job,error);queuedJob.onStart(job);try{await job.result;}finally{this.returnWorkerToQueue(workerThread);}}}returnWorkerToQueue(worker){var shouldDestroyWorker=this.isDestroyed||!this.reuseWorkers||this.count>this._getMaxConcurrency();if(shouldDestroyWorker){worker.destroy();this.count--;}else {this.idleQueue.push(worker);}if(!this.isDestroyed){this._startQueuedJob();}}_getAvailableWorker(){if(this.idleQueue.length>0){return this.idleQueue.shift()||null;}if(this.count<this._getMaxConcurrency()){this.count++;var _name="".concat(this.name.toLowerCase()," (#").concat(this.count," of ").concat(this.maxConcurrency,")");return new WorkerThread({name:_name,source:this.source,url:this.url});}return null;}_getMaxConcurrency(){return isMobile?this.maxMobileConcurrency:this.maxConcurrency;}}var DEFAULT_PROPS$3={maxConcurrency:3,maxMobileConcurrency:1,onDebug:()=>{},reuseWorkers:true};class WorkerFarm{static isSupported(){return WorkerThread.isSupported();}static getWorkerFarm(){var props=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};WorkerFarm._workerFarm=WorkerFarm._workerFarm||new WorkerFarm({});WorkerFarm._workerFarm.setProps(props);return WorkerFarm._workerFarm;}constructor(props){_defineProperty$1(this,"props",void 0);_defineProperty$1(this,"workerPools",new Map());this.props=_objectSpread2({},DEFAULT_PROPS$3);this.setProps(props);this.workerPools=new Map();}destroy(){for(var workerPool of this.workerPools.values()){workerPool.destroy();}}setProps(props){this.props=_objectSpread2(_objectSpread2({},this.props),props);for(var workerPool of this.workerPools.values()){workerPool.setProps(this._getWorkerPoolProps());}}getWorkerPool(options){var{name,source,url}=options;var workerPool=this.workerPools.get(name);if(!workerPool){workerPool=new WorkerPool$2({name,source,url});workerPool.setProps(this._getWorkerPoolProps());this.workerPools.set(name,workerPool);}return workerPool;}_getWorkerPoolProps(){return {maxConcurrency:this.props.maxConcurrency,maxMobileConcurrency:this.props.maxMobileConcurrency,reuseWorkers:this.props.reuseWorkers,onDebug:this.props.onDebug};}}_defineProperty$1(WorkerFarm,"_workerFarm",void 0);var NPM_TAG='latest';function getWorkerURL(worker){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var workerOptions=options[worker.id]||{};var workerFile="".concat(worker.id,"-worker.js");var url=workerOptions.workerUrl;if(!url&&worker.id==='compression'){url=options.workerUrl;}if(options._workerType==='test'){url="modules/".concat(worker.module,"/dist/").concat(workerFile);}if(!url){var version=worker.version;if(version==='latest'){version=NPM_TAG;}var versionTag=version?"@".concat(version):'';url="https://unpkg.com/@loaders.gl/".concat(worker.module).concat(versionTag,"/dist/").concat(workerFile);}assert$6(url);return url;}function validateWorkerVersion(worker){var coreVersion=arguments.length>1&&arguments[1]!==undefined?arguments[1]:VERSION$8;assert$6(worker,'no worker provided');var workerVersion=worker.version;if(!coreVersion||!workerVersion){return false;}return true;}var ChildProcessProxy={};var node=/*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null),ChildProcessProxy,{'default':ChildProcessProxy}));var VERSION$7="3.1.4";var loadLibraryPromises={};async function loadLibrary(libraryUrl){var moduleName=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};if(moduleName){libraryUrl=getLibraryUrl(libraryUrl,moduleName,options);}loadLibraryPromises[libraryUrl]=loadLibraryPromises[libraryUrl]||loadLibraryFromFile(libraryUrl);return await loadLibraryPromises[libraryUrl];}function getLibraryUrl(library,moduleName,options){if(library.startsWith('http')){return library;}var modules=options.modules||{};if(modules[library]){return modules[library];}if(!isBrowser$1){return "modules/".concat(moduleName,"/dist/libs/").concat(library);}if(options.CDN){assert$6(options.CDN.startsWith('http'));return "".concat(options.CDN,"/").concat(moduleName,"@").concat(VERSION$7,"/dist/libs/").concat(library);}if(isWorker){return "../src/libs/".concat(library);}return "modules/".concat(moduleName,"/src/libs/").concat(library);}async function loadLibraryFromFile(libraryUrl){if(libraryUrl.endsWith('wasm')){var _response=await fetch(libraryUrl);return await _response.arrayBuffer();}if(!isBrowser$1){try{return node&&ChildProcessProxy.requireFromFile&&(await ChildProcessProxy.requireFromFile(libraryUrl));}catch(_unused){return null;}}if(isWorker){return importScripts(libraryUrl);}var response=await fetch(libraryUrl);var scriptSource=await response.text();return loadLibraryFromString(scriptSource,libraryUrl);}function loadLibraryFromString(scriptSource,id){if(!isBrowser$1){return ChildProcessProxy.requireFromString&&ChildProcessProxy.requireFromString(scriptSource,id);}if(isWorker){eval.call(global_,scriptSource);return null;}var script=document.createElement('script');script.id=id;try{script.appendChild(document.createTextNode(scriptSource));}catch(e){script.text=scriptSource;}document.body.appendChild(script);return null;}function canParseWithWorker(loader,options){if(!WorkerFarm.isSupported()){return false;}return loader.worker&&(options===null||options===void 0?void 0:options.worker);}async function parseWithWorker(loader,data,options,context,parseOnMainThread){var name=loader.id;var url=getWorkerURL(loader,options);var workerFarm=WorkerFarm.getWorkerFarm(options);var workerPool=workerFarm.getWorkerPool({name,url});options=JSON.parse(JSON.stringify(options));var job=await workerPool.startJob('process-on-worker',onMessage.bind(null,parseOnMainThread));job.postMessage('process',{input:data,options});var result=await job.result;return await result.result;}async function onMessage(parseOnMainThread,job,type,payload){switch(type){case'done':job.done(payload);break;case'error':job.error(new Error(payload.error));break;case'process':var{id,input,options}=payload;try{var result=await parseOnMainThread(input,options);job.postMessage('done',{id,result});}catch(error){var message=error instanceof Error?error.message:'unknown error';job.postMessage('error',{id,error:message});}break;default:console.warn("parse-with-worker unknown message ".concat(type));}}function getFirstCharacters$1(data){var length=arguments.length>1&&arguments[1]!==undefined?arguments[1]:5;if(typeof data==='string'){return data.slice(0,length);}else if(ArrayBuffer.isView(data)){return getMagicString$3(data.buffer,data.byteOffset,length);}else if(data instanceof ArrayBuffer){var byteOffset=0;return getMagicString$3(data,byteOffset,length);}return '';}function getMagicString$3(arrayBuffer,byteOffset,length){if(arrayBuffer.byteLength<=byteOffset+length){return '';}var dataView=new DataView(arrayBuffer);var magic='';for(var _i=0;_i<length;_i++){magic+=String.fromCharCode(dataView.getUint8(byteOffset+_i));}return magic;}function parseJSON(string){try{return JSON.parse(string);}catch(_){throw new Error("Failed to parse JSON from data starting with \"".concat(getFirstCharacters$1(string),"\""));}}function isBuffer$1(value){return value&&typeof value==='object'&&value.isBuffer;}function bufferToArrayBuffer(buffer){if(isBuffer$1(buffer)){var typedArray=new Uint8Array(buffer.buffer,buffer.byteOffset,buffer.length);return typedArray.slice().buffer;}return buffer;}function toArrayBuffer(data){if(isBuffer$1(data)){return bufferToArrayBuffer(data);}if(data instanceof ArrayBuffer){return data;}if(ArrayBuffer.isView(data)){if(data.byteOffset===0&&data.byteLength===data.buffer.byteLength){return data.buffer;}return data.buffer.slice(data.byteOffset,data.byteOffset+data.byteLength);}if(typeof data==='string'){var text=data;var uint8Array=new TextEncoder().encode(text);return uint8Array.buffer;}if(data&&typeof data==='object'&&data._toArrayBuffer){return data._toArrayBuffer();}throw new Error('toArrayBuffer');}function compareArrayBuffers(arrayBuffer1,arrayBuffer2,byteLength){byteLength=byteLength||arrayBuffer1.byteLength;if(arrayBuffer1.byteLength<byteLength||arrayBuffer2.byteLength<byteLength){return false;}var array1=new Uint8Array(arrayBuffer1);var array2=new Uint8Array(arrayBuffer2);for(var _i2=0;_i2<array1.length;++_i2){if(array1[_i2]!==array2[_i2]){return false;}}return true;}function concatenateArrayBuffers(){for(var _len2=arguments.length,sources=new Array(_len2),_key2=0;_key2<_len2;_key2++){sources[_key2]=arguments[_key2];}var sourceArrays=sources.map(source2=>source2 instanceof ArrayBuffer?new Uint8Array(source2):source2);var byteLength=sourceArrays.reduce((length,typedArray)=>length+typedArray.byteLength,0);var result=new Uint8Array(byteLength);var offset=0;for(var sourceArray of sourceArrays){result.set(sourceArray,offset);offset+=sourceArray.byteLength;}return result.buffer;}function sliceArrayBuffer(arrayBuffer,byteOffset,byteLength){var subArray=byteLength!==undefined?new Uint8Array(arrayBuffer).subarray(byteOffset,byteOffset+byteLength):new Uint8Array(arrayBuffer).subarray(byteOffset);var arrayCopy=new Uint8Array(subArray);return arrayCopy.buffer;}function padToNBytes(byteLength,padding){assert$7(byteLength>=0);assert$7(padding>0);return byteLength+(padding-1)&~(padding-1);}function copyToArray(source,target,targetOffset){var sourceArray;if(source instanceof ArrayBuffer){sourceArray=new Uint8Array(source);}else {var srcByteOffset=source.byteOffset;var srcByteLength=source.byteLength;sourceArray=new Uint8Array(source.buffer||source.arrayBuffer,srcByteOffset,srcByteLength);}target.set(sourceArray,targetOffset);return targetOffset+padToNBytes(sourceArray.byteLength,4);}async function concatenateArrayBuffersAsync(asyncIterator){var arrayBuffers=[];var _iteratorAbruptCompletion=false;var _didIteratorError=false;var _iteratorError;try{for(var _iterator=_asyncIterator(asyncIterator),_step;_iteratorAbruptCompletion=!(_step=await _iterator.next()).done;_iteratorAbruptCompletion=false){var chunk=_step.value;{arrayBuffers.push(chunk);}}}catch(err){_didIteratorError=true;_iteratorError=err;}finally{try{if(_iteratorAbruptCompletion&&_iterator.return!=null){await _iterator.return();}}finally{if(_didIteratorError){throw _iteratorError;}}}return concatenateArrayBuffers(...arrayBuffers);}function getHiResTimestamp$1(){var timestamp;if(typeof window!=='undefined'&&window.performance){timestamp=window.performance.now();}else if(typeof process!=='undefined'&&process.hrtime){var timeParts=process.hrtime();timestamp=timeParts[0]*1000+timeParts[1]/1e6;}else {timestamp=Date.now();}return timestamp;}class Stat{constructor(name,type){_defineProperty$1(this,"name",void 0);_defineProperty$1(this,"type",void 0);_defineProperty$1(this,"sampleSize",1);_defineProperty$1(this,"time",void 0);_defineProperty$1(this,"count",void 0);_defineProperty$1(this,"samples",void 0);_defineProperty$1(this,"lastTiming",void 0);_defineProperty$1(this,"lastSampleTime",void 0);_defineProperty$1(this,"lastSampleCount",void 0);_defineProperty$1(this,"_count",0);_defineProperty$1(this,"_time",0);_defineProperty$1(this,"_samples",0);_defineProperty$1(this,"_startTime",0);_defineProperty$1(this,"_timerPending",false);this.name=name;this.type=type;this.reset();}setSampleSize(samples){this.sampleSize=samples;return this;}incrementCount(){this.addCount(1);return this;}decrementCount(){this.subtractCount(1);return this;}addCount(value){this._count+=value;this._samples++;this._checkSampling();return this;}subtractCount(value){this._count-=value;this._samples++;this._checkSampling();return this;}addTime(time){this._time+=time;this.lastTiming=time;this._samples++;this._checkSampling();return this;}timeStart(){this._startTime=getHiResTimestamp$1();this._timerPending=true;return this;}timeEnd(){if(!this._timerPending){return this;}this.addTime(getHiResTimestamp$1()-this._startTime);this._timerPending=false;this._checkSampling();return this;}getSampleAverageCount(){return this.sampleSize>0?this.lastSampleCount/this.sampleSize:0;}getSampleAverageTime(){return this.sampleSize>0?this.lastSampleTime/this.sampleSize:0;}getSampleHz(){return this.lastSampleTime>0?this.sampleSize/(this.lastSampleTime/1000):0;}getAverageCount(){return this.samples>0?this.count/this.samples:0;}getAverageTime(){return this.samples>0?this.time/this.samples:0;}getHz(){return this.time>0?this.samples/(this.time/1000):0;}reset(){this.time=0;this.count=0;this.samples=0;this.lastTiming=0;this.lastSampleTime=0;this.lastSampleCount=0;this._count=0;this._time=0;this._samples=0;this._startTime=0;this._timerPending=false;return this;}_checkSampling(){if(this._samples===this.sampleSize){this.lastSampleTime=this._time;this.lastSampleCount=this._count;this.count+=this._count;this.time+=this._time;this.samples+=this._samples;this._time=0;this._count=0;this._samples=0;}}}class Stats{constructor(options){_defineProperty$1(this,"id",void 0);_defineProperty$1(this,"stats",{});this.id=options.id;this.stats={};this._initializeStats(options.stats);Object.seal(this);}get(name){var type=arguments.length>1&&arguments[1]!==undefined?arguments[1]:'count';return this._getOrCreate({name,type});}get size(){return Object.keys(this.stats).length;}reset(){for(var key in this.stats){this.stats[key].reset();}return this;}forEach(fn){for(var key in this.stats){fn(this.stats[key]);}}getTable(){var table={};this.forEach(stat=>{table[stat.name]={time:stat.time||0,count:stat.count||0,average:stat.getAverageTime()||0,hz:stat.getHz()||0};});return table;}_initializeStats(){var stats=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];stats.forEach(stat=>this._getOrCreate(stat));}_getOrCreate(stat){if(!stat||!stat.name){return null;}var{name,type}=stat;if(!this.stats[name]){if(stat instanceof Stat){this.stats[name]=stat;}else {this.stats[name]=new Stat(name,type);}}return this.stats[name];}}var STAT_QUEUED_REQUESTS='Queued Requests';var STAT_ACTIVE_REQUESTS='Active Requests';var STAT_CANCELLED_REQUESTS='Cancelled Requests';var STAT_QUEUED_REQUESTS_EVER='Queued Requests Ever';var STAT_ACTIVE_REQUESTS_EVER='Active Requests Ever';var DEFAULT_PROPS$2={id:'request-scheduler',throttleRequests:true,maxRequests:6};class RequestScheduler{constructor(){var props=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};_defineProperty$1(this,"props",void 0);_defineProperty$1(this,"stats",void 0);_defineProperty$1(this,"activeRequestCount",0);_defineProperty$1(this,"requestQueue",[]);_defineProperty$1(this,"requestMap",new Map());_defineProperty$1(this,"deferredUpdate",null);this.props=_objectSpread2(_objectSpread2({},DEFAULT_PROPS$2),props);this.stats=new Stats({id:this.props.id});this.stats.get(STAT_QUEUED_REQUESTS);this.stats.get(STAT_ACTIVE_REQUESTS);this.stats.get(STAT_CANCELLED_REQUESTS);this.stats.get(STAT_QUEUED_REQUESTS_EVER);this.stats.get(STAT_ACTIVE_REQUESTS_EVER);}scheduleRequest(handle){var getPriority=arguments.length>1&&arguments[1]!==undefined?arguments[1]:()=>0;if(!this.props.throttleRequests){return Promise.resolve({done:()=>{}});}if(this.requestMap.has(handle)){return this.requestMap.get(handle);}var request={handle,priority:0,getPriority};var promise=new Promise(resolve=>{request.resolve=resolve;return request;});this.requestQueue.push(request);this.requestMap.set(handle,promise);this._issueNewRequests();return promise;}_issueRequest(request){var{handle,resolve}=request;var isDone=false;var done=()=>{if(!isDone){isDone=true;this.requestMap.delete(handle);this.activeRequestCount--;this._issueNewRequests();}};this.activeRequestCount++;return resolve?resolve({done}):Promise.resolve({done});}_issueNewRequests(){if(!this.deferredUpdate){this.deferredUpdate=setTimeout(()=>this._issueNewRequestsAsync(),0);}}_issueNewRequestsAsync(){this.deferredUpdate=null;var freeSlots=Math.max(this.props.maxRequests-this.activeRequestCount,0);if(freeSlots===0){return;}this._updateAllRequests();for(var _i3=0;_i3<freeSlots;++_i3){var request=this.requestQueue.shift();if(request){this._issueRequest(request);}}}_updateAllRequests(){var requestQueue=this.requestQueue;for(var _i4=0;_i4<requestQueue.length;++_i4){var request=requestQueue[_i4];if(!this._updateRequest(request)){requestQueue.splice(_i4,1);this.requestMap.delete(request.handle);_i4--;}}requestQueue.sort((a,b)=>a.priority-b.priority);}_updateRequest(request){request.priority=request.getPriority(request.handle);if(request.priority<0){request.resolve(null);return false;}return true;}}var pathPrefix='';var fileAliases={};function resolvePath(filename){for(var alias in fileAliases){if(filename.startsWith(alias)){var replacement=fileAliases[alias];filename=filename.replace(alias,replacement);}}if(!filename.startsWith('http://')&&!filename.startsWith('https://')){filename="".concat(pathPrefix).concat(filename);}return filename;}function filename(url){var slashIndex=url&&url.lastIndexOf('/');return slashIndex>=0?url.substr(slashIndex+1):'';}function dirname(url){var slashIndex=url&&url.lastIndexOf('/');return slashIndex>=0?url.substr(0,slashIndex):'';}var isBoolean=x=>typeof x==='boolean';var isFunction=x=>typeof x==='function';var isObject=x=>x!==null&&typeof x==='object';var isPureObject=x=>isObject(x)&&x.constructor==={}.constructor;var isIterable=x=>x&&typeof x[Symbol.iterator]==='function';var isAsyncIterable=x=>x&&typeof x[Symbol.asyncIterator]==='function';var isResponse=x=>typeof Response!=='undefined'&&x instanceof Response||x&&x.arrayBuffer&&x.text&&x.json;var isBlob=x=>typeof Blob!=='undefined'&&x instanceof Blob;var isBuffer=x=>x&&typeof x==='object'&&x.isBuffer;var isReadableDOMStream=x=>typeof ReadableStream!=='undefined'&&x instanceof ReadableStream||isObject(x)&&isFunction(x.tee)&&isFunction(x.cancel)&&isFunction(x.getReader);var isReadableNodeStream=x=>isObject(x)&&isFunction(x.read)&&isFunction(x.pipe)&&isBoolean(x.readable);var isReadableStream=x=>isReadableDOMStream(x)||isReadableNodeStream(x);var DATA_URL_PATTERN=/^data:([-\w.]+\/[-\w.+]+)(;|,)/;var MIME_TYPE_PATTERN=/^([-\w.]+\/[-\w.+]+)/;function parseMIMEType(mimeString){var matches=MIME_TYPE_PATTERN.exec(mimeString);if(matches){return matches[1];}return mimeString;}function parseMIMETypeFromURL(url){var matches=DATA_URL_PATTERN.exec(url);if(matches){return matches[1];}return '';}var QUERY_STRING_PATTERN=/\?.*/;function getResourceUrlAndType(resource){if(isResponse(resource)){var url=stripQueryString(resource.url||'');var contentTypeHeader=resource.headers.get('content-type')||'';return {url,type:parseMIMEType(contentTypeHeader)||parseMIMETypeFromURL(url)};}if(isBlob(resource)){return {url:stripQueryString(resource.name||''),type:resource.type||''};}if(typeof resource==='string'){return {url:stripQueryString(resource),type:parseMIMETypeFromURL(resource)};}return {url:'',type:''};}function getResourceContentLength(resource){if(isResponse(resource)){return resource.headers['content-length']||-1;}if(isBlob(resource)){return resource.size;}if(typeof resource==='string'){return resource.length;}if(resource instanceof ArrayBuffer){return resource.byteLength;}if(ArrayBuffer.isView(resource)){return resource.byteLength;}return -1;}function stripQueryString(url){return url.replace(QUERY_STRING_PATTERN,'');}async function makeResponse(resource){if(isResponse(resource)){return resource;}var headers={};var contentLength=getResourceContentLength(resource);if(contentLength>=0){headers['content-length']=String(contentLength);}var{url,type}=getResourceUrlAndType(resource);if(type){headers['content-type']=type;}var initialDataUrl=await getInitialDataUrl(resource);if(initialDataUrl){headers['x-first-bytes']=initialDataUrl;}if(typeof resource==='string'){resource=new TextEncoder().encode(resource);}var response=new Response(resource,{headers});Object.defineProperty(response,'url',{value:url});return response;}async function checkResponse(response){if(!response.ok){var message=await getResponseError(response);throw new Error(message);}}async function getResponseError(response){var message="Failed to fetch resource ".concat(response.url," (").concat(response.status,"): ");try{var contentType=response.headers.get('Content-Type');var text=response.statusText;if(contentType.includes('application/json')){text+=" ".concat(await response.text());}message+=text;message=message.length>60?"".concat(message.slice(60),"..."):message;}catch(error){}return message;}async function getInitialDataUrl(resource){var INITIAL_DATA_LENGTH=5;if(typeof resource==='string'){return "data:,".concat(resource.slice(0,INITIAL_DATA_LENGTH));}if(resource instanceof Blob){var blobSlice=resource.slice(0,5);return await new Promise(resolve=>{var reader=new FileReader();reader.onload=event=>{var _event$target;return resolve(event===null||event===void 0?void 0:(_event$target=event.target)===null||_event$target===void 0?void 0:_event$target.result);};reader.readAsDataURL(blobSlice);});}if(resource instanceof ArrayBuffer){var slice=resource.slice(0,INITIAL_DATA_LENGTH);var base64=arrayBufferToBase64(slice);return "data:base64,".concat(base64);}return null;}function arrayBufferToBase64(buffer){var binary='';var bytes=new Uint8Array(buffer);for(var _i5=0;_i5<bytes.byteLength;_i5++){binary+=String.fromCharCode(bytes[_i5]);}return btoa(binary);}async function fetchFile(url,options){if(typeof url==='string'){url=resolvePath(url);var fetchOptions=options;if(options!==null&&options!==void 0&&options.fetch&&typeof(options===null||options===void 0?void 0:options.fetch)!=='function'){fetchOptions=options.fetch;}return await fetch(url,fetchOptions);}return await makeResponse(url);}function isElectron(mockUserAgent){if(typeof window!=='undefined'&&typeof window.process==='object'&&window.process.type==='renderer'){return true;}if(typeof process!=='undefined'&&typeof process.versions==='object'&&Boolean(process.versions.electron)){return true;}var realUserAgent=typeof navigator==='object'&&typeof navigator.userAgent==='string'&&navigator.userAgent;var userAgent=mockUserAgent||realUserAgent;if(userAgent&&userAgent.indexOf('Electron')>=0){return true;}return false;}function isBrowser(){var isNode=typeof process==='object'&&String(process)==='[object process]'&&!process.browser;return !isNode||isElectron();}var globals={self:typeof self!=='undefined'&&self,window:typeof window!=='undefined'&&window,global:typeof global!=='undefined'&&global,document:typeof document!=='undefined'&&document,process:typeof process==='object'&&process};var window_=globals.window||globals.self||globals.global;var process_=globals.process||{};var VERSION$6=typeof __VERSION__!=='undefined'?__VERSION__:'untranspiled source';isBrowser();function getStorage(type){try{var storage=window[type];var x='__storage_test__';storage.setItem(x,x);storage.removeItem(x);return storage;}catch(e){return null;}}class LocalStorage{constructor(id){var defaultSettings=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var type=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'sessionStorage';_defineProperty$1(this,"storage",void 0);_defineProperty$1(this,"id",void 0);_defineProperty$1(this,"config",{});this.storage=getStorage(type);this.id=id;this.config={};Object.assign(this.config,defaultSettings);this._loadConfiguration();}getConfiguration(){return this.config;}setConfiguration(configuration){this.config={};return this.updateConfiguration(configuration);}updateConfiguration(configuration){Object.assign(this.config,configuration);if(this.storage){var serialized=JSON.stringify(this.config);this.storage.setItem(this.id,serialized);}return this;}_loadConfiguration(){var configuration={};if(this.storage){var serializedConfiguration=this.storage.getItem(this.id);configuration=serializedConfiguration?JSON.parse(serializedConfiguration):{};}Object.assign(this.config,configuration);return this;}}function formatTime(ms){var formatted;if(ms<10){formatted="".concat(ms.toFixed(2),"ms");}else if(ms<100){formatted="".concat(ms.toFixed(1),"ms");}else if(ms<1000){formatted="".concat(ms.toFixed(0),"ms");}else {formatted="".concat((ms/1000).toFixed(2),"s");}return formatted;}function leftPad(string){var length=arguments.length>1&&arguments[1]!==undefined?arguments[1]:8;var padLength=Math.max(length-string.length,0);return "".concat(' '.repeat(padLength)).concat(string);}function formatImage(image,message,scale){var maxWidth=arguments.length>3&&arguments[3]!==undefined?arguments[3]:600;var imageUrl=image.src.replace(/\(/g,'%28').replace(/\)/g,'%29');if(image.width>maxWidth){scale=Math.min(scale,maxWidth/image.width);}var width=image.width*scale;var height=image.height*scale;var 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('');return ["".concat(message," %c+"),style];}var COLOR;(function(COLOR){COLOR[COLOR["BLACK"]=30]="BLACK";COLOR[COLOR["RED"]=31]="RED";COLOR[COLOR["GREEN"]=32]="GREEN";COLOR[COLOR["YELLOW"]=33]="YELLOW";COLOR[COLOR["BLUE"]=34]="BLUE";COLOR[COLOR["MAGENTA"]=35]="MAGENTA";COLOR[COLOR["CYAN"]=36]="CYAN";COLOR[COLOR["WHITE"]=37]="WHITE";COLOR[COLOR["BRIGHT_BLACK"]=90]="BRIGHT_BLACK";COLOR[COLOR["BRIGHT_RED"]=91]="BRIGHT_RED";COLOR[COLOR["BRIGHT_GREEN"]=92]="BRIGHT_GREEN";COLOR[COLOR["BRIGHT_YELLOW"]=93]="BRIGHT_YELLOW";COLOR[COLOR["BRIGHT_BLUE"]=94]="BRIGHT_BLUE";COLOR[COLOR["BRIGHT_MAGENTA"]=95]="BRIGHT_MAGENTA";COLOR[COLOR["BRIGHT_CYAN"]=96]="BRIGHT_CYAN";COLOR[COLOR["BRIGHT_WHITE"]=97]="BRIGHT_WHITE";})(COLOR||(COLOR={}));function getColor$1(color){return typeof color==='string'?COLOR[color.toUpperCase()]||COLOR.WHITE:color;}function addColor(string,color,background){if(!isBrowser&&typeof string==='string'){if(color){color=getColor$1(color);string="\x1B[".concat(color,"m").concat(string,"\x1B[39m");}if(background){color=getColor$1(background);string="\x1B[".concat(background+10,"m").concat(string,"\x1B[49m");}}return string;}function autobind(obj){var predefined=arguments.length>1&&arguments[1]!==undefined?arguments[1]:['constructor'];var proto=Object.getPrototypeOf(obj);var propNames=Object.getOwnPropertyNames(proto);var _loop=function _loop(key){if(typeof obj[key]==='function'){if(!predefined.find(name=>key===name)){obj[key]=obj[key].bind(obj);}}};for(var key of propNames){_loop(key);}}function assert$5(condition,message){if(!condition){throw new Error(message||'Assertion failed');}}function getHiResTimestamp(){var timestamp;if(isBrowser&&'performance'in window_){var _window$performance,_window$performance$n;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);}else if('hrtime'in process_){var _process$hrtime;var timeParts=process_===null||process_===void 0?void 0:(_process$hrtime=process_.hrtime)===null||_process$hrtime===void 0?void 0:_process$hrtime.call(process_);timestamp=timeParts[0]*1000+timeParts[1]/1e6;}else {timestamp=Date.now();}return timestamp;}var originalConsole={debug:isBrowser?console.debug||console.log:console.log,log:console.log,info:console.info,warn:console.warn,error:console.error};var DEFAULT_SETTINGS={enabled:true,level:0};function noop$1(){}var cache={};var ONCE={once:true};class Log{constructor(){var{id}=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{id:''};_defineProperty$1(this,"id",void 0);_defineProperty$1(this,"VERSION",VERSION$6);_defineProperty$1(this,"_startTs",getHiResTimestamp());_defineProperty$1(this,"_deltaTs",getHiResTimestamp());_defineProperty$1(this,"_storage",void 0);_defineProperty$1(this,"userData",{});_defineProperty$1(this,"LOG_THROTTLE_TIMEOUT",0);this.id=id;this._storage=new LocalStorage("__probe-".concat(this.id,"__"),DEFAULT_SETTINGS);this.userData={};this.timeStamp("".concat(this.id," started"));autobind(this);Object.seal(this);}set level(newLevel){this.setLevel(newLevel);}get level(){return this.getLevel();}isEnabled(){return this._storage.config.enabled;}getLevel(){return this._storage.config.level;}getTotal(){return Number((getHiResTimestamp()-this._startTs).toPrecision(10));}getDelta(){return Number((getHiResTimestamp()-this._deltaTs).toPrecision(10));}set priority(newPriority){this.level=newPriority;}get priority(){return this.level;}getPriority(){return this.level;}enable(){var enabled=arguments.length>0&&arguments[0]!==undefined?arguments[0]:true;this._storage.updateConfiguration({enabled});return this;}setLevel(level){this._storage.updateConfiguration({level});return this;}get(setting){return this._storage.config[setting];}set(setting,value){this._storage.updateConfiguration({[setting]:value});}settings(){if(console.table){console.table(this._storage.config);}else {console.log(this._storage.config);}}assert(condition,message){assert$5(condition,message);}warn(message){return this._getLogFunction(0,message,originalConsole.warn,arguments,ONCE);}error(message){return this._getLogFunction(0,message,originalConsole.error,arguments);}deprecated(oldUsage,newUsage){return this.warn("`".concat(oldUsage,"` is deprecated and will be removed in a later version. Use `").concat(newUsage,"` instead"));}removed(oldUsage,newUsage){return this.error("`".concat(oldUsage,"` has been removed. Use `").concat(newUsage,"` instead"));}probe(logLevel,message){return this._getLogFunction(logLevel,message,originalConsole.log,arguments,{time:true,once:true});}log(logLevel,message){return this._getLogFunction(logLevel,message,originalConsole.debug,arguments);}info(logLevel,message){return this._getLogFunction(logLevel,message,console.info,arguments);}once(logLevel,message){for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return this._getLogFunction(logLevel,message,originalConsole.debug||originalConsole.info,arguments,ONCE);}table(logLevel,table,columns){if(table){return this._getLogFunction(logLevel,table,console.table||noop$1,columns&&[columns],{tag:getTableHeader(table)});}return noop$1;}image(_ref){var{logLevel,priority,image,message='',scale=1}=_ref;if(!this._shouldLog(logLevel||priority)){return noop$1;}return isBrowser?logImageInBrowser({image,message,scale}):logImageInNode({image,message,scale});}time(logLevel,message){return this._getLogFunction(logLevel,message,console.time?console.time:console.info);}timeEnd(logLevel,message){return this._getLogFunction(logLevel,message,console.timeEnd?console.timeEnd:console.info);}timeStamp(logLevel,message){return this._getLogFunction(logLevel,message,console.timeStamp||noop$1);}group(logLevel,message){var opts=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{collapsed:false};var options=normalizeArguments({logLevel,message,opts});var{collapsed}=opts;options.method=(collapsed?console.groupCollapsed:console.group)||console.info;return this._getLogFunction(options);}groupCollapsed(logLevel,message){var opts=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};return this.group(logLevel,message,Object.assign({},opts,{collapsed:true}));}groupEnd(logLevel){return this._getLogFunction(logLevel,'',console.groupEnd||noop$1);}withGroup(logLevel,message,func){this.group(logLevel,message)();try{func();}finally{this.groupEnd(logLevel)();}}trace(){if(console.trace){console.trace();}}_shouldLog(logLevel){return this.isEnabled()&&this.getLevel()>=normalizeLogLevel(logLevel);}_getLogFunction(logLevel,message,method,args,opts){if(this._shouldLog(logLevel)){opts=normalizeArguments({logLevel,message,args,opts});method=method||opts.method;assert$5(method);opts.total=this.getTotal();opts.delta=this.getDelta();this._deltaTs=getHiResTimestamp();var tag=opts.tag||opts.message;if(opts.once){if(!cache[tag]){cache[tag]=getHiResTimestamp();}else {return noop$1;}}message=decorateMessage(this.id,opts.message,opts);return method.bind(console,message,...opts.args);}return noop$1;}}_defineProperty$1(Log,"VERSION",VERSION$6);function normalizeLogLevel(logLevel){if(!logLevel){return 0;}var resolvedLevel;switch(typeof logLevel){case'number':resolvedLevel=logLevel;break;case'object':resolvedLevel=logLevel.logLevel||logLevel.priority||0;break;default:return 0;}assert$5(Number.isFinite(resolvedLevel)&&resolvedLevel>=0);return resolvedLevel;}function normalizeArguments(opts){var{logLevel,message}=opts;opts.logLevel=normalizeLogLevel(logLevel);var args=opts.args?Array.from(opts.args):[];while(args.length&&args.shift()!==message){}switch(typeof logLevel){case'string':case'function':if(message!==undefined){args.unshift(message);}opts.message=logLevel;break;case'object':Object.assign(opts,logLevel);break;}if(typeof opts.message==='function'){opts.message=opts.message();}var messageType=typeof opts.message;assert$5(messageType==='string'||messageType==='object');return Object.assign(opts,{args},opts.opts);}function decorateMessage(id,message,opts){if(typeof message==='string'){var time=opts.time?leftPad(formatTime(opts.total)):'';message=opts.time?"".concat(id,": ").concat(time," ").concat(message):"".concat(id,": ").concat(message);message=addColor(message,opts.color,opts.background);}return message;}function logImageInNode(_ref2){var{image,message='',scale=1}=_ref2;var asciify=null;try{asciify=module.require('asciify-image');}catch(error){}if(asciify){return ()=>asciify(image,{fit:'box',width:"".concat(Math.round(80*scale),"%")}).then(data=>console.log(data));}return noop$1;}function logImageInBrowser(_ref3){var{image,message='',scale=1}=_ref3;if(typeof image==='string'){var img=new Image();img.onload=()=>{var args=formatImage(img,message,scale);console.log(...args);};img.src=image;return noop$1;}var element=image.nodeName||'';if(element.toLowerCase()==='img'){console.log(...formatImage(image,message,scale));return noop$1;}if(element.toLowerCase()==='canvas'){var _img=new Image();_img.onload=()=>console.log(...formatImage(_img,message,scale));_img.src=image.toDataURL();return noop$1;}return noop$1;}function getTableHeader(table){for(var key in table){for(var title in table[key]){return title||'untitled';}}return 'empty';}var probeLog=new Log({id:'loaders.gl'});class NullLog{log(){return ()=>{};}info(){return ()=>{};}warn(){return ()=>{};}error(){return ()=>{};}}class ConsoleLog{constructor(){_defineProperty$1(this,"console",void 0);this.console=console;}log(){for(var _len3=arguments.length,args=new Array(_len3),_key3=0;_key3<_len3;_key3++){args[_key3]=arguments[_key3];}return this.console.log.bind(this.console,...args);}info(){for(var _len4=arguments.length,args=new Array(_len4),_key4=0;_key4<_len4;_key4++){args[_key4]=arguments[_key4];}return this.console.info.bind(this.console,...args);}warn(){for(var _len5=arguments.length,args=new Array(_len5),_key5=0;_key5<_len5;_key5++){args[_key5]=arguments[_key5];}return this.console.warn.bind(this.console,...args);}error(){for(var _len6=arguments.length,args=new Array(_len6),_key6=0;_key6<_len6;_key6++){args[_key6]=arguments[_key6];}return this.console.error.bind(this.console,...args);}}var DEFAULT_LOADER_OPTIONS={fetch:null,mimeType:undefined,nothrow:false,log:new ConsoleLog(),CDN:'https://unpkg.com/@loaders.gl',worker:true,maxConcurrency:3,maxMobileConcurrency:1,reuseWorkers:true,_workerType:'',limit:0,_limitMB:0,batchSize:'auto',batchDebounceMs:0,metadata:false,transforms:[]};var REMOVED_LOADER_OPTIONS={throws:'nothrow',dataType:'(no longer used)',uri:'baseUri',method:'fetch.method',headers:'fetch.headers',body:'fetch.body',mode:'fetch.mode',credentials:'fetch.credentials',cache:'fetch.cache',redirect:'fetch.redirect',referrer:'fetch.referrer',referrerPolicy:'fetch.referrerPolicy',integrity:'fetch.integrity',keepalive:'fetch.keepalive',signal:'fetch.signal'};function getGlobalLoaderState(){globalThis.loaders=globalThis.loaders||{};var{loaders}=globalThis;loaders._state=loaders._state||{};return loaders._state;}var getGlobalLoaderOptions=()=>{var state=getGlobalLoaderState();state.globalOptions=state.globalOptions||_objectSpread2({},DEFAULT_LOADER_OPTIONS);return state.globalOptions;};function normalizeOptions(options,loader,loaders,url){loaders=loaders||[];loaders=Array.isArray(loaders)?loaders:[loaders];validateOptions(options,loaders);return normalizeOptionsInternal(loader,options,url);}function getFetchFunction(options,context){var globalOptions=getGlobalLoaderOptions();var fetchOptions=options||globalOptions;if(typeof fetchOptions.fetch==='function'){return fetchOptions.fetch;}if(isObject(fetchOptions.fetch)){return url=>fetchFile(url,fetchOptions);}if(context!==null&&context!==void 0&&context.fetch){return context===null||context===void 0?void 0:context.fetch;}return fetchFile;}function validateOptions(options,loaders){validateOptionsObject(options,null,DEFAULT_LOADER_OPTIONS,REMOVED_LOADER_OPTIONS,loaders);for(var loader of loaders){var idOptions=options&&options[loader.id]||{};var loaderOptions=loader.options&&loader.options[loader.id]||{};var deprecatedOptions=loader.deprecatedOptions&&loader.deprecatedOptions[loader.id]||{};validateOptionsObject(idOptions,loader.id,loaderOptions,deprecatedOptions,loaders);}}function validateOptionsObject(options,id,defaultOptions,deprecatedOptions,loaders){var loaderName=id||'Top level';var prefix=id?"".concat(id,"."):'';for(var key in options){var isSubOptions=!id&&isObject(options[key]);var isBaseUriOption=key==='baseUri'&&!id;var isWorkerUrlOption=key==='workerUrl'&&id;if(!(key in defaultOptions)&&!isBaseUriOption&&!isWorkerUrlOption){if(key in deprecatedOptions){probeLog.warn("".concat(loaderName," loader option '").concat(prefix).concat(key,"' no longer supported, use '").concat(deprecatedOptions[key],"'"))();}else if(!isSubOptions){var suggestion=findSimilarOption(key,loaders);probeLog.warn("".concat(loaderName," loader option '").concat(prefix).concat(key,"' not recognized. ").concat(suggestion))();}}}}function findSimilarOption(optionKey,loaders){var lowerCaseOptionKey=optionKey.toLowerCase();var bestSuggestion='';for(var loader of loaders){for(var key in loader.options){if(optionKey===key){return "Did you mean '".concat(loader.id,".").concat(key,"'?");}var lowerCaseKey=key.toLowerCase();var isPartialMatch=lowerCaseOptionKey.startsWith(lowerCaseKey)||lowerCaseKey.startsWith(lowerCaseOptionKey);if(isPartialMatch){bestSuggestion=bestSuggestion||"Did you mean '".concat(loader.id,".").concat(key,"'?");}}}return bestSuggestion;}function normalizeOptionsInternal(loader,options,url){var loaderDefaultOptions=loader.options||{};var mergedOptions=_objectSpread2({},loaderDefaultOptions);addUrlOptions(mergedOptions,url);if(mergedOptions.log===null){mergedOptions.log=new NullLog();}mergeNestedFields(mergedOptions,getGlobalLoaderOptions());mergeNestedFields(mergedOptions,options);return mergedOptions;}function mergeNestedFields(mergedOptions,options){for(var key in options){if(key in options){var value=options[key];if(isPureObject(value)&&isPureObject(mergedOptions[key])){mergedOptions[key]=_objectSpread2(_objectSpread2({},mergedOptions[key]),options[key]);}else {mergedOptions[key]=options[key];}}}}function addUrlOptions(options,url){if(url&&!('baseUri'in options)){options.baseUri=url;}}function isLoaderObject(loader){var _loader;if(!loader){return false;}if(Array.isArray(loader)){loader=loader[0];}var hasExtensions=Array.isArray((_loader=loader)===null||_loader===void 0?void 0:_loader.extensions);return hasExtensions;}function normalizeLoader(loader){var _loader2,_loader3;assert$7(loader,'null loader');assert$7(isLoaderObject(loader),'invalid loader');var options;if(Array.isArray(loader)){options=loader[1];loader=loader[0];loader=_objectSpread2(_objectSpread2({},loader),{},{options:_objectSpread2(_objectSpread2({},loader.options),options)});}if((_loader2=loader)!==null&&_loader2!==void 0&&_loader2.parseTextSync||(_loader3=loader)!==null&&_loader3!==void 0&&_loader3.parseText){loader.text=true;}if(!loader.text){loader.binary=true;}return loader;}var getGlobalLoaderRegistry=()=>{var state=getGlobalLoaderState();state.loaderRegistry=state.loaderRegistry||[];return state.loaderRegistry;};function getRegisteredLoaders(){return getGlobalLoaderRegistry();}var EXT_PATTERN=/\.([^.]+)$/;async function selectLoader(data){var loaders=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[];var options=arguments.length>2?arguments[2]:undefined;var context=arguments.length>3?arguments[3]:undefined;if(!validHTTPResponse(data)){return null;}var loader=selectLoaderSync(data,loaders,_objectSpread2(_objectSpread2({},options),{},{nothrow:true}),context);if(loader){return loader;}if(isBlob(data)){data=await data.slice(0,10).arrayBuffer();loader=selectLoaderSync(data,loaders,options,context);}if(!loader&&!(options!==null&&options!==void 0&&options.nothrow)){throw new Error(getNoValidLoaderMessage(data));}return loader;}function selectLoaderSync(data){var loaders=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[];var options=arguments.length>2?arguments[2]:undefined;var context=arguments.length>3?arguments[3]:undefined;if(!validHTTPResponse(data)){return null;}if(loaders&&!Array.isArray(loaders)){return normalizeLoader(loaders);}var candidateLoaders=[];if(loaders){candidateLoaders=candidateLoaders.concat(loaders);}if(!(options!==null&&options!==void 0&&options.ignoreRegisteredLoaders)){candidateLoaders.push(...getRegisteredLoaders());}normalizeLoaders(candidateLoaders);var loader=selectLoaderInternal(data,candidateLoaders,options,context);if(!loader&&!(options!==null&&options!==void 0&&options.nothrow)){throw new Error(getNoValidLoaderMessage(data));}return loader;}function selectLoaderInternal(data,loaders,options,context){var{url,type}=getResourceUrlAndType(data);var testUrl=url||(context===null||context===void 0?void 0:context.url);var loader=null;if(options!==null&&options!==void 0&&options.mimeType){loader=findLoaderByMIMEType(loaders,options===null||options===void 0?void 0:options.mimeType);}loader=loader||findLoaderByUrl(loaders,testUrl);loader=loader||findLoaderByMIMEType(loaders,type);loader=loader||findLoaderByInitialBytes(loaders,data);loader=loader||findLoaderByMIMEType(loaders,options===null||options===void 0?void 0:options.fallbackMimeType);return loader;}function validHTTPResponse(data){if(data instanceof Response){if(data.status===204){return false;}}return true;}function getNoValidLoaderMessage(data){var{url,type}=getResourceUrlAndType(data);var message='No valid loader found (';message+=url?"".concat(filename(url),", "):'no url provided, ';message+="MIME type: ".concat(type?"\"".concat(type,"\""):'not provided',", ");var firstCharacters=data?getFirstCharacters(data):'';message+=firstCharacters?" first bytes: \"".concat(firstCharacters,"\""):'first bytes: not available';message+=')';return message;}function normalizeLoaders(loaders){for(var loader of loaders){normalizeLoader(loader);}}function findLoaderByUrl(loaders,url){var match=url&&EXT_PATTERN.exec(url);var extension=match&&match[1];return extension?findLoaderByExtension(loaders,extension):null;}function findLoaderByExtension(loaders,extension){extension=extension.toLowerCase();for(var loader of loaders){for(var loaderExtension of loader.extensions){if(loaderExtension.toLowerCase()===extension){return loader;}}}return null;}function findLoaderByMIMEType(loaders,mimeType){for(var loader of loaders){if(loader.mimeTypes&&loader.mimeTypes.includes(mimeType)){return loader;}if(mimeType==="application/x.".concat(loader.id)){return loader;}}return null;}function findLoaderByInitialBytes(loaders,data){if(!data){return null;}for(var loader of loaders){if(typeof data==='string'){if(testDataAgainstText(data,loader)){return loader;}}else if(ArrayBuffer.isView(data)){if(testDataAgainstBinary(data.buffer,data.byteOffset,loader)){return loader;}}else if(data instanceof ArrayBuffer){var byteOffset=0;if(testDataAgainstBinary(data,byteOffset,loader)){return loader;}}}return null;}function testDataAgainstText(data,loader){if(loader.testText){return loader.testText(data);}var tests=Array.isArray(loader.tests)?loader.tests:[loader.tests];return tests.some(test=>data.startsWith(test));}function testDataAgainstBinary(data,byteOffset,loader){var tests=Array.isArray(loader.tests)?loader.tests:[loader.tests];return tests.some(test=>testBinary(data,byteOffset,loader,test));}function testBinary(data,byteOffset,loader,test){if(test instanceof ArrayBuffer){return compareArrayBuffers(test,data,test.byteLength);}switch(typeof test){case'function':return test(data,loader);case'string':var magic=getMagicString$2(data,byteOffset,test.length);return test===magic;default:return false;}}function getFirstCharacters(data){var length=arguments.length>1&&arguments[1]!==undefined?arguments[1]:5;if(typeof data==='string'){return data.slice(0,length);}else if(ArrayBuffer.isView(data)){return getMagicString$2(data.buffer,data.byteOffset,length);}else if(data instanceof ArrayBuffer){var byteOffset=0;return getMagicString$2(data,byteOffset,length);}return '';}function getMagicString$2(arrayBuffer,byteOffset,length){if(arrayBuffer.byteLength<byteOffset+length){return '';}var dataView=new DataView(arrayBuffer);var magic='';for(var _i6=0;_i6<length;_i6++){magic+=String.fromCharCode(dataView.getUint8(byteOffset+_i6));}return magic;}var DEFAULT_CHUNK_SIZE$2=256*1024;function*makeStringIterator(string,options){var chunkSize=(options===null||options===void 0?void 0:options.chunkSize)||DEFAULT_CHUNK_SIZE$2;var offset=0;var textEncoder=new TextEncoder();while(offset<string.length){var chunkLength=Math.min(string.length-offset,chunkSize);var chunk=string.slice(offset,offset+chunkLength);offset+=chunkLength;yield textEncoder.encode(chunk);}}var DEFAULT_CHUNK_SIZE$1=256*1024;function makeArrayBufferIterator(arrayBuffer){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return function*(){var{chunkSize=DEFAULT_CHUNK_SIZE$1}=options;var byteOffset=0;while(byteOffset<arrayBuffer.byteLength){var chunkByteLength=Math.min(arrayBuffer.byteLength-byteOffset,chunkSize);var chunk=new ArrayBuffer(chunkByteLength);var sourceArray=new Uint8Array(arrayBuffer,byteOffset,chunkByteLength);var chunkArray=new Uint8Array(chunk);chunkArray.set(sourceArray);byteOffset+=chunkByteLength;yield chunk;}}();}var DEFAULT_CHUNK_SIZE=1024*1024;function makeBlobIterator(_x,_x2){return _makeBlobIterator.apply(this,arguments);}function _makeBlobIterator(){_makeBlobIterator=_wrapAsyncGenerator(function*(blob,options){var chunkSize=(options===null||options===void 0?void 0:options.chunkSize)||DEFAULT_CHUNK_SIZE;var offset=0;while(offset<blob.size){var end=offset+chunkSize;var chunk=yield _awaitAsyncGenerator(blob.slice(offset,end).arrayBuffer());offset=end;yield chunk;}});return _makeBlobIterator.apply(this,arguments);}function makeStreamIterator(stream,options){return isBrowser$2?makeBrowserStreamIterator(stream,options):makeNodeStreamIterator(stream);}function makeBrowserStreamIterator(_x3,_x4){return _makeBrowserStreamIterator.apply(this,arguments);}function _makeBrowserStreamIterator(){_makeBrowserStreamIterator=_wrapAsyncGenerator(function*(stream,options){var reader=stream.getReader();var nextBatchPromise;try{while(true){var currentBatchPromise=nextBatchPromise||reader.read();if(options!==null&&options!==void 0&&options._streamReadAhead){nextBatchPromise=reader.read();}var{done,value}=yield _awaitAsyncGenerator(currentBatchPromise);if(done){return;}yield toArrayBuffer(value);}}catch(error){reader.releaseLock();}});return _makeBrowserStreamIterator.apply(this,arguments);}function makeNodeStreamIterator(_x5,_x6){return _makeNodeStreamIterator.apply(this,arguments);}function _makeNodeStreamIterator(){_makeNodeStreamIterator=_wrapAsyncGenerator(function*(stream,options){var _iteratorAbruptCompletion2=false;var _didIteratorError2=false;var _iteratorError2;try{for(var _iterator2=_asyncIterator(stream),_step2;_iteratorAbruptCompletion2=!(_step2=yield _awaitAsyncGenerator(_iterator2.next())).done;_iteratorAbruptCompletion2=false){var chunk=_step2.value;{yield toArrayBuffer(chunk);}}}catch(err){_didIteratorError2=true;_iteratorError2=err;}finally{try{if(_iteratorAbruptCompletion2&&_iterator2.return!=null){yield _awaitAsyncGenerator(_iterator2.return());}}finally{if(_didIteratorError2){throw _iteratorError2;}}}});return _makeNodeStreamIterator.apply(this,arguments);}function makeIterator(data,options){if(typeof data==='string'){return makeStringIterator(data,options);}if(data instanceof ArrayBuffer){return makeArrayBufferIterator(data,options);}if(isBlob(data)){return makeBlobIterator(data,options);}if(isReadableStream(data)){return makeStreamIterator(data,options);}if(isResponse(data)){var response=data;return makeStreamIterator(response.body,options);}throw new Error('makeIterator');}var ERR_DATA='Cannot convert supplied data type';function getArrayBufferOrStringFromDataSync(data,loader,options){if(loader.text&&typeof data==='string'){return data;}if(isBuffer(data)){data=data.buffer;}if(data instanceof ArrayBuffer){var arrayBuffer=data;if(loader.text&&!loader.binary){var textDecoder=new TextDecoder('utf8');return textDecoder.decode(arrayBuffer);}return arrayBuffer;}if(ArrayBuffer.isView(data)){if(loader.text&&!loader.binary){var _textDecoder=new TextDecoder('utf8');return _textDecoder.decode(data);}var _arrayBuffer=data.buffer;var byteLength=data.byteLength||data.length;if(data.byteOffset!==0||byteLength!==_arrayBuffer.byteLength){_arrayBuffer=_arrayBuffer.slice(data.byteOffset,data.byteOffset+byteLength);}return _arrayBuffer;}throw new Error(ERR_DATA);}async function getArrayBufferOrStringFromData(data,loader,options){var isArrayBuffer=data instanceof ArrayBuffer||ArrayBuffer.isView(data);if(typeof data==='string'||isArrayBuffer){return getArrayBufferOrStringFromDataSync(data,loader);}if(isBlob(data)){data=await makeResponse(data);}if(isResponse(data)){var response=data;await checkResponse(response);return loader.binary?await response.arrayBuffer():await response.text();}if(isReadableStream(data)){data=makeIterator(data,options);}if(isIterable(data)||isAsyncIterable(data)){return concatenateArrayBuffersAsync(data);}throw new Error(ERR_DATA);}function getLoaderContext(context,options){var previousContext=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;if(previousContext){return previousContext;}var resolvedContext=_objectSpread2({fetch:getFetchFunction(options,context)},context);if(!Array.isArray(resolvedContext.loaders)){resolvedContext.loaders=null;}return resolvedContext;}function getLoadersFromContext(loaders,context){if(!context&&loaders&&!Array.isArray(loaders)){return loaders;}var candidateLoaders;if(loaders){candidateLoaders=Array.isArray(loaders)?loaders:[loaders];}if(context&&context.loaders){var contextLoaders=Array.isArray(context.loaders)?context.loaders:[context.loaders];candidateLoaders=candidateLoaders?[...candidateLoaders,...contextLoaders]:contextLoaders;}return candidateLoaders&&candidateLoaders.length?candidateLoaders:null;}async function parse$3(data,loaders,options,context){assert$6(!context||typeof context==='object');if(loaders&&!Array.isArray(loaders)&&!isLoaderObject(loaders)){context=undefined;options=loaders;loaders=undefined;}data=await data;options=options||{};var{url}=getResourceUrlAndType(data);var typedLoaders=loaders;var candidateLoaders=getLoadersFromContext(typedLoaders,context);var loader=await selectLoader(data,candidateLoaders,options);if(!loader){return null;}options=normalizeOptions(options,loader,candidateLoaders,url);context=getLoaderContext({url,parse:parse$3,loaders:candidateLoaders},options,context);return await parseWithLoader(loader,data,options,context);}async function parseWithLoader(loader,data,options,context){validateWorkerVersion(loader);data=await getArrayBufferOrStringFromData(data,loader,options);if(loader.parseTextSync&&typeof data==='string'){options.dataType='text';return loader.parseTextSync(data,options,context,loader);}if(canParseWithWorker(loader,options)){return await parseWithWorker(loader,data,options,context,parse$3);}if(loader.parseText&&typeof data==='string'){return await loader.parseText(data,options,context,loader);}if(loader.parse){return await loader.parse(data,options,context,loader);}assert$6(!loader.parseSync);throw new Error("".concat(loader.id," loader - no parser found and worker is disabled"));}async function load(url,loaders,options,context){if(!Array.isArray(loaders)&&!isLoaderObject(loaders)){options=loaders;loaders=undefined;}var fetch=getFetchFunction(options);var data=url;if(typeof url==='string'){data=await fetch(url);}if(isBlob(url)){data=await fetch(url);}return await parse$3(data,loaders,options);}function assert$4(condition,message){if(!condition){throw new Error("math.gl assertion ".concat(message));}}var RADIANS_TO_DEGREES=1/Math.PI*180;var DEGREES_TO_RADIANS=1/180*Math.PI;var config$2={};config$2.EPSILON=1e-12;config$2.debug=false;config$2.precision=4;config$2.printTypes=false;config$2.printDegrees=false;config$2.printRowMajor=true;function round(value){return Math.round(value/config$2.EPSILON)*config$2.EPSILON;}function formatValue(value){var{precision=config$2.precision||4}=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};value=round(value);return "".concat(parseFloat(value.toPrecision(precision)));}function isArray(value){return Array.isArray(value)||ArrayBuffer.isView(value)&&!(value instanceof DataView);}function duplicateArray(array){return array.clone?array.clone():new Array(array.length);}function map$1(value,func,result){if(isArray(value)){result=result||duplicateArray(value);for(var _i7=0;_i7<result.length&&_i7<value.length;++_i7){result[_i7]=func(value[_i7],_i7,result);}return result;}return func(value);}function toRadians(degrees){return radians(degrees);}function toDegrees(radians){return degrees(radians);}function radians(degrees,result){return map$1(degrees,degrees=>degrees*DEGREES_TO_RADIANS,result);}function degrees(radians,result){return map$1(radians,radians=>radians*RADIANS_TO_DEGREES,result);}function clamp(value,min,max){return map$1(value,value=>Math.max(min,Math.min(max,value)));}function equals$1(a,b,epsilon){var oldEpsilon=config$2.EPSILON;if(epsilon){config$2.EPSILON=epsilon;}try{if(a===b){return true;}if(isArray(a)&&isArray(b)){if(a.length!==b.length){return false;}for(var _i8=0;_i8<a.length;++_i8){if(!equals$1(a[_i8],b[_i8])){return false;}}return true;}if(a&&a.equals){return a.equals(b);}if(b&&b.equals){return b.equals(a);}if(Number.isFinite(a)&&Number.isFinite(b)){return Math.abs(a-b)<=config$2.EPSILON*Math.max(1.0,Math.abs(a),Math.abs(b));}return false;}finally{config$2.EPSILON=oldEpsilon;}}function _extendableBuiltin(cls){function ExtendableBuiltin(){var instance=Reflect.construct(cls,Array.from(arguments));Object.setPrototypeOf(instance,Object.getPrototypeOf(this));return instance;}ExtendableBuiltin.prototype=Object.create(cls.prototype,{constructor:{value:cls,enumerable:false,writable:true,configurable:true}});if(Object.setPrototypeOf){Object.setPrototypeOf(ExtendableBuiltin,cls);}else {ExtendableBuiltin.__proto__=cls;}return ExtendableBuiltin;}class MathArray extends _extendableBuiltin(Array){get ELEMENTS(){assert$4(false);return 0;}clone(){return new this.constructor().copy(this);}from(arrayOrObject){return Array.isArray(arrayOrObject)?this.copy(arrayOrObject):this.fromObject(arrayOrObject);}fromArray(array){var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;for(var _i9=0;_i9<this.ELEMENTS;++_i9){this[_i9]=array[_i9+offset];}return this.check();}to(arrayOrObject){if(arrayOrObject===this){return this;}return isArray(arrayOrObject)?this.toArray(arrayOrObject):this.toObject(arrayOrObject);}toTarget(target){return target?this.to(target):this;}toArray(){var array=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];var offset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;for(var _i10=0;_i10<this.ELEMENTS;++_i10){array[offset+_i10]=this[_i10];}return array;}toFloat32Array(){return new Float32Array(this);}toString(){return this.formatString(config$2);}formatString(opts){var string='';for(var _i11=0;_i11<this.ELEMENTS;++_i11){string+=(_i11>0?', ':'')+formatValue(this[_i11],opts);}return "".concat(opts.printTypes?this.constructor.name:'',"[").concat(string,"]");}equals(array){if(!array||this.length!==array.length){return false;}for(var _i12=0;_i12<this.ELEMENTS;++_i12){if(!equals$1(this[_i12],array[_i12])){return false;}}return true;}exactEquals(array){if(!array||this.length!==array.length){return false;}for(var _i13=0;_i13<this.ELEMENTS;++_i13){if(this[_i13]!==array[_i13]){return false;}}return true;}negate(){for(var _i14=0;_i14<this.ELEMENTS;++_i14){this[_i14]=-this[_i14];}return this.check();}lerp(a,b,t){if(t===undefined){t=b;b=a;a=this;}for(var _i15=0;_i15<this.ELEMENTS;++_i15){var ai=a[_i15];this[_i15]=ai+t*(b[_i15]-ai);}return this.check();}min(vector){for(var _i16=0;_i16<this.ELEMENTS;++_i16){this[_i16]=Math.min(vector[_i16],this[_i16]);}return this.check();}max(vector){for(var _i17=0;_i17<this.ELEMENTS;++_i17){this[_i17]=Math.max(vector[_i17],this[_i17]);}return this.check();}clamp(minVector,maxVector){for(var _i18=0;_i18<this.ELEMENTS;++_i18){this[_i18]=Math.min(Math.max(this[_i18],minVector[_i18]),maxVector[_i18]);}return this.check();}add(){for(var _len7=arguments.length,vectors=new Array(_len7),_key7=0;_key7<_len7;_key7++){vectors[_key7]=arguments[_key7];}for(var vector of vectors){for(var _i19=0;_i19<this.ELEMENTS;++_i19){this[_i19]+=vector[_i19];}}return this.check();}subtract(){for(var _len8=arguments.length,vectors=new Array(_len8),_key8=0;_key8<_len8;_key8++){vectors[_key8]=arguments[_key8];}for(var vector of vectors){for(var _i20=0;_i20<this.ELEMENTS;++_i20){this[_i20]-=vector[_i20];}}return this.check();}scale(scale){if(Array.isArray(scale)){return this.multiply(scale);}for(var _i21=0;_i21<this.ELEMENTS;++_i21){this[_i21]*=scale;}return this.check();}sub(a){return this.subtract(a);}setScalar(a){for(var _i22=0;_i22<this.ELEMENTS;++_i22){this[_i22]=a;}return this.check();}addScalar(a){for(var _i23=0;_i23<this.ELEMENTS;++_i23){this[_i23]+=a;}return this.check();}subScalar(a){return this.addScalar(-a);}multiplyScalar(scalar){for(var _i24=0;_i24<this.ELEMENTS;++_i24){this[_i24]*=scalar;}return this.check();}divideScalar(a){return this.scale(1/a);}clampScalar(min,max){for(var _i25=0;_i25<this.ELEMENTS;++_i25){this[_i25]=Math.min(Math.max(this[_i25],min),max);}return this.check();}multiplyByScalar(scalar){return this.scale(scalar);}get elements(){return this;}check(){if(config$2.debug&&!this.validate()){throw new Error("math.gl: ".concat(this.constructor.name," some fields set to invalid numbers'"));}return this;}validate(){var valid=this.length===this.ELEMENTS;for(var _i26=0;_i26<this.ELEMENTS;++_i26){valid=valid&&Number.isFinite(this[_i26]);}return valid;}}function validateVector(v,length){if(v.length!==length){return false;}for(var _i27=0;_i27<v.length;++_i27){if(!Number.isFinite(v[_i27])){return false;}}return true;}function checkNumber(value){if(!Number.isFinite(value)){throw new Error("Invalid number ".concat(value));}return value;}function checkVector(v,length){var callerName=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'';if(config$2.debug&&!validateVector(v,length)){throw new Error("math.gl: ".concat(callerName," some fields set to invalid numbers'"));}return v;}var map={};function deprecated(method,version){if(!map[method]){map[method]=true;console.warn("".concat(method," has been removed in version ").concat(version,", see upgrade guide for more information"));}}class Vector extends MathArray{get ELEMENTS(){assert$4(false);return 0;}copy(vector){assert$4(false);return this;}get x(){return this[0];}set x(value){this[0]=checkNumber(value);}get y(){return this[1];}set y(value){this[1]=checkNumber(value);}len(){return Math.sqrt(this.lengthSquared());}magnitude(){return this.len();}lengthSquared(){var length=0;for(var _i28=0;_i28<this.ELEMENTS;++_i28){length+=this[_i28]*this[_i28];}return length;}magnitudeSquared(){return this.lengthSquared();}distance(mathArray){return Math.sqrt(this.distanceSquared(mathArray));}distanceSquared(mathArray){var length=0;for(var _i29=0;_i29<this.ELEMENTS;++_i29){var dist=this[_i29]-mathArray[_i29];length+=dist*dist;}return checkNumber(length);}dot(mathArray){var product=0;for(var _i30=0;_i30<this.ELEMENTS;++_i30){product+=this[_i30]*mathArray[_i30];}return checkNumber(product);}normalize(){var length=this.magnitude();if(length!==0){for(var _i31=0;_i31<this.ELEMENTS;++_i31){this[_i31]/=length;}}return this.check();}multiply(){for(var _len9=arguments.length,vectors=new Array(_len9),_key9=0;_key9<_len9;_key9++){vectors[_key9]=arguments[_key9];}for(var vector of vectors){for(var _i32=0;_i32<this.ELEMENTS;++_i32){this[_i32]*=vector[_i32];}}return this.check();}divide(){for(var _len10=arguments.length,vectors=new Array(_len10),_key10=0;_key10<_len10;_key10++){vectors[_key10]=arguments[_key10];}for(var vector of vectors){for(var _i33=0;_i33<this.ELEMENTS;++_i33){this[_i33]/=vector[_i33];}}return this.check();}lengthSq(){return this.lengthSquared();}distanceTo(vector){return this.distance(vector);}distanceToSquared(vector){return this.distanceSquared(vector);}getComponent(i){assert$4(i>=0&&i<this.ELEMENTS,'index is out of range');return checkNumber(this[i]);}setComponent(i,value){assert$4(i>=0&&i<this.ELEMENTS,'index is out of range');this[i]=value;return this.check();}addVectors(a,b){return this.copy(a).add(b);}subVectors(a,b){return this.copy(a).subtract(b);}multiplyVectors(a,b){return this.copy(a).multiply(b);}addScaledVector(a,b){return this.add(new this.constructor(a).multiplyScalar(b));}}/**
  56310. * Common utilities
  56311. * @module glMatrix
  56312. */ // Configuration Constants
  56313. var EPSILON=0.000001;var ARRAY_TYPE=typeof Float32Array!=='undefined'?Float32Array:Array;if(!Math.hypot)Math.hypot=function(){var y=0,i=arguments.length;while(i--){y+=arguments[i]*arguments[i];}return Math.sqrt(y);};/**
  56314. * 2 Dimensional Vector
  56315. * @module vec2
  56316. */ /**
  56317. * Creates a new, empty vec2
  56318. *
  56319. * @returns {vec2} a new 2D vector
  56320. */function create$4(){var out=new ARRAY_TYPE(2);if(ARRAY_TYPE!=Float32Array){out[0]=0;out[1]=0;}return out;}/**
  56321. * Transforms the vec2 with a mat2
  56322. *
  56323. * @param {vec2} out the receiving vector
  56324. * @param {ReadonlyVec2} a the vector to transform
  56325. * @param {ReadonlyMat2} m matrix to transform with
  56326. * @returns {vec2} out
  56327. */function transformMat2(out,a,m){var x=a[0],y=a[1];out[0]=m[0]*x+m[2]*y;out[1]=m[1]*x+m[3]*y;return out;}/**
  56328. * Transforms the vec2 with a mat2d
  56329. *
  56330. * @param {vec2} out the receiving vector
  56331. * @param {ReadonlyVec2} a the vector to transform
  56332. * @param {ReadonlyMat2d} m matrix to transform with
  56333. * @returns {vec2} out
  56334. */function transformMat2d(out,a,m){var x=a[0],y=a[1];out[0]=m[0]*x+m[2]*y+m[4];out[1]=m[1]*x+m[3]*y+m[5];return out;}/**
  56335. * Transforms the vec2 with a mat3
  56336. * 3rd vector component is implicitly '1'
  56337. *
  56338. * @param {vec2} out the receiving vector
  56339. * @param {ReadonlyVec2} a the vector to transform
  56340. * @param {ReadonlyMat3} m matrix to transform with
  56341. * @returns {vec2} out
  56342. */function transformMat3$1(out,a,m){var x=a[0],y=a[1];out[0]=m[0]*x+m[3]*y+m[6];out[1]=m[1]*x+m[4]*y+m[7];return out;}/**
  56343. * Transforms the vec2 with a mat4
  56344. * 3rd vector component is implicitly '0'
  56345. * 4th vector component is implicitly '1'
  56346. *
  56347. * @param {vec2} out the receiving vector
  56348. * @param {ReadonlyVec2} a the vector to transform
  56349. * @param {ReadonlyMat4} m matrix to transform with
  56350. * @returns {vec2} out
  56351. */function transformMat4$2(out,a,m){var x=a[0];var y=a[1];out[0]=m[0]*x+m[4]*y+m[12];out[1]=m[1]*x+m[5]*y+m[13];return out;}/**
  56352. * Perform some operation over an array of vec2s.
  56353. *
  56354. * @param {Array} a the array of vectors to iterate over
  56355. * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
  56356. * @param {Number} offset Number of elements to skip at the beginning of the array
  56357. * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
  56358. * @param {Function} fn Function to call for each vector in the array
  56359. * @param {Object} [arg] additional argument to pass to fn
  56360. * @returns {Array} a
  56361. * @function
  56362. */(function(){var vec=create$4();return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=2;}if(!offset){offset=0;}if(count){l=Math.min(count*stride+offset,a.length);}else {l=a.length;}for(i=offset;i<l;i+=stride){vec[0]=a[i];vec[1]=a[i+1];fn(vec,vec,arg);a[i]=vec[0];a[i+1]=vec[1];}return a;};})();function vec2_transformMat4AsVector(out,a,m){var x=a[0];var y=a[1];var w=m[3]*x+m[7]*y||1.0;out[0]=(m[0]*x+m[4]*y)/w;out[1]=(m[1]*x+m[5]*y)/w;return out;}function vec3_transformMat4AsVector(out,a,m){var x=a[0];var y=a[1];var z=a[2];var w=m[3]*x+m[7]*y+m[11]*z||1.0;out[0]=(m[0]*x+m[4]*y+m[8]*z)/w;out[1]=(m[1]*x+m[5]*y+m[9]*z)/w;out[2]=(m[2]*x+m[6]*y+m[10]*z)/w;return out;}function vec3_transformMat2(out,a,m){var x=a[0];var y=a[1];out[0]=m[0]*x+m[2]*y;out[1]=m[1]*x+m[3]*y;out[2]=a[2];return out;}function vec4_transformMat3(out,a,m){var x=a[0];var y=a[1];var z=a[2];out[0]=m[0]*x+m[3]*y+m[6]*z;out[1]=m[1]*x+m[4]*y+m[7]*z;out[2]=m[2]*x+m[5]*y+m[8]*z;out[3]=a[3];return out;}class Vector2$1 extends Vector{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;super(2);if(isArray(x)&&arguments.length===1){this.copy(x);}else {if(config$2.debug){checkNumber(x);checkNumber(y);}this[0]=x;this[1]=y;}}set(x,y){this[0]=x;this[1]=y;return this.check();}copy(array){this[0]=array[0];this[1]=array[1];return this.check();}fromObject(object){if(config$2.debug){checkNumber(object.x);checkNumber(object.y);}this[0]=object.x;this[1]=object.y;return this.check();}toObject(object){object.x=this[0];object.y=this[1];return object;}get ELEMENTS(){return 2;}horizontalAngle(){return Math.atan2(this.y,this.x);}verticalAngle(){return Math.atan2(this.x,this.y);}transform(matrix4){return this.transformAsPoint(matrix4);}transformAsPoint(matrix4){transformMat4$2(this,this,matrix4);return this.check();}transformAsVector(matrix4){vec2_transformMat4AsVector(this,this,matrix4);return this.check();}transformByMatrix3(matrix3){transformMat3$1(this,this,matrix3);return this.check();}transformByMatrix2x3(matrix2x3){transformMat2d(this,this,matrix2x3);return this.check();}transformByMatrix2(matrix2){transformMat2(this,this,matrix2);return this.check();}}/**
  56363. * 3 Dimensional Vector
  56364. * @module vec3
  56365. */ /**
  56366. * Creates a new, empty vec3
  56367. *
  56368. * @returns {vec3} a new 3D vector
  56369. */function create$3(){var out=new ARRAY_TYPE(3);if(ARRAY_TYPE!=Float32Array){out[0]=0;out[1]=0;out[2]=0;}return out;}/**
  56370. * Calculates the length of a vec3
  56371. *
  56372. * @param {ReadonlyVec3} a vector to calculate length of
  56373. * @returns {Number} length of a
  56374. */function length$2(a){var x=a[0];var y=a[1];var z=a[2];return Math.hypot(x,y,z);}/**
  56375. * Creates a new vec3 initialized with the given values
  56376. *
  56377. * @param {Number} x X component
  56378. * @param {Number} y Y component
  56379. * @param {Number} z Z component
  56380. * @returns {vec3} a new 3D vector
  56381. */function fromValues(x,y,z){var out=new ARRAY_TYPE(3);out[0]=x;out[1]=y;out[2]=z;return out;}/**
  56382. * Normalize a vec3
  56383. *
  56384. * @param {vec3} out the receiving vector
  56385. * @param {ReadonlyVec3} a vector to normalize
  56386. * @returns {vec3} out
  56387. */function normalize$2(out,a){var x=a[0];var y=a[1];var z=a[2];var len=x*x+y*y+z*z;if(len>0){//TODO: evaluate use of glm_invsqrt here?
  56388. len=1/Math.sqrt(len);}out[0]=a[0]*len;out[1]=a[1]*len;out[2]=a[2]*len;return out;}/**
  56389. * Calculates the dot product of two vec3's
  56390. *
  56391. * @param {ReadonlyVec3} a the first operand
  56392. * @param {ReadonlyVec3} b the second operand
  56393. * @returns {Number} dot product of a and b
  56394. */function dot$2(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}/**
  56395. * Computes the cross product of two vec3's
  56396. *
  56397. * @param {vec3} out the receiving vector
  56398. * @param {ReadonlyVec3} a the first operand
  56399. * @param {ReadonlyVec3} b the second operand
  56400. * @returns {vec3} out
  56401. */function cross(out,a,b){var ax=a[0],ay=a[1],az=a[2];var bx=b[0],by=b[1],bz=b[2];out[0]=ay*bz-az*by;out[1]=az*bx-ax*bz;out[2]=ax*by-ay*bx;return out;}/**
  56402. * Transforms the vec3 with a mat4.
  56403. * 4th vector component is implicitly '1'
  56404. *
  56405. * @param {vec3} out the receiving vector
  56406. * @param {ReadonlyVec3} a the vector to transform
  56407. * @param {ReadonlyMat4} m matrix to transform with
  56408. * @returns {vec3} out
  56409. */function transformMat4$1(out,a,m){var x=a[0],y=a[1],z=a[2];var w=m[3]*x+m[7]*y+m[11]*z+m[15];w=w||1.0;out[0]=(m[0]*x+m[4]*y+m[8]*z+m[12])/w;out[1]=(m[1]*x+m[5]*y+m[9]*z+m[13])/w;out[2]=(m[2]*x+m[6]*y+m[10]*z+m[14])/w;return out;}/**
  56410. * Transforms the vec3 with a mat3.
  56411. *
  56412. * @param {vec3} out the receiving vector
  56413. * @param {ReadonlyVec3} a the vector to transform
  56414. * @param {ReadonlyMat3} m the 3x3 matrix to transform with
  56415. * @returns {vec3} out
  56416. */function transformMat3(out,a,m){var x=a[0],y=a[1],z=a[2];out[0]=x*m[0]+y*m[3]+z*m[6];out[1]=x*m[1]+y*m[4]+z*m[7];out[2]=x*m[2]+y*m[5]+z*m[8];return out;}/**
  56417. * Transforms the vec3 with a quat
  56418. * Can also be used for dual quaternions. (Multiply it with the real part)
  56419. *
  56420. * @param {vec3} out the receiving vector
  56421. * @param {ReadonlyVec3} a the vector to transform
  56422. * @param {ReadonlyQuat} q quaternion to transform with
  56423. * @returns {vec3} out
  56424. */function transformQuat$1(out,a,q){// benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
  56425. var qx=q[0],qy=q[1],qz=q[2],qw=q[3];var x=a[0],y=a[1],z=a[2];// var qvec = [qx, qy, qz];
  56426. // var uv = vec3.cross([], qvec, a);
  56427. var uvx=qy*z-qz*y,uvy=qz*x-qx*z,uvz=qx*y-qy*x;// var uuv = vec3.cross([], qvec, uv);
  56428. var uuvx=qy*uvz-qz*uvy,uuvy=qz*uvx-qx*uvz,uuvz=qx*uvy-qy*uvx;// vec3.scale(uv, uv, 2 * w);
  56429. var w2=qw*2;uvx*=w2;uvy*=w2;uvz*=w2;// vec3.scale(uuv, uuv, 2);
  56430. uuvx*=2;uuvy*=2;uuvz*=2;// return vec3.add(out, a, vec3.add(out, uv, uuv));
  56431. out[0]=x+uvx+uuvx;out[1]=y+uvy+uuvy;out[2]=z+uvz+uuvz;return out;}/**
  56432. * Rotate a 3D vector around the x-axis
  56433. * @param {vec3} out The receiving vec3
  56434. * @param {ReadonlyVec3} a The vec3 point to rotate
  56435. * @param {ReadonlyVec3} b The origin of the rotation
  56436. * @param {Number} rad The angle of rotation in radians
  56437. * @returns {vec3} out
  56438. */function rotateX$2(out,a,b,rad){var p=[],r=[];//Translate point to the origin
  56439. p[0]=a[0]-b[0];p[1]=a[1]-b[1];p[2]=a[2]-b[2];//perform rotation
  56440. r[0]=p[0];r[1]=p[1]*Math.cos(rad)-p[2]*Math.sin(rad);r[2]=p[1]*Math.sin(rad)+p[2]*Math.cos(rad);//translate to correct position
  56441. out[0]=r[0]+b[0];out[1]=r[1]+b[1];out[2]=r[2]+b[2];return out;}/**
  56442. * Rotate a 3D vector around the y-axis
  56443. * @param {vec3} out The receiving vec3
  56444. * @param {ReadonlyVec3} a The vec3 point to rotate
  56445. * @param {ReadonlyVec3} b The origin of the rotation
  56446. * @param {Number} rad The angle of rotation in radians
  56447. * @returns {vec3} out
  56448. */function rotateY$2(out,a,b,rad){var p=[],r=[];//Translate point to the origin
  56449. p[0]=a[0]-b[0];p[1]=a[1]-b[1];p[2]=a[2]-b[2];//perform rotation
  56450. r[0]=p[2]*Math.sin(rad)+p[0]*Math.cos(rad);r[1]=p[1];r[2]=p[2]*Math.cos(rad)-p[0]*Math.sin(rad);//translate to correct position
  56451. out[0]=r[0]+b[0];out[1]=r[1]+b[1];out[2]=r[2]+b[2];return out;}/**
  56452. * Rotate a 3D vector around the z-axis
  56453. * @param {vec3} out The receiving vec3
  56454. * @param {ReadonlyVec3} a The vec3 point to rotate
  56455. * @param {ReadonlyVec3} b The origin of the rotation
  56456. * @param {Number} rad The angle of rotation in radians
  56457. * @returns {vec3} out
  56458. */function rotateZ$2(out,a,b,rad){var p=[],r=[];//Translate point to the origin
  56459. p[0]=a[0]-b[0];p[1]=a[1]-b[1];p[2]=a[2]-b[2];//perform rotation
  56460. r[0]=p[0]*Math.cos(rad)-p[1]*Math.sin(rad);r[1]=p[0]*Math.sin(rad)+p[1]*Math.cos(rad);r[2]=p[2];//translate to correct position
  56461. out[0]=r[0]+b[0];out[1]=r[1]+b[1];out[2]=r[2]+b[2];return out;}/**
  56462. * Get the angle between two 3D vectors
  56463. * @param {ReadonlyVec3} a The first operand
  56464. * @param {ReadonlyVec3} b The second operand
  56465. * @returns {Number} The angle in radians
  56466. */function angle$1(a,b){var ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2],mag1=Math.sqrt(ax*ax+ay*ay+az*az),mag2=Math.sqrt(bx*bx+by*by+bz*bz),mag=mag1*mag2,cosine=mag&&dot$2(a,b)/mag;return Math.acos(Math.min(Math.max(cosine,-1),1));}/**
  56467. * Alias for {@link vec3.length}
  56468. * @function
  56469. */var len=length$2;/**
  56470. * Perform some operation over an array of vec3s.
  56471. *
  56472. * @param {Array} a the array of vectors to iterate over
  56473. * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
  56474. * @param {Number} offset Number of elements to skip at the beginning of the array
  56475. * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
  56476. * @param {Function} fn Function to call for each vector in the array
  56477. * @param {Object} [arg] additional argument to pass to fn
  56478. * @returns {Array} a
  56479. * @function
  56480. */(function(){var vec=create$3();return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=3;}if(!offset){offset=0;}if(count){l=Math.min(count*stride+offset,a.length);}else {l=a.length;}for(i=offset;i<l;i+=stride){vec[0]=a[i];vec[1]=a[i+1];vec[2]=a[i+2];fn(vec,vec,arg);a[i]=vec[0];a[i+1]=vec[1];a[i+2]=vec[2];}return a;};})();var ORIGIN=[0,0,0];var constants$2={};class Vector3$1 extends Vector{static get ZERO(){return constants$2.ZERO=constants$2.ZERO||Object.freeze(new Vector3$1(0,0,0,0));}constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;super(-0,-0,-0);if(arguments.length===1&&isArray(x)){this.copy(x);}else {if(config$2.debug){checkNumber(x);checkNumber(y);checkNumber(z);}this[0]=x;this[1]=y;this[2]=z;}}set(x,y,z){this[0]=x;this[1]=y;this[2]=z;return this.check();}copy(array){this[0]=array[0];this[1]=array[1];this[2]=array[2];return this.check();}fromObject(object){if(config$2.debug){checkNumber(object.x);checkNumber(object.y);checkNumber(object.z);}this[0]=object.x;this[1]=object.y;this[2]=object.z;return this.check();}toObject(object){object.x=this[0];object.y=this[1];object.z=this[2];return object;}get ELEMENTS(){return 3;}get z(){return this[2];}set z(value){this[2]=checkNumber(value);}angle(vector){return angle$1(this,vector);}cross(vector){cross(this,this,vector);return this.check();}rotateX(_ref4){var{radians,origin=ORIGIN}=_ref4;rotateX$2(this,this,origin,radians);return this.check();}rotateY(_ref5){var{radians,origin=ORIGIN}=_ref5;rotateY$2(this,this,origin,radians);return this.check();}rotateZ(_ref6){var{radians,origin=ORIGIN}=_ref6;rotateZ$2(this,this,origin,radians);return this.check();}transform(matrix4){return this.transformAsPoint(matrix4);}transformAsPoint(matrix4){transformMat4$1(this,this,matrix4);return this.check();}transformAsVector(matrix4){vec3_transformMat4AsVector(this,this,matrix4);return this.check();}transformByMatrix3(matrix3){transformMat3(this,this,matrix3);return this.check();}transformByMatrix2(matrix2){vec3_transformMat2(this,this,matrix2);return this.check();}transformByQuaternion(quaternion){transformQuat$1(this,this,quaternion);return this.check();}}class Matrix extends MathArray{get ELEMENTS(){assert$4(false);return 0;}get RANK(){assert$4(false);return 0;}toString(){var string='[';if(config$2.printRowMajor){string+='row-major:';for(var row=0;row<this.RANK;++row){for(var col=0;col<this.RANK;++col){string+=" ".concat(this[col*this.RANK+row]);}}}else {string+='column-major:';for(var _i34=0;_i34<this.ELEMENTS;++_i34){string+=" ".concat(this[_i34]);}}string+=']';return string;}getElementIndex(row,col){return col*this.RANK+row;}getElement(row,col){return this[col*this.RANK+row];}setElement(row,col,value){this[col*this.RANK+row]=checkNumber(value);return this;}getColumn(columnIndex){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Array(this.RANK).fill(-0);var firstIndex=columnIndex*this.RANK;for(var _i35=0;_i35<this.RANK;++_i35){result[_i35]=this[firstIndex+_i35];}return result;}setColumn(columnIndex,columnVector){var firstIndex=columnIndex*this.RANK;for(var _i36=0;_i36<this.RANK;++_i36){this[firstIndex+_i36]=columnVector[_i36];}return this;}}/**
  56481. * 3x3 Matrix
  56482. * @module mat3
  56483. */ /**
  56484. * Creates a new identity mat3
  56485. *
  56486. * @returns {mat3} a new 3x3 matrix
  56487. */function create$2(){var out=new ARRAY_TYPE(9);if(ARRAY_TYPE!=Float32Array){out[1]=0;out[2]=0;out[3]=0;out[5]=0;out[6]=0;out[7]=0;}out[0]=1;out[4]=1;out[8]=1;return out;}/**
  56488. * Transpose the values of a mat3
  56489. *
  56490. * @param {mat3} out the receiving matrix
  56491. * @param {ReadonlyMat3} a the source matrix
  56492. * @returns {mat3} out
  56493. */function transpose$1(out,a){// If we are transposing ourselves we can skip a few steps but have to cache some values
  56494. if(out===a){var a01=a[1],a02=a[2],a12=a[5];out[1]=a[3];out[2]=a[6];out[3]=a01;out[5]=a[7];out[6]=a02;out[7]=a12;}else {out[0]=a[0];out[1]=a[3];out[2]=a[6];out[3]=a[1];out[4]=a[4];out[5]=a[7];out[6]=a[2];out[7]=a[5];out[8]=a[8];}return out;}/**
  56495. * Inverts a mat3
  56496. *
  56497. * @param {mat3} out the receiving matrix
  56498. * @param {ReadonlyMat3} a the source matrix
  56499. * @returns {mat3} out
  56500. */function invert$2(out,a){var a00=a[0],a01=a[1],a02=a[2];var a10=a[3],a11=a[4],a12=a[5];var a20=a[6],a21=a[7],a22=a[8];var b01=a22*a11-a12*a21;var b11=-a22*a10+a12*a20;var b21=a21*a10-a11*a20;// Calculate the determinant
  56501. var det=a00*b01+a01*b11+a02*b21;if(!det){return null;}det=1.0/det;out[0]=b01*det;out[1]=(-a22*a01+a02*a21)*det;out[2]=(a12*a01-a02*a11)*det;out[3]=b11*det;out[4]=(a22*a00-a02*a20)*det;out[5]=(-a12*a00+a02*a10)*det;out[6]=b21*det;out[7]=(-a21*a00+a01*a20)*det;out[8]=(a11*a00-a01*a10)*det;return out;}/**
  56502. * Calculates the determinant of a mat3
  56503. *
  56504. * @param {ReadonlyMat3} a the source matrix
  56505. * @returns {Number} determinant of a
  56506. */function determinant$1(a){var a00=a[0],a01=a[1],a02=a[2];var a10=a[3],a11=a[4],a12=a[5];var a20=a[6],a21=a[7],a22=a[8];return a00*(a22*a11-a12*a21)+a01*(-a22*a10+a12*a20)+a02*(a21*a10-a11*a20);}/**
  56507. * Multiplies two mat3's
  56508. *
  56509. * @param {mat3} out the receiving matrix
  56510. * @param {ReadonlyMat3} a the first operand
  56511. * @param {ReadonlyMat3} b the second operand
  56512. * @returns {mat3} out
  56513. */function multiply$2(out,a,b){var a00=a[0],a01=a[1],a02=a[2];var a10=a[3],a11=a[4],a12=a[5];var a20=a[6],a21=a[7],a22=a[8];var b00=b[0],b01=b[1],b02=b[2];var b10=b[3],b11=b[4],b12=b[5];var b20=b[6],b21=b[7],b22=b[8];out[0]=b00*a00+b01*a10+b02*a20;out[1]=b00*a01+b01*a11+b02*a21;out[2]=b00*a02+b01*a12+b02*a22;out[3]=b10*a00+b11*a10+b12*a20;out[4]=b10*a01+b11*a11+b12*a21;out[5]=b10*a02+b11*a12+b12*a22;out[6]=b20*a00+b21*a10+b22*a20;out[7]=b20*a01+b21*a11+b22*a21;out[8]=b20*a02+b21*a12+b22*a22;return out;}/**
  56514. * Translate a mat3 by the given vector
  56515. *
  56516. * @param {mat3} out the receiving matrix
  56517. * @param {ReadonlyMat3} a the matrix to translate
  56518. * @param {ReadonlyVec2} v vector to translate by
  56519. * @returns {mat3} out
  56520. */function translate$1(out,a,v){var a00=a[0],a01=a[1],a02=a[2],a10=a[3],a11=a[4],a12=a[5],a20=a[6],a21=a[7],a22=a[8],x=v[0],y=v[1];out[0]=a00;out[1]=a01;out[2]=a02;out[3]=a10;out[4]=a11;out[5]=a12;out[6]=x*a00+y*a10+a20;out[7]=x*a01+y*a11+a21;out[8]=x*a02+y*a12+a22;return out;}/**
  56521. * Rotates a mat3 by the given angle
  56522. *
  56523. * @param {mat3} out the receiving matrix
  56524. * @param {ReadonlyMat3} a the matrix to rotate
  56525. * @param {Number} rad the angle to rotate the matrix by
  56526. * @returns {mat3} out
  56527. */function rotate$1(out,a,rad){var a00=a[0],a01=a[1],a02=a[2],a10=a[3],a11=a[4],a12=a[5],a20=a[6],a21=a[7],a22=a[8],s=Math.sin(rad),c=Math.cos(rad);out[0]=c*a00+s*a10;out[1]=c*a01+s*a11;out[2]=c*a02+s*a12;out[3]=c*a10-s*a00;out[4]=c*a11-s*a01;out[5]=c*a12-s*a02;out[6]=a20;out[7]=a21;out[8]=a22;return out;}/**
  56528. * Scales the mat3 by the dimensions in the given vec2
  56529. *
  56530. * @param {mat3} out the receiving matrix
  56531. * @param {ReadonlyMat3} a the matrix to rotate
  56532. * @param {ReadonlyVec2} v the vec2 to scale the matrix by
  56533. * @returns {mat3} out
  56534. **/function scale$3(out,a,v){var x=v[0],y=v[1];out[0]=x*a[0];out[1]=x*a[1];out[2]=x*a[2];out[3]=y*a[3];out[4]=y*a[4];out[5]=y*a[5];out[6]=a[6];out[7]=a[7];out[8]=a[8];return out;}/**
  56535. * Calculates a 3x3 matrix from the given quaternion
  56536. *
  56537. * @param {mat3} out mat3 receiving operation result
  56538. * @param {ReadonlyQuat} q Quaternion to create matrix from
  56539. *
  56540. * @returns {mat3} out
  56541. */function fromQuat$1(out,q){var x=q[0],y=q[1],z=q[2],w=q[3];var x2=x+x;var y2=y+y;var z2=z+z;var xx=x*x2;var yx=y*x2;var yy=y*y2;var zx=z*x2;var zy=z*y2;var zz=z*z2;var wx=w*x2;var wy=w*y2;var wz=w*z2;out[0]=1-yy-zz;out[3]=yx-wz;out[6]=zx+wy;out[1]=yx+wz;out[4]=1-xx-zz;out[7]=zy-wx;out[2]=zx-wy;out[5]=zy+wx;out[8]=1-xx-yy;return out;}var IDENTITY$1=Object.freeze([1,0,0,0,1,0,0,0,1]);var ZERO$1=Object.freeze([0,0,0,0,0,0,0,0,0]);var INDICES$1=Object.freeze({COL0ROW0:0,COL0ROW1:1,COL0ROW2:2,COL1ROW0:3,COL1ROW1:4,COL1ROW2:5,COL2ROW0:6,COL2ROW1:7,COL2ROW2:8});var constants$1={};class Matrix3$1 extends Matrix{static get IDENTITY(){constants$1.IDENTITY=constants$1.IDENTITY||Object.freeze(new Matrix3$1(IDENTITY$1));return constants$1.IDENTITY;}static get ZERO(){constants$1.ZERO=constants$1.ZERO||Object.freeze(new Matrix3$1(ZERO$1));return constants$1.ZERO;}get ELEMENTS(){return 9;}get RANK(){return 3;}get INDICES(){return INDICES$1;}constructor(array){super(-0,-0,-0,-0,-0,-0,-0,-0,-0);if(arguments.length===1&&Array.isArray(array)){this.copy(array);}else {this.identity();}}copy(array){this[0]=array[0];this[1]=array[1];this[2]=array[2];this[3]=array[3];this[4]=array[4];this[5]=array[5];this[6]=array[6];this[7]=array[7];this[8]=array[8];return this.check();}set(m00,m10,m20,m01,m11,m21,m02,m12,m22){this[0]=m00;this[1]=m10;this[2]=m20;this[3]=m01;this[4]=m11;this[5]=m21;this[6]=m02;this[7]=m12;this[8]=m22;return this.check();}setRowMajor(m00,m01,m02,m10,m11,m12,m20,m21,m22){this[0]=m00;this[1]=m10;this[2]=m20;this[3]=m01;this[4]=m11;this[5]=m21;this[6]=m02;this[7]=m12;this[8]=m22;return this.check();}determinant(){return determinant$1(this);}identity(){return this.copy(IDENTITY$1);}fromQuaternion(q){fromQuat$1(this,q);return this.check();}transpose(){transpose$1(this,this);return this.check();}invert(){invert$2(this,this);return this.check();}multiplyLeft(a){multiply$2(this,a,this);return this.check();}multiplyRight(a){multiply$2(this,this,a);return this.check();}rotate(radians){rotate$1(this,this,radians);return this.check();}scale(factor){if(Array.isArray(factor)){scale$3(this,this,factor);}else {scale$3(this,this,[factor,factor,factor]);}return this.check();}translate(vec){translate$1(this,this,vec);return this.check();}transform(vector,result){switch(vector.length){case 2:result=transformMat3$1(result||[-0,-0],vector,this);break;case 3:result=transformMat3(result||[-0,-0,-0],vector,this);break;case 4:result=vec4_transformMat3(result||[-0,-0,-0,-0],vector,this);break;default:throw new Error('Illegal vector');}checkVector(result,vector.length);return result;}transformVector(vector,result){deprecated('Matrix3.transformVector');return this.transform(vector,result);}transformVector2(vector,result){deprecated('Matrix3.transformVector');return this.transform(vector,result);}transformVector3(vector,result){deprecated('Matrix3.transformVector');return this.transform(vector,result);}}/**
  56542. * Set a mat4 to the identity matrix
  56543. *
  56544. * @param {mat4} out the receiving matrix
  56545. * @returns {mat4} out
  56546. */function identity$1(out){out[0]=1;out[1]=0;out[2]=0;out[3]=0;out[4]=0;out[5]=1;out[6]=0;out[7]=0;out[8]=0;out[9]=0;out[10]=1;out[11]=0;out[12]=0;out[13]=0;out[14]=0;out[15]=1;return out;}/**
  56547. * Transpose the values of a mat4
  56548. *
  56549. * @param {mat4} out the receiving matrix
  56550. * @param {ReadonlyMat4} a the source matrix
  56551. * @returns {mat4} out
  56552. */function transpose(out,a){// If we are transposing ourselves we can skip a few steps but have to cache some values
  56553. if(out===a){var a01=a[1],a02=a[2],a03=a[3];var a12=a[6],a13=a[7];var a23=a[11];out[1]=a[4];out[2]=a[8];out[3]=a[12];out[4]=a01;out[6]=a[9];out[7]=a[13];out[8]=a02;out[9]=a12;out[11]=a[14];out[12]=a03;out[13]=a13;out[14]=a23;}else {out[0]=a[0];out[1]=a[4];out[2]=a[8];out[3]=a[12];out[4]=a[1];out[5]=a[5];out[6]=a[9];out[7]=a[13];out[8]=a[2];out[9]=a[6];out[10]=a[10];out[11]=a[14];out[12]=a[3];out[13]=a[7];out[14]=a[11];out[15]=a[15];}return out;}/**
  56554. * Inverts a mat4
  56555. *
  56556. * @param {mat4} out the receiving matrix
  56557. * @param {ReadonlyMat4} a the source matrix
  56558. * @returns {mat4} out
  56559. */function invert$1(out,a){var a00=a[0],a01=a[1],a02=a[2],a03=a[3];var a10=a[4],a11=a[5],a12=a[6],a13=a[7];var a20=a[8],a21=a[9],a22=a[10],a23=a[11];var a30=a[12],a31=a[13],a32=a[14],a33=a[15];var b00=a00*a11-a01*a10;var b01=a00*a12-a02*a10;var b02=a00*a13-a03*a10;var b03=a01*a12-a02*a11;var b04=a01*a13-a03*a11;var b05=a02*a13-a03*a12;var b06=a20*a31-a21*a30;var b07=a20*a32-a22*a30;var b08=a20*a33-a23*a30;var b09=a21*a32-a22*a31;var b10=a21*a33-a23*a31;var b11=a22*a33-a23*a32;// Calculate the determinant
  56560. var det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;if(!det){return null;}det=1.0/det;out[0]=(a11*b11-a12*b10+a13*b09)*det;out[1]=(a02*b10-a01*b11-a03*b09)*det;out[2]=(a31*b05-a32*b04+a33*b03)*det;out[3]=(a22*b04-a21*b05-a23*b03)*det;out[4]=(a12*b08-a10*b11-a13*b07)*det;out[5]=(a00*b11-a02*b08+a03*b07)*det;out[6]=(a32*b02-a30*b05-a33*b01)*det;out[7]=(a20*b05-a22*b02+a23*b01)*det;out[8]=(a10*b10-a11*b08+a13*b06)*det;out[9]=(a01*b08-a00*b10-a03*b06)*det;out[10]=(a30*b04-a31*b02+a33*b00)*det;out[11]=(a21*b02-a20*b04-a23*b00)*det;out[12]=(a11*b07-a10*b09-a12*b06)*det;out[13]=(a00*b09-a01*b07+a02*b06)*det;out[14]=(a31*b01-a30*b03-a32*b00)*det;out[15]=(a20*b03-a21*b01+a22*b00)*det;return out;}/**
  56561. * Calculates the determinant of a mat4
  56562. *
  56563. * @param {ReadonlyMat4} a the source matrix
  56564. * @returns {Number} determinant of a
  56565. */function determinant(a){var a00=a[0],a01=a[1],a02=a[2],a03=a[3];var a10=a[4],a11=a[5],a12=a[6],a13=a[7];var a20=a[8],a21=a[9],a22=a[10],a23=a[11];var a30=a[12],a31=a[13],a32=a[14],a33=a[15];var b00=a00*a11-a01*a10;var b01=a00*a12-a02*a10;var b02=a00*a13-a03*a10;var b03=a01*a12-a02*a11;var b04=a01*a13-a03*a11;var b05=a02*a13-a03*a12;var b06=a20*a31-a21*a30;var b07=a20*a32-a22*a30;var b08=a20*a33-a23*a30;var b09=a21*a32-a22*a31;var b10=a21*a33-a23*a31;var b11=a22*a33-a23*a32;// Calculate the determinant
  56566. return b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;}/**
  56567. * Multiplies two mat4s
  56568. *
  56569. * @param {mat4} out the receiving matrix
  56570. * @param {ReadonlyMat4} a the first operand
  56571. * @param {ReadonlyMat4} b the second operand
  56572. * @returns {mat4} out
  56573. */function multiply$1(out,a,b){var a00=a[0],a01=a[1],a02=a[2],a03=a[3];var a10=a[4],a11=a[5],a12=a[6],a13=a[7];var a20=a[8],a21=a[9],a22=a[10],a23=a[11];var a30=a[12],a31=a[13],a32=a[14],a33=a[15];// Cache only the current line of the second matrix
  56574. var b0=b[0],b1=b[1],b2=b[2],b3=b[3];out[0]=b0*a00+b1*a10+b2*a20+b3*a30;out[1]=b0*a01+b1*a11+b2*a21+b3*a31;out[2]=b0*a02+b1*a12+b2*a22+b3*a32;out[3]=b0*a03+b1*a13+b2*a23+b3*a33;b0=b[4];b1=b[5];b2=b[6];b3=b[7];out[4]=b0*a00+b1*a10+b2*a20+b3*a30;out[5]=b0*a01+b1*a11+b2*a21+b3*a31;out[6]=b0*a02+b1*a12+b2*a22+b3*a32;out[7]=b0*a03+b1*a13+b2*a23+b3*a33;b0=b[8];b1=b[9];b2=b[10];b3=b[11];out[8]=b0*a00+b1*a10+b2*a20+b3*a30;out[9]=b0*a01+b1*a11+b2*a21+b3*a31;out[10]=b0*a02+b1*a12+b2*a22+b3*a32;out[11]=b0*a03+b1*a13+b2*a23+b3*a33;b0=b[12];b1=b[13];b2=b[14];b3=b[15];out[12]=b0*a00+b1*a10+b2*a20+b3*a30;out[13]=b0*a01+b1*a11+b2*a21+b3*a31;out[14]=b0*a02+b1*a12+b2*a22+b3*a32;out[15]=b0*a03+b1*a13+b2*a23+b3*a33;return out;}/**
  56575. * Translate a mat4 by the given vector
  56576. *
  56577. * @param {mat4} out the receiving matrix
  56578. * @param {ReadonlyMat4} a the matrix to translate
  56579. * @param {ReadonlyVec3} v vector to translate by
  56580. * @returns {mat4} out
  56581. */function translate(out,a,v){var x=v[0],y=v[1],z=v[2];var a00,a01,a02,a03;var a10,a11,a12,a13;var a20,a21,a22,a23;if(a===out){out[12]=a[0]*x+a[4]*y+a[8]*z+a[12];out[13]=a[1]*x+a[5]*y+a[9]*z+a[13];out[14]=a[2]*x+a[6]*y+a[10]*z+a[14];out[15]=a[3]*x+a[7]*y+a[11]*z+a[15];}else {a00=a[0];a01=a[1];a02=a[2];a03=a[3];a10=a[4];a11=a[5];a12=a[6];a13=a[7];a20=a[8];a21=a[9];a22=a[10];a23=a[11];out[0]=a00;out[1]=a01;out[2]=a02;out[3]=a03;out[4]=a10;out[5]=a11;out[6]=a12;out[7]=a13;out[8]=a20;out[9]=a21;out[10]=a22;out[11]=a23;out[12]=a00*x+a10*y+a20*z+a[12];out[13]=a01*x+a11*y+a21*z+a[13];out[14]=a02*x+a12*y+a22*z+a[14];out[15]=a03*x+a13*y+a23*z+a[15];}return out;}/**
  56582. * Scales the mat4 by the dimensions in the given vec3 not using vectorization
  56583. *
  56584. * @param {mat4} out the receiving matrix
  56585. * @param {ReadonlyMat4} a the matrix to scale
  56586. * @param {ReadonlyVec3} v the vec3 to scale the matrix by
  56587. * @returns {mat4} out
  56588. **/function scale$2(out,a,v){var x=v[0],y=v[1],z=v[2];out[0]=a[0]*x;out[1]=a[1]*x;out[2]=a[2]*x;out[3]=a[3]*x;out[4]=a[4]*y;out[5]=a[5]*y;out[6]=a[6]*y;out[7]=a[7]*y;out[8]=a[8]*z;out[9]=a[9]*z;out[10]=a[10]*z;out[11]=a[11]*z;out[12]=a[12];out[13]=a[13];out[14]=a[14];out[15]=a[15];return out;}/**
  56589. * Rotates a mat4 by the given angle around the given axis
  56590. *
  56591. * @param {mat4} out the receiving matrix
  56592. * @param {ReadonlyMat4} a the matrix to rotate
  56593. * @param {Number} rad the angle to rotate the matrix by
  56594. * @param {ReadonlyVec3} axis the axis to rotate around
  56595. * @returns {mat4} out
  56596. */function rotate(out,a,rad,axis){var x=axis[0],y=axis[1],z=axis[2];var len=Math.hypot(x,y,z);var s,c,t;var a00,a01,a02,a03;var a10,a11,a12,a13;var a20,a21,a22,a23;var b00,b01,b02;var b10,b11,b12;var b20,b21,b22;if(len<EPSILON){return null;}len=1/len;x*=len;y*=len;z*=len;s=Math.sin(rad);c=Math.cos(rad);t=1-c;a00=a[0];a01=a[1];a02=a[2];a03=a[3];a10=a[4];a11=a[5];a12=a[6];a13=a[7];a20=a[8];a21=a[9];a22=a[10];a23=a[11];// Construct the elements of the rotation matrix
  56597. b00=x*x*t+c;b01=y*x*t+z*s;b02=z*x*t-y*s;b10=x*y*t-z*s;b11=y*y*t+c;b12=z*y*t+x*s;b20=x*z*t+y*s;b21=y*z*t-x*s;b22=z*z*t+c;// Perform rotation-specific matrix multiplication
  56598. out[0]=a00*b00+a10*b01+a20*b02;out[1]=a01*b00+a11*b01+a21*b02;out[2]=a02*b00+a12*b01+a22*b02;out[3]=a03*b00+a13*b01+a23*b02;out[4]=a00*b10+a10*b11+a20*b12;out[5]=a01*b10+a11*b11+a21*b12;out[6]=a02*b10+a12*b11+a22*b12;out[7]=a03*b10+a13*b11+a23*b12;out[8]=a00*b20+a10*b21+a20*b22;out[9]=a01*b20+a11*b21+a21*b22;out[10]=a02*b20+a12*b21+a22*b22;out[11]=a03*b20+a13*b21+a23*b22;if(a!==out){// If the source and destination differ, copy the unchanged last row
  56599. out[12]=a[12];out[13]=a[13];out[14]=a[14];out[15]=a[15];}return out;}/**
  56600. * Rotates a matrix by the given angle around the X axis
  56601. *
  56602. * @param {mat4} out the receiving matrix
  56603. * @param {ReadonlyMat4} a the matrix to rotate
  56604. * @param {Number} rad the angle to rotate the matrix by
  56605. * @returns {mat4} out
  56606. */function rotateX$1(out,a,rad){var s=Math.sin(rad);var c=Math.cos(rad);var a10=a[4];var a11=a[5];var a12=a[6];var a13=a[7];var a20=a[8];var a21=a[9];var a22=a[10];var a23=a[11];if(a!==out){// If the source and destination differ, copy the unchanged rows
  56607. out[0]=a[0];out[1]=a[1];out[2]=a[2];out[3]=a[3];out[12]=a[12];out[13]=a[13];out[14]=a[14];out[15]=a[15];}// Perform axis-specific matrix multiplication
  56608. out[4]=a10*c+a20*s;out[5]=a11*c+a21*s;out[6]=a12*c+a22*s;out[7]=a13*c+a23*s;out[8]=a20*c-a10*s;out[9]=a21*c-a11*s;out[10]=a22*c-a12*s;out[11]=a23*c-a13*s;return out;}/**
  56609. * Rotates a matrix by the given angle around the Y axis
  56610. *
  56611. * @param {mat4} out the receiving matrix
  56612. * @param {ReadonlyMat4} a the matrix to rotate
  56613. * @param {Number} rad the angle to rotate the matrix by
  56614. * @returns {mat4} out
  56615. */function rotateY$1(out,a,rad){var s=Math.sin(rad);var c=Math.cos(rad);var a00=a[0];var a01=a[1];var a02=a[2];var a03=a[3];var a20=a[8];var a21=a[9];var a22=a[10];var a23=a[11];if(a!==out){// If the source and destination differ, copy the unchanged rows
  56616. out[4]=a[4];out[5]=a[5];out[6]=a[6];out[7]=a[7];out[12]=a[12];out[13]=a[13];out[14]=a[14];out[15]=a[15];}// Perform axis-specific matrix multiplication
  56617. out[0]=a00*c-a20*s;out[1]=a01*c-a21*s;out[2]=a02*c-a22*s;out[3]=a03*c-a23*s;out[8]=a00*s+a20*c;out[9]=a01*s+a21*c;out[10]=a02*s+a22*c;out[11]=a03*s+a23*c;return out;}/**
  56618. * Rotates a matrix by the given angle around the Z axis
  56619. *
  56620. * @param {mat4} out the receiving matrix
  56621. * @param {ReadonlyMat4} a the matrix to rotate
  56622. * @param {Number} rad the angle to rotate the matrix by
  56623. * @returns {mat4} out
  56624. */function rotateZ$1(out,a,rad){var s=Math.sin(rad);var c=Math.cos(rad);var a00=a[0];var a01=a[1];var a02=a[2];var a03=a[3];var a10=a[4];var a11=a[5];var a12=a[6];var a13=a[7];if(a!==out){// If the source and destination differ, copy the unchanged last row
  56625. out[8]=a[8];out[9]=a[9];out[10]=a[10];out[11]=a[11];out[12]=a[12];out[13]=a[13];out[14]=a[14];out[15]=a[15];}// Perform axis-specific matrix multiplication
  56626. out[0]=a00*c+a10*s;out[1]=a01*c+a11*s;out[2]=a02*c+a12*s;out[3]=a03*c+a13*s;out[4]=a10*c-a00*s;out[5]=a11*c-a01*s;out[6]=a12*c-a02*s;out[7]=a13*c-a03*s;return out;}/**
  56627. * Returns the scaling factor component of a transformation
  56628. * matrix. If a matrix is built with fromRotationTranslationScale
  56629. * with a normalized Quaternion paramter, the returned vector will be
  56630. * the same as the scaling vector
  56631. * originally supplied.
  56632. * @param {vec3} out Vector to receive scaling factor component
  56633. * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
  56634. * @return {vec3} out
  56635. */function getScaling(out,mat){var m11=mat[0];var m12=mat[1];var m13=mat[2];var m21=mat[4];var m22=mat[5];var m23=mat[6];var m31=mat[8];var m32=mat[9];var m33=mat[10];out[0]=Math.hypot(m11,m12,m13);out[1]=Math.hypot(m21,m22,m23);out[2]=Math.hypot(m31,m32,m33);return out;}/**
  56636. * Calculates a 4x4 matrix from the given quaternion
  56637. *
  56638. * @param {mat4} out mat4 receiving operation result
  56639. * @param {ReadonlyQuat} q Quaternion to create matrix from
  56640. *
  56641. * @returns {mat4} out
  56642. */function fromQuat(out,q){var x=q[0],y=q[1],z=q[2],w=q[3];var x2=x+x;var y2=y+y;var z2=z+z;var xx=x*x2;var yx=y*x2;var yy=y*y2;var zx=z*x2;var zy=z*y2;var zz=z*z2;var wx=w*x2;var wy=w*y2;var wz=w*z2;out[0]=1-yy-zz;out[1]=yx+wz;out[2]=zx-wy;out[3]=0;out[4]=yx-wz;out[5]=1-xx-zz;out[6]=zy+wx;out[7]=0;out[8]=zx+wy;out[9]=zy-wx;out[10]=1-xx-yy;out[11]=0;out[12]=0;out[13]=0;out[14]=0;out[15]=1;return out;}/**
  56643. * Generates a frustum matrix with the given bounds
  56644. *
  56645. * @param {mat4} out mat4 frustum matrix will be written into
  56646. * @param {Number} left Left bound of the frustum
  56647. * @param {Number} right Right bound of the frustum
  56648. * @param {Number} bottom Bottom bound of the frustum
  56649. * @param {Number} top Top bound of the frustum
  56650. * @param {Number} near Near bound of the frustum
  56651. * @param {Number} far Far bound of the frustum
  56652. * @returns {mat4} out
  56653. */function frustum(out,left,right,bottom,top,near,far){var rl=1/(right-left);var tb=1/(top-bottom);var nf=1/(near-far);out[0]=near*2*rl;out[1]=0;out[2]=0;out[3]=0;out[4]=0;out[5]=near*2*tb;out[6]=0;out[7]=0;out[8]=(right+left)*rl;out[9]=(top+bottom)*tb;out[10]=(far+near)*nf;out[11]=-1;out[12]=0;out[13]=0;out[14]=far*near*2*nf;out[15]=0;return out;}/**
  56654. * Generates a perspective projection matrix with the given bounds.
  56655. * Passing null/undefined/no value for far will generate infinite projection matrix.
  56656. *
  56657. * @param {mat4} out mat4 frustum matrix will be written into
  56658. * @param {number} fovy Vertical field of view in radians
  56659. * @param {number} aspect Aspect ratio. typically viewport width/height
  56660. * @param {number} near Near bound of the frustum
  56661. * @param {number} far Far bound of the frustum, can be null or Infinity
  56662. * @returns {mat4} out
  56663. */function perspective(out,fovy,aspect,near,far){var f=1.0/Math.tan(fovy/2),nf;out[0]=f/aspect;out[1]=0;out[2]=0;out[3]=0;out[4]=0;out[5]=f;out[6]=0;out[7]=0;out[8]=0;out[9]=0;out[11]=-1;out[12]=0;out[13]=0;out[15]=0;if(far!=null&&far!==Infinity){nf=1/(near-far);out[10]=(far+near)*nf;out[14]=2*far*near*nf;}else {out[10]=-1;out[14]=-2*near;}return out;}/**
  56664. * Generates a orthogonal projection matrix with the given bounds
  56665. *
  56666. * @param {mat4} out mat4 frustum matrix will be written into
  56667. * @param {number} left Left bound of the frustum
  56668. * @param {number} right Right bound of the frustum
  56669. * @param {number} bottom Bottom bound of the frustum
  56670. * @param {number} top Top bound of the frustum
  56671. * @param {number} near Near bound of the frustum
  56672. * @param {number} far Far bound of the frustum
  56673. * @returns {mat4} out
  56674. */function ortho(out,left,right,bottom,top,near,far){var lr=1/(left-right);var bt=1/(bottom-top);var nf=1/(near-far);out[0]=-2*lr;out[1]=0;out[2]=0;out[3]=0;out[4]=0;out[5]=-2*bt;out[6]=0;out[7]=0;out[8]=0;out[9]=0;out[10]=2*nf;out[11]=0;out[12]=(left+right)*lr;out[13]=(top+bottom)*bt;out[14]=(far+near)*nf;out[15]=1;return out;}/**
  56675. * Generates a look-at matrix with the given eye position, focal point, and up axis.
  56676. * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
  56677. *
  56678. * @param {mat4} out mat4 frustum matrix will be written into
  56679. * @param {ReadonlyVec3} eye Position of the viewer
  56680. * @param {ReadonlyVec3} center Point the viewer is looking at
  56681. * @param {ReadonlyVec3} up vec3 pointing up
  56682. * @returns {mat4} out
  56683. */function lookAt(out,eye,center,up){var x0,x1,x2,y0,y1,y2,z0,z1,z2,len;var eyex=eye[0];var eyey=eye[1];var eyez=eye[2];var upx=up[0];var upy=up[1];var upz=up[2];var centerx=center[0];var centery=center[1];var centerz=center[2];if(Math.abs(eyex-centerx)<EPSILON&&Math.abs(eyey-centery)<EPSILON&&Math.abs(eyez-centerz)<EPSILON){return identity$1(out);}z0=eyex-centerx;z1=eyey-centery;z2=eyez-centerz;len=1/Math.hypot(z0,z1,z2);z0*=len;z1*=len;z2*=len;x0=upy*z2-upz*z1;x1=upz*z0-upx*z2;x2=upx*z1-upy*z0;len=Math.hypot(x0,x1,x2);if(!len){x0=0;x1=0;x2=0;}else {len=1/len;x0*=len;x1*=len;x2*=len;}y0=z1*x2-z2*x1;y1=z2*x0-z0*x2;y2=z0*x1-z1*x0;len=Math.hypot(y0,y1,y2);if(!len){y0=0;y1=0;y2=0;}else {len=1/len;y0*=len;y1*=len;y2*=len;}out[0]=x0;out[1]=y0;out[2]=z0;out[3]=0;out[4]=x1;out[5]=y1;out[6]=z1;out[7]=0;out[8]=x2;out[9]=y2;out[10]=z2;out[11]=0;out[12]=-(x0*eyex+x1*eyey+x2*eyez);out[13]=-(y0*eyex+y1*eyey+y2*eyez);out[14]=-(z0*eyex+z1*eyey+z2*eyez);out[15]=1;return out;}/**
  56684. * 4 Dimensional Vector
  56685. * @module vec4
  56686. */ /**
  56687. * Creates a new, empty vec4
  56688. *
  56689. * @returns {vec4} a new 4D vector
  56690. */function create$1(){var out=new ARRAY_TYPE(4);if(ARRAY_TYPE!=Float32Array){out[0]=0;out[1]=0;out[2]=0;out[3]=0;}return out;}/**
  56691. * Adds two vec4's
  56692. *
  56693. * @param {vec4} out the receiving vector
  56694. * @param {ReadonlyVec4} a the first operand
  56695. * @param {ReadonlyVec4} b the second operand
  56696. * @returns {vec4} out
  56697. */function add$1(out,a,b){out[0]=a[0]+b[0];out[1]=a[1]+b[1];out[2]=a[2]+b[2];out[3]=a[3]+b[3];return out;}/**
  56698. * Scales a vec4 by a scalar number
  56699. *
  56700. * @param {vec4} out the receiving vector
  56701. * @param {ReadonlyVec4} a the vector to scale
  56702. * @param {Number} b amount to scale the vector by
  56703. * @returns {vec4} out
  56704. */function scale$1(out,a,b){out[0]=a[0]*b;out[1]=a[1]*b;out[2]=a[2]*b;out[3]=a[3]*b;return out;}/**
  56705. * Calculates the length of a vec4
  56706. *
  56707. * @param {ReadonlyVec4} a vector to calculate length of
  56708. * @returns {Number} length of a
  56709. */function length$1(a){var x=a[0];var y=a[1];var z=a[2];var w=a[3];return Math.hypot(x,y,z,w);}/**
  56710. * Calculates the squared length of a vec4
  56711. *
  56712. * @param {ReadonlyVec4} a vector to calculate squared length of
  56713. * @returns {Number} squared length of a
  56714. */function squaredLength$1(a){var x=a[0];var y=a[1];var z=a[2];var w=a[3];return x*x+y*y+z*z+w*w;}/**
  56715. * Normalize a vec4
  56716. *
  56717. * @param {vec4} out the receiving vector
  56718. * @param {ReadonlyVec4} a vector to normalize
  56719. * @returns {vec4} out
  56720. */function normalize$1(out,a){var x=a[0];var y=a[1];var z=a[2];var w=a[3];var len=x*x+y*y+z*z+w*w;if(len>0){len=1/Math.sqrt(len);}out[0]=x*len;out[1]=y*len;out[2]=z*len;out[3]=w*len;return out;}/**
  56721. * Calculates the dot product of two vec4's
  56722. *
  56723. * @param {ReadonlyVec4} a the first operand
  56724. * @param {ReadonlyVec4} b the second operand
  56725. * @returns {Number} dot product of a and b
  56726. */function dot$1(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3];}/**
  56727. * Performs a linear interpolation between two vec4's
  56728. *
  56729. * @param {vec4} out the receiving vector
  56730. * @param {ReadonlyVec4} a the first operand
  56731. * @param {ReadonlyVec4} b the second operand
  56732. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  56733. * @returns {vec4} out
  56734. */function lerp$1(out,a,b,t){var ax=a[0];var ay=a[1];var az=a[2];var aw=a[3];out[0]=ax+t*(b[0]-ax);out[1]=ay+t*(b[1]-ay);out[2]=az+t*(b[2]-az);out[3]=aw+t*(b[3]-aw);return out;}/**
  56735. * Transforms the vec4 with a mat4.
  56736. *
  56737. * @param {vec4} out the receiving vector
  56738. * @param {ReadonlyVec4} a the vector to transform
  56739. * @param {ReadonlyMat4} m matrix to transform with
  56740. * @returns {vec4} out
  56741. */function transformMat4(out,a,m){var x=a[0],y=a[1],z=a[2],w=a[3];out[0]=m[0]*x+m[4]*y+m[8]*z+m[12]*w;out[1]=m[1]*x+m[5]*y+m[9]*z+m[13]*w;out[2]=m[2]*x+m[6]*y+m[10]*z+m[14]*w;out[3]=m[3]*x+m[7]*y+m[11]*z+m[15]*w;return out;}/**
  56742. * Transforms the vec4 with a quat
  56743. *
  56744. * @param {vec4} out the receiving vector
  56745. * @param {ReadonlyVec4} a the vector to transform
  56746. * @param {ReadonlyQuat} q quaternion to transform with
  56747. * @returns {vec4} out
  56748. */function transformQuat(out,a,q){var x=a[0],y=a[1],z=a[2];var qx=q[0],qy=q[1],qz=q[2],qw=q[3];// calculate quat * vec
  56749. var ix=qw*x+qy*z-qz*y;var iy=qw*y+qz*x-qx*z;var iz=qw*z+qx*y-qy*x;var iw=-qx*x-qy*y-qz*z;// calculate result * inverse quat
  56750. out[0]=ix*qw+iw*-qx+iy*-qz-iz*-qy;out[1]=iy*qw+iw*-qy+iz*-qx-ix*-qz;out[2]=iz*qw+iw*-qz+ix*-qy-iy*-qx;out[3]=a[3];return out;}/**
  56751. * Perform some operation over an array of vec4s.
  56752. *
  56753. * @param {Array} a the array of vectors to iterate over
  56754. * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
  56755. * @param {Number} offset Number of elements to skip at the beginning of the array
  56756. * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
  56757. * @param {Function} fn Function to call for each vector in the array
  56758. * @param {Object} [arg] additional argument to pass to fn
  56759. * @returns {Array} a
  56760. * @function
  56761. */(function(){var vec=create$1();return function(a,stride,offset,count,fn,arg){var i,l;if(!stride){stride=4;}if(!offset){offset=0;}if(count){l=Math.min(count*stride+offset,a.length);}else {l=a.length;}for(i=offset;i<l;i+=stride){vec[0]=a[i];vec[1]=a[i+1];vec[2]=a[i+2];vec[3]=a[i+3];fn(vec,vec,arg);a[i]=vec[0];a[i+1]=vec[1];a[i+2]=vec[2];a[i+3]=vec[3];}return a;};})();var IDENTITY=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);var ZERO=Object.freeze([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);var INDICES=Object.freeze({COL0ROW0:0,COL0ROW1:1,COL0ROW2:2,COL0ROW3:3,COL1ROW0:4,COL1ROW1:5,COL1ROW2:6,COL1ROW3:7,COL2ROW0:8,COL2ROW1:9,COL2ROW2:10,COL2ROW3:11,COL3ROW0:12,COL3ROW1:13,COL3ROW2:14,COL3ROW3:15});var constants={};class Matrix4$1 extends Matrix{static get IDENTITY(){constants.IDENTITY=constants.IDENTITY||Object.freeze(new Matrix4$1(IDENTITY));return constants.IDENTITY;}static get ZERO(){constants.ZERO=constants.ZERO||Object.freeze(new Matrix4$1(ZERO));return constants.ZERO;}get INDICES(){return INDICES;}get ELEMENTS(){return 16;}get RANK(){return 4;}constructor(array){super(-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0);if(arguments.length===1&&Array.isArray(array)){this.copy(array);}else {this.identity();}}copy(array){this[0]=array[0];this[1]=array[1];this[2]=array[2];this[3]=array[3];this[4]=array[4];this[5]=array[5];this[6]=array[6];this[7]=array[7];this[8]=array[8];this[9]=array[9];this[10]=array[10];this[11]=array[11];this[12]=array[12];this[13]=array[13];this[14]=array[14];this[15]=array[15];return this.check();}set(m00,m10,m20,m30,m01,m11,m21,m31,m02,m12,m22,m32,m03,m13,m23,m33){this[0]=m00;this[1]=m10;this[2]=m20;this[3]=m30;this[4]=m01;this[5]=m11;this[6]=m21;this[7]=m31;this[8]=m02;this[9]=m12;this[10]=m22;this[11]=m32;this[12]=m03;this[13]=m13;this[14]=m23;this[15]=m33;return this.check();}setRowMajor(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33){this[0]=m00;this[1]=m10;this[2]=m20;this[3]=m30;this[4]=m01;this[5]=m11;this[6]=m21;this[7]=m31;this[8]=m02;this[9]=m12;this[10]=m22;this[11]=m32;this[12]=m03;this[13]=m13;this[14]=m23;this[15]=m33;return this.check();}toRowMajor(result){result[0]=this[0];result[1]=this[4];result[2]=this[8];result[3]=this[12];result[4]=this[1];result[5]=this[5];result[6]=this[9];result[7]=this[13];result[8]=this[2];result[9]=this[6];result[10]=this[10];result[11]=this[14];result[12]=this[3];result[13]=this[7];result[14]=this[11];result[15]=this[15];return result;}identity(){return this.copy(IDENTITY);}fromQuaternion(q){fromQuat(this,q);return this.check();}frustum(_ref7){var{left,right,bottom,top,near,far}=_ref7;if(far===Infinity){Matrix4$1._computeInfinitePerspectiveOffCenter(this,left,right,bottom,top,near);}else {frustum(this,left,right,bottom,top,near,far);}return this.check();}static _computeInfinitePerspectiveOffCenter(result,left,right,bottom,top,near){var column0Row0=2.0*near/(right-left);var column1Row1=2.0*near/(top-bottom);var column2Row0=(right+left)/(right-left);var column2Row1=(top+bottom)/(top-bottom);var column2Row2=-1.0;var column2Row3=-1.0;var column3Row2=-2.0*near;result[0]=column0Row0;result[1]=0.0;result[2]=0.0;result[3]=0.0;result[4]=0.0;result[5]=column1Row1;result[6]=0.0;result[7]=0.0;result[8]=column2Row0;result[9]=column2Row1;result[10]=column2Row2;result[11]=column2Row3;result[12]=0.0;result[13]=0.0;result[14]=column3Row2;result[15]=0.0;return result;}lookAt(eye,center,up){if(arguments.length===1){({eye,center,up}=eye);}center=center||[0,0,0];up=up||[0,1,0];lookAt(this,eye,center,up);return this.check();}ortho(_ref8){var{left,right,bottom,top,near=0.1,far=500}=_ref8;ortho(this,left,right,bottom,top,near,far);return this.check();}orthographic(_ref9){var{fovy=45*Math.PI/180,aspect=1,focalDistance=1,near=0.1,far=500}=_ref9;if(fovy>Math.PI*2){throw Error('radians');}var halfY=fovy/2;var top=focalDistance*Math.tan(halfY);var right=top*aspect;return new Matrix4$1().ortho({left:-right,right,bottom:-top,top,near,far});}perspective(){var{fovy=undefined,fov=45*Math.PI/180,aspect=1,near=0.1,far=500}=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};fovy=fovy||fov;if(fovy>Math.PI*2){throw Error('radians');}perspective(this,fovy,aspect,near,far);return this.check();}determinant(){return determinant(this);}getScale(){var result=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[-0,-0,-0];result[0]=Math.sqrt(this[0]*this[0]+this[1]*this[1]+this[2]*this[2]);result[1]=Math.sqrt(this[4]*this[4]+this[5]*this[5]+this[6]*this[6]);result[2]=Math.sqrt(this[8]*this[8]+this[9]*this[9]+this[10]*this[10]);return result;}getTranslation(){var result=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[-0,-0,-0];result[0]=this[12];result[1]=this[13];result[2]=this[14];return result;}getRotation(){var result=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0];var scaleResult=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;var scale=this.getScale(scaleResult||[-0,-0,-0]);var inverseScale0=1/scale[0];var inverseScale1=1/scale[1];var inverseScale2=1/scale[2];result[0]=this[0]*inverseScale0;result[1]=this[1]*inverseScale1;result[2]=this[2]*inverseScale2;result[3]=0;result[4]=this[4]*inverseScale0;result[5]=this[5]*inverseScale1;result[6]=this[6]*inverseScale2;result[7]=0;result[8]=this[8]*inverseScale0;result[9]=this[9]*inverseScale1;result[10]=this[10]*inverseScale2;result[11]=0;result[12]=0;result[13]=0;result[14]=0;result[15]=1;return result;}getRotationMatrix3(){var result=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[-0,-0,-0,-0,-0,-0,-0,-0,-0];var scaleResult=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;var scale=this.getScale(scaleResult||[-0,-0,-0]);var inverseScale0=1/scale[0];var inverseScale1=1/scale[1];var inverseScale2=1/scale[2];result[0]=this[0]*inverseScale0;result[1]=this[1]*inverseScale1;result[2]=this[2]*inverseScale2;result[3]=this[4]*inverseScale0;result[4]=this[5]*inverseScale1;result[5]=this[6]*inverseScale2;result[6]=this[8]*inverseScale0;result[7]=this[9]*inverseScale1;result[8]=this[10]*inverseScale2;return result;}transpose(){transpose(this,this);return this.check();}invert(){invert$1(this,this);return this.check();}multiplyLeft(a){multiply$1(this,a,this);return this.check();}multiplyRight(a){multiply$1(this,this,a);return this.check();}rotateX(radians){rotateX$1(this,this,radians);return this.check();}rotateY(radians){rotateY$1(this,this,radians);return this.check();}rotateZ(radians){rotateZ$1(this,this,radians);return this.check();}rotateXYZ(_ref10){var[rx,ry,rz]=_ref10;return this.rotateX(rx).rotateY(ry).rotateZ(rz);}rotateAxis(radians,axis){rotate(this,this,radians,axis);return this.check();}scale(factor){if(Array.isArray(factor)){scale$2(this,this,factor);}else {scale$2(this,this,[factor,factor,factor]);}return this.check();}translate(vec){translate(this,this,vec);return this.check();}transform(vector,result){if(vector.length===4){result=transformMat4(result||[-0,-0,-0,-0],vector,this);checkVector(result,4);return result;}return this.transformAsPoint(vector,result);}transformAsPoint(vector,result){var{length}=vector;switch(length){case 2:result=transformMat4$2(result||[-0,-0],vector,this);break;case 3:result=transformMat4$1(result||[-0,-0,-0],vector,this);break;default:throw new Error('Illegal vector');}checkVector(result,vector.length);return result;}transformAsVector(vector,result){switch(vector.length){case 2:result=vec2_transformMat4AsVector(result||[-0,-0],vector,this);break;case 3:result=vec3_transformMat4AsVector(result||[-0,-0,-0],vector,this);break;default:throw new Error('Illegal vector');}checkVector(result,vector.length);return result;}makeRotationX(radians){return this.identity().rotateX(radians);}makeTranslation(x,y,z){return this.identity().translate([x,y,z]);}transformPoint(vector,result){deprecated('Matrix4.transformPoint','3.0');return this.transformAsPoint(vector,result);}transformVector(vector,result){deprecated('Matrix4.transformVector','3.0');return this.transformAsPoint(vector,result);}transformDirection(vector,result){deprecated('Matrix4.transformDirection','3.0');return this.transformAsVector(vector,result);}}/**
  56762. * Quaternion
  56763. * @module quat
  56764. */ /**
  56765. * Creates a new identity quat
  56766. *
  56767. * @returns {quat} a new quaternion
  56768. */function create(){var out=new ARRAY_TYPE(4);if(ARRAY_TYPE!=Float32Array){out[0]=0;out[1]=0;out[2]=0;}out[3]=1;return out;}/**
  56769. * Set a quat to the identity quaternion
  56770. *
  56771. * @param {quat} out the receiving quaternion
  56772. * @returns {quat} out
  56773. */function identity(out){out[0]=0;out[1]=0;out[2]=0;out[3]=1;return out;}/**
  56774. * Sets a quat from the given angle and rotation axis,
  56775. * then returns it.
  56776. *
  56777. * @param {quat} out the receiving quaternion
  56778. * @param {ReadonlyVec3} axis the axis around which to rotate
  56779. * @param {Number} rad the angle in radians
  56780. * @returns {quat} out
  56781. **/function setAxisAngle(out,axis,rad){rad=rad*0.5;var s=Math.sin(rad);out[0]=s*axis[0];out[1]=s*axis[1];out[2]=s*axis[2];out[3]=Math.cos(rad);return out;}/**
  56782. * Multiplies two quat's
  56783. *
  56784. * @param {quat} out the receiving quaternion
  56785. * @param {ReadonlyQuat} a the first operand
  56786. * @param {ReadonlyQuat} b the second operand
  56787. * @returns {quat} out
  56788. */function multiply(out,a,b){var ax=a[0],ay=a[1],az=a[2],aw=a[3];var bx=b[0],by=b[1],bz=b[2],bw=b[3];out[0]=ax*bw+aw*bx+ay*bz-az*by;out[1]=ay*bw+aw*by+az*bx-ax*bz;out[2]=az*bw+aw*bz+ax*by-ay*bx;out[3]=aw*bw-ax*bx-ay*by-az*bz;return out;}/**
  56789. * Rotates a quaternion by the given angle about the X axis
  56790. *
  56791. * @param {quat} out quat receiving operation result
  56792. * @param {ReadonlyQuat} a quat to rotate
  56793. * @param {number} rad angle (in radians) to rotate
  56794. * @returns {quat} out
  56795. */function rotateX(out,a,rad){rad*=0.5;var ax=a[0],ay=a[1],az=a[2],aw=a[3];var bx=Math.sin(rad),bw=Math.cos(rad);out[0]=ax*bw+aw*bx;out[1]=ay*bw+az*bx;out[2]=az*bw-ay*bx;out[3]=aw*bw-ax*bx;return out;}/**
  56796. * Rotates a quaternion by the given angle about the Y axis
  56797. *
  56798. * @param {quat} out quat receiving operation result
  56799. * @param {ReadonlyQuat} a quat to rotate
  56800. * @param {number} rad angle (in radians) to rotate
  56801. * @returns {quat} out
  56802. */function rotateY(out,a,rad){rad*=0.5;var ax=a[0],ay=a[1],az=a[2],aw=a[3];var by=Math.sin(rad),bw=Math.cos(rad);out[0]=ax*bw-az*by;out[1]=ay*bw+aw*by;out[2]=az*bw+ax*by;out[3]=aw*bw-ay*by;return out;}/**
  56803. * Rotates a quaternion by the given angle about the Z axis
  56804. *
  56805. * @param {quat} out quat receiving operation result
  56806. * @param {ReadonlyQuat} a quat to rotate
  56807. * @param {number} rad angle (in radians) to rotate
  56808. * @returns {quat} out
  56809. */function rotateZ(out,a,rad){rad*=0.5;var ax=a[0],ay=a[1],az=a[2],aw=a[3];var bz=Math.sin(rad),bw=Math.cos(rad);out[0]=ax*bw+ay*bz;out[1]=ay*bw-ax*bz;out[2]=az*bw+aw*bz;out[3]=aw*bw-az*bz;return out;}/**
  56810. * Calculates the W component of a quat from the X, Y, and Z components.
  56811. * Assumes that quaternion is 1 unit in length.
  56812. * Any existing W component will be ignored.
  56813. *
  56814. * @param {quat} out the receiving quaternion
  56815. * @param {ReadonlyQuat} a quat to calculate W component of
  56816. * @returns {quat} out
  56817. */function calculateW(out,a){var x=a[0],y=a[1],z=a[2];out[0]=x;out[1]=y;out[2]=z;out[3]=Math.sqrt(Math.abs(1.0-x*x-y*y-z*z));return out;}/**
  56818. * Performs a spherical linear interpolation between two quat
  56819. *
  56820. * @param {quat} out the receiving quaternion
  56821. * @param {ReadonlyQuat} a the first operand
  56822. * @param {ReadonlyQuat} b the second operand
  56823. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  56824. * @returns {quat} out
  56825. */function slerp(out,a,b,t){// benchmarks:
  56826. // http://jsperf.com/quaternion-slerp-implementations
  56827. var ax=a[0],ay=a[1],az=a[2],aw=a[3];var bx=b[0],by=b[1],bz=b[2],bw=b[3];var omega,cosom,sinom,scale0,scale1;// calc cosine
  56828. cosom=ax*bx+ay*by+az*bz+aw*bw;// adjust signs (if necessary)
  56829. if(cosom<0.0){cosom=-cosom;bx=-bx;by=-by;bz=-bz;bw=-bw;}// calculate coefficients
  56830. if(1.0-cosom>EPSILON){// standard case (slerp)
  56831. omega=Math.acos(cosom);sinom=Math.sin(omega);scale0=Math.sin((1.0-t)*omega)/sinom;scale1=Math.sin(t*omega)/sinom;}else {// "from" and "to" quaternions are very close
  56832. // ... so we can do a linear interpolation
  56833. scale0=1.0-t;scale1=t;}// calculate final values
  56834. out[0]=scale0*ax+scale1*bx;out[1]=scale0*ay+scale1*by;out[2]=scale0*az+scale1*bz;out[3]=scale0*aw+scale1*bw;return out;}/**
  56835. * Calculates the inverse of a quat
  56836. *
  56837. * @param {quat} out the receiving quaternion
  56838. * @param {ReadonlyQuat} a quat to calculate inverse of
  56839. * @returns {quat} out
  56840. */function invert(out,a){var a0=a[0],a1=a[1],a2=a[2],a3=a[3];var dot=a0*a0+a1*a1+a2*a2+a3*a3;var invDot=dot?1.0/dot:0;// TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
  56841. out[0]=-a0*invDot;out[1]=-a1*invDot;out[2]=-a2*invDot;out[3]=a3*invDot;return out;}/**
  56842. * Calculates the conjugate of a quat
  56843. * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
  56844. *
  56845. * @param {quat} out the receiving quaternion
  56846. * @param {ReadonlyQuat} a quat to calculate conjugate of
  56847. * @returns {quat} out
  56848. */function conjugate(out,a){out[0]=-a[0];out[1]=-a[1];out[2]=-a[2];out[3]=a[3];return out;}/**
  56849. * Creates a quaternion from the given 3x3 rotation matrix.
  56850. *
  56851. * NOTE: The resultant quaternion is not normalized, so you should be sure
  56852. * to renormalize the quaternion yourself where necessary.
  56853. *
  56854. * @param {quat} out the receiving quaternion
  56855. * @param {ReadonlyMat3} m rotation matrix
  56856. * @returns {quat} out
  56857. * @function
  56858. */function fromMat3(out,m){// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
  56859. // article "Quaternion Calculus and Fast Animation".
  56860. var fTrace=m[0]+m[4]+m[8];var fRoot;if(fTrace>0.0){// |w| > 1/2, may as well choose w > 1/2
  56861. fRoot=Math.sqrt(fTrace+1.0);// 2w
  56862. out[3]=0.5*fRoot;fRoot=0.5/fRoot;// 1/(4w)
  56863. out[0]=(m[5]-m[7])*fRoot;out[1]=(m[6]-m[2])*fRoot;out[2]=(m[1]-m[3])*fRoot;}else {// |w| <= 1/2
  56864. var i=0;if(m[4]>m[0])i=1;if(m[8]>m[i*3+i])i=2;var j=(i+1)%3;var k=(i+2)%3;fRoot=Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k]+1.0);out[i]=0.5*fRoot;fRoot=0.5/fRoot;out[3]=(m[j*3+k]-m[k*3+j])*fRoot;out[j]=(m[j*3+i]+m[i*3+j])*fRoot;out[k]=(m[k*3+i]+m[i*3+k])*fRoot;}return out;}/**
  56865. * Adds two quat's
  56866. *
  56867. * @param {quat} out the receiving quaternion
  56868. * @param {ReadonlyQuat} a the first operand
  56869. * @param {ReadonlyQuat} b the second operand
  56870. * @returns {quat} out
  56871. * @function
  56872. */var add=add$1;/**
  56873. * Scales a quat by a scalar number
  56874. *
  56875. * @param {quat} out the receiving vector
  56876. * @param {ReadonlyQuat} a the vector to scale
  56877. * @param {Number} b amount to scale the vector by
  56878. * @returns {quat} out
  56879. * @function
  56880. */var scale=scale$1;/**
  56881. * Calculates the dot product of two quat's
  56882. *
  56883. * @param {ReadonlyQuat} a the first operand
  56884. * @param {ReadonlyQuat} b the second operand
  56885. * @returns {Number} dot product of a and b
  56886. * @function
  56887. */var dot=dot$1;/**
  56888. * Performs a linear interpolation between two quat's
  56889. *
  56890. * @param {quat} out the receiving quaternion
  56891. * @param {ReadonlyQuat} a the first operand
  56892. * @param {ReadonlyQuat} b the second operand
  56893. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  56894. * @returns {quat} out
  56895. * @function
  56896. */var lerp$2=lerp$1;/**
  56897. * Calculates the length of a quat
  56898. *
  56899. * @param {ReadonlyQuat} a vector to calculate length of
  56900. * @returns {Number} length of a
  56901. */var length=length$1;/**
  56902. * Calculates the squared length of a quat
  56903. *
  56904. * @param {ReadonlyQuat} a vector to calculate squared length of
  56905. * @returns {Number} squared length of a
  56906. * @function
  56907. */var squaredLength=squaredLength$1;/**
  56908. * Normalize a quat
  56909. *
  56910. * @param {quat} out the receiving quaternion
  56911. * @param {ReadonlyQuat} a quaternion to normalize
  56912. * @returns {quat} out
  56913. * @function
  56914. */var normalize=normalize$1;/**
  56915. * Sets a quaternion to represent the shortest rotation from one
  56916. * vector to another.
  56917. *
  56918. * Both vectors are assumed to be unit length.
  56919. *
  56920. * @param {quat} out the receiving quaternion.
  56921. * @param {ReadonlyVec3} a the initial vector
  56922. * @param {ReadonlyVec3} b the destination vector
  56923. * @returns {quat} out
  56924. */var rotationTo=function(){var tmpvec3=create$3();var xUnitVec3=fromValues(1,0,0);var yUnitVec3=fromValues(0,1,0);return function(out,a,b){var dot=dot$2(a,b);if(dot<-0.999999){cross(tmpvec3,xUnitVec3,a);if(len(tmpvec3)<0.000001)cross(tmpvec3,yUnitVec3,a);normalize$2(tmpvec3,tmpvec3);setAxisAngle(out,tmpvec3,Math.PI);return out;}else if(dot>0.999999){out[0]=0;out[1]=0;out[2]=0;out[3]=1;return out;}else {cross(tmpvec3,a,b);out[0]=tmpvec3[0];out[1]=tmpvec3[1];out[2]=tmpvec3[2];out[3]=1+dot;return normalize(out,out);}};}();/**
  56925. * Performs a spherical linear interpolation with two control points
  56926. *
  56927. * @param {quat} out the receiving quaternion
  56928. * @param {ReadonlyQuat} a the first operand
  56929. * @param {ReadonlyQuat} b the second operand
  56930. * @param {ReadonlyQuat} c the third operand
  56931. * @param {ReadonlyQuat} d the fourth operand
  56932. * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
  56933. * @returns {quat} out
  56934. */(function(){var temp1=create();var temp2=create();return function(out,a,b,c,d,t){slerp(temp1,a,d,t);slerp(temp2,b,c,t);slerp(out,temp1,temp2,2*t*(1-t));return out;};})();/**
  56935. * Sets the specified quaternion with values corresponding to the given
  56936. * axes. Each axis is a vec3 and is expected to be unit length and
  56937. * perpendicular to all other specified axes.
  56938. *
  56939. * @param {ReadonlyVec3} view the vector representing the viewing direction
  56940. * @param {ReadonlyVec3} right the vector representing the local "right" direction
  56941. * @param {ReadonlyVec3} up the vector representing the local "up" direction
  56942. * @returns {quat} out
  56943. */(function(){var matr=create$2();return function(out,view,right,up){matr[0]=right[0];matr[3]=right[1];matr[6]=right[2];matr[1]=up[0];matr[4]=up[1];matr[7]=up[2];matr[2]=-view[0];matr[5]=-view[1];matr[8]=-view[2];return normalize(out,fromMat3(out,matr));};})();var IDENTITY_QUATERNION=[0,0,0,1];class Quaternion$1 extends MathArray{constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var w=arguments.length>3&&arguments[3]!==undefined?arguments[3]:1;super(-0,-0,-0,-0);if(Array.isArray(x)&&arguments.length===1){this.copy(x);}else {this.set(x,y,z,w);}}copy(array){this[0]=array[0];this[1]=array[1];this[2]=array[2];this[3]=array[3];return this.check();}set(x,y,z,w){this[0]=x;this[1]=y;this[2]=z;this[3]=w;return this.check();}fromMatrix3(m){fromMat3(this,m);return this.check();}identity(){identity(this);return this.check();}fromAxisRotation(axis,rad){setAxisAngle(this,axis,rad);return this.check();}setAxisAngle(axis,rad){return this.fromAxisRotation(axis,rad);}get ELEMENTS(){return 4;}get x(){return this[0];}set x(value){this[0]=checkNumber(value);}get y(){return this[1];}set y(value){this[1]=checkNumber(value);}get z(){return this[2];}set z(value){this[2]=checkNumber(value);}get w(){return this[3];}set w(value){this[3]=checkNumber(value);}len(){return length(this);}lengthSquared(){return squaredLength(this);}dot(a,b){if(b!==undefined){throw new Error('Quaternion.dot only takes one argument');}return dot(this,a);}rotationTo(vectorA,vectorB){rotationTo(this,vectorA,vectorB);return this.check();}add(a,b){if(b!==undefined){throw new Error('Quaternion.add only takes one argument');}add(this,this,a);return this.check();}calculateW(){calculateW(this,this);return this.check();}conjugate(){conjugate(this,this);return this.check();}invert(){invert(this,this);return this.check();}lerp(a,b,t){lerp$2(this,a,b,t);return this.check();}multiplyRight(a,b){assert$4(!b);multiply(this,this,a);return this.check();}multiplyLeft(a,b){assert$4(!b);multiply(this,a,this);return this.check();}normalize(){var length=this.len();var l=length>0?1/length:0;this[0]=this[0]*l;this[1]=this[1]*l;this[2]=this[2]*l;this[3]=this[3]*l;if(length===0){this[3]=1;}return this.check();}rotateX(rad){rotateX(this,this,rad);return this.check();}rotateY(rad){rotateY(this,this,rad);return this.check();}rotateZ(rad){rotateZ(this,this,rad);return this.check();}scale(b){scale(this,this,b);return this.check();}slerp(start,target,ratio){switch(arguments.length){case 1:({start=IDENTITY_QUATERNION,target,ratio}=arguments[0]);break;case 2:[target,ratio]=arguments;start=this;break;}slerp(this,start,target,ratio);return this.check();}transformVector4(vector){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:vector;transformQuat(result,vector,this);return checkVector(result,4);}lengthSq(){return this.lengthSquared();}setFromAxisAngle(axis,rad){return this.setAxisAngle(axis,rad);}premultiply(a,b){return this.multiplyLeft(a,b);}multiply(a,b){return this.multiplyRight(a,b);}}var _MathUtils={EPSILON1:1e-1,EPSILON2:1e-2,EPSILON3:1e-3,EPSILON4:1e-4,EPSILON5:1e-5,EPSILON6:1e-6,EPSILON7:1e-7,EPSILON8:1e-8,EPSILON9:1e-9,EPSILON10:1e-10,EPSILON11:1e-11,EPSILON12:1e-12,EPSILON13:1e-13,EPSILON14:1e-14,EPSILON15:1e-15,EPSILON16:1e-16,EPSILON17:1e-17,EPSILON18:1e-18,EPSILON19:1e-19,EPSILON20:1e-20,PI_OVER_TWO:Math.PI/2,PI_OVER_FOUR:Math.PI/4,PI_OVER_SIX:Math.PI/6,TWO_PI:Math.PI*2};var WGS84_RADIUS_X$1=6378137.0;var WGS84_RADIUS_Y$1=6378137.0;var WGS84_RADIUS_Z$1=6356752.3142451793;var noop$2=x=>x;var scratchVector$6=new Vector3$1();function fromCartographic(cartographic,result){var map=arguments.length>2&&arguments[2]!==undefined?arguments[2]:noop$2;if(isArray(cartographic)){result[0]=map(cartographic[0]);result[1]=map(cartographic[1]);result[2]=cartographic[2];}else if('longitude'in cartographic){result[0]=map(cartographic.longitude);result[1]=map(cartographic.latitude);result[2]=cartographic.height;}else {result[0]=map(cartographic.x);result[1]=map(cartographic.y);result[2]=cartographic.z;}return result;}function fromCartographicToRadians(cartographic){var vector=arguments.length>1&&arguments[1]!==undefined?arguments[1]:scratchVector$6;return fromCartographic(cartographic,vector,config$2._cartographicRadians?noop$2:toRadians);}function toCartographic(vector,cartographic){var map=arguments.length>2&&arguments[2]!==undefined?arguments[2]:noop$2;if(isArray(cartographic)){cartographic[0]=map(vector[0]);cartographic[1]=map(vector[1]);cartographic[2]=vector[2];}else if('longitude'in cartographic){cartographic.longitude=map(vector[0]);cartographic.latitude=map(vector[1]);cartographic.height=vector[2];}else {cartographic.x=map(vector[0]);cartographic.y=map(vector[1]);cartographic.z=vector[2];}return cartographic;}function toCartographicFromRadians(vector,cartographic){return toCartographic(vector,cartographic,config$2._cartographicRadians?noop$2:toDegrees);}var scratchVector$5=new Vector3$1();var scaleToGeodeticSurfaceIntersection=new Vector3$1();var scaleToGeodeticSurfaceGradient=new Vector3$1();function scaleToGeodeticSurface(cartesian,ellipsoid){var result=arguments.length>2&&arguments[2]!==undefined?arguments[2]:new Vector3$1();var{oneOverRadii,oneOverRadiiSquared,centerToleranceSquared}=ellipsoid;scratchVector$5.from(cartesian);var positionX=cartesian.x;var positionY=cartesian.y;var positionZ=cartesian.z;var oneOverRadiiX=oneOverRadii.x;var oneOverRadiiY=oneOverRadii.y;var oneOverRadiiZ=oneOverRadii.z;var x2=positionX*positionX*oneOverRadiiX*oneOverRadiiX;var y2=positionY*positionY*oneOverRadiiY*oneOverRadiiY;var z2=positionZ*positionZ*oneOverRadiiZ*oneOverRadiiZ;var squaredNorm=x2+y2+z2;var ratio=Math.sqrt(1.0/squaredNorm);if(!Number.isFinite(ratio)){return undefined;}var intersection=scaleToGeodeticSurfaceIntersection;intersection.copy(cartesian).scale(ratio);if(squaredNorm<centerToleranceSquared){return intersection.to(result);}var oneOverRadiiSquaredX=oneOverRadiiSquared.x;var oneOverRadiiSquaredY=oneOverRadiiSquared.y;var oneOverRadiiSquaredZ=oneOverRadiiSquared.z;var gradient=scaleToGeodeticSurfaceGradient;gradient.set(intersection.x*oneOverRadiiSquaredX*2.0,intersection.y*oneOverRadiiSquaredY*2.0,intersection.z*oneOverRadiiSquaredZ*2.0);var lambda=(1.0-ratio)*cartesian.len()/(0.5*gradient.len());var correction=0.0;var xMultiplier;var yMultiplier;var zMultiplier;var func;do{lambda-=correction;xMultiplier=1.0/(1.0+lambda*oneOverRadiiSquaredX);yMultiplier=1.0/(1.0+lambda*oneOverRadiiSquaredY);zMultiplier=1.0/(1.0+lambda*oneOverRadiiSquaredZ);var xMultiplier2=xMultiplier*xMultiplier;var yMultiplier2=yMultiplier*yMultiplier;var zMultiplier2=zMultiplier*zMultiplier;var xMultiplier3=xMultiplier2*xMultiplier;var yMultiplier3=yMultiplier2*yMultiplier;var zMultiplier3=zMultiplier2*zMultiplier;func=x2*xMultiplier2+y2*yMultiplier2+z2*zMultiplier2-1.0;var denominator=x2*xMultiplier3*oneOverRadiiSquaredX+y2*yMultiplier3*oneOverRadiiSquaredY+z2*zMultiplier3*oneOverRadiiSquaredZ;var derivative=-2.0*denominator;correction=func/derivative;}while(Math.abs(func)>_MathUtils.EPSILON12);return scratchVector$5.scale([xMultiplier,yMultiplier,zMultiplier]).to(result);}var EPSILON14=1e-14;var scratchOrigin=new Vector3$1();var VECTOR_PRODUCT_LOCAL_FRAME={up:{south:'east',north:'west',west:'south',east:'north'},down:{south:'west',north:'east',west:'north',east:'south'},south:{up:'west',down:'east',west:'down',east:'up'},north:{up:'east',down:'west',west:'up',east:'down'},west:{up:'north',down:'south',north:'down',south:'up'},east:{up:'south',down:'north',north:'up',south:'down'}};var degeneratePositionLocalFrame={north:[-1,0,0],east:[0,1,0],up:[0,0,1],south:[1,0,0],west:[0,-1,0],down:[0,0,-1]};var scratchAxisVectors={east:new Vector3$1(),north:new Vector3$1(),up:new Vector3$1(),west:new Vector3$1(),south:new Vector3$1(),down:new Vector3$1()};var scratchVector1=new Vector3$1();var scratchVector2$1=new Vector3$1();var scratchVector3$1=new Vector3$1();function localFrameToFixedFrame(ellipsoid,firstAxis,secondAxis,thirdAxis,cartesianOrigin,result){var thirdAxisInferred=VECTOR_PRODUCT_LOCAL_FRAME[firstAxis]&&VECTOR_PRODUCT_LOCAL_FRAME[firstAxis][secondAxis];assert$4(thirdAxisInferred&&(!thirdAxis||thirdAxis===thirdAxisInferred));var firstAxisVector;var secondAxisVector;var thirdAxisVector;var origin=scratchOrigin.copy(cartesianOrigin);var atPole=equals$1(origin.x,0.0,EPSILON14)&&equals$1(origin.y,0.0,EPSILON14);if(atPole){var sign=Math.sign(origin.z);firstAxisVector=scratchVector1.fromArray(degeneratePositionLocalFrame[firstAxis]);if(firstAxis!=='east'&&firstAxis!=='west'){firstAxisVector.scale(sign);}secondAxisVector=scratchVector2$1.fromArray(degeneratePositionLocalFrame[secondAxis]);if(secondAxis!=='east'&&secondAxis!=='west'){secondAxisVector.scale(sign);}thirdAxisVector=scratchVector3$1.fromArray(degeneratePositionLocalFrame[thirdAxis]);if(thirdAxis!=='east'&&thirdAxis!=='west'){thirdAxisVector.scale(sign);}}else {var{up,east,north}=scratchAxisVectors;east.set(-origin.y,origin.x,0.0).normalize();ellipsoid.geodeticSurfaceNormal(origin,up);north.copy(up).cross(east);var{down,west,south}=scratchAxisVectors;down.copy(up).scale(-1);west.copy(east).scale(-1);south.copy(north).scale(-1);firstAxisVector=scratchAxisVectors[firstAxis];secondAxisVector=scratchAxisVectors[secondAxis];thirdAxisVector=scratchAxisVectors[thirdAxis];}result[0]=firstAxisVector.x;result[1]=firstAxisVector.y;result[2]=firstAxisVector.z;result[3]=0.0;result[4]=secondAxisVector.x;result[5]=secondAxisVector.y;result[6]=secondAxisVector.z;result[7]=0.0;result[8]=thirdAxisVector.x;result[9]=thirdAxisVector.y;result[10]=thirdAxisVector.z;result[11]=0.0;result[12]=origin.x;result[13]=origin.y;result[14]=origin.z;result[15]=1.0;return result;}var scratchVector$4=new Vector3$1();var scratchNormal$2=new Vector3$1();var scratchK=new Vector3$1();var scratchPosition$2=new Vector3$1();var scratchHeight=new Vector3$1();var scratchCartesian=new Vector3$1();var wgs84;class Ellipsoid{static get WGS84(){wgs84=wgs84||new Ellipsoid(WGS84_RADIUS_X$1,WGS84_RADIUS_Y$1,WGS84_RADIUS_Z$1);return wgs84;}constructor(){var x=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0.0;var y=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0.0;var z=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0.0;assert$4(x>=0.0);assert$4(y>=0.0);assert$4(z>=0.0);this.radii=new Vector3$1(x,y,z);this.radiiSquared=new Vector3$1(x*x,y*y,z*z);this.radiiToTheFourth=new Vector3$1(x*x*x*x,y*y*y*y,z*z*z*z);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);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));this.minimumRadius=Math.min(x,y,z);this.maximumRadius=Math.max(x,y,z);this.centerToleranceSquared=_MathUtils.EPSILON1;if(this.radiiSquared.z!==0){this.squaredXOverSquaredZ=this.radiiSquared.x/this.radiiSquared.z;}Object.freeze(this);}equals(right){return this===right||Boolean(right&&this.radii.equals(right.radii));}toString(){return this.radii.toString();}cartographicToCartesian(cartographic){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];var normal=scratchNormal$2;var k=scratchK;var[,,height]=cartographic;this.geodeticSurfaceNormalCartographic(cartographic,normal);k.copy(this.radiiSquared).scale(normal);var gamma=Math.sqrt(normal.dot(k));k.scale(1/gamma);normal.scale(height);k.add(normal);return k.to(result);}cartesianToCartographic(cartesian){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];scratchCartesian.from(cartesian);var point=this.scaleToGeodeticSurface(scratchCartesian,scratchPosition$2);if(!point){return undefined;}var normal=this.geodeticSurfaceNormal(point,scratchNormal$2);var h=scratchHeight;h.copy(scratchCartesian).subtract(point);var longitude=Math.atan2(normal.y,normal.x);var latitude=Math.asin(normal.z);var height=Math.sign(dot$2(h,scratchCartesian))*length$2(h);return toCartographicFromRadians([longitude,latitude,height],result);}eastNorthUpToFixedFrame(origin){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:new Matrix4$1();return localFrameToFixedFrame(this,'east','north','up',origin,result);}localFrameToFixedFrame(firstAxis,secondAxis,thirdAxis,origin){var result=arguments.length>4&&arguments[4]!==undefined?arguments[4]:new Matrix4$1();return localFrameToFixedFrame(this,firstAxis,secondAxis,thirdAxis,origin,result);}geocentricSurfaceNormal(cartesian){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];return scratchVector$4.from(cartesian).normalize().to(result);}geodeticSurfaceNormalCartographic(cartographic){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];var cartographicVectorRadians=fromCartographicToRadians(cartographic);var longitude=cartographicVectorRadians[0];var latitude=cartographicVectorRadians[1];var cosLatitude=Math.cos(latitude);scratchVector$4.set(cosLatitude*Math.cos(longitude),cosLatitude*Math.sin(longitude),Math.sin(latitude)).normalize();return scratchVector$4.to(result);}geodeticSurfaceNormal(cartesian){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];return scratchVector$4.from(cartesian).scale(this.oneOverRadiiSquared).normalize().to(result);}scaleToGeodeticSurface(cartesian,result){return scaleToGeodeticSurface(cartesian,this,result);}scaleToGeocentricSurface(cartesian){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];scratchPosition$2.from(cartesian);var positionX=scratchPosition$2.x;var positionY=scratchPosition$2.y;var positionZ=scratchPosition$2.z;var oneOverRadiiSquared=this.oneOverRadiiSquared;var beta=1.0/Math.sqrt(positionX*positionX*oneOverRadiiSquared.x+positionY*positionY*oneOverRadiiSquared.y+positionZ*positionZ*oneOverRadiiSquared.z);return scratchPosition$2.multiplyScalar(beta).to(result);}transformPositionToScaledSpace(position){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];return scratchPosition$2.from(position).scale(this.oneOverRadii).to(result);}transformPositionFromScaledSpace(position){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];return scratchPosition$2.from(position).scale(this.radii).to(result);}getSurfaceNormalIntersectionWithZAxis(position){var buffer=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0.0;var result=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[0,0,0];assert$4(equals$1(this.radii.x,this.radii.y,_MathUtils.EPSILON15));assert$4(this.radii.z>0);scratchPosition$2.from(position);var z=scratchPosition$2.z*(1-this.squaredXOverSquaredZ);if(Math.abs(z)>=this.radii.z-buffer){return undefined;}return scratchPosition$2.set(0.0,0.0,z).to(result);}}class DoublyLinkedListNode{constructor(item,previous,next){_defineProperty$1(this,"item",void 0);_defineProperty$1(this,"previous",void 0);_defineProperty$1(this,"next",void 0);this.item=item;this.previous=previous;this.next=next;}}class DoublyLinkedList{constructor(){_defineProperty$1(this,"head",null);_defineProperty$1(this,"tail",null);_defineProperty$1(this,"_length",0);}get length(){return this._length;}add(item){var node=new DoublyLinkedListNode(item,this.tail,null);if(this.tail){this.tail.next=node;this.tail=node;}else {this.head=node;this.tail=node;}++this._length;return node;}remove(node){if(!node){return;}if(node.previous&&node.next){node.previous.next=node.next;node.next.previous=node.previous;}else if(node.previous){node.previous.next=null;this.tail=node.previous;}else if(node.next){node.next.previous=null;this.head=node.next;}else {this.head=null;this.tail=null;}node.next=null;node.previous=null;--this._length;}splice(node,nextNode){if(node===nextNode){return;}this.remove(nextNode);this._insert(node,nextNode);}_insert(node,nextNode){var oldNodeNext=node.next;node.next=nextNode;if(this.tail===node){this.tail=nextNode;}else {oldNodeNext.previous=nextNode;}nextNode.next=oldNodeNext;nextNode.previous=node;++this._length;}}function defined$5(x){return x!==undefined&&x!==null;}class TilesetCache{constructor(){_defineProperty$1(this,"_list",void 0);_defineProperty$1(this,"_sentinel",void 0);_defineProperty$1(this,"_trimTiles",void 0);this._list=new DoublyLinkedList();this._sentinel=this._list.add('sentinel');this._trimTiles=false;}reset(){this._list.splice(this._list.tail,this._sentinel);}touch(tile){var node=tile._cacheNode;if(defined$5(node)){this._list.splice(this._sentinel,node);}}add(tileset,tile,addCallback){if(!defined$5(tile._cacheNode)){tile._cacheNode=this._list.add(tile);if(addCallback){addCallback(tileset,tile);}}}unloadTile(tileset,tile,unloadCallback){var node=tile._cacheNode;if(!defined$5(node)){return;}this._list.remove(node);tile._cacheNode=undefined;if(unloadCallback){unloadCallback(tileset,tile);}}unloadTiles(tileset,unloadCallback){var trimTiles=this._trimTiles;this._trimTiles=false;var list=this._list;var maximumMemoryUsageInBytes=(Potree.settings.tiles3DMaxMemory||tileset.maximumMemoryUsage)*1024*1024;var sentinel=this._sentinel;var node=list.head;/* while (node !== sentinel && (tileset.gpuMemoryUsageInBytes > maximumMemoryUsageInBytes || trimTiles)) {
  56944. const tile = node.item;
  56945. node = node.next;
  56946. this.unloadTile(tileset, tile, unloadCallback);
  56947. } */ //改
  56948. while(node!==sentinel&&(getGpuMemoryUsage()>maximumMemoryUsageInBytes||trimTiles)){var tile=node.item;node=node.next;this.unloadTile(tileset,tile,unloadCallback);}}trim(){this._trimTiles=true;}}function calculateTransformProps(tileHeader,tile){assert$7(tileHeader);assert$7(tile);var{rtcCenter,gltfUpAxis}=tile;var{computedTransform,boundingVolume:{center}}=tileHeader;var modelMatrix=new Matrix4$1(computedTransform);if(rtcCenter){modelMatrix.translate(rtcCenter);}switch(gltfUpAxis){case'Z':break;case'Y':var rotationY=new Matrix4$1().rotateX(Math.PI/2);modelMatrix=modelMatrix.multiplyRight(rotationY);break;case'X':var rotationX=new Matrix4$1().rotateY(-Math.PI/2);modelMatrix=modelMatrix.multiplyRight(rotationX);break;}if(tile.isQuantized){modelMatrix.translate(tile.quantizedVolumeOffset).scale(tile.quantizedVolumeScale);}var cartesianOrigin=new Vector3$1(center);tile.cartesianModelMatrix=modelMatrix;tile.cartesianOrigin=cartesianOrigin;var cartographicOrigin=Ellipsoid.WGS84.cartesianToCartographic(cartesianOrigin,new Vector3$1());var fromFixedFrameMatrix=Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin);var toFixedFrameMatrix=fromFixedFrameMatrix.invert();tile.cartographicModelMatrix=toFixedFrameMatrix.multiplyRight(modelMatrix);tile.cartographicOrigin=cartographicOrigin;if(!tile.coordinateSystem){tile.modelMatrix=tile.cartographicModelMatrix;}}var INTERSECTION=Object.freeze({OUTSIDE:-1,INTERSECTING:0,INSIDE:1});new Vector3$1();new Vector3$1();var scratchVector$3=new Vector3$1();var scratchVector2=new Vector3$1();class BoundingSphere{constructor(){var center=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[0,0,0];var radius=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0.0;this.radius=-0;this.center=new Vector3$1();this.fromCenterRadius(center,radius);}fromCenterRadius(center,radius){this.center.from(center);this.radius=radius;return this;}fromCornerPoints(corner,oppositeCorner){oppositeCorner=scratchVector$3.from(oppositeCorner);this.center=new Vector3$1().from(corner).add(oppositeCorner).scale(0.5);this.radius=this.center.distance(oppositeCorner);return this;}equals(right){return this===right||Boolean(right)&&this.center.equals(right.center)&&this.radius===right.radius;}clone(){return new BoundingSphere(this.center,this.radius);}union(boundingSphere){var leftCenter=this.center;var leftRadius=this.radius;var rightCenter=boundingSphere.center;var rightRadius=boundingSphere.radius;var toRightCenter=scratchVector$3.copy(rightCenter).subtract(leftCenter);var centerSeparation=toRightCenter.magnitude();if(leftRadius>=centerSeparation+rightRadius){return this.clone();}if(rightRadius>=centerSeparation+leftRadius){return boundingSphere.clone();}var halfDistanceBetweenTangentPoints=(leftRadius+centerSeparation+rightRadius)*0.5;scratchVector2.copy(toRightCenter).scale((-leftRadius+halfDistanceBetweenTangentPoints)/centerSeparation).add(leftCenter);this.center.copy(scratchVector2);this.radius=halfDistanceBetweenTangentPoints;return this;}expand(point){point=scratchVector$3.from(point);var radius=point.subtract(this.center).magnitude();if(radius>this.radius){this.radius=radius;}return this;}transform(transform){this.center.transform(transform);var scale=getScaling(scratchVector$3,transform);this.radius=Math.max(scale[0],Math.max(scale[1],scale[2]))*this.radius;return this;}distanceSquaredTo(point){var d=this.distanceTo(point);return d*d;}distanceTo(point){point=scratchVector$3.from(point);var delta=point.subtract(this.center);return Math.max(0,delta.len()-this.radius);}intersectPlane(plane){var center=this.center;var radius=this.radius;var normal=plane.normal;var distanceToPlane=normal.dot(center)+plane.distance;if(distanceToPlane<-radius){return INTERSECTION.OUTSIDE;}if(distanceToPlane<radius){return INTERSECTION.INTERSECTING;}return INTERSECTION.INSIDE;}}var scratchVector3=new Vector3$1();var scratchOffset=new Vector3$1();var scratchVectorU=new Vector3$1();var scratchVectorV=new Vector3$1();var scratchVectorW=new Vector3$1();var scratchCorner=new Vector3$1();var scratchToCenter=new Vector3$1();var MATRIX3={COLUMN0ROW0:0,COLUMN0ROW1:1,COLUMN0ROW2:2,COLUMN1ROW0:3,COLUMN1ROW1:4,COLUMN1ROW2:5,COLUMN2ROW0:6,COLUMN2ROW1:7,COLUMN2ROW2:8};class OrientedBoundingBox{constructor(){var center=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[0,0,0];var halfAxes=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0,0,0,0,0,0,0];this.center=new Vector3$1().from(center);this.halfAxes=new Matrix3$1(halfAxes);}get halfSize(){var xAxis=this.halfAxes.getColumn(0);var yAxis=this.halfAxes.getColumn(1);var zAxis=this.halfAxes.getColumn(2);return [new Vector3$1(xAxis).len(),new Vector3$1(yAxis).len(),new Vector3$1(zAxis).len()];}get quaternion(){var xAxis=this.halfAxes.getColumn(0);var yAxis=this.halfAxes.getColumn(1);var zAxis=this.halfAxes.getColumn(2);var normXAxis=new Vector3$1(xAxis).normalize();var normYAxis=new Vector3$1(yAxis).normalize();var normZAxis=new Vector3$1(zAxis).normalize();return new Quaternion$1().fromMatrix3(new Matrix3$1([...normXAxis,...normYAxis,...normZAxis]));}fromCenterHalfSizeQuaternion(center,halfSize,quaternion){var quaternionObject=new Quaternion$1(quaternion);var directionsMatrix=new Matrix3$1().fromQuaternion(quaternionObject);directionsMatrix[0]=directionsMatrix[0]*halfSize[0];directionsMatrix[1]=directionsMatrix[1]*halfSize[0];directionsMatrix[2]=directionsMatrix[2]*halfSize[0];directionsMatrix[3]=directionsMatrix[3]*halfSize[1];directionsMatrix[4]=directionsMatrix[4]*halfSize[1];directionsMatrix[5]=directionsMatrix[5]*halfSize[1];directionsMatrix[6]=directionsMatrix[6]*halfSize[2];directionsMatrix[7]=directionsMatrix[7]*halfSize[2];directionsMatrix[8]=directionsMatrix[8]*halfSize[2];this.center=new Vector3$1().from(center);this.halfAxes=directionsMatrix;return this;}clone(){return new OrientedBoundingBox(this.center,this.halfAxes);}equals(right){return this===right||Boolean(right)&&this.center.equals(right.center)&&this.halfAxes.equals(right.halfAxes);}getBoundingSphere(){var result=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new BoundingSphere();var halfAxes=this.halfAxes;var u=halfAxes.getColumn(0,scratchVectorU);//前三个
  56949. var v=halfAxes.getColumn(1,scratchVectorV);var w=halfAxes.getColumn(2,scratchVectorW);var cornerVector=scratchVector3.copy(u).add(v).add(w);result.center.copy(this.center);result.radius=cornerVector.magnitude();return result;}intersectPlane(plane){var center=this.center;var normal=plane.normal;var halfAxes=this.halfAxes;var normalX=normal.x;var normalY=normal.y;var normalZ=normal.z;var 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]);var distanceToPlane=normal.dot(center)+plane.distance;if(distanceToPlane<=-radEffective){return INTERSECTION.OUTSIDE;}else if(distanceToPlane>=radEffective){return INTERSECTION.INSIDE;}return INTERSECTION.INTERSECTING;//在相机frustum内
  56950. }distanceTo(point){return Math.sqrt(this.distanceSquaredTo(point));}/* distanceSquaredTo(point) {//相机到bound外壳的距离平方
  56951. let center = this.center.clone()
  56952. center.z *= -1
  56953. const offset = scratchOffset.from(point).subtract(center);
  56954. const halfAxes = this.halfAxes;
  56955. const u = halfAxes.getColumn(0, scratchVectorU);
  56956. const v = halfAxes.getColumn(1, scratchVectorV);
  56957. const w = halfAxes.getColumn(2, scratchVectorW);
  56958. u.z *= -1
  56959. v.z *= -1
  56960. w.z *= -1
  56961. const uHalf = u.magnitude();
  56962. const vHalf = v.magnitude();
  56963. const wHalf = w.magnitude();
  56964. u.normalize();
  56965. v.normalize();
  56966. w.normalize();
  56967. let distanceSquared = 0.0;
  56968. let d;
  56969. d = Math.abs(offset.dot(u)) - uHalf;
  56970. if (d > 0) {
  56971. distanceSquared += d * d;
  56972. }
  56973. d = Math.abs(offset.dot(v)) - vHalf;
  56974. if (d > 0) {
  56975. distanceSquared += d * d;
  56976. }
  56977. d = Math.abs(offset.dot(w)) - wHalf;
  56978. if (d > 0) {
  56979. distanceSquared += d * d;
  56980. }
  56981. return distanceSquared;
  56982. } */distanceSquaredTo(point){//相机到bound外壳的距离平方
  56983. var offset=scratchOffset.from(point).subtract(this.center);var halfAxes=this.halfAxes;var u=halfAxes.getColumn(0,scratchVectorU);var v=halfAxes.getColumn(1,scratchVectorV);var w=halfAxes.getColumn(2,scratchVectorW);var uHalf=u.magnitude();var vHalf=v.magnitude();var wHalf=w.magnitude();u.normalize();v.normalize();w.normalize();var distanceSquared=0.0;var d;d=Math.abs(offset.dot(u))-uHalf;if(d>0){distanceSquared+=d*d;}d=Math.abs(offset.dot(v))-vHalf;if(d>0){distanceSquared+=d*d;}d=Math.abs(offset.dot(w))-wHalf;if(d>0){distanceSquared+=d*d;}return distanceSquared;}computePlaneDistances(position,direction){var result=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[-0,-0];var minDist=Number.POSITIVE_INFINITY;var maxDist=Number.NEGATIVE_INFINITY;var center=this.center;var halfAxes=this.halfAxes;var u=halfAxes.getColumn(0,scratchVectorU);var v=halfAxes.getColumn(1,scratchVectorV);var w=halfAxes.getColumn(2,scratchVectorW);var corner=scratchCorner.copy(u).add(v).add(w).add(center);var toCenter=scratchToCenter.copy(corner).subtract(position);var mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);corner.copy(center).add(u).add(v).subtract(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);corner.copy(center).add(u).subtract(v).add(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);corner.copy(center).add(u).subtract(v).subtract(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);center.copy(corner).subtract(u).add(v).add(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);center.copy(corner).subtract(u).add(v).subtract(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);center.copy(corner).subtract(u).subtract(v).add(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);center.copy(corner).subtract(u).subtract(v).subtract(w);toCenter.copy(corner).subtract(position);mag=direction.dot(toCenter);minDist=Math.min(mag,minDist);maxDist=Math.max(mag,maxDist);result[0]=minDist;result[1]=maxDist;return result;}transform(transformation){this.center.transformAsPoint(transformation);var xAxis=this.halfAxes.getColumn(0,scratchVectorU);xAxis.transformAsPoint(transformation);var yAxis=this.halfAxes.getColumn(1,scratchVectorV);yAxis.transformAsPoint(transformation);var zAxis=this.halfAxes.getColumn(2,scratchVectorW);zAxis.transformAsPoint(transformation);this.halfAxes=new Matrix3$1([...xAxis,...yAxis,...zAxis]);return this;}getTransform(){throw new Error('not implemented');}}var scratchPosition$1=new Vector3$1();var scratchNormal$1=new Vector3$1();class Plane$1{constructor(){var normal=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[0,0,1];var distance=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;this.normal=new Vector3$1();this.distance=-0;this.fromNormalDistance(normal,distance);}fromNormalDistance(normal,distance){assert$4(Number.isFinite(distance));this.normal.from(normal).normalize();this.distance=distance;return this;}fromPointNormal(point,normal){point=scratchPosition$1.from(point);this.normal.from(normal).normalize();var distance=-this.normal.dot(point);this.distance=distance;return this;}fromCoefficients(a,b,c,d){this.normal.set(a,b,c);assert$4(equals$1(this.normal.len(),1));this.distance=d;return this;}clone(plane){return new Plane$1(this.normal,this.distance);}equals(right){return equals$1(this.distance,right.distance)&&equals$1(this.normal,right.normal);}getPointDistance(point){return this.normal.dot(point)+this.distance;}transform(matrix4){var normal=scratchNormal$1.copy(this.normal).transformAsVector(matrix4).normalize();var point=this.normal.scale(-this.distance).transform(matrix4);return this.fromPointNormal(point,normal);}projectPointOntoPlane(point){var result=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];point=scratchPosition$1.from(point);var pointDistance=this.getPointDistance(point);var scaledNormal=scratchNormal$1.copy(this.normal).scale(pointDistance);return point.subtract(scaledNormal).to(result);}}var faces=[new Vector3$1([1,0,0]),new Vector3$1([0,1,0]),new Vector3$1([0,0,1])];var scratchPlaneCenter=new Vector3$1();var scratchPlaneNormal$1=new Vector3$1();new Plane$1(new Vector3$1(1.0,0.0,0.0),0.0);class CullingVolume{static get MASK_OUTSIDE(){return 0xffffffff;}static get MASK_INSIDE(){return 0x00000000;}static get MASK_INDETERMINATE(){return 0x7fffffff;}constructor(){var planes=arguments.length>0&&arguments[0]!==undefined?arguments[0]:[];this.planes=planes;assert$4(this.planes.every(plane=>plane instanceof Plane$1));}fromBoundingSphere(boundingSphere){this.planes.length=2*faces.length;var center=boundingSphere.center;var radius=boundingSphere.radius;var planeIndex=0;for(var faceNormal of faces){var plane0=this.planes[planeIndex];var plane1=this.planes[planeIndex+1];if(!plane0){plane0=this.planes[planeIndex]=new Plane$1();}if(!plane1){plane1=this.planes[planeIndex+1]=new Plane$1();}var plane0Center=scratchPlaneCenter.copy(faceNormal).scale(-radius).add(center);-faceNormal.dot(plane0Center);plane0.fromPointNormal(plane0Center,faceNormal);var plane1Center=scratchPlaneCenter.copy(faceNormal).scale(radius).add(center);var negatedFaceNormal=scratchPlaneNormal$1.copy(faceNormal).negate();-negatedFaceNormal.dot(plane1Center);plane1.fromPointNormal(plane1Center,negatedFaceNormal);planeIndex+=2;}return this;}computeVisibility(boundingVolume){assert$4(boundingVolume);var intersect=INTERSECTION.INSIDE;for(var plane of this.planes){var result=boundingVolume.intersectPlane(plane);switch(result){case INTERSECTION.OUTSIDE:return INTERSECTION.OUTSIDE;case INTERSECTION.INTERSECTING:intersect=INTERSECTION.INTERSECTING;break;}}return intersect;}computeVisibilityWithPlaneMask(boundingVolume,parentPlaneMask){assert$4(boundingVolume,'boundingVolume is required.');assert$4(Number.isFinite(parentPlaneMask),'parentPlaneMask is required.');if(parentPlaneMask===CullingVolume.MASK_OUTSIDE||parentPlaneMask===CullingVolume.MASK_INSIDE){return parentPlaneMask;}var mask=CullingVolume.MASK_INSIDE;var planes=this.planes;for(var k=0;k<this.planes.length;++k){var flag=k<31?1<<k:0;if(k<31&&(parentPlaneMask&flag)===0){continue;}var plane=planes[k];var result=boundingVolume.intersectPlane(plane);if(result===INTERSECTION.OUTSIDE){return CullingVolume.MASK_OUTSIDE;}else if(result===INTERSECTION.INTERSECTING){mask|=flag;}}return mask;}}var scratchPlaneUpVector=new Vector3$1();var scratchPlaneRightVector=new Vector3$1();var scratchPlaneNearCenter=new Vector3$1();var scratchPlaneFarCenter=new Vector3$1();var scratchPlaneNormal=new Vector3$1();class PerspectiveOffCenterFrustum{constructor(){var options=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};options=_objectSpread2({near:1.0,far:500000000.0},options);this.left=options.left;this._left=undefined;this.right=options.right;this._right=undefined;this.top=options.top;this._top=undefined;this.bottom=options.bottom;this._bottom=undefined;this.near=options.near;this._near=this.near;this.far=options.far;this._far=this.far;this._cullingVolume=new CullingVolume([new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1()]);this._perspectiveMatrix=new Matrix4$1();this._infinitePerspective=new Matrix4$1();}clone(){return new PerspectiveOffCenterFrustum({right:this.right,left:this.left,top:this.top,bottom:this.bottom,near:this.near,far:this.far});}equals(other){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;}get projectionMatrix(){update$1(this);return this._perspectiveMatrix;}get infiniteProjectionMatrix(){update$1(this);return this._infinitePerspective;}computeCullingVolume(position,direction,up){assert$4(position,'position is required.');assert$4(direction,'direction is required.');assert$4(up,'up is required.');var planes=this._cullingVolume.planes;up=scratchPlaneUpVector.copy(up).normalize();var right=scratchPlaneRightVector.copy(direction).cross(up).normalize();var nearCenter=scratchPlaneNearCenter.copy(direction).multiplyByScalar(this.near).add(position);var farCenter=scratchPlaneFarCenter.copy(direction).multiplyByScalar(this.far).add(position);var normal=scratchPlaneNormal;normal.copy(right).multiplyByScalar(this.left).add(nearCenter).subtract(position).cross(up);planes[0].fromPointNormal(position,normal);normal.copy(right).multiplyByScalar(this.right).add(nearCenter).subtract(position).cross(up).negate();planes[1].fromPointNormal(position,normal);normal.copy(up).multiplyByScalar(this.bottom).add(nearCenter).subtract(position).cross(right).negate();planes[2].fromPointNormal(position,normal);normal.copy(up).multiplyByScalar(this.top).add(nearCenter).subtract(position).cross(right);planes[3].fromPointNormal(position,normal);normal=new Vector3$1().copy(direction);planes[4].fromPointNormal(nearCenter,normal);normal.negate();planes[5].fromPointNormal(farCenter,normal);return this._cullingVolume;}getPixelDimensions(drawingBufferWidth,drawingBufferHeight,distance,result){update$1(this);assert$4(Number.isFinite(drawingBufferWidth)&&Number.isFinite(drawingBufferHeight));assert$4(drawingBufferWidth>0);assert$4(drawingBufferHeight>0);assert$4(distance>0);assert$4(result);var inverseNear=1.0/this.near;var tanTheta=this.top*inverseNear;var pixelHeight=2.0*distance*tanTheta/drawingBufferHeight;tanTheta=this.right*inverseNear;var pixelWidth=2.0*distance*tanTheta/drawingBufferWidth;result.x=pixelWidth;result.y=pixelHeight;return result;}}function update$1(frustum){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));var{top,bottom,right,left,near,far}=frustum;if(top!==frustum._top||bottom!==frustum._bottom||left!==frustum._left||right!==frustum._right||near!==frustum._near||far!==frustum._far){assert$4(frustum.near>0&&frustum.near<frustum.far,'near must be greater than zero and less than far.');frustum._left=left;frustum._right=right;frustum._top=top;frustum._bottom=bottom;frustum._near=near;frustum._far=far;frustum._perspectiveMatrix=new Matrix4$1().frustum({left,right,bottom,top,near,far});frustum._infinitePerspective=new Matrix4$1().frustum({left,right,bottom,top,near,far:Infinity});}}var defined$4=val=>val!==null&&typeof val!=='undefined';class PerspectiveFrustum{constructor(){var options=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};options=_objectSpread2({near:1.0,far:500000000.0,xOffset:0.0,yOffset:0.0},options);this._offCenterFrustum=new PerspectiveOffCenterFrustum();this.fov=options.fov;this._fov=undefined;this._fovy=undefined;this._sseDenominator=undefined;this.aspectRatio=options.aspectRatio;this._aspectRatio=undefined;this.near=options.near;this._near=this.near;this.far=options.far;this._far=this.far;this.xOffset=options.xOffset;this._xOffset=this.xOffset;this.yOffset=options.yOffset;this._yOffset=this.yOffset;}clone(){return new PerspectiveFrustum({aspectRatio:this.aspectRatio,fov:this.fov,near:this.near,far:this.far});}equals(other){if(!defined$4(other)||!(other instanceof PerspectiveFrustum)){return false;}update(this);update(other);return this.fov===other.fov&&this.aspectRatio===other.aspectRatio&&this.near===other.near&&this.far===other.far&&this._offCenterFrustum.equals(other._offCenterFrustum);}get projectionMatrix(){update(this);return this._offCenterFrustum.projectionMatrix;}get infiniteProjectionMatrix(){update(this);return this._offCenterFrustum.infiniteProjectionMatrix;}get fovy(){update(this);return this._fovy;}get sseDenominator(){update(this);return this._sseDenominator;}computeCullingVolume(position,direction,up){update(this);return this._offCenterFrustum.computeCullingVolume(position,direction,up);}getPixelDimensions(drawingBufferWidth,drawingBufferHeight,distance,result){update(this);return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth,drawingBufferHeight,distance,result);}}function update(frustum){assert$4(Number.isFinite(frustum.fov)&&Number.isFinite(frustum.aspectRatio)&&Number.isFinite(frustum.near)&&Number.isFinite(frustum.far));var f=frustum._offCenterFrustum;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){assert$4(frustum.fov>=0&&frustum.fov<Math.PI);//assert$4(frustum.aspectRatio > 0);
  56984. if(frustum.aspectRatio==0){console.log(1);}assert$4(frustum.near>=0&&frustum.near<frustum.far);frustum._aspectRatio=Math.max(0.001,frustum.aspectRatio);frustum._fov=frustum.fov;frustum._fovy=frustum._aspectRatio<=1?frustum.fov:Math.atan(Math.tan(frustum.fov*0.5)/frustum._aspectRatio)*2.0;frustum._near=frustum.near;frustum._far=frustum.far;frustum._sseDenominator=2.0*Math.tan(0.5*frustum._fovy);frustum._xOffset=frustum.xOffset;frustum._yOffset=frustum.yOffset;f.top=frustum.near*Math.tan(0.5*frustum._fovy);f.bottom=-f.top;f.right=frustum._aspectRatio*f.top;f.left=-f.right;f.near=frustum.near;f.far=frustum.far;f.right+=frustum.xOffset;f.left+=frustum.xOffset;f.top+=frustum.yOffset;f.bottom+=frustum.yOffset;}}new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Matrix3$1();new Matrix3$1();new Matrix3$1();new Matrix3$1();new Matrix3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();new Matrix3$1();({diagonal:new Matrix3$1(),unitary:new Matrix3$1()});var scratchVector$2=new Vector3$1();var scratchPosition=new Vector3$1();var cullingVolume=new CullingVolume([new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1(),new Plane$1()]);function getFrameState(viewport,frameNumber){var{cameraDirection,cameraUp,height}=viewport;var{metersPerUnit}=viewport.distanceScales;var viewportCenterCartographic=viewport.unprojectPosition(viewport.center);var viewportCenterCartesian=Ellipsoid.WGS84.cartographicToCartesian(viewportCenterCartographic,new Vector3$1());var enuToFixedTransform=Ellipsoid.WGS84.eastNorthUpToFixedFrame(viewportCenterCartesian);var cameraPositionCartographic=viewport.unprojectPosition(viewport.cameraPosition);var cameraPositionCartesian=Ellipsoid.WGS84.cartographicToCartesian(cameraPositionCartographic,new Vector3$1());var cameraDirectionCartesian=new Vector3$1(enuToFixedTransform.transformAsVector(new Vector3$1(cameraDirection).scale(metersPerUnit))).normalize();var cameraUpCartesian=new Vector3$1(enuToFixedTransform.transformAsVector(new Vector3$1(cameraUp).scale(metersPerUnit))).normalize();commonSpacePlanesToWGS84(viewport,viewportCenterCartesian);return {camera:{position:cameraPositionCartesian,direction:cameraDirectionCartesian,up:cameraUpCartesian},viewport,height,cullingVolume,frameNumber,sseDenominator:1.15};}function commonSpacePlanesToWGS84(viewport,viewportCenterCartesian){var frustumPlanes=viewport.getFrustumPlanes();var i=0;for(var dir in frustumPlanes){var plane=frustumPlanes[dir];var distanceToCenter=plane.normal.dot(viewport.center);scratchPosition.copy(plane.normal).scale(plane.distance-distanceToCenter).add(viewport.center);var cartographicPos=viewport.unprojectPosition(scratchPosition);var cartesianPos=Ellipsoid.WGS84.cartographicToCartesian(cartographicPos,new Vector3$1());cullingVolume.planes[i++].fromPointNormal(cartesianPos,scratchVector$2.copy(viewportCenterCartesian).subtract(cartesianPos));}}var WGS84_RADIUS_X=6378137.0;var WGS84_RADIUS_Y=6378137.0;var WGS84_RADIUS_Z=6356752.3142451793;var scratchVector$1=new Vector3$1();function getZoomFromBoundingVolume(boundingVolume){var{halfAxes,radius,width,height}=boundingVolume;if(halfAxes){var obbSize=getObbSize(halfAxes);return Math.log2(WGS84_RADIUS_Z/obbSize);}else if(radius){return Math.log2(WGS84_RADIUS_Z/radius);}else if(height&&width){var zoomX=Math.log2(WGS84_RADIUS_X/width);var zoomY=Math.log2(WGS84_RADIUS_Y/height);return (zoomX+zoomY)/2;}return 1;}function getObbSize(halfAxes){halfAxes.getColumn(0,scratchVector$1);var axeY=halfAxes.getColumn(1);var axeZ=halfAxes.getColumn(2);var farthestVertex=scratchVector$1.add(axeY).add(axeZ);var size=farthestVertex.len();return size;}var TILE_CONTENT_STATE={UNLOADED:0,LOADING:1,PROCESSING:2,READY:3,EXPIRED:4,FAILED:5};var TILE_REFINEMENT={ADD:1,REPLACE:2};var TILE_TYPE={EMPTY:'empty',SCENEGRAPH:'scenegraph',POINTCLOUD:'pointcloud',MESH:'mesh'};var TILESET_TYPE={I3S:'I3S',TILES3D:'TILES3D'};var LOD_METRIC_TYPE={GEOMETRIC_ERROR:'geometricError',MAX_SCREEN_THRESHOLD:'maxScreenThreshold'};var TILE3D_OPTIMIZATION_HINT={NOT_COMPUTED:-1,USE_OPTIMIZATION:1,SKIP_OPTIMIZATION:0};function defined$3(x){return x!==undefined&&x!==null;}var scratchScale=new Vector3$1();var scratchNorthWest=new Vector3$1();var scratchSouthEast=new Vector3$1();function createBoundingVolume(boundingVolumeHeader,transform,result){assert$7(boundingVolumeHeader,'3D Tile: boundingVolume must be defined');if(boundingVolumeHeader.box){return createBox(boundingVolumeHeader.box,transform,result);}if(boundingVolumeHeader.region){var[west,south,east,north,minHeight,maxHeight]=boundingVolumeHeader.region;var northWest=Ellipsoid.WGS84.cartographicToCartesian([degrees(west),degrees(north),minHeight],scratchNorthWest);var southEast=Ellipsoid.WGS84.cartographicToCartesian([degrees(east),degrees(south),maxHeight],scratchSouthEast);var centerInCartesian=new Vector3$1().addVectors(northWest,southEast).multiplyScalar(0.5);var radius=new Vector3$1().subVectors(northWest,southEast).len()/2.0;return createSphere([centerInCartesian[0],centerInCartesian[1],centerInCartesian[2],radius],new Matrix4$1());}if(boundingVolumeHeader.sphere){return createSphere(boundingVolumeHeader.sphere,transform,result);}throw new Error('3D Tile: boundingVolume must contain a sphere, region, or box');}function createBox(box,transform,result){var center=new Vector3$1(box[0],box[1],box[2]);result&&(result.oriCenter=center);//add
  56985. transform.transform(center,center);var origin=[];if(box.length===10){var halfSize=box.slice(3,6);var quaternion=new Quaternion$1();quaternion.fromArray(box,6);var x=new Vector3$1([1,0,0]);var y=new Vector3$1([0,1,0]);var z=new Vector3$1([0,0,1]);x.transformByQuaternion(quaternion);x.scale(halfSize[0]);y.transformByQuaternion(quaternion);y.scale(halfSize[1]);z.transformByQuaternion(quaternion);z.scale(halfSize[2]);origin=[...x.toArray(),...y.toArray(),...z.toArray()];}else {origin=[...box.slice(3,6),...box.slice(6,9),...box.slice(9,12)];}var xAxis=transform.transformAsVector(origin.slice(0,3));var yAxis=transform.transformAsVector(origin.slice(3,6));var zAxis=transform.transformAsVector(origin.slice(6,9));var halfAxes=new Matrix3$1([xAxis[0],xAxis[1],xAxis[2],yAxis[0],yAxis[1],yAxis[2],zAxis[0],zAxis[1],zAxis[2]]);//const halfAxes = new Matrix3([xAxis[0], xAxis[1], -xAxis[2], yAxis[0], yAxis[1], -yAxis[2], zAxis[0], zAxis[1], -zAxis[2]]);//改
  56986. //center.z *= -1//add
  56987. if(defined$3(result)){result.center=center;result.halfAxes=halfAxes;return result;}return new OrientedBoundingBox(center,halfAxes);}function createSphere(sphere,transform,result){var center=new Vector3$1(sphere[0],sphere[1],sphere[2]);transform.transform(center,center);var scale=transform.getScale(scratchScale);var uniformScale=Math.max(Math.max(scale[0],scale[1]),scale[2]);var radius=sphere[3]*uniformScale;if(defined$3(result)){result.center=center;result.radius=radius;return result;}return new BoundingSphere(center,radius);}new Vector3$1();new Vector3$1();new Matrix4$1();new Vector3$1();new Vector3$1();new Vector3$1();function fog(distanceToCamera,density){var scalar=distanceToCamera*density;return 1.0-Math.exp(-(scalar*scalar));}function getDynamicScreenSpaceError(tileset,distanceToCamera){if(tileset.dynamicScreenSpaceError&&tileset.dynamicScreenSpaceErrorComputedDensity){var density=tileset.dynamicScreenSpaceErrorComputedDensity;var factor=tileset.dynamicScreenSpaceErrorFactor;var dynamicError=fog(distanceToCamera,density)*factor;return dynamicError;}return 0;}function getTiles3DScreenSpaceError(tile,frameState,useParentLodMetric){var tileset=tile.tileset;var parentLodMetricValue=tile.parent&&tile.parent.lodMetricValue||tile.lodMetricValue;var lodMetricValue=useParentLodMetric?parentLodMetricValue:tile.lodMetricValue;if(lodMetricValue===0.0){return 0.0;}var distance=Math.max(tile._distanceToCamera,1e-7);var{height,sseDenominator}=frameState;var{viewDistanceScale}=tileset.options;var error=lodMetricValue*height*(viewDistanceScale||1.0)/(distance*sseDenominator);error-=getDynamicScreenSpaceError(tileset,distance);return error;}function getLodStatus(tile,frameState){if(tile.lodMetricValue===0||isNaN(tile.lodMetricValue)){return 'DIG';}var screenSize=2*getProjectedRadius(tile,frameState);if(screenSize<2){return 'OUT';}if(!tile.header.children||screenSize<=tile.lodMetricValue){return 'DRAW';}else if(tile.header.children){return 'DIG';}return 'OUT';}function getProjectedRadius(tile,frameState){var originalViewport=frameState.viewport;var ViewportClass=originalViewport.constructor;var{longitude,latitude,height,width,bearing,zoom}=originalViewport;var viewport=new ViewportClass({longitude,latitude,height,width,bearing,zoom,pitch:0});var mbsLat=tile.header.mbs[1];var mbsLon=tile.header.mbs[0];var mbsZ=tile.header.mbs[2];var mbsR=tile.header.mbs[3];var mbsCenterCartesian=[...tile.boundingVolume.center];var cameraPositionCartographic=viewport.unprojectPosition(viewport.cameraPosition);var cameraPositionCartesian=Ellipsoid.WGS84.cartographicToCartesian(cameraPositionCartographic,new Vector3$1());var toEye=new Vector3$1(cameraPositionCartesian).subtract(mbsCenterCartesian).normalize();var enuToCartesianMatrix=new Matrix4$1();Ellipsoid.WGS84.eastNorthUpToFixedFrame(mbsCenterCartesian,enuToCartesianMatrix);var cartesianToEnuMatrix=new Matrix4$1(enuToCartesianMatrix).invert();var cameraPositionEnu=new Vector3$1(cameraPositionCartesian).transform(cartesianToEnuMatrix);var projection=Math.sqrt(cameraPositionEnu[0]*cameraPositionEnu[0]+cameraPositionEnu[1]*cameraPositionEnu[1]);var extraZ=projection*projection/cameraPositionEnu[2];var extraVertexEnu=new Vector3$1([cameraPositionEnu[0],cameraPositionEnu[1],extraZ]);var extraVertexCartesian=extraVertexEnu.transform(enuToCartesianMatrix);var extraVectorCartesian=new Vector3$1(extraVertexCartesian).subtract(mbsCenterCartesian).normalize();var radiusVector=toEye.cross(extraVectorCartesian).normalize().scale(mbsR);var sphereMbsBorderVertexCartesian=new Vector3$1(mbsCenterCartesian).add(radiusVector);var sphereMbsBorderVertexCartographic=Ellipsoid.WGS84.cartesianToCartographic(sphereMbsBorderVertexCartesian);var projectedOrigin=viewport.project([mbsLon,mbsLat,mbsZ]);var projectedMbsBorderVertex=viewport.project(sphereMbsBorderVertexCartographic);var projectedRadius=new Vector3$1(projectedOrigin).subtract(projectedMbsBorderVertex).magnitude();return projectedRadius;}function get3dTilesOptions(tileset){return {assetGltfUpAxis:tileset.asset&&tileset.asset.gltfUpAxis||'Y'};}class ManagedArray{constructor(){var length=arguments.length>0&&arguments[0]!==undefined?arguments[0]:0;_defineProperty$1(this,"_map",new Map());_defineProperty$1(this,"_array",void 0);_defineProperty$1(this,"_length",void 0);this._array=new Array(length);this._length=length;}get length(){return this._length;}set length(length){this._length=length;if(length>this._array.length){this._array.length=length;}}get values(){return this._array;}get(index){assert$7(index<this._array.length);return this._array[index];}set(index,element){assert$7(index>=0);if(index>=this.length){this.length=index+1;}if(this._map.has(this._array[index])){this._map.delete(this._array[index]);}this._array[index]=element;this._map.set(element,index);}delete(element){var index=this._map.get(element);if(index>=0){this._array.splice(index,1);this._map.delete(element);this.length--;}}peek(){return this._array[this._length-1];}push(element){if(!this._map.has(element)){var index=this.length++;this._array[index]=element;this._map.set(element,index);}}pop(){var element=this._array[--this.length];this._map.delete(element);return element;}reserve(length){assert$7(length>=0);if(length>this._array.length){this._array.length=length;}}resize(length){assert$7(length>=0);this.length=length;}trim(length){if(length===null||length===undefined){length=this.length;}this._array.length=length;}reset(){this._array=[];this._map=new Map();this._length=0;}find(target){return this._map.has(target);}}var DEFAULT_PROPS$1={loadSiblings:false,skipLevelOfDetail:false,maximumScreenSpaceError:2,updateTransforms:true,onTraversalEnd:()=>{},viewportTraversersMap:{},basePath:''};class TilesetTraverser{constructor(options){_defineProperty$1(this,"options",void 0);_defineProperty$1(this,"root",void 0);_defineProperty$1(this,"requestedTiles",void 0);_defineProperty$1(this,"selectedTiles",void 0);_defineProperty$1(this,"emptyTiles",void 0);_defineProperty$1(this,"_traversalStack",void 0);_defineProperty$1(this,"_emptyTraversalStack",void 0);_defineProperty$1(this,"_frameNumber",void 0);this.options=_objectSpread2(_objectSpread2({},DEFAULT_PROPS$1),options);this._traversalStack=new ManagedArray();this._emptyTraversalStack=new ManagedArray();this._frameNumber=null;this.root=null;this.selectedTiles={};this.requestedTiles={};this.emptyTiles={};}traverse(root,frameState,options){this.root=root;this.options=_objectSpread2(_objectSpread2({},this.options),options);this.reset();this.updateTile(root,frameState);this._frameNumber=frameState.frameNumber;this.executeTraversal(root,frameState);}reset(){this.requestedTiles={};this.selectedTiles={};this.emptyTiles={};this._traversalStack.reset();this._emptyTraversalStack.reset();}executeTraversal(root,frameState){// 遍历root
  56988. var stack=this._traversalStack;root._selectionDepth=1;stack.push(root);while(stack.length>0){var tile=stack.pop();var shouldRefine=false;// !zeg改 循环遍历子tile, maxDepth用来限制可加载的最大深度
  56989. if(this.canTraverse(tile,frameState)&&(tile.depth</* this.options. */maxDepth||tile.type!='scenegraph')){//add maxDepth 是否继续遍历子集
  56990. this.updateChildTiles(tile,frameState);shouldRefine=this.updateAndPushChildren(tile,frameState,stack,tile.hasRenderContent?tile._selectionDepth+1:tile._selectionDepth);}var parent=tile.parent;var parentRefines=Boolean(!parent||parent._shouldRefine);var stoppedRefining=!shouldRefine;if(!tile.hasRenderContent){this.emptyTiles[tile.id]=tile;this.loadTile(tile,frameState);if(stoppedRefining){this.selectTile(tile,frameState);}}else if(tile.refine===TILE_REFINEMENT.ADD){this.loadTile(tile,frameState);this.selectTile(tile,frameState);}else if(tile.refine===TILE_REFINEMENT.REPLACE){this.loadTile(tile,frameState);if(stoppedRefining){this.selectTile(tile,frameState);}}this.touchTile(tile,frameState);tile._shouldRefine=shouldRefine&&parentRefines;}this.options.onTraversalEnd(frameState);}updateChildTiles(tile,frameState){var children=tile.children;for(var child of children){this.updateTile(child,frameState);}return true;}updateAndPushChildren(tile,frameState,stack,depth){var{loadSiblings,skipLevelOfDetail}=this.options;var children=tile.children;children.sort(this.compareDistanceToCamera.bind(this));var checkRefines=tile.refine===TILE_REFINEMENT.REPLACE&&tile.hasRenderContent&&!skipLevelOfDetail;var hasVisibleChild=false;var refines=true;for(var child of children){child._selectionDepth=depth;if(child.isVisibleAndInRequestVolume){if(stack.find(child)){stack.delete(child);}stack.push(child);hasVisibleChild=true;}else if(checkRefines||loadSiblings){this.loadTile(child,frameState);this.touchTile(child,frameState);}if(checkRefines){var childRefines=void 0;if(!child._inRequestVolume){childRefines=false;}else if(!child.hasRenderContent){childRefines=this.executeEmptyTraversal(child,frameState);}else {childRefines=child.contentAvailable;}refines=refines&&childRefines;if(!refines){return false;}}}if(!hasVisibleChild){refines=false;}return refines;}updateTile(tile,frameState){this.updateTileVisibility(tile,frameState);}selectTile(tile,frameState){if(this.shouldSelectTile(tile)){tile._selectedFrame=frameState.frameNumber;this.selectedTiles[tile.id]=tile;}}loadTile(tile,frameState){if(this.shouldLoadTile(tile)){tile._requestedFrame=frameState.frameNumber;tile._priority=tile._getPriority();this.requestedTiles[tile.id]=tile;}}touchTile(tile,frameState){tile.tileset._cache.touch(tile);tile._touchedFrame=frameState.frameNumber;}canTraverse(tile,frameState){var useParentMetric=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var ignoreVisibility=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;if(!tile.hasChildren){return false;}if(tile.hasTilesetContent){return !tile.contentExpired;}if(!ignoreVisibility&&!tile.isVisibleAndInRequestVolume){return false;}return this.shouldRefine(tile,frameState,useParentMetric);}shouldLoadTile(tile){return tile.hasUnloadedContent||tile.contentExpired;}shouldSelectTile(tile){return tile.contentAvailable&&!this.options.skipLevelOfDetail;}shouldRefine(tile,frameState,useParentMetric){// 是否更新更精细的模型 canTraverse
  56991. if(tile.tileset.options.loadMaxLevelDirect){return true;//xzw add : 直接加载到最高清晰度,用于截图 //是只加载屏幕里的吗
  56992. }var screenSpaceError=tile._screenSpaceError;if(useParentMetric){screenSpaceError=tile.getScreenSpaceError(frameState,true);}var maxSSE=this.options.maximumScreenSpaceError;if(tile.tileset.root.header.boundingVolume.sphere)maxSSE/=5;//cesium那边的自带坐标的模型
  56993. return screenSpaceError>maxSSE;// 距离越近,SSE越大
  56994. }updateTileVisibility(tile,frameState){var viewportIds=[];if(this.options.viewportTraversersMap){for(var key in this.options.viewportTraversersMap){var value=this.options.viewportTraversersMap[key];if(value===frameState.viewport.id){viewportIds.push(key);}}}else {viewportIds.push(frameState.viewport.id);}tile.updateVisibility(frameState,viewportIds);}compareDistanceToCamera(b,a){return b._distanceToCamera-a._distanceToCamera;}anyChildrenVisible(tile,frameState){var anyVisible=false;for(var child of tile.children){child.updateVisibility(frameState);anyVisible=anyVisible||child.isVisibleAndInRequestVolume;}return anyVisible;}executeEmptyTraversal(root,frameState){var allDescendantsLoaded=true;var stack=this._emptyTraversalStack;stack.push(root);while(stack.length>0&&allDescendantsLoaded){var tile=stack.pop();this.updateTile(tile,frameState);if(!tile.isVisibleAndInRequestVolume){this.loadTile(tile,frameState);}this.touchTile(tile,frameState);var traverse=!tile.hasRenderContent&&this.canTraverse(tile,frameState,false,true);if(traverse){var children=tile.children;for(var child of children){if(stack.find(child)){stack.delete(child);}stack.push(child);}}else if(!tile.contentAvailable){allDescendantsLoaded=false;}}return allDescendantsLoaded;}}var scratchVector=new Vector3$1();function defined$2(x){return x!==undefined&&x!==null;}class TileHeader{constructor(tileset,header,parentHeader){var _header$contentUrl;var extendedId=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'';_defineProperty$1(this,"tileset",void 0);_defineProperty$1(this,"header",void 0);_defineProperty$1(this,"id",void 0);_defineProperty$1(this,"url",void 0);_defineProperty$1(this,"parent",void 0);_defineProperty$1(this,"refine",void 0);_defineProperty$1(this,"type",void 0);_defineProperty$1(this,"contentUrl",void 0);_defineProperty$1(this,"lodMetricType",void 0);_defineProperty$1(this,"lodMetricValue",void 0);_defineProperty$1(this,"boundingVolume",void 0);_defineProperty$1(this,"content",void 0);_defineProperty$1(this,"contentState",void 0);_defineProperty$1(this,"gpuMemoryUsageInBytes",void 0);_defineProperty$1(this,"children",void 0);_defineProperty$1(this,"depth",void 0);_defineProperty$1(this,"viewportIds",void 0);_defineProperty$1(this,"transform",void 0);_defineProperty$1(this,"extensions",void 0);_defineProperty$1(this,"userData",void 0);_defineProperty$1(this,"computedTransform",void 0);_defineProperty$1(this,"hasEmptyContent",void 0);_defineProperty$1(this,"hasTilesetContent",void 0);_defineProperty$1(this,"traverser",void 0);_defineProperty$1(this,"_cacheNode",void 0);_defineProperty$1(this,"_frameNumber",void 0);_defineProperty$1(this,"_lodJudge",void 0);_defineProperty$1(this,"_expireDate",void 0);_defineProperty$1(this,"_expiredContent",void 0);_defineProperty$1(this,"_shouldRefine",void 0);_defineProperty$1(this,"_distanceToCamera",void 0);_defineProperty$1(this,"_centerZDepth",void 0);_defineProperty$1(this,"_screenSpaceError",void 0);_defineProperty$1(this,"_visibilityPlaneMask",void 0);_defineProperty$1(this,"_visible",void 0);_defineProperty$1(this,"_inRequestVolume",void 0);_defineProperty$1(this,"_stackLength",void 0);_defineProperty$1(this,"_selectionDepth",void 0);_defineProperty$1(this,"_touchedFrame",void 0);_defineProperty$1(this,"_visitedFrame",void 0);_defineProperty$1(this,"_selectedFrame",void 0);_defineProperty$1(this,"_requestedFrame",void 0);_defineProperty$1(this,"_priority",void 0);_defineProperty$1(this,"_contentBoundingVolume",void 0);_defineProperty$1(this,"_viewerRequestVolume",void 0);_defineProperty$1(this,"_initialTransform",void 0);_defineProperty$1(this,"tilesetMatrix",void 0);//add
  56995. _defineProperty$1(this,"tileContent",void 0);//add
  56996. _defineProperty$1(this,"contentTransform",void 0);//add
  56997. _defineProperty$1(this,"volumeBox",void 0);//add
  56998. _defineProperty$1(this,"boundUntransformed",void 0);//add
  56999. _defineProperty$1(this,"rtcCenterState",rtcCenterGlobal);//add 初始时的状态,当mesh加载完检查下
  57000. _defineProperty$1(this,"posCount",0);//add
  57001. _defineProperty$1(this,"texArea",0);//add
  57002. _defineProperty$1(this,"floorIndex",null);//add
  57003. this.header=header;this.tileset=tileset;this.id=extendedId||header.id;this.url=header.url;this.parent=parentHeader;this.refine=this._getRefine(header.refine);this.type=header.type;this.contentUrl=header.contentUrl;//add:-----
  57004. var floorMatch=(_header$contentUrl=header.contentUrl)===null||_header$contentUrl===void 0?void 0:_header$contentUrl.match(/floor_([0-9]+)./);this.floorIndex=floorMatch?parseInt(floorMatch[1]):null;//---------
  57005. this.lodMetricType='geometricError';this.lodMetricValue=0;this.boundingVolume=null;this.content=null;this.contentState=TILE_CONTENT_STATE.UNLOADED;this.gpuMemoryUsageInBytes=0;this.children=[];this.hasEmptyContent=false;this.hasTilesetContent=false;this.depth=0;this.viewportIds=[];this.userData={};this.extensions=null;this._priority=0;this._touchedFrame=0;this._visitedFrame=0;this._selectedFrame=0;this._requestedFrame=0;this._screenSpaceError=0;this._cacheNode=null;this._frameNumber=null;this._cacheNode=null;this.traverser=new TilesetTraverser({});this._shouldRefine=false;this._distanceToCamera=0;this._centerZDepth=0;this._visible=undefined;this._inRequestVolume=false;this._stackLength=0;this._selectionDepth=0;this._initialTransform=new Matrix4$1();this.transform=new Matrix4$1();this._initializeLodMetric(header);this._initializeTransforms(header);this._initializeBoundingVolumes(header);this._initializeContent(header);this._initializeRenderingState(header);this._lodJudge=null;this._expireDate=null;this._expiredContent=null;Object.seal(this);}destroy(){this.header=null;}isDestroyed(){return this.header===null;}get selected(){return this._selectedFrame===this.tileset._frameNumber;}get isVisible(){return this._visible;}get isVisibleAndInRequestVolume(){var v=/* this._visible && */this.tileset.visible&&this._inRequestVolume//用_updateBoundingVolume这个算的在相机靠近时不准确,容易缺块
  57006. &&(this.tileset.options.is4dkkModel?this.tileset.currentFloor=='all'||this.floorIndex==this.tileset.currentFloor||this.floorIndex==void 0:true);if(window.tileVisi2)v=this._visible&&v;return v;}get hasRenderContent(){return !this.hasEmptyContent&&!this.hasTilesetContent;}get hasChildren(){return this.children.length>0||this.header.children&&this.header.children.length>0;}get contentReady(){return this.contentState===TILE_CONTENT_STATE.READY||this.hasEmptyContent;}get contentAvailable(){return Boolean(this.contentReady&&this.hasRenderContent||this._expiredContent&&!this.contentFailed);}get hasUnloadedContent(){return this.hasRenderContent&&this.contentUnloaded;}get contentUnloaded(){return this.contentState===TILE_CONTENT_STATE.UNLOADED;}get contentExpired(){return this.contentState===TILE_CONTENT_STATE.EXPIRED;}get contentFailed(){return this.contentState===TILE_CONTENT_STATE.FAILED;}getScreenSpaceError(frameState,useParentLodMetric){switch(this.tileset.type){case TILESET_TYPE.I3S:return getProjectedRadius(this,frameState);case TILESET_TYPE.TILES3D:return getTiles3DScreenSpaceError(this,frameState,useParentLodMetric);default:throw new Error('Unsupported tileset type');}}get byteLength(){var _this$content,_this$content2;//add
  57007. var len=((_this$content=this.content)===null||_this$content===void 0?void 0:_this$content.byteLength)||((_this$content2=this.content)===null||_this$content2===void 0||(_this$content2=_this$content2.gltf)===null||_this$content2===void 0?void 0:_this$content2.buffers[0].byteLength)||0;// 后者为glTF型的tile
  57008. if(len==0&&this.tileContent)console.log('tile.byteLength == 0???');//url为json的话确实为0, 模型被删除后mesh没了也为0
  57009. return len;}_getPriority(){var traverser=this.tileset._traverser;var{skipLevelOfDetail}=traverser.options;var maySkipTile=this.refine===TILE_REFINEMENT.ADD||skipLevelOfDetail;if(maySkipTile&&!this.isVisible&&this._visible!==undefined){return -1;}if(this.tileset._frameNumber-this._touchedFrame>=1){return -1;}if(this.contentState===TILE_CONTENT_STATE.UNLOADED){return -1;}var parent=this.parent;var useParentScreenSpaceError=parent&&(!maySkipTile||this._screenSpaceError===0.0||parent.hasTilesetContent);var screenSpaceError=useParentScreenSpaceError?parent._screenSpaceError:this._screenSpaceError;var rootScreenSpaceError=traverser.root?traverser.root._screenSpaceError:0.0;var v=Math.max(rootScreenSpaceError-screenSpaceError,0);if(!this._visible){v=THREE.Math.clamp(v*0.1,-0.9,100);//xzw add 因为this._visible我也令其显示所以这里降低这些的优先级
  57010. }return v;}async loadContent(){if(this.hasEmptyContent){return false;}if(this.content){return true;}var expired=this.contentExpired;if(expired){this._expireDate=null;}this.contentState=TILE_CONTENT_STATE.LOADING;var requestToken=await this.tileset._requestScheduler.scheduleRequest(this.id,this._getPriority.bind(this));if(!requestToken){this.contentState=TILE_CONTENT_STATE.UNLOADED;return false;}try{var contentUrl=this.tileset.getTileUrl(this.contentUrl)+"?_=".concat(this.tileset.options.updateTime);// !zeg改 添加version后缀 原:imageVersion
  57011. var loader=this.tileset.loader;var options=_objectSpread2(_objectSpread2({},this.tileset.loadOptions),{},{[loader.id]:_objectSpread2(_objectSpread2({},this.tileset.loadOptions[loader.id]),{},{isTileset:this.type==='json'},this._getLoaderSpecificOptions(loader.id))});this.content=await load(contentUrl,loader,options);// !zeg改
  57012. if(/* this.tileset.options. */maxDepth<this.depth&&this.type=='scenegraph'){//有的场景depth为1的不是mesh,只是json,即实际最低depth>1
  57013. this.unloadContent();return false;}if(this.tileset.options.contentLoader){await this.tileset.options.contentLoader(this);}if(this._isTileset()){this.tileset._initializeTileHeaders(this.content,this);}this.contentState=TILE_CONTENT_STATE.READY;this._onContentLoaded();return true;}catch(error){this.contentState=TILE_CONTENT_STATE.FAILED;throw error;}finally{requestToken.done();}}unloadContent(){if(this.content&&this.content.destroy){this.content.destroy();}this.content=null;if(this.header.content&&this.header.content.destroy){this.header.content.destroy();}this.header.content=null;this.contentState=TILE_CONTENT_STATE.UNLOADED;return true;}updateVisibility(frameState,viewportIds){if(this._frameNumber===frameState.frameNumber){return;}var parent=this.parent;var parentVisibilityPlaneMask=parent?parent._visibilityPlaneMask:CullingVolume.MASK_INDETERMINATE;if(this.tileset._traverser.options.updateTransforms){var parentTransform=parent?parent.computedTransform:new Matrix4$1().elements;//this.tileset.modelMatrix; 改:去掉左乘modelMatrix
  57014. this._updateTransform(parentTransform);}this._distanceToCamera=this.distanceToTile(frameState);this._screenSpaceError=this.getScreenSpaceError(frameState,false);this._visibilityPlaneMask=this.visibility(frameState,parentVisibilityPlaneMask);this._visible=this._visibilityPlaneMask!==CullingVolume.MASK_OUTSIDE;this._inRequestVolume=this.insideViewerRequestVolume(frameState);this._frameNumber=frameState.frameNumber;this.viewportIds=viewportIds;}visibility(frameState,parentVisibilityPlaneMask){var{cullingVolume}=frameState;var{boundingVolume}=this;return cullingVolume.computeVisibilityWithPlaneMask(boundingVolume,parentVisibilityPlaneMask);}contentVisibility(){return true;}distanceToTile(frameState){var boundingVolume=this.boundingVolume;return Math.sqrt(Math.max(boundingVolume.distanceSquaredTo(frameState.camera.position),0));}cameraSpaceZDepth(_ref11){var{camera}=_ref11;var boundingVolume=this.boundingVolume;scratchVector.subVectors(boundingVolume.center,camera.position);return camera.direction.dot(scratchVector);}insideViewerRequestVolume(frameState){var viewerRequestVolume=this._viewerRequestVolume;return !viewerRequestVolume||viewerRequestVolume.distanceSquaredTo(frameState.camera.position)<=0;}updateExpiration(){if(defined$2(this._expireDate)&&this.contentReady&&!this.hasEmptyContent){var now=Date.now();if(Date.lessThan(this._expireDate,now)){this.contentState=TILE_CONTENT_STATE.EXPIRED;this._expiredContent=this.content;}}}get extras(){return this.header.extras;}_initializeLodMetric(header){if('lodMetricType'in header){this.lodMetricType=header.lodMetricType;}else {this.lodMetricType=this.parent&&this.parent.lodMetricType||this.tileset.lodMetricType;console.warn("3D Tile: Required prop lodMetricType is undefined. Using parent lodMetricType");}if('lodMetricValue'in header){this.lodMetricValue=header.lodMetricValue;}else {this.lodMetricValue=this.parent&&this.parent.lodMetricValue||this.tileset.lodMetricValue;console.warn('3D Tile: Required prop lodMetricValue is undefined. Using parent lodMetricValue');}}_initializeTransforms(tileHeader){//xzw改
  57015. var transform=tileHeader.transform;// || tileHeader.boundingVolume.sphere && [1,0,0,0, 0,1,0,0, 0,0,1,0, ...tileHeader.boundingVolume.sphere.slice(0,3),1 ] //xzw add
  57016. this.transform=transform?new Matrix4$1(transform):new Matrix4$1();//this.transform = tileHeader.transform ? new Matrix4(tileHeader.transform) : new Matrix4();
  57017. var parent=this.parent;var tileset=this.tileset;var parentTransform=parent&&parent.computedTransform?parent.computedTransform.clone():new Matrix4$1().elements;// tileset.modelMatrix.clone(); 改:去掉左乘modelMatrix
  57018. this.computedTransform=new Matrix4$1(parentTransform).multiplyRight(this.transform);var parentInitialTransform=parent&&parent._initialTransform?parent._initialTransform.clone():new Matrix4$1();this._initialTransform=new Matrix4$1(parentInitialTransform).multiplyRight(this.transform);}_initializeBoundingVolumes(tileHeader){this._contentBoundingVolume=null;this._viewerRequestVolume=null;this._updateBoundingVolume(tileHeader);}_initializeContent(tileHeader){this.content={_tileset:this.tileset,_tile:this};this.hasEmptyContent=true;this.contentState=TILE_CONTENT_STATE.UNLOADED;this.hasTilesetContent=false;if(tileHeader.contentUrl){this.content=null;this.hasEmptyContent=false;}}_initializeRenderingState(header){this.depth=header.level||(this.parent?this.parent.depth+1:0);this._shouldRefine=false;this._distanceToCamera=0;this._centerZDepth=0;this._screenSpaceError=0;this._visibilityPlaneMask=CullingVolume.MASK_INDETERMINATE;this._visible=undefined;this._inRequestVolume=false;this._stackLength=0;this._selectionDepth=0;this._frameNumber=0;this._touchedFrame=0;this._visitedFrame=0;this._selectedFrame=0;this._requestedFrame=0;this._priority=0.0;}_getRefine(refine){return refine||this.parent&&this.parent.refine||TILE_REFINEMENT.REPLACE;}_isTileset(){return this.contentUrl.indexOf('.json')!==-1;}_onContentLoaded(){switch(this.content&&this.content.type){case'vctr':case'geom':this.tileset._traverser.disableSkipLevelOfDetail=true;break;}if(this._isTileset()){this.hasTilesetContent=true;}}_updateBoundingVolume(header){var computedTransform;/* if(header.id == 'root_0' || !header.id){
  57019. console.log('root_0')
  57020. } */if(!this.tileset.lastRootTransform){//没事过后会因_updateTransform重算
  57021. /* if(header.boundingVolume.sphere) computedTransform = new Matrix4(this.tileset.modelMatrix)//xzw改
  57022. else */computedTransform=new Matrix4$1(this.tileset.modelMatrix).multiplyRight(this.computedTransform);//add
  57023. }else {computedTransform=new Matrix4$1(new Matrix4().multiplyMatrices(this.tileset.lastRootTransform,this.getContentTransform()).elements);}this.boundingVolume=createBoundingVolume(header.boundingVolume,computedTransform/* this.computedTransform */,this.boundingVolume);var content=header.content;//if(this.boundingVolume.center.y > 500){
  57024. // console.log(this.boundingVolume.center)
  57025. //}
  57026. if(!content){return;}if(content.boundingVolume){this._contentBoundingVolume=createBoundingVolume(content.boundingVolume,computedTransform,this._contentBoundingVolume);}if(header.viewerRequestVolume){this._viewerRequestVolume=createBoundingVolume(header.viewerRequestVolume,computedTransform,this._viewerRequestVolume);}}getBoundUntransformed(){//add 这个会在mesh加载好后才会执行
  57027. this.getContentTransform();var computedTransform2=new Matrix4$1(this.contentTransform.elements);this.boundUntransformed=createBoundingVolume(this.header.boundingVolume,computedTransform2,this.boundUntransformed);//add
  57028. return this.boundUntransformed;}getContentTransform(force){//add 获取该tile在创建boundingVolume时需要的matrix,不包含最外层对整体模型的变换.
  57029. var rtcCenter,contentTransform;if(this.contentTransform&&!force){//无需更新
  57030. return this.contentTransform.clone();}if(this.header.boundingVolume.sphere){this.contentTransform=this.tileset.root.header.boundingVolume.rotGeoToZeroMat;}else {if(!this.tileset.tileTransInvert){this.tileset.tileTransInvert=new Matrix4$1();}this.contentTransform=new Matrix4().fromArray(this.computedTransform).premultiply(new Matrix4().fromArray(this.tileset.tileTransInvert));rtcCenter=!!this.tileset.root.header.boundingVolume.sphere;//针对适应cesium的自带坐标的模型
  57031. if(!rtcCenter){if(this.tileContent){rtcCenter=this.content.rtcCenter;}else {rtcCenter=this.rtcCenterState;}}//rtcCenter = !rtcCenter
  57032. /* let tranM = new Matrix4$1()
  57033. if(!rtcCenter) {
  57034. tranM.makeScale( 1,-1,1)
  57035. }else{
  57036. tranM.makeScale( 1,-1,-1)
  57037. }
  57038. this.contentTransform.premultiply(tranM) */if(!rtcCenter){var tranM=new Matrix4();//tranM.makeScale( 1,-1,1)
  57039. tranM.makeScale(1,1,-1);//大部分是这种情况. 就是因为这个变换才加的这个函数,之前bounding没考虑这个不准。不知道为什么原生的代码不用scaleZ
  57040. this.contentTransform.premultiply(tranM);}//如果有rtcCenter的话一开始boundingVolume不准?会不会有显示问题?
  57041. }return this.contentTransform.clone();}_updateTransform(){var parentTransform=arguments.length>0&&arguments[0]!==undefined?arguments[0]:new Matrix4$1();var computedTransform=parentTransform.clone().multiplyRight(this.transform);var didTransformChange=!computedTransform.equals(this.computedTransform)||!this.tilesetMatrix||!this.tilesetMatrix.equals(this.tileset.modelMatrix);//改 后面加了两个判断,为了在模型移动后更新_updateBoundingVolume
  57042. if(!didTransformChange){return;}this.tileset.modelMatrix;this.computedTransform=computedTransform;this.tilesetMatrix=this.tileset.modelMatrix;//add 标记
  57043. this._updateBoundingVolume(this.header);}_getLoaderSpecificOptions(loaderId){switch(loaderId){case'i3s':return _objectSpread2(_objectSpread2({},this.tileset.options.i3s),{},{tile:this.header,tileset:this.tileset.tileset,isTileHeader:false});case'3d-tiles':case'cesium-ion':default:return get3dTilesOptions(this.tileset.tileset);}}}class Tileset3DTraverser extends TilesetTraverser{compareDistanceToCamera(a,b){return b._distanceToCamera===0&&a._distanceToCamera===0?b._centerZDepth-a._centerZDepth:b._distanceToCamera-a._distanceToCamera;}updateTileVisibility(tile,frameState){super.updateTileVisibility(tile,frameState);if(!tile.isVisibleAndInRequestVolume){return;}var hasChildren=tile.children.length>0;if(tile.hasTilesetContent&&hasChildren){var firstChild=tile.children[0];this.updateTileVisibility(firstChild,frameState);tile._visible=firstChild._visible;return;}if(this.meetsScreenSpaceErrorEarly(tile,frameState)){tile._visible=false;return;}var replace=tile.refine===TILE_REFINEMENT.REPLACE;var useOptimization=tile._optimChildrenWithinParent===TILE3D_OPTIMIZATION_HINT.USE_OPTIMIZATION;if(replace&&useOptimization&&hasChildren){if(!this.anyChildrenVisible(tile,frameState)){tile._visible=false;return;}}}meetsScreenSpaceErrorEarly(tile,frameState){var{parent}=tile;if(!parent||parent.hasTilesetContent||parent.refine!==TILE_REFINEMENT.ADD){return false;}return !this.shouldRefine(tile,frameState,true);}}var STATUS={REQUESTED:'REQUESTED',COMPLETED:'COMPLETED',ERROR:'ERROR'};class I3STileManager{constructor(){_defineProperty$1(this,"_statusMap",void 0);this._statusMap={};}add(request,key,callback,frameState){if(!this._statusMap[key]){this._statusMap[key]={request,callback,key,frameState,status:STATUS.REQUESTED};request().then(data=>{this._statusMap[key].status=STATUS.COMPLETED;this._statusMap[key].callback(data,frameState);}).catch(error=>{this._statusMap[key].status=STATUS.ERROR;callback(error);});}}update(key,frameState){if(this._statusMap[key]){this._statusMap[key].frameState=frameState;}}find(key){return this._statusMap[key];}}class I3STilesetTraverser extends TilesetTraverser{constructor(options){super(options);_defineProperty$1(this,"_tileManager",void 0);this._tileManager=new I3STileManager();}shouldRefine(tile,frameState){tile._lodJudge=getLodStatus(tile,frameState);return tile._lodJudge==='DIG';}updateChildTiles(tile,frameState){var _this=this;var children=tile.header.children||[];var childTiles=tile.children;var tileset=tile.tileset;var _loop2=function _loop2(child){var extendedId="".concat(child.id,"-").concat(frameState.viewport.id);var childTile=childTiles&&childTiles.find(t=>t.id===extendedId);if(!childTile){var request=()=>_this._loadTile(child.id,tileset);var cachedRequest=_this._tileManager.find(extendedId);if(!cachedRequest){if(tileset.tileset.nodePages){request=()=>tileset.tileset.nodePagesTile.formTileFromNodePages(child.id);}_this._tileManager.add(request,extendedId,header=>_this._onTileLoad(header,tile,extendedId),frameState);}else {_this._tileManager.update(extendedId,frameState);}}else if(childTile){_this.updateTile(childTile,frameState);}};for(var child of children){_loop2(child);}return false;}async _loadTile(nodeId,tileset){var{loader}=tileset;var nodeUrl=tileset.getTileUrl("".concat(tileset.url,"/nodes/").concat(nodeId));var options=_objectSpread2(_objectSpread2({},tileset.loadOptions),{},{i3s:_objectSpread2(_objectSpread2({},tileset.loadOptions.i3s),{},{isTileHeader:true,loadContent:false})});return await load(nodeUrl,loader,options);}_onTileLoad(header,tile,extendedId){var childTile=new TileHeader(tile.tileset,header,tile,extendedId);tile.children.push(childTile);var frameState=this._tileManager.find(childTile.id).frameState;this.updateTile(childTile,frameState);if(this._frameNumber===frameState.frameNumber){this.executeTraversal(childTile,frameState);}}}var DEFAULT_PROPS={description:'',ellipsoid:Ellipsoid.WGS84,modelMatrix:new Matrix4$1(),throttleRequests:true,maxRequests:64,maximumMemoryUsage:32,onTileLoad:()=>{},onTileUnload:()=>{},onTileError:()=>{},onTraversalComplete:selectedTiles=>selectedTiles,contentLoader:undefined,viewDistanceScale:1.0,maximumScreenSpaceError:8,loadTiles:true,updateTransforms:true,viewportTraversersMap:null,loadOptions:{fetch:{}},attributions:[],basePath:'',i3s:{}};var TILES_TOTAL='Tiles In Tileset(s)';var TILES_IN_MEMORY='Tiles In Memory';var TILES_IN_VIEW='Tiles In View';var TILES_RENDERABLE='Tiles To Render';var TILES_LOADED='Tiles Loaded';var TILES_LOADING='Tiles Loading';var TILES_UNLOADED='Tiles Unloaded';var TILES_LOAD_FAILED='Failed Tile Loads';var POINTS_COUNT='Points';var TILES_GPU_MEMORY='Tile Memory Use';var tilesetSid=0;//add
  57044. class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
  57045. constructor(json,options){super();viewer.visiVertexCount=viewer.visiVertexCount||0;_defineProperty$1(this,"options",void 0);_defineProperty$1(this,"loadOptions",void 0);_defineProperty$1(this,"type",void 0);_defineProperty$1(this,"tileset",void 0);_defineProperty$1(this,"loader",void 0);_defineProperty$1(this,"url",void 0);_defineProperty$1(this,"basePath",void 0);_defineProperty$1(this,"modelMatrix",void 0);_defineProperty$1(this,"ellipsoid",void 0);_defineProperty$1(this,"lodMetricType",void 0);_defineProperty$1(this,"lodMetricValue",void 0);_defineProperty$1(this,"refine",void 0);_defineProperty$1(this,"root",void 0);_defineProperty$1(this,"roots",void 0);_defineProperty$1(this,"asset",void 0);_defineProperty$1(this,"description",void 0);_defineProperty$1(this,"properties",void 0);_defineProperty$1(this,"extras",void 0);_defineProperty$1(this,"attributions",void 0);_defineProperty$1(this,"credits",void 0);_defineProperty$1(this,"stats",void 0);_defineProperty$1(this,"traverseCounter",void 0);_defineProperty$1(this,"geometricError",void 0);_defineProperty$1(this,"selectedTiles",void 0);_defineProperty$1(this,"cartographicCenter",void 0);_defineProperty$1(this,"cartesianCenter",void 0);_defineProperty$1(this,"zoom",void 0);_defineProperty$1(this,"boundingVolume",void 0);_defineProperty$1(this,"gpuMemoryUsageInBytes",void 0);_defineProperty$1(this,"dynamicScreenSpaceErrorComputedDensity",void 0);_defineProperty$1(this,"_traverser",void 0);_defineProperty$1(this,"_cache",void 0);_defineProperty$1(this,"_requestScheduler",void 0);_defineProperty$1(this,"_frameNumber",void 0);_defineProperty$1(this,"_queryParamsString",void 0);_defineProperty$1(this,"_queryParams",void 0);_defineProperty$1(this,"_extensionsUsed",void 0);_defineProperty$1(this,"_tiles",void 0);_defineProperty$1(this,"_pendingCount",void 0);_defineProperty$1(this,"lastUpdatedVieports",void 0);_defineProperty$1(this,"_requestedTiles",void 0);_defineProperty$1(this,"_emptyTiles",void 0);_defineProperty$1(this,"frameStateData",void 0);_defineProperty$1(this,"maximumMemoryUsage",void 0);_defineProperty$1(this,"visible",true);//add
  57046. assert$7(json);this.options=_objectSpread2(_objectSpread2({},DEFAULT_PROPS),options);this.tileset=json;this.loader=json.loader;this.type=json.type;this.url=json.url;this.basePath=json.basePath||dirname(this.url);this.modelMatrix=this.options.modelMatrix;this.ellipsoid=this.options.ellipsoid;this.lodMetricType=json.lodMetricType;this.lodMetricValue=json.lodMetricValue;this.refine=json.root.refine;this.loadOptions=this.options.loadOptions||{};this.root=null;this.roots={};this.cartographicCenter=null;this.cartesianCenter=null;this.zoom=1;this.boundingVolume=null;this.traverseCounter=0;this.geometricError=0;this._traverser=this._initializeTraverser();this._cache=new TilesetCache();this._requestScheduler=new RequestScheduler({throttleRequests:this.options.throttleRequests,maxRequests:this.options.maxRequests});this._frameNumber=0;this._pendingCount=0;this._tiles={};this.selectedTiles=[];this._emptyTiles=[];this._requestedTiles=[];this.frameStateData={};this.lastUpdatedVieports=null;this._queryParams={};this._queryParamsString='';this.maximumMemoryUsage=this.options.maximumMemoryUsage||32;this.gpuMemoryUsageInBytes=0;this.stats=new Stats({id:this.url});this._initializeStats();this._extensionsUsed=undefined;this.dynamicScreenSpaceErrorComputedDensity=0.0;this.extras=null;this.asset={};this.credits={};this.description=this.options.description||'';this._initializeTileSet(json);}destroy(){this._destroy();}isLoaded(){return this._pendingCount===0&&this._frameNumber!==0;}get tiles(){return Object.values(this._tiles);}get frameNumber(){return this._frameNumber;}get queryParams(){if(!this._queryParamsString){this._queryParamsString=getQueryParamString(this._queryParams);}return this._queryParamsString;}setProps(props){this.options=_objectSpread2(_objectSpread2({},this.options),props);}setOptions(options){this.options=_objectSpread2(_objectSpread2({},this.options),options);}getTileUrl(tilePath){var isDataUrl=tilePath.startsWith('data:');tilePath=Potree.Common.dealURL(tilePath);//add 去除'+'
  57047. if(isDataUrl){return tilePath;}return "".concat(tilePath).concat(this.queryParams);}hasExtension(extensionName){return Boolean(this._extensionsUsed&&this._extensionsUsed.indexOf(extensionName)>-1);}update(viewports){if('loadTiles'in this.options&&!this.options.loadTiles){return;}if(this.traverseCounter>0){return;}if(!viewports&&this.lastUpdatedVieports){viewports=this.lastUpdatedVieports;}else {this.lastUpdatedVieports=viewports;}if(!(viewports instanceof Array)){viewports=[viewports];}this._cache.reset();this._frameNumber++;this.traverseCounter=viewports.length;var viewportsToTraverse=[];for(var viewport of viewports){var id=viewport.id;if(this._needTraverse(id)){viewportsToTraverse.push(id);}else {this.traverseCounter--;}}for(var _viewport of viewports){var _id=_viewport.id;if(!this.roots[_id]){this.roots[_id]=this._initializeTileHeaders(this.tileset,null);}if(!viewportsToTraverse.includes(_id)){continue;}var frameState=getFrameState(_viewport,this._frameNumber);this._traverser.traverse(this.roots[_id],frameState,this.options);}}_needTraverse(viewportId){var traverserId=viewportId;if(this.options.viewportTraversersMap){traverserId=this.options.viewportTraversersMap[viewportId];}if(traverserId!==viewportId){return false;}return true;}_onTraversalEnd(frameState){var id=frameState.viewport.id;if(!this.frameStateData[id]){this.frameStateData[id]={selectedTiles:[],_requestedTiles:[],_emptyTiles:[]};}var currentFrameStateData=this.frameStateData[id];var selectedTiles=Object.values(this._traverser.selectedTiles);currentFrameStateData.selectedTiles=selectedTiles;currentFrameStateData._requestedTiles=Object.values(this._traverser.requestedTiles);currentFrameStateData._emptyTiles=Object.values(this._traverser.emptyTiles);this.traverseCounter--;if(this.traverseCounter>0){return;}this._updateTiles();}_updateTiles(){this.selectedTiles=[];this._requestedTiles=[];this._emptyTiles=[];for(var frameStateKey in this.frameStateData){var frameStateDataValue=this.frameStateData[frameStateKey];this.selectedTiles=this.selectedTiles.concat(frameStateDataValue.selectedTiles);this._requestedTiles=this._requestedTiles.concat(frameStateDataValue._requestedTiles);this._emptyTiles=this._emptyTiles.concat(frameStateDataValue._emptyTiles);}this.selectedTiles=this.options.onTraversalComplete(this.selectedTiles);for(var tile of this.selectedTiles){this._tiles[tile.id]=tile;}this._loadTiles();this._unloadTiles();this._updateStats();}_tilesChanged(oldSelectedTiles,selectedTiles){if(oldSelectedTiles.length!==selectedTiles.length){return true;}var set1=new Set(oldSelectedTiles.map(t=>t.id));var set2=new Set(selectedTiles.map(t=>t.id));var changed=oldSelectedTiles.filter(x=>!set2.has(x.id)).length>0;changed=changed||selectedTiles.filter(x=>!set1.has(x.id)).length>0;return changed;}_loadTiles(){for(var tile of this._requestedTiles){if(tile.contentUnloaded){this._loadTile(tile);}}}_unloadTiles(){this._cache.unloadTiles(this,(tileset,tile)=>tileset._unloadTile(tile));}_updateStats(){var tilesRenderable=0;var pointsRenderable=0;for(var tile of this.selectedTiles){if(tile.contentAvailable&&tile.content){tilesRenderable++;if(tile.content.pointCount){pointsRenderable+=tile.content.pointCount;}}}this.stats.get(TILES_IN_VIEW).count=this.selectedTiles.length;this.stats.get(TILES_RENDERABLE).count=tilesRenderable;this.stats.get(POINTS_COUNT).count=pointsRenderable;}_initializeTileSet(tilesetJson){if(tilesetJson.root.boundingVolume.sphere){//xzw add 针对适应cesium的自带坐标的模型
  57048. //this.boundWhole = new THREE.Box3
  57049. tilesetJson.root.boundingVolume.sphereOri=tilesetJson.root.boundingVolume.sphere;//cesium坐标
  57050. tilesetJson.root.boundingVolume.sphere=[0,0,0,tilesetJson.root.boundingVolume.sphere[3]];//将其转到地球正面(经纬度0,0)
  57051. var origin=new THREE.Vector3().fromArray(tilesetJson.root.boundingVolume.sphereOri);var qua=Potree.math.getQuaFromPosAim(new THREE.Vector3(),origin.normalize());//法向量
  57052. var quaInv=qua.invert();//这样就能朝向(0,0,-1)
  57053. //viewer.objs.children[0].applyQuaternion(quaInv)
  57054. var lastQua=new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI,0,Math.PI));//最后翻转下修正 测出来的
  57055. //viewer.objs.children[0].applyQuaternion(qua1)
  57056. quaInv.premultiply(lastQua);tilesetJson.root.boundingVolume.rotGeoToZeroMat=new THREE.Matrix4().makeRotationFromQuaternion(quaInv);//尚不知是否所有sphere的都带坐标,不是的话再说
  57057. }this.root=this._initializeTileHeaders(tilesetJson,null);if(this.type===TILESET_TYPE.TILES3D){this._initializeCesiumTileset(tilesetJson);}if(this.type===TILESET_TYPE.I3S){this._initializeI3STileset();}this._calculateViewProps();}_calculateViewProps(){var root=this.root;assert$7(root);var{center}=root.boundingVolume;if(!center){console.warn('center was not pre-calculated for the root tile');this.cartographicCenter=new Vector3$1();this.zoom=1;return;}this.cartographicCenter=Ellipsoid.WGS84.cartesianToCartographic(center,new Vector3$1());this.cartesianCenter=center;this.zoom=getZoomFromBoundingVolume(root.boundingVolume);}_initializeStats(){this.stats.get(TILES_TOTAL);this.stats.get(TILES_LOADING);this.stats.get(TILES_IN_MEMORY);this.stats.get(TILES_IN_VIEW);this.stats.get(TILES_RENDERABLE);this.stats.get(TILES_LOADED);this.stats.get(TILES_UNLOADED);this.stats.get(TILES_LOAD_FAILED);this.stats.get(POINTS_COUNT,'memory');this.stats.get(TILES_GPU_MEMORY,'memory');}changeHeaderBoundSphere(header,json){//add 去掉 适应cesium的自带坐标的模型的位移
  57058. if(header.boundingVolume.sphereOri)return;//is root
  57059. var rootVolume=this.root?this.root.header.boundingVolume:json.root.boundingVolume;if(header.boundingVolume.sphere){header.boundingVolume.sphereOri=header.boundingVolume.sphere;for(var _i37=0;_i37<3;_i37++){header.boundingVolume.sphere[_i37]-=rootVolume.sphereOri[_i37];}var center=new THREE.Vector3(...header.boundingVolume.sphere);//this.boundWhole.expandByPoint(center)
  57060. }}_initializeTileHeaders(tilesetJson,parentTileHeader){//建立该tileset的某个json所有tile xzw改
  57061. this.changeHeaderBoundSphere(tilesetJson.root,tilesetJson);//add
  57062. var rootTile=new TileHeader(this,tilesetJson.root,parentTileHeader,parentTileHeader==void 0&&'root_'+tilesetSid++);if(parentTileHeader){parentTileHeader.children.push(rootTile);rootTile.depth=parentTileHeader.depth+1;}if(this.type===TILESET_TYPE.TILES3D){var _stack=[];_stack.push(rootTile);while(_stack.length>0){var tile=_stack.pop();this.stats.get(TILES_TOTAL).incrementCount();var children=tile.header.children||[];// !zeg改
  57063. if(tile.depth</* this.options. */maxDepth){for(var childHeader of children){this.changeHeaderBoundSphere(childHeader,tilesetJson);//xzw add
  57064. var childTile=new TileHeader(this,childHeader,tile);tile.children.push(childTile);childTile.depth=tile.depth+1;_stack.push(childTile);}}window.maxTileDepth=Math.max(window.maxTileDepth||0,tile.depth);}}return rootTile;}_initializeTraverser(){var TraverserClass;var type=this.type;switch(type){case TILESET_TYPE.TILES3D:TraverserClass=Tileset3DTraverser;break;case TILESET_TYPE.I3S:TraverserClass=I3STilesetTraverser;break;default:TraverserClass=TilesetTraverser;}return new TraverserClass({basePath:this.basePath,onTraversalEnd:this._onTraversalEnd.bind(this)});}_destroyTileHeaders(parentTile){this._destroySubtree(parentTile);}async _loadTile(tile){var loaded;try{this._onStartTileLoading();loaded=await tile.loadContent();}catch(error){this._onTileLoadError(tile,error);}finally{this._onEndTileLoading(tile);//
  57065. this._onTileLoad(tile,loaded);}}_onTileLoadError(tile,error){this.stats.get(TILES_LOAD_FAILED).incrementCount();var message=error.message||error.toString();var url=tile.url;console.error("A 3D tile failed to load: ".concat(tile.url," ").concat(message));this.options.onTileError(tile,message,url);}_onTileLoad(tile,loaded){if(!loaded){return;}if(tile&&tile.content){calculateTransformProps(tile,tile.content);}this._addTileToCache(tile);this.options.onTileLoad(tile);}_onStartTileLoading(){this._pendingCount++;this.stats.get(TILES_LOADING).incrementCount();}_onEndTileLoading(tile){this._pendingCount--;this.stats.get(TILES_LOADING).decrementCount();this.dispatchEvent({type:'endTileLoading',tile,loadingCount:this._pendingCount});// !zeg改
  57066. }_addTileToCache(tile){this._cache.add(this,tile,tileset=>tileset._updateCacheStats(tile));}_updateCacheStats(tile){this.stats.get(TILES_LOADED).incrementCount();this.stats.get(TILES_IN_MEMORY).incrementCount();this.gpuMemoryUsageInBytes+=tile.byteLength;this.stats.get(TILES_GPU_MEMORY).count=this.gpuMemoryUsageInBytes;}_unloadTile(tile){this.gpuMemoryUsageInBytes-=tile.byteLength;//
  57067. this.stats.get(TILES_IN_MEMORY).decrementCount();this.stats.get(TILES_UNLOADED).incrementCount();this.stats.get(TILES_GPU_MEMORY).count=this.gpuMemoryUsageInBytes;this.options.onTileUnload(tile);tile.unloadContent();changeModelPointCount(tile,'sub');}_destroy(){var stack=[];if(this.root){stack.push(this.root);}while(stack.length>0){var tile=stack.pop();for(var child of tile.children){stack.push(child);}this._destroyTile(tile);}getGpuMemoryUsage();this.root=null;}_destroySubtree(tile){var root=tile;var stack=[];stack.push(root);while(stack.length>0){tile=stack.pop();for(var child of tile.children){stack.push(child);}if(tile!==root){this._destroyTile(tile);}}root.children=[];}_destroyTile(tile){this._cache.unloadTile(this,tile);this._unloadTile(tile);tile.destroy();}_initializeCesiumTileset(tilesetJson){this.asset=tilesetJson.asset;if(!this.asset){throw new Error('Tileset must have an asset property.');}if(this.asset.version!=='0.0'&&this.asset.version!=='1.0'){throw new Error('The tileset must be 3D Tiles version 0.0 or 1.0.');}if('tilesetVersion'in this.asset){this._queryParams.v=this.asset.tilesetVersion;}this.credits={attributions:this.options.attributions||[]};this.description=this.options.description||'';this.properties=tilesetJson.properties;this.geometricError=tilesetJson.geometricError;this._extensionsUsed=tilesetJson.extensionsUsed;this.extras=tilesetJson.extras;}_initializeI3STileset(){if(this.loadOptions.i3s&&'token'in this.loadOptions.i3s){this._queryParams.token=this.loadOptions.i3s.token;}}}function getQueryParamString(queryParams){var queryParamStrings=[];for(var key of Object.keys(queryParams)){queryParamStrings.push("".concat(key,"=").concat(queryParams[key]));}switch(queryParamStrings.length){case 0:return '';case 1:return "?".concat(queryParamStrings[0]);default:return "?".concat(queryParamStrings.join('&'));}}var VERSION$5="3.1.4";var TILE3D_TYPE={COMPOSITE:'cmpt',POINT_CLOUD:'pnts',BATCHED_3D_MODEL:'b3dm',INSTANCED_3D_MODEL:'i3dm',GEOMETRY:'geom',VECTOR:'vect',GLTF:'glTF'};function getStringFromArrayBuffer(arrayBuffer,byteOffset,byteLength){assert$7(arrayBuffer instanceof ArrayBuffer);var textDecoder=new TextDecoder('utf8');var typedArray=new Uint8Array(arrayBuffer,byteOffset,byteLength);var string=textDecoder.decode(typedArray);return string;}function getMagicString$1(arrayBuffer){var byteOffset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var dataView=new DataView(arrayBuffer);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)));}var VERSION$4="3.1.4";var DEFAULT_DRACO_OPTIONS={draco:{decoderType:typeof WebAssembly==='object'?'wasm':'js',libraryPath:'libs/',extraAttributes:{},attributeNameEntry:undefined}};var DracoLoader$1={name:'Draco',id:'draco',module:'draco',shapes:['mesh'],version:VERSION$4,worker:true,extensions:['drc'],mimeTypes:['application/octet-stream'],binary:true,tests:['DRACO'],options:DEFAULT_DRACO_OPTIONS};function getMeshBoundingBox(attributes){var minX=Infinity;var minY=Infinity;var minZ=Infinity;var maxX=-Infinity;var maxY=-Infinity;var maxZ=-Infinity;var positions=attributes.POSITION?attributes.POSITION.value:[];var len=positions&&positions.length;for(var _i38=0;_i38<len;_i38+=3){var x=positions[_i38];var y=positions[_i38+1];var z=positions[_i38+2];minX=x<minX?x:minX;minY=y<minY?y:minY;minZ=z<minZ?z:minZ;maxX=x>maxX?x:maxX;maxY=y>maxY?y:maxY;maxZ=z>maxZ?z:maxZ;}return [[minX,minY,minZ],[maxX,maxY,maxZ]];}function assert$3(condition,message){if(!condition){throw new Error(message||'loader assertion failed.');}}class Schema{constructor(fields,metadata){_defineProperty$1(this,"fields",void 0);_defineProperty$1(this,"metadata",void 0);assert$3(Array.isArray(fields));checkNames(fields);this.fields=fields;this.metadata=metadata||new Map();}compareTo(other){if(this.metadata!==other.metadata){return false;}if(this.fields.length!==other.fields.length){return false;}for(var _i39=0;_i39<this.fields.length;++_i39){if(!this.fields[_i39].compareTo(other.fields[_i39])){return false;}}return true;}select(){var nameMap=Object.create(null);for(var _len11=arguments.length,columnNames=new Array(_len11),_key11=0;_key11<_len11;_key11++){columnNames[_key11]=arguments[_key11];}for(var _name2 of columnNames){nameMap[_name2]=true;}var selectedFields=this.fields.filter(field=>nameMap[field.name]);return new Schema(selectedFields,this.metadata);}selectAt(){for(var _len12=arguments.length,columnIndices=new Array(_len12),_key12=0;_key12<_len12;_key12++){columnIndices[_key12]=arguments[_key12];}var selectedFields=columnIndices.map(index=>this.fields[index]).filter(Boolean);return new Schema(selectedFields,this.metadata);}assign(schemaOrFields){var fields;var metadata=this.metadata;if(schemaOrFields instanceof Schema){var otherSchema=schemaOrFields;fields=otherSchema.fields;metadata=mergeMaps(mergeMaps(new Map(),this.metadata),otherSchema.metadata);}else {fields=schemaOrFields;}var fieldMap=Object.create(null);for(var field of this.fields){fieldMap[field.name]=field;}for(var _field of fields){fieldMap[_field.name]=_field;}var mergedFields=Object.values(fieldMap);return new Schema(mergedFields,metadata);}}function checkNames(fields){var usedNames={};for(var field of fields){if(usedNames[field.name]){console.warn('Schema: duplicated field name',field.name,field);}usedNames[field.name]=true;}}function mergeMaps(m1,m2){return new Map([...(m1||new Map()),...(m2||new Map())]);}class Field{constructor(name,type){var nullable=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var metadata=arguments.length>3&&arguments[3]!==undefined?arguments[3]:new Map();_defineProperty$1(this,"name",void 0);_defineProperty$1(this,"type",void 0);_defineProperty$1(this,"nullable",void 0);_defineProperty$1(this,"metadata",void 0);this.name=name;this.type=type;this.nullable=nullable;this.metadata=metadata;}get typeId(){return this.type&&this.type.typeId;}clone(){return new Field(this.name,this.type,this.nullable,this.metadata);}compareTo(other){return this.name===other.name&&this.type===other.type&&this.nullable===other.nullable&&this.metadata===other.metadata;}toString(){return "".concat(this.type).concat(this.nullable?', nullable':'').concat(this.metadata?", metadata: ".concat(this.metadata):'');}}var Type;(function(Type){Type[Type["NONE"]=0]="NONE";Type[Type["Null"]=1]="Null";Type[Type["Int"]=2]="Int";Type[Type["Float"]=3]="Float";Type[Type["Binary"]=4]="Binary";Type[Type["Utf8"]=5]="Utf8";Type[Type["Bool"]=6]="Bool";Type[Type["Decimal"]=7]="Decimal";Type[Type["Date"]=8]="Date";Type[Type["Time"]=9]="Time";Type[Type["Timestamp"]=10]="Timestamp";Type[Type["Interval"]=11]="Interval";Type[Type["List"]=12]="List";Type[Type["Struct"]=13]="Struct";Type[Type["Union"]=14]="Union";Type[Type["FixedSizeBinary"]=15]="FixedSizeBinary";Type[Type["FixedSizeList"]=16]="FixedSizeList";Type[Type["Map"]=17]="Map";Type[Type["Dictionary"]=-1]="Dictionary";Type[Type["Int8"]=-2]="Int8";Type[Type["Int16"]=-3]="Int16";Type[Type["Int32"]=-4]="Int32";Type[Type["Int64"]=-5]="Int64";Type[Type["Uint8"]=-6]="Uint8";Type[Type["Uint16"]=-7]="Uint16";Type[Type["Uint32"]=-8]="Uint32";Type[Type["Uint64"]=-9]="Uint64";Type[Type["Float16"]=-10]="Float16";Type[Type["Float32"]=-11]="Float32";Type[Type["Float64"]=-12]="Float64";Type[Type["DateDay"]=-13]="DateDay";Type[Type["DateMillisecond"]=-14]="DateMillisecond";Type[Type["TimestampSecond"]=-15]="TimestampSecond";Type[Type["TimestampMillisecond"]=-16]="TimestampMillisecond";Type[Type["TimestampMicrosecond"]=-17]="TimestampMicrosecond";Type[Type["TimestampNanosecond"]=-18]="TimestampNanosecond";Type[Type["TimeSecond"]=-19]="TimeSecond";Type[Type["TimeMillisecond"]=-20]="TimeMillisecond";Type[Type["TimeMicrosecond"]=-21]="TimeMicrosecond";Type[Type["TimeNanosecond"]=-22]="TimeNanosecond";Type[Type["DenseUnion"]=-23]="DenseUnion";Type[Type["SparseUnion"]=-24]="SparseUnion";Type[Type["IntervalDayTime"]=-25]="IntervalDayTime";Type[Type["IntervalYearMonth"]=-26]="IntervalYearMonth";})(Type||(Type={}));var _Symbol$toStringTag,_Symbol$toStringTag2,_Symbol$toStringTag7;class DataType{static isNull(x){return x&&x.typeId===Type.Null;}static isInt(x){return x&&x.typeId===Type.Int;}static isFloat(x){return x&&x.typeId===Type.Float;}static isBinary(x){return x&&x.typeId===Type.Binary;}static isUtf8(x){return x&&x.typeId===Type.Utf8;}static isBool(x){return x&&x.typeId===Type.Bool;}static isDecimal(x){return x&&x.typeId===Type.Decimal;}static isDate(x){return x&&x.typeId===Type.Date;}static isTime(x){return x&&x.typeId===Type.Time;}static isTimestamp(x){return x&&x.typeId===Type.Timestamp;}static isInterval(x){return x&&x.typeId===Type.Interval;}static isList(x){return x&&x.typeId===Type.List;}static isStruct(x){return x&&x.typeId===Type.Struct;}static isUnion(x){return x&&x.typeId===Type.Union;}static isFixedSizeBinary(x){return x&&x.typeId===Type.FixedSizeBinary;}static isFixedSizeList(x){return x&&x.typeId===Type.FixedSizeList;}static isMap(x){return x&&x.typeId===Type.Map;}static isDictionary(x){return x&&x.typeId===Type.Dictionary;}get typeId(){return Type.NONE;}compareTo(other){return this===other;}}_Symbol$toStringTag=Symbol.toStringTag;class Int extends DataType{constructor(isSigned,bitWidth){super();_defineProperty$1(this,"isSigned",void 0);_defineProperty$1(this,"bitWidth",void 0);this.isSigned=isSigned;this.bitWidth=bitWidth;}get typeId(){return Type.Int;}get[_Symbol$toStringTag](){return 'Int';}toString(){return "".concat(this.isSigned?'I':'Ui',"nt").concat(this.bitWidth);}}class Int8 extends Int{constructor(){super(true,8);}}class Int16 extends Int{constructor(){super(true,16);}}class Int32 extends Int{constructor(){super(true,32);}}class Uint8 extends Int{constructor(){super(false,8);}}class Uint16 extends Int{constructor(){super(false,16);}}class Uint32 extends Int{constructor(){super(false,32);}}var Precision={HALF:16,SINGLE:32,DOUBLE:64};_Symbol$toStringTag2=Symbol.toStringTag;class Float extends DataType{constructor(precision){super();_defineProperty$1(this,"precision",void 0);this.precision=precision;}get typeId(){return Type.Float;}get[_Symbol$toStringTag2](){return 'Float';}toString(){return "Float".concat(this.precision);}}class Float32 extends Float{constructor(){super(Precision.SINGLE);}}class Float64 extends Float{constructor(){super(Precision.DOUBLE);}}_Symbol$toStringTag7=Symbol.toStringTag;class FixedSizeList extends DataType{constructor(listSize,child){super();_defineProperty$1(this,"listSize",void 0);_defineProperty$1(this,"children",void 0);this.listSize=listSize;this.children=[child];}get typeId(){return Type.FixedSizeList;}get valueType(){return this.children[0].type;}get valueField(){return this.children[0];}get[_Symbol$toStringTag7](){return 'FixedSizeList';}toString(){return "FixedSizeList[".concat(this.listSize,"]<").concat(this.valueType,">");}}function getArrowTypeFromTypedArray(array){switch(array.constructor){case Int8Array:return new Int8();case Uint8Array:return new Uint8();case Int16Array:return new Int16();case Uint16Array:return new Uint16();case Int32Array:return new Int32();case Uint32Array:return new Uint32();case Float32Array:return new Float32();case Float64Array:return new Float64();default:throw new Error('array type not supported');}}function deduceMeshField(attributeName,attribute,optionalMetadata){var type=getArrowTypeFromTypedArray(attribute.value);var metadata=optionalMetadata?optionalMetadata:makeMeshAttributeMetadata(attribute);var field=new Field(attributeName,new FixedSizeList(attribute.size,new Field('value',type)),false,metadata);return field;}function makeMeshAttributeMetadata(attribute){var result=new Map();if('byteOffset'in attribute){result.set('byteOffset',attribute.byteOffset.toString(10));}if('byteStride'in attribute){result.set('byteStride',attribute.byteStride.toString(10));}if('normalized'in attribute){result.set('normalized',attribute.normalized.toString());}return result;}function getDracoSchema(attributes,loaderData,indices){var metadataMap=makeMetadata(loaderData.metadata);var fields=[];var namedLoaderDataAttributes=transformAttributesLoaderData(loaderData.attributes);for(var attributeName in attributes){var attribute=attributes[attributeName];var field=getArrowFieldFromAttribute(attributeName,attribute,namedLoaderDataAttributes[attributeName]);fields.push(field);}if(indices){var indicesField=getArrowFieldFromAttribute('indices',indices);fields.push(indicesField);}return new Schema(fields,metadataMap);}function transformAttributesLoaderData(loaderData){var result={};for(var key in loaderData){var dracoAttribute=loaderData[key];result[dracoAttribute.name||'undefined']=dracoAttribute;}return result;}function getArrowFieldFromAttribute(attributeName,attribute,loaderData){var metadataMap=loaderData?makeMetadata(loaderData.metadata):undefined;var field=deduceMeshField(attributeName,attribute,metadataMap);return field;}function makeMetadata(metadata){var metadataMap=new Map();for(var key in metadata){metadataMap.set("".concat(key,".string"),JSON.stringify(metadata[key]));}return metadataMap;}var DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP={POSITION:'POSITION',NORMAL:'NORMAL',COLOR:'COLOR_0',TEX_COORD:'TEXCOORD_0'};var DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP={1:Int8Array,2:Uint8Array,3:Int16Array,4:Uint16Array,5:Int32Array,6:Uint32Array,9:Float32Array};var INDEX_ITEM_SIZE=4;class DracoParser{constructor(draco){_defineProperty$1(this,"draco",void 0);_defineProperty$1(this,"decoder",void 0);_defineProperty$1(this,"metadataQuerier",void 0);this.draco=draco;this.decoder=new this.draco.Decoder();this.metadataQuerier=new this.draco.MetadataQuerier();}destroy(){this.draco.destroy(this.decoder);this.draco.destroy(this.metadataQuerier);}parseSync(arrayBuffer){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var buffer=new this.draco.DecoderBuffer();buffer.Init(new Int8Array(arrayBuffer),arrayBuffer.byteLength);this._disableAttributeTransforms(options);var geometry_type=this.decoder.GetEncodedGeometryType(buffer);var dracoGeometry=geometry_type===this.draco.TRIANGULAR_MESH?new this.draco.Mesh():new this.draco.PointCloud();try{var dracoStatus;switch(geometry_type){case this.draco.TRIANGULAR_MESH:dracoStatus=this.decoder.DecodeBufferToMesh(buffer,dracoGeometry);break;case this.draco.POINT_CLOUD:dracoStatus=this.decoder.DecodeBufferToPointCloud(buffer,dracoGeometry);break;default:throw new Error('DRACO: Unknown geometry type.');}if(!dracoStatus.ok()||!dracoGeometry.ptr){var message="DRACO decompression failed: ".concat(dracoStatus.error_msg());throw new Error(message);}var loaderData=this._getDracoLoaderData(dracoGeometry,geometry_type,options);var geometry=this._getMeshData(dracoGeometry,loaderData,options);var boundingBox=getMeshBoundingBox(geometry.attributes);var schema=getDracoSchema(geometry.attributes,loaderData,geometry.indices);var data=_objectSpread2(_objectSpread2({loader:'draco',loaderData,header:{vertexCount:dracoGeometry.num_points(),boundingBox}},geometry),{},{schema});return data;}finally{this.draco.destroy(buffer);if(dracoGeometry){this.draco.destroy(dracoGeometry);}}}_getDracoLoaderData(dracoGeometry,geometry_type,options){var metadata=this._getTopLevelMetadata(dracoGeometry);var attributes=this._getDracoAttributes(dracoGeometry,options);return {geometry_type,num_attributes:dracoGeometry.num_attributes(),num_points:dracoGeometry.num_points(),num_faces:dracoGeometry instanceof this.draco.Mesh?dracoGeometry.num_faces():0,metadata,attributes};}_getDracoAttributes(dracoGeometry,options){var dracoAttributes={};for(var attributeId=0;attributeId<dracoGeometry.num_attributes();attributeId++){var dracoAttribute=this.decoder.GetAttribute(dracoGeometry,attributeId);var metadata=this._getAttributeMetadata(dracoGeometry,attributeId);dracoAttributes[dracoAttribute.unique_id()]={unique_id:dracoAttribute.unique_id(),attribute_type:dracoAttribute.attribute_type(),data_type:dracoAttribute.data_type(),num_components:dracoAttribute.num_components(),byte_offset:dracoAttribute.byte_offset(),byte_stride:dracoAttribute.byte_stride(),normalized:dracoAttribute.normalized(),attribute_index:attributeId,metadata};var quantization=this._getQuantizationTransform(dracoAttribute,options);if(quantization){dracoAttributes[dracoAttribute.unique_id()].quantization_transform=quantization;}var octahedron=this._getOctahedronTransform(dracoAttribute,options);if(octahedron){dracoAttributes[dracoAttribute.unique_id()].octahedron_transform=octahedron;}}return dracoAttributes;}_getMeshData(dracoGeometry,loaderData,options){var attributes=this._getMeshAttributes(loaderData,dracoGeometry,options);var positionAttribute=attributes.POSITION;if(!positionAttribute){throw new Error('DRACO: No position attribute found.');}if(dracoGeometry instanceof this.draco.Mesh){switch(options.topology){case'triangle-strip':return {topology:'triangle-strip',mode:4,attributes,indices:{value:this._getTriangleStripIndices(dracoGeometry),size:1}};case'triangle-list':default:return {topology:'triangle-list',mode:5,attributes,indices:{value:this._getTriangleListIndices(dracoGeometry),size:1}};}}return {topology:'point-list',mode:0,attributes};}_getMeshAttributes(loaderData,dracoGeometry,options){var attributes={};for(var loaderAttribute of Object.values(loaderData.attributes)){var attributeName=this._deduceAttributeName(loaderAttribute,options);loaderAttribute.name=attributeName;var{value,size}=this._getAttributeValues(dracoGeometry,loaderAttribute);attributes[attributeName]={value,size,byteOffset:loaderAttribute.byte_offset,byteStride:loaderAttribute.byte_stride,normalized:loaderAttribute.normalized};}return attributes;}_getTriangleListIndices(dracoGeometry){var numFaces=dracoGeometry.num_faces();var numIndices=numFaces*3;var byteLength=numIndices*INDEX_ITEM_SIZE;var ptr=this.draco._malloc(byteLength);try{this.decoder.GetTrianglesUInt32Array(dracoGeometry,byteLength,ptr);return new Uint32Array(this.draco.HEAPF32.buffer,ptr,numIndices).slice();}finally{this.draco._free(ptr);}}_getTriangleStripIndices(dracoGeometry){var dracoArray=new this.draco.DracoInt32Array();try{this.decoder.GetTriangleStripsFromMesh(dracoGeometry,dracoArray);return getUint32Array(dracoArray);}finally{this.draco.destroy(dracoArray);}}_getAttributeValues(dracoGeometry,attribute){var TypedArrayCtor=DRACO_DATA_TYPE_TO_TYPED_ARRAY_MAP[attribute.data_type];var numComponents=attribute.num_components;var numPoints=dracoGeometry.num_points();var numValues=numPoints*numComponents;var byteLength=numValues*TypedArrayCtor.BYTES_PER_ELEMENT;var dataType=getDracoDataType(this.draco,TypedArrayCtor);var value;var ptr=this.draco._malloc(byteLength);try{var dracoAttribute=this.decoder.GetAttribute(dracoGeometry,attribute.attribute_index);this.decoder.GetAttributeDataArrayForAllPoints(dracoGeometry,dracoAttribute,dataType,byteLength,ptr);value=new TypedArrayCtor(this.draco.HEAPF32.buffer,ptr,numValues).slice();}finally{this.draco._free(ptr);}return {value,size:numComponents};}_deduceAttributeName(attribute,options){var uniqueId=attribute.unique_id;for(var[attributeName,attributeUniqueId]of Object.entries(options.extraAttributes||{})){if(attributeUniqueId===uniqueId){return attributeName;}}var thisAttributeType=attribute.attribute_type;for(var dracoAttributeConstant in DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP){var attributeType=this.draco[dracoAttributeConstant];if(attributeType===thisAttributeType){return DRACO_TO_GLTF_ATTRIBUTE_NAME_MAP[dracoAttributeConstant];}}var entryName=options.attributeNameEntry||'name';if(attribute.metadata[entryName]){return attribute.metadata[entryName].string;}return "CUSTOM_ATTRIBUTE_".concat(uniqueId);}_getTopLevelMetadata(dracoGeometry){var dracoMetadata=this.decoder.GetMetadata(dracoGeometry);return this._getDracoMetadata(dracoMetadata);}_getAttributeMetadata(dracoGeometry,attributeId){var dracoMetadata=this.decoder.GetAttributeMetadata(dracoGeometry,attributeId);return this._getDracoMetadata(dracoMetadata);}_getDracoMetadata(dracoMetadata){if(!dracoMetadata||!dracoMetadata.ptr){return {};}var result={};var numEntries=this.metadataQuerier.NumEntries(dracoMetadata);for(var entryIndex=0;entryIndex<numEntries;entryIndex++){var entryName=this.metadataQuerier.GetEntryName(dracoMetadata,entryIndex);result[entryName]=this._getDracoMetadataField(dracoMetadata,entryName);}return result;}_getDracoMetadataField(dracoMetadata,entryName){var dracoArray=new this.draco.DracoInt32Array();try{this.metadataQuerier.GetIntEntryArray(dracoMetadata,entryName,dracoArray);var intArray=getInt32Array(dracoArray);return {int:this.metadataQuerier.GetIntEntry(dracoMetadata,entryName),string:this.metadataQuerier.GetStringEntry(dracoMetadata,entryName),double:this.metadataQuerier.GetDoubleEntry(dracoMetadata,entryName),intArray};}finally{this.draco.destroy(dracoArray);}}_disableAttributeTransforms(options){var{quantizedAttributes=[],octahedronAttributes=[]}=options;var skipAttributes=[...quantizedAttributes,...octahedronAttributes];for(var dracoAttributeName of skipAttributes){this.decoder.SkipAttributeTransform(this.draco[dracoAttributeName]);}}_getQuantizationTransform(dracoAttribute,options){var{quantizedAttributes=[]}=options;var attribute_type=dracoAttribute.attribute_type();var skip=quantizedAttributes.map(type=>this.decoder[type]).includes(attribute_type);if(skip){var transform=new this.draco.AttributeQuantizationTransform();try{if(transform.InitFromAttribute(dracoAttribute)){return {quantization_bits:transform.quantization_bits(),range:transform.range(),min_values:new Float32Array([1,2,3]).map(i=>transform.min_value(i))};}}finally{this.draco.destroy(transform);}}return null;}_getOctahedronTransform(dracoAttribute,options){var{octahedronAttributes=[]}=options;var attribute_type=dracoAttribute.attribute_type();var octahedron=octahedronAttributes.map(type=>this.decoder[type]).includes(attribute_type);if(octahedron){var transform=new this.draco.AttributeQuantizationTransform();try{if(transform.InitFromAttribute(dracoAttribute)){return {quantization_bits:transform.quantization_bits()};}}finally{this.draco.destroy(transform);}}return null;}}function getDracoDataType(draco,attributeType){switch(attributeType){case Float32Array:return draco.DT_FLOAT32;case Int8Array:return draco.DT_INT8;case Int16Array:return draco.DT_INT16;case Int32Array:return draco.DT_INT32;case Uint8Array:return draco.DT_UINT8;case Uint16Array:return draco.DT_UINT16;case Uint32Array:return draco.DT_UINT32;default:return draco.DT_INVALID;}}function getInt32Array(dracoArray){var numValues=dracoArray.size();var intArray=new Int32Array(numValues);for(var _i40=0;_i40<numValues;_i40++){intArray[_i40]=dracoArray.GetValue(_i40);}return intArray;}function getUint32Array(dracoArray){var numValues=dracoArray.size();var intArray=new Int32Array(numValues);for(var _i41=0;_i41<numValues;_i41++){intArray[_i41]=dracoArray.GetValue(_i41);}return intArray;}var DRACO_VERSION='1.4.1';var DRACO_JS_DECODER_URL="https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION,"/draco_decoder.js");var DRACO_WASM_WRAPPER_URL="https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION,"/draco_wasm_wrapper.js");var DRACO_WASM_DECODER_URL="https://www.gstatic.com/draco/versioned/decoders/".concat(DRACO_VERSION,"/draco_decoder.wasm");var loadDecoderPromise;async function loadDracoDecoderModule(options){var modules=options.modules||{};if(modules.draco3d){loadDecoderPromise=loadDecoderPromise||modules.draco3d.createDecoderModule({}).then(draco=>{return {draco};});}else {loadDecoderPromise=loadDecoderPromise||loadDracoDecoder(options);}return await loadDecoderPromise;}async function loadDracoDecoder(options){var DracoDecoderModule;var wasmBinary;switch(options.draco&&options.draco.decoderType){case'js':DracoDecoderModule=await loadLibrary(DRACO_JS_DECODER_URL,'draco',options);break;case'wasm':default:[DracoDecoderModule,wasmBinary]=await Promise.all([await loadLibrary(DRACO_WASM_WRAPPER_URL,'draco',options),await loadLibrary(DRACO_WASM_DECODER_URL,'draco',options)]);}DracoDecoderModule=DracoDecoderModule||globalThis.DracoDecoderModule;return await initializeDracoDecoder(DracoDecoderModule,wasmBinary);}function initializeDracoDecoder(DracoDecoderModule,wasmBinary){var options={};if(wasmBinary){options.wasmBinary=wasmBinary;}return new Promise(resolve=>{DracoDecoderModule(_objectSpread2(_objectSpread2({},options),{},{onModuleLoaded:draco=>resolve({draco})}));});}var DracoLoader=_objectSpread2(_objectSpread2({},DracoLoader$1),{},{parse:parse$2});async function parse$2(arrayBuffer,options){var{draco}=await loadDracoDecoderModule(options);var dracoParser=new DracoParser(draco);try{return dracoParser.parseSync(arrayBuffer,options===null||options===void 0?void 0:options.draco);}finally{dracoParser.destroy();}}var GL_PRIMITIVE_MODE={POINTS:0x0000,LINES:0x0001,LINE_LOOP:0x0002,LINE_STRIP:0x0003,TRIANGLES:0x0004,TRIANGLE_STRIP:0x0005,TRIANGLE_FAN:0x0006};var GL_TYPE={BYTE:5120,UNSIGNED_BYTE:5121,SHORT:5122,UNSIGNED_SHORT:5123,INT:5124,UNSIGNED_INT:5125,FLOAT:5126,DOUBLE:5130};var GL$1=_objectSpread2(_objectSpread2({},GL_PRIMITIVE_MODE),GL_TYPE);var GL_TYPE_TO_ARRAY_TYPE={[GL_TYPE.DOUBLE]:Float64Array,[GL_TYPE.FLOAT]:Float32Array,[GL_TYPE.UNSIGNED_SHORT]:Uint16Array,[GL_TYPE.UNSIGNED_INT]:Uint32Array,[GL_TYPE.UNSIGNED_BYTE]:Uint8Array,[GL_TYPE.BYTE]:Int8Array,[GL_TYPE.SHORT]:Int16Array,[GL_TYPE.INT]:Int32Array};var NAME_TO_GL_TYPE={DOUBLE:GL_TYPE.DOUBLE,FLOAT:GL_TYPE.FLOAT,UNSIGNED_SHORT:GL_TYPE.UNSIGNED_SHORT,UNSIGNED_INT:GL_TYPE.UNSIGNED_INT,UNSIGNED_BYTE:GL_TYPE.UNSIGNED_BYTE,BYTE:GL_TYPE.BYTE,SHORT:GL_TYPE.SHORT,INT:GL_TYPE.INT};var ERR_TYPE_CONVERSION='Failed to convert GL type';class GLType{static fromTypedArray(arrayOrType){arrayOrType=ArrayBuffer.isView(arrayOrType)?arrayOrType.constructor:arrayOrType;for(var glType in GL_TYPE_TO_ARRAY_TYPE){var ArrayType=GL_TYPE_TO_ARRAY_TYPE[glType];if(ArrayType===arrayOrType){return glType;}}throw new Error(ERR_TYPE_CONVERSION);}static fromName(name){var glType=NAME_TO_GL_TYPE[name];if(!glType){throw new Error(ERR_TYPE_CONVERSION);}return glType;}static getArrayType(glType){switch(glType){case GL_TYPE.UNSIGNED_SHORT_5_6_5:case GL_TYPE.UNSIGNED_SHORT_4_4_4_4:case GL_TYPE.UNSIGNED_SHORT_5_5_5_1:return Uint16Array;default:var ArrayType=GL_TYPE_TO_ARRAY_TYPE[glType];if(!ArrayType){throw new Error(ERR_TYPE_CONVERSION);}return ArrayType;}}static getByteSize(glType){var ArrayType=GLType.getArrayType(glType);return ArrayType.BYTES_PER_ELEMENT;}static validate(glType){return Boolean(GLType.getArrayType(glType));}static createTypedArray(glType,buffer){var byteOffset=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var length=arguments.length>3?arguments[3]:undefined;if(length===undefined){length=(buffer.byteLength-byteOffset)/GLType.getByteSize(glType);}var ArrayType=GLType.getArrayType(glType);return new ArrayType(buffer,byteOffset,length);}}function assert$2(condition,message){if(!condition){throw new Error("math.gl assertion failed. ".concat(message));}}function decodeRGB565(rgb565){var target=arguments.length>1&&arguments[1]!==undefined?arguments[1]:[0,0,0];var r5=rgb565>>11&31;var g6=rgb565>>5&63;var b5=rgb565&31;target[0]=r5<<3;target[1]=g6<<2;target[2]=b5<<3;return target;}new Vector2$1();new Vector3$1();new Vector2$1();new Vector2$1();function fromSNorm(value){var rangeMaximum=arguments.length>1&&arguments[1]!==undefined?arguments[1]:255;return clamp(value,0.0,rangeMaximum)/rangeMaximum*2.0-1.0;}function signNotZero(value){return value<0.0?-1.0:1.0;}function octDecodeInRange(x,y,rangeMax,result){assert$2(result);if(x<0||x>rangeMax||y<0||y>rangeMax){throw new Error("x and y must be unsigned normalized integers between 0 and ".concat(rangeMax));}result.x=fromSNorm(x,rangeMax);result.y=fromSNorm(y,rangeMax);result.z=1.0-(Math.abs(result.x)+Math.abs(result.y));if(result.z<0.0){var oldVX=result.x;result.x=(1.0-Math.abs(result.y))*signNotZero(oldVX);result.y=(1.0-Math.abs(oldVX))*signNotZero(result.y);}return result.normalize();}function octDecode(x,y,result){return octDecodeInRange(x,y,255,result);}class Tile3DFeatureTable{constructor(featureTableJson,featureTableBinary){_defineProperty$1(this,"json",void 0);_defineProperty$1(this,"buffer",void 0);_defineProperty$1(this,"featuresLength",0);_defineProperty$1(this,"_cachedTypedArrays",{});this.json=featureTableJson;this.buffer=featureTableBinary;}getExtension(extensionName){return this.json.extensions&&this.json.extensions[extensionName];}hasProperty(propertyName){return Boolean(this.json[propertyName]);}getGlobalProperty(propertyName){var componentType=arguments.length>1&&arguments[1]!==undefined?arguments[1]:GL$1.UNSIGNED_INT;var componentLength=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1;var jsonValue=this.json[propertyName];if(jsonValue&&Number.isFinite(jsonValue.byteOffset)){return this._getTypedArrayFromBinary(propertyName,componentType,componentLength,1,jsonValue.byteOffset);}return jsonValue;}getPropertyArray(propertyName,componentType,componentLength){var jsonValue=this.json[propertyName];if(jsonValue&&Number.isFinite(jsonValue.byteOffset)){if('componentType'in jsonValue){componentType=GLType.fromName(jsonValue.componentType);}return this._getTypedArrayFromBinary(propertyName,componentType,componentLength,this.featuresLength,jsonValue.byteOffset);}return this._getTypedArrayFromArray(propertyName,componentType,jsonValue);}getProperty(propertyName,componentType,componentLength,featureId,result){var jsonValue=this.json[propertyName];if(!jsonValue){return jsonValue;}var typedArray=this.getPropertyArray(propertyName,componentType,componentLength);if(componentLength===1){return typedArray[featureId];}for(var _i42=0;_i42<componentLength;++_i42){result[_i42]=typedArray[componentLength*featureId+_i42];}return result;}_getTypedArrayFromBinary(propertyName,componentType,componentLength,count,byteOffset){var cachedTypedArrays=this._cachedTypedArrays;var typedArray=cachedTypedArrays[propertyName];if(!typedArray){typedArray=GLType.createTypedArray(componentType,this.buffer.buffer,this.buffer.byteOffset+byteOffset,count*componentLength);cachedTypedArrays[propertyName]=typedArray;}return typedArray;}_getTypedArrayFromArray(propertyName,componentType,array){var cachedTypedArrays=this._cachedTypedArrays;var typedArray=cachedTypedArrays[propertyName];if(!typedArray){typedArray=GLType.createTypedArray(componentType,array);cachedTypedArrays[propertyName]=typedArray;}return typedArray;}}var COMPONENTS_PER_ATTRIBUTE={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16};var UNPACKER={SCALAR:(values,i)=>values[i],VEC2:(values,i)=>[values[2*i+0],values[2*i+1]],VEC3:(values,i)=>[values[3*i+0],values[3*i+1],values[3*i+2]],VEC4:(values,i)=>[values[4*i+0],values[4*i+1],values[4*i+2],values[4*i+3]],MAT2:(values,i)=>[values[4*i+0],values[4*i+1],values[4*i+2],values[4*i+3]],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]],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]]};var PACKER={SCALAR:(x,values,i)=>{values[i]=x;},VEC2:(x,values,i)=>{values[2*i+0]=x[0];values[2*i+1]=x[1];},VEC3:(x,values,i)=>{values[3*i+0]=x[0];values[3*i+1]=x[1];values[3*i+2]=x[2];},VEC4:(x,values,i)=>{values[4*i+0]=x[0];values[4*i+1]=x[1];values[4*i+2]=x[2];values[4*i+3]=x[3];},MAT2:(x,values,i)=>{values[4*i+0]=x[0];values[4*i+1]=x[1];values[4*i+2]=x[2];values[4*i+3]=x[3];},MAT3:(x,values,i)=>{values[9*i+0]=x[0];values[9*i+1]=x[1];values[9*i+2]=x[2];values[9*i+3]=x[3];values[9*i+4]=x[4];values[9*i+5]=x[5];values[9*i+6]=x[6];values[9*i+7]=x[7];values[9*i+8]=x[8];values[9*i+9]=x[9];},MAT4:(x,values,i)=>{values[16*i+0]=x[0];values[16*i+1]=x[1];values[16*i+2]=x[2];values[16*i+3]=x[3];values[16*i+4]=x[4];values[16*i+5]=x[5];values[16*i+6]=x[6];values[16*i+7]=x[7];values[16*i+8]=x[8];values[16*i+9]=x[9];values[16*i+10]=x[10];values[16*i+11]=x[11];values[16*i+12]=x[12];values[16*i+13]=x[13];values[16*i+14]=x[14];values[16*i+15]=x[15];}};function createTypedArrayFromAccessor(tile3DAccessor,buffer,byteOffset,length){var{componentType}=tile3DAccessor;assert$7(tile3DAccessor.componentType);var type=typeof componentType==='string'?GLType.fromName(componentType):componentType;var size=COMPONENTS_PER_ATTRIBUTE[tile3DAccessor.type];var unpacker=UNPACKER[tile3DAccessor.type];var packer=PACKER[tile3DAccessor.type];byteOffset+=tile3DAccessor.byteOffset;var values=GLType.createTypedArray(type,buffer,byteOffset,size*length);return {values,type,size,unpacker,packer};}var defined$1=x=>x!==undefined;function initializeHierarchy(batchTable,jsonHeader,binaryBody){if(!jsonHeader){return null;}var hierarchy=batchTable.getExtension('3DTILES_batch_table_hierarchy');var legacyHierarchy=jsonHeader.HIERARCHY;if(legacyHierarchy){console.warn('3D Tile Parser: HIERARCHY is deprecated. Use 3DTILES_batch_table_hierarchy.');jsonHeader.extensions=jsonHeader.extensions||{};jsonHeader.extensions['3DTILES_batch_table_hierarchy']=legacyHierarchy;hierarchy=legacyHierarchy;}if(!hierarchy){return null;}return initializeHierarchyValues(hierarchy,binaryBody);}function initializeHierarchyValues(hierarchyJson,binaryBody){var i;var classId;var binaryAccessor;var instancesLength=hierarchyJson.instancesLength;var classes=hierarchyJson.classes;var classIds=hierarchyJson.classIds;var parentCounts=hierarchyJson.parentCounts;var parentIds=hierarchyJson.parentIds;var parentIdsLength=instancesLength;if(defined$1(classIds.byteOffset)){classIds.componentType=defaultValue(classIds.componentType,GL.UNSIGNED_SHORT);classIds.type=AttributeType.SCALAR;binaryAccessor=getBinaryAccessor(classIds);classIds=binaryAccessor.createArrayBufferView(binaryBody.buffer,binaryBody.byteOffset+classIds.byteOffset,instancesLength);}var parentIndexes;if(defined$1(parentCounts)){if(defined$1(parentCounts.byteOffset)){parentCounts.componentType=defaultValue(parentCounts.componentType,GL.UNSIGNED_SHORT);parentCounts.type=AttributeType.SCALAR;binaryAccessor=getBinaryAccessor(parentCounts);parentCounts=binaryAccessor.createArrayBufferView(binaryBody.buffer,binaryBody.byteOffset+parentCounts.byteOffset,instancesLength);}parentIndexes=new Uint16Array(instancesLength);parentIdsLength=0;for(i=0;i<instancesLength;++i){parentIndexes[i]=parentIdsLength;parentIdsLength+=parentCounts[i];}}if(defined$1(parentIds)&&defined$1(parentIds.byteOffset)){parentIds.componentType=defaultValue(parentIds.componentType,GL.UNSIGNED_SHORT);parentIds.type=AttributeType.SCALAR;binaryAccessor=getBinaryAccessor(parentIds);parentIds=binaryAccessor.createArrayBufferView(binaryBody.buffer,binaryBody.byteOffset+parentIds.byteOffset,parentIdsLength);}var classesLength=classes.length;for(i=0;i<classesLength;++i){var classInstancesLength=classes[i].length;var properties=classes[i].instances;var binaryProperties=getBinaryProperties(classInstancesLength,properties,binaryBody);classes[i].instances=combine(binaryProperties,properties);}var classCounts=new Array(classesLength).fill(0);var classIndexes=new Uint16Array(instancesLength);for(i=0;i<instancesLength;++i){classId=classIds[i];classIndexes[i]=classCounts[classId];++classCounts[classId];}var hierarchy={classes,classIds,classIndexes,parentCounts,parentIndexes,parentIds};validateHierarchy(hierarchy);return hierarchy;}function traverseHierarchy(hierarchy,instanceIndex,endConditionCallback){if(!hierarchy){return;}var parentCounts=hierarchy.parentCounts;var parentIds=hierarchy.parentIds;if(parentIds){return endConditionCallback(hierarchy,instanceIndex);}if(parentCounts>0){return traverseHierarchyMultipleParents(hierarchy,instanceIndex,endConditionCallback);}return traverseHierarchySingleParent(hierarchy,instanceIndex,endConditionCallback);}function traverseHierarchyMultipleParents(hierarchy,instanceIndex,endConditionCallback){var classIds=hierarchy.classIds;var parentCounts=hierarchy.parentCounts;var parentIds=hierarchy.parentIds;var parentIndexes=hierarchy.parentIndexes;var instancesLength=classIds.length;var visited=scratchVisited;visited.length=Math.max(visited.length,instancesLength);var visitedMarker=++marker;var stack=scratchStack;stack.length=0;stack.push(instanceIndex);while(stack.length>0){instanceIndex=stack.pop();if(visited[instanceIndex]===visitedMarker){continue;}visited[instanceIndex]=visitedMarker;var result=endConditionCallback(hierarchy,instanceIndex);if(defined$1(result)){return result;}var parentCount=parentCounts[instanceIndex];var parentIndex=parentIndexes[instanceIndex];for(var _i43=0;_i43<parentCount;++_i43){var parentId=parentIds[parentIndex+_i43];if(parentId!==instanceIndex){stack.push(parentId);}}}return null;}function traverseHierarchySingleParent(hierarchy,instanceIndex,endConditionCallback){var hasParent=true;while(hasParent){var result=endConditionCallback(hierarchy,instanceIndex);if(defined$1(result)){return result;}var parentId=hierarchy.parentIds[instanceIndex];hasParent=parentId!==instanceIndex;instanceIndex=parentId;}throw new Error('traverseHierarchySingleParent');}function validateHierarchy(hierarchy){var classIds=hierarchy.classIds;var instancesLength=classIds.length;for(var _i44=0;_i44<instancesLength;++_i44){validateInstance(hierarchy,_i44,stack);}}function validateInstance(hierarchy,instanceIndex,stack){var parentCounts=hierarchy.parentCounts;var parentIds=hierarchy.parentIds;var parentIndexes=hierarchy.parentIndexes;var classIds=hierarchy.classIds;var instancesLength=classIds.length;if(!defined$1(parentIds)){return;}assert(instanceIndex<instancesLength,"Parent index ".concat(instanceIndex," exceeds the total number of instances: ").concat(instancesLength));assert(stack.indexOf(instanceIndex)===-1,'Circular dependency detected in the batch table hierarchy.');stack.push(instanceIndex);var parentCount=defined$1(parentCounts)?parentCounts[instanceIndex]:1;var parentIndex=defined$1(parentCounts)?parentIndexes[instanceIndex]:instanceIndex;for(var _i45=0;_i45<parentCount;++_i45){var parentId=parentIds[parentIndex+_i45];if(parentId!==instanceIndex){validateInstance(hierarchy,parentId,stack);}}stack.pop(instanceIndex);}function defined(x){return x!==undefined&&x!==null;}var clone=(x,y)=>x;var IGNORED_PROPERTY_FIELDS={HIERARCHY:true,extensions:true,extras:true};class Tile3DBatchTableParser{constructor(json,binary,featureCount){var options=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};var _this$json;_defineProperty$1(this,"json",void 0);_defineProperty$1(this,"binary",void 0);_defineProperty$1(this,"featureCount",void 0);_defineProperty$1(this,"_extensions",void 0);_defineProperty$1(this,"_properties",void 0);_defineProperty$1(this,"_binaryProperties",void 0);_defineProperty$1(this,"_hierarchy",void 0);assert$7(featureCount>=0);this.json=json||{};this.binary=binary;this.featureCount=featureCount;this._extensions=((_this$json=this.json)===null||_this$json===void 0?void 0:_this$json.extensions)||{};this._properties={};for(var propertyName in this.json){if(!IGNORED_PROPERTY_FIELDS[propertyName]){this._properties[propertyName]=this.json[propertyName];}}this._binaryProperties=this._initializeBinaryProperties();if(options['3DTILES_batch_table_hierarchy']){this._hierarchy=initializeHierarchy(this,this.json,this.binary);}}getExtension(extensionName){return this.json&&this.json.extensions&&this.json.extensions[extensionName];}memorySizeInBytes(){return 0;}isClass(batchId,className){this._checkBatchId(batchId);assert$7(typeof className==='string',className);if(this._hierarchy){var result=traverseHierarchy(this._hierarchy,batchId,(hierarchy,instanceIndex)=>{var classId=hierarchy.classIds[instanceIndex];var instanceClass=hierarchy.classes[classId];return instanceClass.name===className;});return defined(result);}return false;}isExactClass(batchId,className){assert$7(typeof className==='string',className);return this.getExactClassName(batchId)===className;}getExactClassName(batchId){this._checkBatchId(batchId);if(this._hierarchy){var classId=this._hierarchy.classIds[batchId];var instanceClass=this._hierarchy.classes[classId];return instanceClass.name;}return undefined;}hasProperty(batchId,name){this._checkBatchId(batchId);assert$7(typeof name==='string',name);return defined(this._properties[name])||this._hasPropertyInHierarchy(batchId,name);}getPropertyNames(batchId,results){this._checkBatchId(batchId);results=defined(results)?results:[];results.length=0;var propertyNames=Object.keys(this._properties);results.push(...propertyNames);if(this._hierarchy){this._getPropertyNamesInHierarchy(batchId,results);}return results;}getProperty(batchId,name){this._checkBatchId(batchId);assert$7(typeof name==='string',name);if(this._binaryProperties){var binaryProperty=this._binaryProperties[name];if(defined(binaryProperty)){return this._getBinaryProperty(binaryProperty,batchId);}}var propertyValues=this._properties[name];if(defined(propertyValues)){return clone(propertyValues[batchId]);}if(this._hierarchy){var hierarchyProperty=this._getHierarchyProperty(batchId,name);if(defined(hierarchyProperty)){return hierarchyProperty;}}return undefined;}setProperty(batchId,name,value){var featureCount=this.featureCount;this._checkBatchId(batchId);assert$7(typeof name==='string',name);if(this._binaryProperties){var binaryProperty=this._binaryProperties[name];if(binaryProperty){this._setBinaryProperty(binaryProperty,batchId,value);return;}}if(this._hierarchy){if(this._setHierarchyProperty(this,batchId,name,value)){return;}}var propertyValues=this._properties[name];if(!defined(propertyValues)){this._properties[name]=new Array(featureCount);propertyValues=this._properties[name];}propertyValues[batchId]=clone(value);}_checkBatchId(batchId){var valid=batchId>=0&&batchId<this.featureCount;if(!valid){throw new Error('batchId not in range [0, featureCount - 1].');}}_getBinaryProperty(binaryProperty,index){return binaryProperty.unpack(binaryProperty.typedArray,index);}_setBinaryProperty(binaryProperty,index,value){binaryProperty.pack(value,binaryProperty.typedArray,index);}_initializeBinaryProperties(){var binaryProperties=null;for(var _name3 in this._properties){var property=this._properties[_name3];var binaryProperty=this._initializeBinaryProperty(_name3,property);if(binaryProperty){binaryProperties=binaryProperties||{};binaryProperties[_name3]=binaryProperty;}}return binaryProperties;}_initializeBinaryProperty(name,property){if('byteOffset'in property){var tile3DAccessor=property;assert$7(this.binary,"Property ".concat(name," requires a batch table binary."));assert$7(tile3DAccessor.type,"Property ".concat(name," requires a type."));var accessor=createTypedArrayFromAccessor(tile3DAccessor,this.binary.buffer,this.binary.byteOffset|0,this.featureCount);return {typedArray:accessor.values,componentCount:accessor.size,unpack:accessor.unpacker,pack:accessor.packer};}return null;}_hasPropertyInHierarchy(batchId,name){if(!this._hierarchy){return false;}var result=traverseHierarchy(this._hierarchy,batchId,(hierarchy,instanceIndex)=>{var classId=hierarchy.classIds[instanceIndex];var instances=hierarchy.classes[classId].instances;return defined(instances[name]);});return defined(result);}_getPropertyNamesInHierarchy(batchId,results){traverseHierarchy(this._hierarchy,batchId,(hierarchy,instanceIndex)=>{var classId=hierarchy.classIds[instanceIndex];var instances=hierarchy.classes[classId].instances;for(var _name4 in instances){if(instances.hasOwnProperty(_name4)){if(results.indexOf(_name4)===-1){results.push(_name4);}}}});}_getHierarchyProperty(batchId,name){return traverseHierarchy(this._hierarchy,batchId,(hierarchy,instanceIndex)=>{var classId=hierarchy.classIds[instanceIndex];var instanceClass=hierarchy.classes[classId];var indexInClass=hierarchy.classIndexes[instanceIndex];var propertyValues=instanceClass.instances[name];if(defined(propertyValues)){if(defined(propertyValues.typedArray)){return this._getBinaryProperty(propertyValues,indexInClass);}return clone(propertyValues[indexInClass]);}return null;});}_setHierarchyProperty(batchTable,batchId,name,value){var result=traverseHierarchy(this._hierarchy,batchId,(hierarchy,instanceIndex)=>{var classId=hierarchy.classIds[instanceIndex];var instanceClass=hierarchy.classes[classId];var indexInClass=hierarchy.classIndexes[instanceIndex];var propertyValues=instanceClass.instances[name];if(defined(propertyValues)){assert$7(instanceIndex===batchId,"Inherited property \"".concat(name,"\" is read-only."));if(defined(propertyValues.typedArray)){this._setBinaryProperty(propertyValues,indexInClass,value);}else {propertyValues[indexInClass]=clone(value);}return true;}return false;});return defined(result);}}var SIZEOF_UINT32$1=4;function parse3DTileHeaderSync(tile,arrayBuffer){var byteOffset=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var view=new DataView(arrayBuffer);tile.magic=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32$1;tile.version=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32$1;tile.byteLength=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32$1;if(tile.version!==1){throw new Error("3D Tile Version ".concat(tile.version," not supported"));}return byteOffset;}var SIZEOF_UINT32=4;var DEPRECATION_WARNING='b3dm tile in legacy format.';function parse3DTileTablesHeaderSync(tile,arrayBuffer,byteOffset){var view=new DataView(arrayBuffer);var batchLength;tile.header=tile.header||{};var featureTableJsonByteLength=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32;var featureTableBinaryByteLength=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32;var batchTableJsonByteLength=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32;var batchTableBinaryByteLength=view.getUint32(byteOffset,true);byteOffset+=SIZEOF_UINT32;if(batchTableJsonByteLength>=570425344){byteOffset-=SIZEOF_UINT32*2;batchLength=featureTableJsonByteLength;batchTableJsonByteLength=featureTableBinaryByteLength;batchTableBinaryByteLength=0;featureTableJsonByteLength=0;featureTableBinaryByteLength=0;console.warn(DEPRECATION_WARNING);}else if(batchTableBinaryByteLength>=570425344){byteOffset-=SIZEOF_UINT32;batchLength=batchTableJsonByteLength;batchTableJsonByteLength=featureTableJsonByteLength;batchTableBinaryByteLength=featureTableBinaryByteLength;featureTableJsonByteLength=0;featureTableBinaryByteLength=0;console.warn(DEPRECATION_WARNING);}tile.header.featureTableJsonByteLength=featureTableJsonByteLength;tile.header.featureTableBinaryByteLength=featureTableBinaryByteLength;tile.header.batchTableJsonByteLength=batchTableJsonByteLength;tile.header.batchTableBinaryByteLength=batchTableBinaryByteLength;tile.header.batchLength=batchLength;return byteOffset;}function parse3DTileTablesSync(tile,arrayBuffer,byteOffset,options){byteOffset=parse3DTileFeatureTable(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileBatchTable(tile,arrayBuffer,byteOffset);return byteOffset;}function parse3DTileFeatureTable(tile,arrayBuffer,byteOffset,options){var{featureTableJsonByteLength,featureTableBinaryByteLength,batchLength}=tile.header;tile.featureTableJson={BATCH_LENGTH:batchLength||0};if(featureTableJsonByteLength>0){var featureTableString=getStringFromArrayBuffer(arrayBuffer,byteOffset,featureTableJsonByteLength);tile.featureTableJson=JSON.parse(featureTableString);}byteOffset+=featureTableJsonByteLength;tile.featureTableBinary=new Uint8Array(arrayBuffer,byteOffset,featureTableBinaryByteLength);byteOffset+=featureTableBinaryByteLength;return byteOffset;}function parse3DTileBatchTable(tile,arrayBuffer,byteOffset,options){var{batchTableJsonByteLength,batchTableBinaryByteLength}=tile.header;if(batchTableJsonByteLength>0){var batchTableString=getStringFromArrayBuffer(arrayBuffer,byteOffset,batchTableJsonByteLength);tile.batchTableJson=JSON.parse(batchTableString);byteOffset+=batchTableJsonByteLength;if(batchTableBinaryByteLength>0){tile.batchTableBinary=new Uint8Array(arrayBuffer,byteOffset,batchTableBinaryByteLength);tile.batchTableBinary=new Uint8Array(tile.batchTableBinary);byteOffset+=batchTableBinaryByteLength;}}return byteOffset;}function normalize3DTileColorAttribute(tile,colors,batchTable){if(!colors&&(!tile||!tile.batchIds||!batchTable)){return null;}var{batchIds,isRGB565,pointCount}=tile;if(batchIds&&batchTable){var colorArray=new Uint8ClampedArray(pointCount*3);for(var _i46=0;_i46<pointCount;_i46++){var batchId=batchIds[_i46];var dimensions=batchTable.getProperty(batchId,'dimensions');var color=dimensions.map(d=>d*255);colorArray[_i46*3]=color[0];colorArray[_i46*3+1]=color[1];colorArray[_i46*3+2]=color[2];}return {type:GL$1.UNSIGNED_BYTE,value:colorArray,size:3,normalized:true};}if(isRGB565){var _colorArray=new Uint8ClampedArray(pointCount*3);for(var _i47=0;_i47<pointCount;_i47++){var _color=decodeRGB565(colors[_i47]);_colorArray[_i47*3]=_color[0];_colorArray[_i47*3+1]=_color[1];_colorArray[_i47*3+2]=_color[2];}return {type:GL$1.UNSIGNED_BYTE,value:_colorArray,size:3,normalized:true};}if(colors&&colors.length===pointCount*3){return {type:GL$1.UNSIGNED_BYTE,value:colors,size:3,normalized:true};}return {type:GL$1.UNSIGNED_BYTE,value:colors,size:4,normalized:true};}var scratchNormal=new Vector3$1();function normalize3DTileNormalAttribute(tile,normals){if(!normals){return null;}if(tile.isOctEncoded16P){var decodedArray=new Float32Array(tile.pointsLength*3);for(var _i48=0;_i48<tile.pointsLength;_i48++){octDecode(normals[_i48*2],normals[_i48*2+1],scratchNormal);scratchNormal.toArray(decodedArray,_i48*3);}return {type:GL$1.FLOAT,size:2,value:decodedArray};}return {type:GL$1.FLOAT,size:2,value:normals};}function normalize3DTilePositionAttribute(tile,positions,options){if(!tile.isQuantized){return positions;}if(options['3d-tiles']&&options['3d-tiles'].decodeQuantizedPositions){tile.isQuantized=false;return decodeQuantizedPositions(tile,positions);}return {type:GL$1.UNSIGNED_SHORT,value:positions,size:3,normalized:true};}function decodeQuantizedPositions(tile,positions){var scratchPosition=new Vector3$1();var decodedArray=new Float32Array(tile.pointCount*3);for(var _i49=0;_i49<tile.pointCount;_i49++){scratchPosition.set(positions[_i49*3],positions[_i49*3+1],positions[_i49*3+2]).scale(1/tile.quantizedRange).multiply(tile.quantizedVolumeScale).add(tile.quantizedVolumeOffset).toArray(decodedArray,_i49*3);}return decodedArray;}async function parsePointCloud3DTile(tile,arrayBuffer,byteOffset,options,context){byteOffset=parse3DTileHeaderSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileTablesHeaderSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileTablesSync(tile,arrayBuffer,byteOffset);initializeTile(tile);var{featureTable,batchTable}=parsePointCloudTables(tile);await parseDraco(tile,featureTable,batchTable,options,context);parsePositions(tile,featureTable,options);parseColors(tile,featureTable,batchTable);parseNormals(tile,featureTable);return byteOffset;}function initializeTile(tile){tile.attributes={positions:null,colors:null,normals:null,batchIds:null};tile.isQuantized=false;tile.isTranslucent=false;tile.isRGB565=false;tile.isOctEncoded16P=false;}function parsePointCloudTables(tile){var featureTable=new Tile3DFeatureTable(tile.featureTableJson,tile.featureTableBinary);var pointsLength=featureTable.getGlobalProperty('POINTS_LENGTH');if(!Number.isFinite(pointsLength)){throw new Error('POINTS_LENGTH must be defined');}featureTable.featuresLength=pointsLength;tile.featuresLength=pointsLength;tile.pointsLength=pointsLength;tile.pointCount=pointsLength;tile.rtcCenter=featureTable.getGlobalProperty('RTC_CENTER',GL$1.FLOAT,3);var batchTable=parseBatchIds(tile,featureTable);return {featureTable,batchTable};}function parsePositions(tile,featureTable,options){if(!tile.attributes.positions){if(featureTable.hasProperty('POSITION')){tile.attributes.positions=featureTable.getPropertyArray('POSITION',GL$1.FLOAT,3);}else if(featureTable.hasProperty('POSITION_QUANTIZED')){var positions=featureTable.getPropertyArray('POSITION_QUANTIZED',GL$1.UNSIGNED_SHORT,3);tile.isQuantized=true;tile.quantizedRange=(1<<16)-1;tile.quantizedVolumeScale=featureTable.getGlobalProperty('QUANTIZED_VOLUME_SCALE',GL$1.FLOAT,3);if(!tile.quantizedVolumeScale){throw new Error('QUANTIZED_VOLUME_SCALE must be defined for quantized positions.');}tile.quantizedVolumeOffset=featureTable.getGlobalProperty('QUANTIZED_VOLUME_OFFSET',GL$1.FLOAT,3);if(!tile.quantizedVolumeOffset){throw new Error('QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.');}tile.attributes.positions=normalize3DTilePositionAttribute(tile,positions,options);}}if(!tile.attributes.positions){throw new Error('Either POSITION or POSITION_QUANTIZED must be defined.');}}function parseColors(tile,featureTable,batchTable){if(!tile.attributes.colors){var colors=null;if(featureTable.hasProperty('RGBA')){colors=featureTable.getPropertyArray('RGBA',GL$1.UNSIGNED_BYTE,4);tile.isTranslucent=true;}else if(featureTable.hasProperty('RGB')){colors=featureTable.getPropertyArray('RGB',GL$1.UNSIGNED_BYTE,3);}else if(featureTable.hasProperty('RGB565')){colors=featureTable.getPropertyArray('RGB565',GL$1.UNSIGNED_SHORT,1);tile.isRGB565=true;}tile.attributes.colors=normalize3DTileColorAttribute(tile,colors,batchTable);}if(featureTable.hasProperty('CONSTANT_RGBA')){tile.constantRGBA=featureTable.getGlobalProperty('CONSTANT_RGBA',GL$1.UNSIGNED_BYTE,4);}}function parseNormals(tile,featureTable){if(!tile.attributes.normals){var normals=null;if(featureTable.hasProperty('NORMAL')){normals=featureTable.getPropertyArray('NORMAL',GL$1.FLOAT,3);}else if(featureTable.hasProperty('NORMAL_OCT16P')){normals=featureTable.getPropertyArray('NORMAL_OCT16P',GL$1.UNSIGNED_BYTE,2);tile.isOctEncoded16P=true;}tile.attributes.normals=normalize3DTileNormalAttribute(tile,normals);}}function parseBatchIds(tile,featureTable){var batchTable=null;if(!tile.batchIds&&featureTable.hasProperty('BATCH_ID')){tile.batchIds=featureTable.getPropertyArray('BATCH_ID',GL$1.UNSIGNED_SHORT,1);if(tile.batchIds){var batchFeatureLength=featureTable.getGlobalProperty('BATCH_LENGTH');if(!batchFeatureLength){throw new Error('Global property: BATCH_LENGTH must be defined when BATCH_ID is defined.');}var{batchTableJson,batchTableBinary}=tile;batchTable=new Tile3DBatchTableParser(batchTableJson,batchTableBinary,batchFeatureLength);}}return batchTable;}async function parseDraco(tile,featureTable,batchTable,options,context){var dracoBuffer;var dracoFeatureTableProperties;var dracoBatchTableProperties;var batchTableDraco=tile.batchTableJson&&tile.batchTableJson.extensions&&tile.batchTableJson.extensions['3DTILES_draco_point_compression'];if(batchTableDraco){dracoBatchTableProperties=batchTableDraco.properties;}var featureTableDraco=featureTable.getExtension('3DTILES_draco_point_compression');if(featureTableDraco){dracoFeatureTableProperties=featureTableDraco.properties;var dracoByteOffset=featureTableDraco.byteOffset;var dracoByteLength=featureTableDraco.byteLength;if(!dracoFeatureTableProperties||!Number.isFinite(dracoByteOffset)||!dracoByteLength){throw new Error('Draco properties, byteOffset, and byteLength must be defined');}dracoBuffer=tile.featureTableBinary.slice(dracoByteOffset,dracoByteOffset+dracoByteLength);tile.hasPositions=Number.isFinite(dracoFeatureTableProperties.POSITION);tile.hasColors=Number.isFinite(dracoFeatureTableProperties.RGB)||Number.isFinite(dracoFeatureTableProperties.RGBA);tile.hasNormals=Number.isFinite(dracoFeatureTableProperties.NORMAL);tile.hasBatchIds=Number.isFinite(dracoFeatureTableProperties.BATCH_ID);tile.isTranslucent=Number.isFinite(dracoFeatureTableProperties.RGBA);}if(!dracoBuffer){return true;}var dracoData={buffer:dracoBuffer,properties:_objectSpread2(_objectSpread2({},dracoFeatureTableProperties),dracoBatchTableProperties),featureTableProperties:dracoFeatureTableProperties,batchTableProperties:dracoBatchTableProperties,dequantizeInShader:false};return await loadDraco(tile,dracoData,options,context);}async function loadDraco(tile,dracoData,options,context){var{parse}=context;var dracoOptions=_objectSpread2(_objectSpread2({},options),{},{draco:_objectSpread2(_objectSpread2({},options.draco),{},{extraAttributes:dracoData.batchTableProperties||{}})});delete dracoOptions['3d-tiles'];var data=await parse(dracoData.buffer,DracoLoader,dracoOptions);var decodedPositions=data.attributes.POSITION&&data.attributes.POSITION.value;var decodedColors=data.attributes.COLOR_0&&data.attributes.COLOR_0.value;var decodedNormals=data.attributes.NORMAL&&data.attributes.NORMAL.value;var decodedBatchIds=data.attributes.BATCH_ID&&data.attributes.BATCH_ID.value;var isQuantizedDraco=decodedPositions&&data.attributes.POSITION.value.quantization;var isOctEncodedDraco=decodedNormals&&data.attributes.NORMAL.value.quantization;if(isQuantizedDraco){var quantization=data.POSITION.data.quantization;var range=quantization.range;tile.quantizedVolumeScale=new Vector3$1(range,range,range);tile.quantizedVolumeOffset=new Vector3$1(quantization.minValues);tile.quantizedRange=(1<<quantization.quantizationBits)-1.0;tile.isQuantizedDraco=true;}if(isOctEncodedDraco){tile.octEncodedRange=(1<<data.NORMAL.data.quantization.quantizationBits)-1.0;tile.isOctEncodedDraco=true;}var batchTableAttributes={};if(dracoData.batchTableProperties){for(var attributeName of Object.keys(dracoData.batchTableProperties)){if(data.attributes[attributeName]&&data.attributes[attributeName].value){batchTableAttributes[attributeName.toLowerCase()]=data.attributes[attributeName].value;}}}tile.attributes=_objectSpread2({positions:decodedPositions,colors:normalize3DTileColorAttribute(tile,decodedColors,undefined),normals:decodedNormals,batchIds:decodedBatchIds},batchTableAttributes);}var VERSION$3="3.1.4";var VERSION$2="3.1.4";var VERSION$1="3.1.4";var BASIS_CDN_ENCODER_WASM="https://unpkg.com/@loaders.gl/textures@".concat(VERSION$1,"/dist/libs/basis_encoder.wasm");var BASIS_CDN_ENCODER_JS="https://unpkg.com/@loaders.gl/textures@".concat(VERSION$1,"/dist/libs/basis_encoder.js");var loadBasisTranscoderPromise;async function loadBasisTrascoderModule(options){var modules=options.modules||{};if(modules.basis){return modules.basis;}loadBasisTranscoderPromise=loadBasisTranscoderPromise||loadBasisTrascoder(options);return await loadBasisTranscoderPromise;}async function loadBasisTrascoder(options){var BASIS=null;var wasmBinary=null;[BASIS,wasmBinary]=await Promise.all([await loadLibrary('basis_transcoder.js','textures',options),await loadLibrary('basis_transcoder.wasm','textures',options)]);BASIS=BASIS||globalThis.BASIS;return await initializeBasisTrascoderModule(BASIS,wasmBinary);}function initializeBasisTrascoderModule(BasisModule,wasmBinary){var options={};if(wasmBinary){options.wasmBinary=wasmBinary;}return new Promise(resolve=>{BasisModule(options).then(module=>{var{BasisFile,initializeBasis}=module;initializeBasis();resolve({BasisFile});});});}var loadBasisEncoderPromise;async function loadBasisEncoderModule(options){var modules=options.modules||{};if(modules.basisEncoder){return modules.basisEncoder;}loadBasisEncoderPromise=loadBasisEncoderPromise||loadBasisEncoder(options);return await loadBasisEncoderPromise;}async function loadBasisEncoder(options){var BASIS_ENCODER=null;var wasmBinary=null;[BASIS_ENCODER,wasmBinary]=await Promise.all([await loadLibrary(BASIS_CDN_ENCODER_JS,'textures',options),await loadLibrary(BASIS_CDN_ENCODER_WASM,'textures',options)]);BASIS_ENCODER=BASIS_ENCODER||globalThis.BASIS;return await initializeBasisEncoderModule(BASIS_ENCODER,wasmBinary);}function initializeBasisEncoderModule(BasisEncoderModule,wasmBinary){var options={};if(wasmBinary){options.wasmBinary=wasmBinary;}return new Promise(resolve=>{BasisEncoderModule(options).then(module=>{var{BasisFile,KTX2File,initializeBasis,BasisEncoder}=module;initializeBasis();resolve({BasisFile,KTX2File,BasisEncoder});});});}var GL_EXTENSIONS_CONSTANTS={COMPRESSED_RGB_S3TC_DXT1_EXT:0x83f0,COMPRESSED_RGBA_S3TC_DXT1_EXT:0x83f1,COMPRESSED_RGBA_S3TC_DXT3_EXT:0x83f2,COMPRESSED_RGBA_S3TC_DXT5_EXT:0x83f3,COMPRESSED_R11_EAC:0x9270,COMPRESSED_SIGNED_R11_EAC:0x9271,COMPRESSED_RG11_EAC:0x9272,COMPRESSED_SIGNED_RG11_EAC:0x9273,COMPRESSED_RGB8_ETC2:0x9274,COMPRESSED_RGBA8_ETC2_EAC:0x9275,COMPRESSED_SRGB8_ETC2:0x9276,COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:0x9277,COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:0x9278,COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:0x9279,COMPRESSED_RGB_PVRTC_4BPPV1_IMG:0x8c00,COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:0x8c02,COMPRESSED_RGB_PVRTC_2BPPV1_IMG:0x8c01,COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:0x8c03,COMPRESSED_RGB_ETC1_WEBGL:0x8d64,COMPRESSED_RGB_ATC_WEBGL:0x8c92,COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL:0x8c93,COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL:0x87ee,COMPRESSED_RGBA_ASTC_4X4_KHR:0x93b0,COMPRESSED_RGBA_ASTC_5X4_KHR:0x93b1,COMPRESSED_RGBA_ASTC_5X5_KHR:0x93b2,COMPRESSED_RGBA_ASTC_6X5_KHR:0x93b3,COMPRESSED_RGBA_ASTC_6X6_KHR:0x93b4,COMPRESSED_RGBA_ASTC_8X5_KHR:0x93b5,COMPRESSED_RGBA_ASTC_8X6_KHR:0x93b6,COMPRESSED_RGBA_ASTC_8X8_KHR:0x93b7,COMPRESSED_RGBA_ASTC_10X5_KHR:0x93b8,COMPRESSED_RGBA_ASTC_10X6_KHR:0x93b9,COMPRESSED_RGBA_ASTC_10X8_KHR:0x93ba,COMPRESSED_RGBA_ASTC_10X10_KHR:0x93bb,COMPRESSED_RGBA_ASTC_12X10_KHR:0x93bc,COMPRESSED_RGBA_ASTC_12X12_KHR:0x93bd,COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR:0x93d0,COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR:0x93d1,COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR:0x93d2,COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR:0x93d3,COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR:0x93d4,COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR:0x93d5,COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR:0x93d6,COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR:0x93d7,COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR:0x93d8,COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR:0x93d9,COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR:0x93da,COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR:0x93db,COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR:0x93dc,COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR:0x93dd,COMPRESSED_RED_RGTC1_EXT:0x8dbb,COMPRESSED_SIGNED_RED_RGTC1_EXT:0x8dbc,COMPRESSED_RED_GREEN_RGTC2_EXT:0x8dbd,COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:0x8dbe,COMPRESSED_SRGB_S3TC_DXT1_EXT:0x8c4c,COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:0x8c4d,COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:0x8c4e,COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:0x8c4f};var BROWSER_PREFIXES=['','WEBKIT_','MOZ_'];var WEBGL_EXTENSIONS={WEBGL_compressed_texture_s3tc:'dxt',WEBGL_compressed_texture_s3tc_srgb:'dxt-srgb',WEBGL_compressed_texture_etc1:'etc1',WEBGL_compressed_texture_etc:'etc2',WEBGL_compressed_texture_pvrtc:'pvrtc',WEBGL_compressed_texture_atc:'atc',WEBGL_compressed_texture_astc:'astc',EXT_texture_compression_rgtc:'rgtc'};var formats=null;function getSupportedGPUTextureFormats(gl){if(!formats){gl=gl||getWebGLContext()||undefined;formats=new Set();for(var prefix of BROWSER_PREFIXES){for(var extension in WEBGL_EXTENSIONS){if(gl&&gl.getExtension("".concat(prefix).concat(extension))){var gpuTextureFormat=WEBGL_EXTENSIONS[extension];formats.add(gpuTextureFormat);}}}}return formats;}function getWebGLContext(){try{var canvas=document.createElement('canvas');return canvas.getContext('webgl');}catch(error){return null;}}var n$2,i$3,s$1,a$2,r$1,o$2,l$2,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$3||(i$3={})),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$2||(o$2={})),function(t){t[t.RGB=0]="RGB",t[t.RRR=3]="RRR",t[t.GGG=4]="GGG",t[t.AAA=15]="AAA";}(l$2||(l$2={})),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={}));var KTX2_ID=[0xab,0x4b,0x54,0x58,0x20,0x32,0x30,0xbb,0x0d,0x0a,0x1a,0x0a];function isKTX(data){var id=new Uint8Array(data);var 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];return !notKTX;}var OutputFormat={etc1:{basisFormat:0,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_ETC1_WEBGL},etc2:{basisFormat:1,compressed:true},bc1:{basisFormat:2,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT},bc3:{basisFormat:3,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT},bc4:{basisFormat:4,compressed:true},bc5:{basisFormat:5,compressed:true},'bc7-m6-opaque-only':{basisFormat:6,compressed:true},'bc7-m5':{basisFormat:7,compressed:true},'pvrtc1-4-rgb':{basisFormat:8,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG},'pvrtc1-4-rgba':{basisFormat:9,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG},'astc-4x4':{basisFormat:10,compressed:true,format:GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_ASTC_4X4_KHR},'atc-rgb':{basisFormat:11,compressed:true},'atc-rgba-interpolated-alpha':{basisFormat:12,compressed:true},rgba32:{basisFormat:13,compressed:false},rgb565:{basisFormat:14,compressed:false},bgr565:{basisFormat:15,compressed:false},rgba4444:{basisFormat:16,compressed:false}};async function parseBasis(data,options){if(options.basis.containerFormat==='auto'){if(isKTX(data)){var fileConstructors=await loadBasisEncoderModule(options);return parseKTX2File(fileConstructors.KTX2File,data,options);}var{BasisFile}=await loadBasisTrascoderModule(options);return parseBasisFile(BasisFile,data,options);}switch(options.basis.module){case'encoder':var _fileConstructors=await loadBasisEncoderModule(options);switch(options.basis.containerFormat){case'ktx2':return parseKTX2File(_fileConstructors.KTX2File,data,options);case'basis':default:return parseBasisFile(_fileConstructors.BasisFile,data,options);}case'transcoder':default:var{BasisFile:_BasisFile}=await loadBasisTrascoderModule(options);return parseBasisFile(_BasisFile,data,options);}}function parseBasisFile(BasisFile,data,options){var basisFile=new BasisFile(new Uint8Array(data));try{if(!basisFile.startTranscoding()){return null;}var imageCount=basisFile.getNumImages();var images=[];for(var imageIndex=0;imageIndex<imageCount;imageIndex++){var levelsCount=basisFile.getNumLevels(imageIndex);var levels=[];for(var levelIndex=0;levelIndex<levelsCount;levelIndex++){levels.push(transcodeImage(basisFile,imageIndex,levelIndex,options));}images.push(levels);}return images;}finally{basisFile.close();basisFile.delete();}}function transcodeImage(basisFile,imageIndex,levelIndex,options){var width=basisFile.getImageWidth(imageIndex,levelIndex);var height=basisFile.getImageHeight(imageIndex,levelIndex);var hasAlpha=basisFile.getHasAlpha();var{compressed,format,basisFormat}=getBasisOptions(options,hasAlpha);var decodedSize=basisFile.getImageTranscodedSizeInBytes(imageIndex,levelIndex,basisFormat);var decodedData=new Uint8Array(decodedSize);if(!basisFile.transcodeImage(decodedData,imageIndex,levelIndex,basisFormat,0,0)){return null;}return {width,height,data:decodedData,compressed,hasAlpha,format};}function parseKTX2File(KTX2File,data,options){var ktx2File=new KTX2File(new Uint8Array(data));try{if(!ktx2File.startTranscoding()){return null;}var levelsCount=ktx2File.getLevels();var levels=[];for(var levelIndex=0;levelIndex<levelsCount;levelIndex++){levels.push(transcodeKTX2Image(ktx2File,levelIndex,options));break;}return levels;}finally{ktx2File.close();ktx2File.delete();}}function transcodeKTX2Image(ktx2File,levelIndex,options){var{alphaFlag,height,width}=ktx2File.getImageLevelInfo(levelIndex,0,0);var{compressed,format,basisFormat}=getBasisOptions(options,alphaFlag);var decodedSize=ktx2File.getImageTranscodedSizeInBytes(levelIndex,0,0,basisFormat);var decodedData=new Uint8Array(decodedSize);if(!ktx2File.transcodeImage(decodedData,levelIndex,0,0,basisFormat,0,-1,-1)){return null;}return {width,height,data:decodedData,compressed,alphaFlag,format};}function getBasisOptions(options,hasAlpha){var format=options&&options.basis&&options.basis.format;if(format==='auto'){format=selectSupportedBasisFormat();}if(typeof format==='object'){format=hasAlpha?format.alpha:format.noAlpha;}format=format.toLowerCase();return OutputFormat[format];}function selectSupportedBasisFormat(){var supportedFormats=getSupportedGPUTextureFormats();if(supportedFormats.has('astc')){return 'astc-4x4';}else if(supportedFormats.has('dxt')){return {alpha:'bc3',noAlpha:'bc1'};}else if(supportedFormats.has('pvrtc')){return {alpha:'pvrtc1-4-rgba',noAlpha:'pvrtc1-4-rgb'};}else if(supportedFormats.has('etc1')){return 'etc1';}else if(supportedFormats.has('etc2')){return 'etc2';}return 'rgb565';}var BasisWorkerLoader={name:'Basis',id:'basis',module:'textures',version:VERSION$2,worker:true,extensions:['basis','ktx2'],mimeTypes:['application/octet-stream','image/ktx2'],tests:['sB'],binary:true,options:{basis:{format:'auto',libraryPath:'libs/',containerFormat:'auto',module:'transcoder'}}};var BasisLoader=_objectSpread2(_objectSpread2({},BasisWorkerLoader),{},{parse:parseBasis});var VERSION="3.1.4";var{_parseImageNode}=globalThis;var IMAGE_SUPPORTED=typeof Image!=='undefined';var IMAGE_BITMAP_SUPPORTED=typeof ImageBitmap!=='undefined';var NODE_IMAGE_SUPPORTED=Boolean(_parseImageNode);var DATA_SUPPORTED=isBrowser$2?true:NODE_IMAGE_SUPPORTED;function isImageTypeSupported(type){switch(type){case'auto':return IMAGE_BITMAP_SUPPORTED||IMAGE_SUPPORTED||DATA_SUPPORTED;case'imagebitmap':return IMAGE_BITMAP_SUPPORTED;case'image':return IMAGE_SUPPORTED;case'data':return DATA_SUPPORTED;default:throw new Error("@loaders.gl/images: image ".concat(type," not supported in this environment"));}}function getDefaultImageType(){if(IMAGE_BITMAP_SUPPORTED){return 'imagebitmap';}if(IMAGE_SUPPORTED){return 'image';}if(DATA_SUPPORTED){return 'data';}throw new Error('Install \'@loaders.gl/polyfills\' to parse images under Node.js');}function getImageType(image){var format=getImageTypeOrNull(image);if(!format){throw new Error('Not an image');}return format;}function getImageData(image){switch(getImageType(image)){case'data':return image;case'image':case'imagebitmap':var canvas=document.createElement('canvas');var context=canvas.getContext('2d');if(!context){throw new Error('getImageData');}canvas.width=image.width;canvas.height=image.height;context.drawImage(image,0,0);return context.getImageData(0,0,image.width,image.height);default:throw new Error('getImageData');}}function getImageTypeOrNull(image){if(typeof ImageBitmap!=='undefined'&&image instanceof ImageBitmap){return 'imagebitmap';}if(typeof Image!=='undefined'&&image instanceof Image){return 'image';}if(image&&typeof image==='object'&&image.data&&image.width&&image.height){return 'data';}return null;}var SVG_DATA_URL_PATTERN=/^data:image\/svg\+xml/;var SVG_URL_PATTERN=/\.svg((\?|#).*)?$/;function isSVG(url){return url&&(SVG_DATA_URL_PATTERN.test(url)||SVG_URL_PATTERN.test(url));}function getBlobOrSVGDataUrl(arrayBuffer,url){if(isSVG(url)){var textDecoder=new TextDecoder();var xmlText=textDecoder.decode(arrayBuffer);try{if(typeof unescape==='function'&&typeof encodeURIComponent==='function'){xmlText=unescape(encodeURIComponent(xmlText));}}catch(error){throw new Error(error.message);}var src="data:image/svg+xml;base64,".concat(btoa(xmlText));return src;}return getBlob(arrayBuffer,url);}function getBlob(arrayBuffer,url){if(isSVG(url)){throw new Error('SVG cannot be parsed directly to imagebitmap');}return new Blob([new Uint8Array(arrayBuffer)]);}async function parseToImage(arrayBuffer,options,url){var blobOrDataUrl=getBlobOrSVGDataUrl(arrayBuffer,url);var URL=self.URL||self.webkitURL;var objectUrl=typeof blobOrDataUrl!=='string'&&URL.createObjectURL(blobOrDataUrl);try{return await loadToImage(objectUrl||blobOrDataUrl,options);}finally{if(objectUrl){URL.revokeObjectURL(objectUrl);}}}async function loadToImage(url,options){var image=new Image();image.src=url;if(options.image&&options.image.decode&&image.decode){await image.decode();return image;}return await new Promise((resolve,reject)=>{try{image.onload=()=>resolve(image);image.onerror=err=>reject(new Error("Could not load image ".concat(url,": ").concat(err)));}catch(error){reject(error);}});}var EMPTY_OBJECT={};var imagebitmapOptionsSupported=true;async function parseToImageBitmap(arrayBuffer,options,url){var blob;if(isSVG(url)){var image=await parseToImage(arrayBuffer,options,url);blob=image;}else {blob=getBlob(arrayBuffer,url);}var imagebitmapOptions=options&&options.imagebitmap;return await safeCreateImageBitmap(blob,imagebitmapOptions);}async function safeCreateImageBitmap(blob){var imagebitmapOptions=arguments.length>1&&arguments[1]!==undefined?arguments[1]:null;if(isEmptyObject(imagebitmapOptions)||!imagebitmapOptionsSupported){imagebitmapOptions=null;}if(imagebitmapOptions){try{return await createImageBitmap(blob,imagebitmapOptions);}catch(error){console.warn(error);imagebitmapOptionsSupported=false;}}return await createImageBitmap(blob);}function isEmptyObject(object){for(var key in object||EMPTY_OBJECT){return false;}return true;}var BIG_ENDIAN=false;var LITTLE_ENDIAN=true;function getBinaryImageMetadata(binaryData){var dataView=toDataView(binaryData);return getPngMetadata(dataView)||getJpegMetadata(dataView)||getGifMetadata(dataView)||getBmpMetadata(dataView);}function getPngMetadata(binaryData){var dataView=toDataView(binaryData);var isPng=dataView.byteLength>=24&&dataView.getUint32(0,BIG_ENDIAN)===0x89504e47;if(!isPng){return null;}return {mimeType:'image/png',width:dataView.getUint32(16,BIG_ENDIAN),height:dataView.getUint32(20,BIG_ENDIAN)};}function getGifMetadata(binaryData){var dataView=toDataView(binaryData);var isGif=dataView.byteLength>=10&&dataView.getUint32(0,BIG_ENDIAN)===0x47494638;if(!isGif){return null;}return {mimeType:'image/gif',width:dataView.getUint16(6,LITTLE_ENDIAN),height:dataView.getUint16(8,LITTLE_ENDIAN)};}function getBmpMetadata(binaryData){var dataView=toDataView(binaryData);var isBmp=dataView.byteLength>=14&&dataView.getUint16(0,BIG_ENDIAN)===0x424d&&dataView.getUint32(2,LITTLE_ENDIAN)===dataView.byteLength;if(!isBmp){return null;}return {mimeType:'image/bmp',width:dataView.getUint32(18,LITTLE_ENDIAN),height:dataView.getUint32(22,LITTLE_ENDIAN)};}function getJpegMetadata(binaryData){var dataView=toDataView(binaryData);var isJpeg=dataView.byteLength>=3&&dataView.getUint16(0,BIG_ENDIAN)===0xffd8&&dataView.getUint8(2)===0xff;if(!isJpeg){return null;}var{tableMarkers,sofMarkers}=getJpegMarkers();var i=2;while(i+9<dataView.byteLength){var _marker=dataView.getUint16(i,BIG_ENDIAN);if(sofMarkers.has(_marker)){return {mimeType:'image/jpeg',height:dataView.getUint16(i+5,BIG_ENDIAN),width:dataView.getUint16(i+7,BIG_ENDIAN)};}if(!tableMarkers.has(_marker)){return null;}i+=2;i+=dataView.getUint16(i,BIG_ENDIAN);}return null;}function getJpegMarkers(){var tableMarkers=new Set([0xffdb,0xffc4,0xffcc,0xffdd,0xfffe]);for(var _i50=0xffe0;_i50<0xfff0;++_i50){tableMarkers.add(_i50);}var sofMarkers=new Set([0xffc0,0xffc1,0xffc2,0xffc3,0xffc5,0xffc6,0xffc7,0xffc9,0xffca,0xffcb,0xffcd,0xffce,0xffcf,0xffde]);return {tableMarkers,sofMarkers};}function toDataView(data){if(data instanceof DataView){return data;}if(ArrayBuffer.isView(data)){return new DataView(data.buffer);}if(data instanceof ArrayBuffer){return new DataView(data);}throw new Error('toDataView');}async function parseToNodeImage(arrayBuffer,options){var{mimeType}=getBinaryImageMetadata(arrayBuffer)||{};var _parseImageNode=globalThis._parseImageNode;assert$7(_parseImageNode);return await _parseImageNode(arrayBuffer,mimeType);}async function parseImage(arrayBuffer,options,context){options=options||{};var imageOptions=options.image||{};var imageType=imageOptions.type||'auto';var{url}=context||{};var loadType=getLoadableImageType(imageType);var image;switch(loadType){case'imagebitmap':image=await parseToImageBitmap(arrayBuffer,options,url);break;case'image':image=await parseToImage(arrayBuffer,options,url);break;case'data':image=await parseToNodeImage(arrayBuffer);break;default:assert$7(false);}if(imageType==='data'){image=getImageData(image);}return image;}function getLoadableImageType(type){switch(type){case'auto':case'data':return getDefaultImageType();default:isImageTypeSupported(type);return type;}}var EXTENSIONS$1=['png','jpg','jpeg','gif','webp','bmp','ico','svg'];var MIME_TYPES=['image/png','image/jpeg','image/gif','image/webp','image/bmp','image/vnd.microsoft.icon','image/svg+xml'];var DEFAULT_IMAGE_LOADER_OPTIONS={image:{type:'auto',decode:true}};var ImageLoader$1={id:'image',module:'images',name:'Images',version:VERSION,mimeTypes:MIME_TYPES,extensions:EXTENSIONS$1,parse:parseImage,tests:[arrayBuffer=>Boolean(getBinaryImageMetadata(new DataView(arrayBuffer)))],options:DEFAULT_IMAGE_LOADER_OPTIONS};var NODE_FORMAT_SUPPORT=['image/png','image/jpeg','image/gif'];var mimeTypeSupported={};function _isImageFormatSupported(mimeType){if(mimeTypeSupported[mimeType]===undefined){mimeTypeSupported[mimeType]=checkFormatSupport(mimeType);}return mimeTypeSupported[mimeType];}function checkFormatSupport(mimeType){switch(mimeType){case'image/webp':return checkWebPSupport();case'image/svg':return isBrowser$2;default:if(!isBrowser$2){var{_parseImageNode:_parseImageNode2}=globalThis;return Boolean(_parseImageNode2)&&NODE_FORMAT_SUPPORT.includes(mimeType);}return true;}}function checkWebPSupport(){if(!isBrowser$2){return false;}try{var element=document.createElement('canvas');return element.toDataURL('image/webp').indexOf('data:image/webp')===0;}catch(_unused2){return false;}}function assert$1(condition,message){if(!condition){throw new Error(message||'assert failed: gltf');}}function resolveUrl(url,options){var absolute=url.startsWith('data:')||url.startsWith('http:')||url.startsWith('https:');if(absolute){return url;}var baseUrl=options.baseUri||options.uri;if(!baseUrl){throw new Error("'baseUri' must be provided to resolve relative url ".concat(url));}return baseUrl.substr(0,baseUrl.lastIndexOf('/')+1)+url;}function getTypedArrayForBufferView(json,buffers,bufferViewIndex){var bufferView=json.bufferViews[bufferViewIndex];assert$1(bufferView);var bufferIndex=bufferView.buffer;var binChunk=buffers[bufferIndex];assert$1(binChunk);var byteOffset=(bufferView.byteOffset||0)+binChunk.byteOffset;return new Uint8Array(binChunk.arrayBuffer,byteOffset,bufferView.byteLength);}var TYPES=['SCALAR','VEC2','VEC3','VEC4'];var ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT=[[Int8Array,5120],[Uint8Array,5121],[Int16Array,5122],[Uint16Array,5123],[Uint32Array,5125],[Float32Array,5126],[Float64Array,5130]];var ARRAY_TO_COMPONENT_TYPE=new Map(ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT);var ATTRIBUTE_TYPE_TO_COMPONENTS={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16};var ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE={5120:1,5121:1,5122:2,5123:2,5125:4,5126:4};var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array};function getAccessorTypeFromSize(size){var type=TYPES[size-1];return type||TYPES[0];}function getComponentTypeFromArray(typedArray){var componentType=ARRAY_TO_COMPONENT_TYPE.get(typedArray.constructor);if(!componentType){throw new Error('Illegal typed array');}return componentType;}function getAccessorArrayTypeAndLength(accessor,bufferView){var ArrayType=ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];var components=ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];var bytesPerComponent=ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[accessor.componentType];var length=accessor.count*components;var byteLength=accessor.count*components*bytesPerComponent;assert$1(byteLength>=0&&byteLength<=bufferView.byteLength);return {ArrayType,length,byteLength};}var DEFAULT_GLTF_JSON={asset:{version:'2.0',generator:'loaders.gl'},buffers:[]};class GLTFScenegraph{constructor(gltf){_defineProperty$1(this,"gltf",void 0);_defineProperty$1(this,"sourceBuffers",void 0);_defineProperty$1(this,"byteLength",void 0);this.gltf=gltf||{json:_objectSpread2({},DEFAULT_GLTF_JSON),buffers:[]};this.sourceBuffers=[];this.byteLength=0;if(this.gltf.buffers&&this.gltf.buffers[0]){this.byteLength=this.gltf.buffers[0].byteLength;this.sourceBuffers=[this.gltf.buffers[0]];}}get json(){return this.gltf.json;}getApplicationData(key){var data=this.json[key];return data;}getExtraData(key){var extras=this.json.extras||{};return extras[key];}getExtension(extensionName){var isExtension=this.getUsedExtensions().find(name=>name===extensionName);var extensions=this.json.extensions||{};return isExtension?extensions[extensionName]||true:null;}getRequiredExtension(extensionName){var isRequired=this.getRequiredExtensions().find(name=>name===extensionName);return isRequired?this.getExtension(extensionName):null;}getRequiredExtensions(){return this.json.extensionsRequired||[];}getUsedExtensions(){return this.json.extensionsUsed||[];}getObjectExtension(object,extensionName){var extensions=object.extensions||{};return extensions[extensionName];}getScene(index){return this.getObject('scenes',index);}getNode(index){return this.getObject('nodes',index);}getSkin(index){return this.getObject('skins',index);}getMesh(index){return this.getObject('meshes',index);}getMaterial(index){return this.getObject('materials',index);}getAccessor(index){return this.getObject('accessors',index);}getTexture(index){return this.getObject('textures',index);}getSampler(index){return this.getObject('samplers',index);}getImage(index){return this.getObject('images',index);}getBufferView(index){return this.getObject('bufferViews',index);}getBuffer(index){return this.getObject('buffers',index);}getObject(array,index){if(typeof index==='object'){return index;}var object=this.json[array]&&this.json[array][index];if(!object){throw new Error("glTF file error: Could not find ".concat(array,"[").concat(index,"]"));}return object;}getTypedArrayForBufferView(bufferView){bufferView=this.getBufferView(bufferView);var bufferIndex=bufferView.buffer;var binChunk=this.gltf.buffers[bufferIndex];assert$1(binChunk);var byteOffset=(bufferView.byteOffset||0)+binChunk.byteOffset;return new Uint8Array(binChunk.arrayBuffer,byteOffset,bufferView.byteLength);}getTypedArrayForAccessor(accessor){accessor=this.getAccessor(accessor);var bufferView=this.getBufferView(accessor.bufferView);var buffer=this.getBuffer(bufferView.buffer);var arrayBuffer=buffer.data;var{ArrayType,length}=getAccessorArrayTypeAndLength(accessor,bufferView);var byteOffset=bufferView.byteOffset+accessor.byteOffset;return new ArrayType(arrayBuffer,byteOffset,length);}getTypedArrayForImageData(image){image=this.getAccessor(image);var bufferView=this.getBufferView(image.bufferView);var buffer=this.getBuffer(bufferView.buffer);var arrayBuffer=buffer.data;var byteOffset=bufferView.byteOffset||0;return new Uint8Array(arrayBuffer,byteOffset,bufferView.byteLength);}addApplicationData(key,data){this.json[key]=data;return this;}addExtraData(key,data){this.json.extras=this.json.extras||{};this.json.extras[key]=data;return this;}addObjectExtension(object,extensionName,data){object.extensions=object.extensions||{};object.extensions[extensionName]=data;this.registerUsedExtension(extensionName);return this;}setObjectExtension(object,extensionName,data){var extensions=object.extensions||{};extensions[extensionName]=data;}removeObjectExtension(object,extensionName){var extensions=object.extensions||{};var extension=extensions[extensionName];delete extensions[extensionName];return extension;}addExtension(extensionName){var extensionData=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};assert$1(extensionData);this.json.extensions=this.json.extensions||{};this.json.extensions[extensionName]=extensionData;this.registerUsedExtension(extensionName);return extensionData;}addRequiredExtension(extensionName){var extensionData=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};assert$1(extensionData);this.addExtension(extensionName,extensionData);this.registerRequiredExtension(extensionName);return extensionData;}registerUsedExtension(extensionName){this.json.extensionsUsed=this.json.extensionsUsed||[];if(!this.json.extensionsUsed.find(ext=>ext===extensionName)){this.json.extensionsUsed.push(extensionName);}}registerRequiredExtension(extensionName){this.registerUsedExtension(extensionName);this.json.extensionsRequired=this.json.extensionsRequired||[];if(!this.json.extensionsRequired.find(ext=>ext===extensionName)){this.json.extensionsRequired.push(extensionName);}}removeExtension(extensionName){if(this.json.extensionsRequired){this._removeStringFromArray(this.json.extensionsRequired,extensionName);}if(this.json.extensionsUsed){this._removeStringFromArray(this.json.extensionsUsed,extensionName);}if(this.json.extensions){delete this.json.extensions[extensionName];}}setDefaultScene(sceneIndex){this.json.scene=sceneIndex;}addScene(scene){var{nodeIndices}=scene;this.json.scenes=this.json.scenes||[];this.json.scenes.push({nodes:nodeIndices});return this.json.scenes.length-1;}addNode(node){var{meshIndex,matrix}=node;this.json.nodes=this.json.nodes||[];var nodeData={mesh:meshIndex};if(matrix){nodeData.matrix=matrix;}this.json.nodes.push(nodeData);return this.json.nodes.length-1;}addMesh(mesh){var{attributes,indices,material,mode=4}=mesh;var accessors=this._addAttributes(attributes);var glTFMesh={primitives:[{attributes:accessors,mode}]};if(indices){var indicesAccessor=this._addIndices(indices);glTFMesh.primitives[0].indices=indicesAccessor;}if(Number.isFinite(material)){glTFMesh.primitives[0].material=material;}this.json.meshes=this.json.meshes||[];this.json.meshes.push(glTFMesh);return this.json.meshes.length-1;}addPointCloud(attributes){var accessorIndices=this._addAttributes(attributes);var glTFMesh={primitives:[{attributes:accessorIndices,mode:0}]};this.json.meshes=this.json.meshes||[];this.json.meshes.push(glTFMesh);return this.json.meshes.length-1;}addImage(imageData,mimeTypeOpt){var metadata=getBinaryImageMetadata(imageData);var mimeType=mimeTypeOpt||(metadata===null||metadata===void 0?void 0:metadata.mimeType);var bufferViewIndex=this.addBufferView(imageData);var glTFImage={bufferView:bufferViewIndex,mimeType};this.json.images=this.json.images||[];this.json.images.push(glTFImage);return this.json.images.length-1;}addBufferView(buffer){var byteLength=buffer.byteLength;assert$1(Number.isFinite(byteLength));this.sourceBuffers=this.sourceBuffers||[];this.sourceBuffers.push(buffer);var glTFBufferView={buffer:0,byteOffset:this.byteLength,byteLength};this.byteLength+=padToNBytes(byteLength,4);this.json.bufferViews=this.json.bufferViews||[];this.json.bufferViews.push(glTFBufferView);return this.json.bufferViews.length-1;}addAccessor(bufferViewIndex,accessor){var glTFAccessor={bufferView:bufferViewIndex,type:getAccessorTypeFromSize(accessor.size),componentType:accessor.componentType,count:accessor.count,max:accessor.max,min:accessor.min};this.json.accessors=this.json.accessors||[];this.json.accessors.push(glTFAccessor);return this.json.accessors.length-1;}addBinaryBuffer(sourceBuffer){var accessor=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{size:3};var bufferViewIndex=this.addBufferView(sourceBuffer);var minMax={min:accessor.min,max:accessor.max};if(!minMax.min||!minMax.max){minMax=this._getAccessorMinMax(sourceBuffer,accessor.size);}var accessorDefaults={size:accessor.size,componentType:getComponentTypeFromArray(sourceBuffer),count:Math.round(sourceBuffer.length/accessor.size),min:minMax.min,max:minMax.max};return this.addAccessor(bufferViewIndex,Object.assign(accessorDefaults,accessor));}addTexture(texture){var{imageIndex}=texture;var glTFTexture={source:imageIndex};this.json.textures=this.json.textures||[];this.json.textures.push(glTFTexture);return this.json.textures.length-1;}addMaterial(pbrMaterialInfo){this.json.materials=this.json.materials||[];this.json.materials.push(pbrMaterialInfo);return this.json.materials.length-1;}createBinaryChunk(){var _this$json,_this$json$buffers;this.gltf.buffers=[];var totalByteLength=this.byteLength;var arrayBuffer=new ArrayBuffer(totalByteLength);var targetArray=new Uint8Array(arrayBuffer);var dstByteOffset=0;for(var sourceBuffer of this.sourceBuffers||[]){dstByteOffset=copyToArray(sourceBuffer,targetArray,dstByteOffset);}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]){this.json.buffers[0].byteLength=totalByteLength;}else {this.json.buffers=[{byteLength:totalByteLength}];}this.gltf.binary=arrayBuffer;this.sourceBuffers=[arrayBuffer];}_removeStringFromArray(array,string){var found=true;while(found){var index=array.indexOf(string);if(index>-1){array.splice(index,1);}else {found=false;}}}_addAttributes(){var attributes=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var result={};for(var attributeKey in attributes){var attributeData=attributes[attributeKey];var attrName=this._getGltfAttributeName(attributeKey);var accessor=this.addBinaryBuffer(attributeData.value,attributeData);result[attrName]=accessor;}return result;}_addIndices(indices){return this.addBinaryBuffer(indices,{size:1});}_getGltfAttributeName(attributeName){switch(attributeName.toLowerCase()){case'position':case'positions':case'vertices':return 'POSITION';case'normal':case'normals':return 'NORMAL';case'color':case'colors':return 'COLOR_0';case'texcoord':case'texcoords':return 'TEXCOORD_0';default:return attributeName;}}_getAccessorMinMax(buffer,size){var result={min:null,max:null};if(buffer.length<size){return result;}result.min=[];result.max=[];var initValues=buffer.subarray(0,size);for(var value of initValues){result.min.push(value);result.max.push(value);}for(var index=size;index<buffer.length;index+=size){for(var componentIndex=0;componentIndex<size;componentIndex++){result.min[0+componentIndex]=Math.min(result.min[0+componentIndex],buffer[index+componentIndex]);result.max[0+componentIndex]=Math.max(result.max[0+componentIndex],buffer[index+componentIndex]);}}return result;}}var isWebAssemblySupported=typeof WebAssembly!=='object';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';var 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';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]);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]);var FILTERS={0:'',1:'meshopt_decodeFilterOct',2:'meshopt_decodeFilterQuat',3:'meshopt_decodeFilterExp',NONE:'',OCTAHEDRAL:'meshopt_decodeFilterOct',QUATERNION:'meshopt_decodeFilterQuat',EXPONENTIAL:'meshopt_decodeFilterExp'};var DECODERS={0:'meshopt_decodeVertexBuffer',1:'meshopt_decodeIndexBuffer',2:'meshopt_decodeIndexSequence',ATTRIBUTES:'meshopt_decodeVertexBuffer',TRIANGLES:'meshopt_decodeIndexBuffer',INDICES:'meshopt_decodeIndexSequence'};function isMeshoptSupported(){return isWebAssemblySupported;}async function meshoptDecodeGltfBuffer(target,count,size,source,mode){var filter=arguments.length>5&&arguments[5]!==undefined?arguments[5]:'NONE';var instance=await loadWasmInstance();decode$5(instance,instance.exports[DECODERS[mode]],target,count,size,source,instance.exports[FILTERS[filter||'NONE']]);}var wasmPromise;async function loadWasmInstance(){if(!wasmPromise){wasmPromise=loadWasmModule();}return wasmPromise;}async function loadWasmModule(){var wasm=wasm_base;if(WebAssembly.validate(detector)){wasm=wasm_simd;console.log('Warning: meshopt_decoder is using experimental SIMD support');}var result=await WebAssembly.instantiate(unpack(wasm),{});await result.instance.exports.__wasm_call_ctors();return result.instance;}function unpack(data){var result=new Uint8Array(data.length);for(var _i51=0;_i51<data.length;++_i51){var ch=data.charCodeAt(_i51);result[_i51]=ch>96?ch-71:ch>64?ch-65:ch>47?ch+4:ch>46?63:62;}var write=0;for(var _i52=0;_i52<data.length;++_i52){result[write++]=result[_i52]<60?wasmpack[result[_i52]]:(result[_i52]-60)*64+result[++_i52];}return result.buffer.slice(0,write);}function decode$5(instance,fun,target,count,size,source,filter){var sbrk=instance.exports.sbrk;var count4=count+3&~3;var tp=sbrk(count4*size);var sp=sbrk(source.length);var heap=new Uint8Array(instance.exports.memory.buffer);heap.set(source,sp);var res=fun(tp,count,size,sp,source.length);if(res===0&&filter){filter(tp,count4,size);}target.set(heap.subarray(tp,tp+count*size));sbrk(tp-sbrk(0));if(res!==0){throw new Error("Malformed buffer data: ".concat(res));}}var EXT_MESHOPT_COMPRESSION='EXT_meshopt_compression';var name$6=EXT_MESHOPT_COMPRESSION;function preprocess$4(gltfData){var scenegraph=new GLTFScenegraph(gltfData);if(scenegraph.getRequiredExtensions().includes(EXT_MESHOPT_COMPRESSION)&&!isMeshoptSupported()){throw new Error("gltf: Required extension ".concat(EXT_MESHOPT_COMPRESSION," not supported by browser"));}}async function decode$4(gltfData,options){var _options$gltf;var scenegraph=new GLTFScenegraph(gltfData);if(!(options!==null&&options!==void 0&&(_options$gltf=options.gltf)!==null&&_options$gltf!==void 0&&_options$gltf.decompressMeshes)){return;}var promises=[];for(var bufferViewIndex of gltfData.json.bufferViews||[]){promises.push(decodeMeshoptBufferView(scenegraph,bufferViewIndex));}await Promise.all(promises);scenegraph.removeExtension(EXT_MESHOPT_COMPRESSION);}async function decodeMeshoptBufferView(scenegraph,bufferView){var meshoptExtension=scenegraph.getObjectExtension(bufferView,EXT_MESHOPT_COMPRESSION);if(meshoptExtension){var buffer=bufferView.buffer;var{byteOffset=0,byteLength=0,byteStride,count,mode,filter='NONE'}=meshoptExtension;var source=new Uint8Array(buffer,byteOffset,byteLength);var result=new ArrayBuffer(count*byteStride);await meshoptDecodeGltfBuffer(new Uint8Array(result),count,byteStride,source,mode,filter);return result;}return null;}var EXT_meshopt_compression=/*#__PURE__*/Object.freeze({__proto__:null,name:name$6,preprocess:preprocess$4,decode:decode$4});var EXT_TEXTURE_WEBP='EXT_texture_webp';var name$5=EXT_TEXTURE_WEBP;function preprocess$3(gltfData,options){var scenegraph=new GLTFScenegraph(gltfData);if(!_isImageFormatSupported('image/webp')){if(scenegraph.getRequiredExtensions().includes(EXT_TEXTURE_WEBP)){throw new Error("gltf: Required extension ".concat(EXT_TEXTURE_WEBP," not supported by browser"));}return;}var{json}=scenegraph;for(var texture of json.textures||[]){var extension=scenegraph.getObjectExtension(texture,EXT_TEXTURE_WEBP);if(extension){texture.source=extension.source;}scenegraph.removeObjectExtension(texture,EXT_TEXTURE_WEBP);}scenegraph.removeExtension(EXT_TEXTURE_WEBP);}var EXT_texture_webp=/*#__PURE__*/Object.freeze({__proto__:null,name:name$5,preprocess:preprocess$3});var KHR_TEXTURE_BASISU='KHR_texture_basisu';var name$4=KHR_TEXTURE_BASISU;function preprocess$2(gltfData,options){var scene=new GLTFScenegraph(gltfData);var{json}=scene;for(var texture of json.textures||[]){var extension=scene.getObjectExtension(texture,KHR_TEXTURE_BASISU);if(extension){texture.source=extension.source;}scene.removeObjectExtension(texture,KHR_TEXTURE_BASISU);}scene.removeExtension(KHR_TEXTURE_BASISU);}var KHR_texture_basisu=/*#__PURE__*/Object.freeze({__proto__:null,name:name$4,preprocess:preprocess$2});function getGLTFAccessors(attributes){var accessors={};for(var _name5 in attributes){var attribute=attributes[_name5];if(_name5!=='indices'){var glTFAccessor=getGLTFAccessor(attribute);accessors[_name5]=glTFAccessor;}}return accessors;}function getGLTFAccessor(attribute){var{buffer,size,count}=getAccessorData(attribute);var glTFAccessor={value:buffer,size,byteOffset:0,count,type:getAccessorTypeFromSize(size),componentType:getComponentTypeFromArray(buffer)};return glTFAccessor;}function getAccessorData(attribute){var buffer=attribute;var size=1;var count=0;if(attribute&&attribute.value){buffer=attribute.value;size=attribute.size||1;}if(buffer){if(!ArrayBuffer.isView(buffer)){buffer=toTypedArray(buffer,Float32Array);}count=buffer.length/size;}return {buffer,size,count};}function toTypedArray(array,ArrayType){var convertTypedArrays=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;if(!array){return null;}if(Array.isArray(array)){return new ArrayType(array);}if(convertTypedArrays&&!(array instanceof ArrayType)){return new ArrayType(array);}return array;}var KHR_DRACO_MESH_COMPRESSION='KHR_draco_mesh_compression';var name$3=KHR_DRACO_MESH_COMPRESSION;function preprocess$1(gltfData,options,context){var scenegraph=new GLTFScenegraph(gltfData);for(var primitive of makeMeshPrimitiveIterator(scenegraph)){if(scenegraph.getObjectExtension(primitive,KHR_DRACO_MESH_COMPRESSION));}}async function decode$3(gltfData,options,context){var _options$gltf;if(!(options!==null&&options!==void 0&&(_options$gltf=options.gltf)!==null&&_options$gltf!==void 0&&_options$gltf.decompressMeshes)){return;}var scenegraph=new GLTFScenegraph(gltfData);var promises=[];for(var primitive of makeMeshPrimitiveIterator(scenegraph)){if(scenegraph.getObjectExtension(primitive,KHR_DRACO_MESH_COMPRESSION)){promises.push(decompressPrimitive(scenegraph,primitive,options,context));}}await Promise.all(promises);scenegraph.removeExtension(KHR_DRACO_MESH_COMPRESSION);}function encode$3(gltfData){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var scenegraph=new GLTFScenegraph(gltfData);for(var mesh of scenegraph.json.meshes||[]){compressMesh(mesh);scenegraph.addRequiredExtension(KHR_DRACO_MESH_COMPRESSION);}}async function decompressPrimitive(scenegraph,primitive,options,context){var dracoExtension=scenegraph.getObjectExtension(primitive,KHR_DRACO_MESH_COMPRESSION);if(!dracoExtension){return;}var buffer=scenegraph.getTypedArrayForBufferView(dracoExtension.bufferView);var bufferCopy=sliceArrayBuffer(buffer.buffer,buffer.byteOffset);var{parse}=context;var dracoOptions=_objectSpread2({},options);delete dracoOptions['3d-tiles'];var decodedData=await parse(bufferCopy,DracoLoader,dracoOptions,context);var decodedAttributes=getGLTFAccessors(decodedData.attributes);for(var[attributeName,decodedAttribute]of Object.entries(decodedAttributes)){if(attributeName in primitive.attributes){var accessorIndex=primitive.attributes[attributeName];var accessor=scenegraph.getAccessor(accessorIndex);if(accessor!==null&&accessor!==void 0&&accessor.min&&accessor!==null&&accessor!==void 0&&accessor.max){decodedAttribute.min=accessor.min;decodedAttribute.max=accessor.max;}}}primitive.attributes=decodedAttributes;if(decodedData.indices){primitive.indices=getGLTFAccessor(decodedData.indices);}checkPrimitive(primitive);}function compressMesh(attributes,indices){var mode=arguments.length>2&&arguments[2]!==undefined?arguments[2]:4;var options=arguments.length>3?arguments[3]:undefined;var context=arguments.length>4?arguments[4]:undefined;var _context$parseSync;if(!options.DracoWriter){throw new Error('options.gltf.DracoWriter not provided');}var compressedData=options.DracoWriter.encodeSync({attributes});var decodedData=context===null||context===void 0?void 0:(_context$parseSync=context.parseSync)===null||_context$parseSync===void 0?void 0:_context$parseSync.call(context,{attributes});var fauxAccessors=options._addFauxAttributes(decodedData.attributes);var bufferViewIndex=options.addBufferView(compressedData);var glTFMesh={primitives:[{attributes:fauxAccessors,mode,extensions:{[KHR_DRACO_MESH_COMPRESSION]:{bufferView:bufferViewIndex,attributes:fauxAccessors}}}]};return glTFMesh;}function checkPrimitive(primitive){if(!primitive.attributes&&Object.keys(primitive.attributes).length>0){throw new Error('glTF: Empty primitive detected: Draco decompression failure?');}}function*makeMeshPrimitiveIterator(scenegraph){for(var mesh of scenegraph.json.meshes||[]){for(var primitive of mesh.primitives){yield primitive;}}}var KHR_draco_mesh_compression=/*#__PURE__*/Object.freeze({__proto__:null,name:name$3,preprocess:preprocess$1,decode:decode$3,encode:encode$3});var KHR_LIGHTS_PUNCTUAL='KHR_lights_punctual';var name$2=KHR_LIGHTS_PUNCTUAL;async function decode$2(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;var extension=gltfScenegraph.getExtension(KHR_LIGHTS_PUNCTUAL);if(extension){gltfScenegraph.json.lights=extension.lights;gltfScenegraph.removeExtension(KHR_LIGHTS_PUNCTUAL);}for(var _node of json.nodes||[]){var nodeExtension=gltfScenegraph.getObjectExtension(_node,KHR_LIGHTS_PUNCTUAL);if(nodeExtension){_node.light=nodeExtension.light;}gltfScenegraph.removeObjectExtension(_node,KHR_LIGHTS_PUNCTUAL);}}async function encode$2(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;if(json.lights){var extension=gltfScenegraph.addExtension(KHR_LIGHTS_PUNCTUAL);assert$1(!extension.lights);extension.lights=json.lights;delete json.lights;}if(gltfScenegraph.json.lights){for(var light of gltfScenegraph.json.lights){var _node2=light.node;gltfScenegraph.addObjectExtension(_node2,KHR_LIGHTS_PUNCTUAL,light);}delete gltfScenegraph.json.lights;}}var KHR_lights_punctual=/*#__PURE__*/Object.freeze({__proto__:null,name:name$2,decode:decode$2,encode:encode$2});var KHR_MATERIALS_UNLIT='KHR_materials_unlit';var name$1=KHR_MATERIALS_UNLIT;async function decode$1(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;gltfScenegraph.removeExtension(KHR_MATERIALS_UNLIT);for(var material of json.materials||[]){var extension=material.extensions&&material.extensions.KHR_materials_unlit;if(extension){material.unlit=true;}gltfScenegraph.removeObjectExtension(material,KHR_MATERIALS_UNLIT);}}function encode$1(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;if(gltfScenegraph.materials){for(var material of json.materials||[]){if(material.unlit){delete material.unlit;gltfScenegraph.addObjectExtension(material,KHR_MATERIALS_UNLIT,{});gltfScenegraph.addExtension(KHR_MATERIALS_UNLIT);}}}}var KHR_materials_unlit=/*#__PURE__*/Object.freeze({__proto__:null,name:name$1,decode:decode$1,encode:encode$1});var KHR_TECHNIQUES_WEBGL='KHR_techniques_webgl';var name$7=KHR_TECHNIQUES_WEBGL;async function decode(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;var extension=gltfScenegraph.getExtension(KHR_TECHNIQUES_WEBGL);if(extension){var techniques=resolveTechniques(extension,gltfScenegraph);for(var material of json.materials||[]){var materialExtension=gltfScenegraph.getObjectExtension(material,KHR_TECHNIQUES_WEBGL);if(materialExtension){material.technique=Object.assign({},materialExtension,techniques[materialExtension.technique]);material.technique.values=resolveValues(material.technique,gltfScenegraph);}gltfScenegraph.removeObjectExtension(material,KHR_TECHNIQUES_WEBGL);}gltfScenegraph.removeExtension(KHR_TECHNIQUES_WEBGL);}}async function encode(gltfData,options){}function resolveTechniques(techniquesExtension,gltfScenegraph){var{programs=[],shaders=[],techniques=[]}=techniquesExtension;var textDecoder=new TextDecoder();shaders.forEach(shader=>{if(Number.isFinite(shader.bufferView)){shader.code=textDecoder.decode(gltfScenegraph.getTypedArrayForBufferView(shader.bufferView));}else {throw new Error('KHR_techniques_webgl: no shader code');}});programs.forEach(program=>{program.fragmentShader=shaders[program.fragmentShader];program.vertexShader=shaders[program.vertexShader];});techniques.forEach(technique=>{technique.program=programs[technique.program];});return techniques;}function resolveValues(technique,gltfScenegraph){var values=Object.assign({},technique.values);Object.keys(technique.uniforms||{}).forEach(uniform=>{if(technique.uniforms[uniform].value&&!(uniform in values)){values[uniform]=technique.uniforms[uniform].value;}});Object.keys(values).forEach(uniform=>{if(typeof values[uniform]==='object'&&values[uniform].index!==undefined){values[uniform].texture=gltfScenegraph.getTexture(values[uniform].index);}});return values;}var KHR_techniques_webgl=/*#__PURE__*/Object.freeze({__proto__:null,name:name$7,decode:decode,encode:encode});var EXTENSIONS=[EXT_meshopt_compression,EXT_texture_webp,KHR_texture_basisu,KHR_draco_mesh_compression,KHR_lights_punctual,KHR_materials_unlit,KHR_techniques_webgl];function preprocessExtensions(gltf){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var context=arguments.length>2?arguments[2]:undefined;var extensions=EXTENSIONS.filter(extension=>useExtension(extension.name,options));for(var extension of extensions){var _extension$preprocess;(_extension$preprocess=extension.preprocess)===null||_extension$preprocess===void 0?void 0:_extension$preprocess.call(extension,gltf,options,context);}}async function decodeExtensions(gltf){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var context=arguments.length>2?arguments[2]:undefined;var extensions=EXTENSIONS.filter(extension=>useExtension(extension.name,options));for(var extension of extensions){var _extension$decode;await((_extension$decode=extension.decode)===null||_extension$decode===void 0?void 0:_extension$decode.call(extension,gltf,options,context));}}function useExtension(extensionName,options){var _options$gltf;var excludes=(options===null||options===void 0?void 0:(_options$gltf=options.gltf)===null||_options$gltf===void 0?void 0:_options$gltf.excludeExtensions)||{};var exclude=extensionName in excludes&&!excludes[extensionName];return !exclude;}var KHR_BINARY_GLTF='KHR_binary_glTF';function preprocess(gltfData){var gltfScenegraph=new GLTFScenegraph(gltfData);var{json}=gltfScenegraph;for(var image of json.images||[]){var extension=gltfScenegraph.getObjectExtension(image,KHR_BINARY_GLTF);if(extension){Object.assign(image,extension);}gltfScenegraph.removeObjectExtension(image,KHR_BINARY_GLTF);}if(json.buffers&&json.buffers[0]){delete json.buffers[0].uri;}gltfScenegraph.removeExtension(KHR_BINARY_GLTF);}var GLTF_ARRAYS={accessors:'accessor',animations:'animation',buffers:'buffer',bufferViews:'bufferView',images:'image',materials:'material',meshes:'mesh',nodes:'node',samplers:'sampler',scenes:'scene',skins:'skin',textures:'texture'};var GLTF_KEYS={accessor:'accessors',animations:'animation',buffer:'buffers',bufferView:'bufferViews',image:'images',material:'materials',mesh:'meshes',node:'nodes',sampler:'samplers',scene:'scenes',skin:'skins',texture:'textures'};class GLTFV1Normalizer{constructor(){_defineProperty$1(this,"idToIndexMap",{animations:{},accessors:{},buffers:{},bufferViews:{},images:{},materials:{},meshes:{},nodes:{},samplers:{},scenes:{},skins:{},textures:{}});_defineProperty$1(this,"json",void 0);}normalize(gltf,options){this.json=gltf.json;var json=gltf.json;switch(json.asset&&json.asset.version){case'2.0':return;case undefined:case'1.0':break;default:console.warn("glTF: Unknown version ".concat(json.asset.version));return;}if(!options.normalize){throw new Error('glTF v1 is not supported.');}console.warn('Converting glTF v1 to glTF v2 format. This is experimental and may fail.');this._addAsset(json);this._convertTopLevelObjectsToArrays(json);preprocess(gltf);this._convertObjectIdsToArrayIndices(json);this._updateObjects(json);this._updateMaterial(json);}_addAsset(json){json.asset=json.asset||{};json.asset.version='2.0';json.asset.generator=json.asset.generator||'Normalized to glTF 2.0 by loaders.gl';}_convertTopLevelObjectsToArrays(json){for(var arrayName in GLTF_ARRAYS){this._convertTopLevelObjectToArray(json,arrayName);}}_convertTopLevelObjectToArray(json,mapName){var objectMap=json[mapName];if(!objectMap||Array.isArray(objectMap)){return;}json[mapName]=[];for(var id in objectMap){var object=objectMap[id];object.id=object.id||id;var index=json[mapName].length;json[mapName].push(object);this.idToIndexMap[mapName][id]=index;}}_convertObjectIdsToArrayIndices(json){for(var arrayName in GLTF_ARRAYS){this._convertIdsToIndices(json,arrayName);}if('scene'in json){json.scene=this._convertIdToIndex(json.scene,'scene');}for(var texture of json.textures){this._convertTextureIds(texture);}for(var mesh of json.meshes){this._convertMeshIds(mesh);}for(var _node3 of json.nodes){this._convertNodeIds(_node3);}for(var _node4 of json.scenes){this._convertSceneIds(_node4);}}_convertTextureIds(texture){if(texture.source){texture.source=this._convertIdToIndex(texture.source,'image');}}_convertMeshIds(mesh){for(var primitive of mesh.primitives){var{attributes,indices,material}=primitive;for(var attributeName in attributes){attributes[attributeName]=this._convertIdToIndex(attributes[attributeName],'accessor');}if(indices){primitive.indices=this._convertIdToIndex(indices,'accessor');}if(material){primitive.material=this._convertIdToIndex(material,'material');}}}_convertNodeIds(node){if(node.children){node.children=node.children.map(child=>this._convertIdToIndex(child,'node'));}if(node.meshes){node.meshes=node.meshes.map(mesh=>this._convertIdToIndex(mesh,'mesh'));}}_convertSceneIds(scene){if(scene.nodes){scene.nodes=scene.nodes.map(node=>this._convertIdToIndex(node,'node'));}}_convertIdsToIndices(json,topLevelArrayName){if(!json[topLevelArrayName]){console.warn("gltf v1: json doesn't contain attribute ".concat(topLevelArrayName));json[topLevelArrayName]=[];}for(var object of json[topLevelArrayName]){for(var key in object){var id=object[key];var index=this._convertIdToIndex(id,key);object[key]=index;}}}_convertIdToIndex(id,key){var arrayName=GLTF_KEYS[key];if(arrayName in this.idToIndexMap){var index=this.idToIndexMap[arrayName][id];if(!Number.isFinite(index)){throw new Error("gltf v1: failed to resolve ".concat(key," with id ").concat(id));}return index;}return id;}_updateObjects(json){for(var buffer of this.json.buffers){delete buffer.type;}}_updateMaterial(json){var _loop3=function _loop3(){material.pbrMetallicRoughness={baseColorFactor:[1,1,1,1],metallicFactor:1,roughnessFactor:1};var textureId=material.values&&material.values.tex;var textureIndex=json.textures.findIndex(texture=>texture.id===textureId);if(textureIndex!==-1){material.pbrMetallicRoughness.baseColorTexture={index:textureIndex};}};for(var material of json.materials){_loop3();}}}function normalizeGLTFV1(gltf){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return new GLTFV1Normalizer().normalize(gltf,options);}var COMPONENTS={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16};var BYTES={5120:1,5121:1,5122:2,5123:2,5125:4,5126:4};var GL_SAMPLER={TEXTURE_MAG_FILTER:0x2800,TEXTURE_MIN_FILTER:0x2801,TEXTURE_WRAP_S:0x2802,TEXTURE_WRAP_T:0x2803,REPEAT:0x2901,LINEAR:0x2601,NEAREST_MIPMAP_LINEAR:0x2702};var SAMPLER_PARAMETER_GLTF_TO_GL={magFilter:GL_SAMPLER.TEXTURE_MAG_FILTER,minFilter:GL_SAMPLER.TEXTURE_MIN_FILTER,wrapS:GL_SAMPLER.TEXTURE_WRAP_S,wrapT:GL_SAMPLER.TEXTURE_WRAP_T};var DEFAULT_SAMPLER={[GL_SAMPLER.TEXTURE_MAG_FILTER]:GL_SAMPLER.LINEAR,[GL_SAMPLER.TEXTURE_MIN_FILTER]:GL_SAMPLER.NEAREST_MIPMAP_LINEAR,[GL_SAMPLER.TEXTURE_WRAP_S]:GL_SAMPLER.REPEAT,[GL_SAMPLER.TEXTURE_WRAP_T]:GL_SAMPLER.REPEAT};function getBytesFromComponentType(componentType){return BYTES[componentType];}function getSizeFromAccessorType(type){return COMPONENTS[type];}class GLTFPostProcessor{constructor(){_defineProperty$1(this,"baseUri",'');_defineProperty$1(this,"json",{});_defineProperty$1(this,"buffers",[]);_defineProperty$1(this,"images",[]);}postProcess(gltf){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var{json,buffers=[],images=[],baseUri=''}=gltf;assert$1(json);this.baseUri=baseUri;this.json=json;this.buffers=buffers;this.images=images;this._resolveTree(this.json,options);return this.json;}_resolveTree(json){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};if(json.bufferViews){json.bufferViews=json.bufferViews.map((bufView,i)=>this._resolveBufferView(bufView,i));}if(json.images){json.images=json.images.map((image,i)=>this._resolveImage(image,i));}if(json.samplers){json.samplers=json.samplers.map((sampler,i)=>this._resolveSampler(sampler,i));}if(json.textures){json.textures=json.textures.map((texture,i)=>this._resolveTexture(texture,i));}if(json.accessors){json.accessors=json.accessors.map((accessor,i)=>this._resolveAccessor(accessor,i));}if(json.materials){json.materials=json.materials.map((material,i)=>this._resolveMaterial(material,i));}if(json.meshes){json.meshes=json.meshes.map((mesh,i)=>this._resolveMesh(mesh,i));}if(json.nodes){json.nodes=json.nodes.map((node,i)=>this._resolveNode(node,i));}if(json.skins){json.skins=json.skins.map((skin,i)=>this._resolveSkin(skin,i));}if(json.scenes){json.scenes=json.scenes.map((scene,i)=>this._resolveScene(scene,i));}if(json.scene!==undefined){json.scene=json.scenes[this.json.scene];}}getScene(index){return this._get('scenes',index);}getNode(index){return this._get('nodes',index);}getSkin(index){return this._get('skins',index);}getMesh(index){return this._get('meshes',index);}getMaterial(index){return this._get('materials',index);}getAccessor(index){return this._get('accessors',index);}getCamera(index){return null;}getTexture(index){return this._get('textures',index);}getSampler(index){return this._get('samplers',index);}getImage(index){return this._get('images',index);}getBufferView(index){return this._get('bufferViews',index);}getBuffer(index){return this._get('buffers',index);}_get(array,index){if(typeof index==='object'){return index;}var object=this.json[array]&&this.json[array][index];if(!object){console.warn("glTF file error: Could not find ".concat(array,"[").concat(index,"]"));}return object;}_resolveScene(scene,index){scene.id=scene.id||"scene-".concat(index);scene.nodes=(scene.nodes||[]).map(node=>this.getNode(node));return scene;}_resolveNode(node,index){node.id=node.id||"node-".concat(index);if(node.children){node.children=node.children.map(child=>this.getNode(child));}if(node.mesh!==undefined){node.mesh=this.getMesh(node.mesh);}else if(node.meshes!==undefined&&node.meshes.length){node.mesh=node.meshes.reduce((accum,meshIndex)=>{var mesh=this.getMesh(meshIndex);accum.id=mesh.id;accum.primitives=accum.primitives.concat(mesh.primitives);return accum;},{primitives:[]});}if(node.camera!==undefined){node.camera=this.getCamera(node.camera);}if(node.skin!==undefined){node.skin=this.getSkin(node.skin);}return node;}_resolveSkin(skin,index){skin.id=skin.id||"skin-".concat(index);skin.inverseBindMatrices=this.getAccessor(skin.inverseBindMatrices);return skin;}_resolveMesh(mesh,index){mesh.id=mesh.id||"mesh-".concat(index);if(mesh.primitives){mesh.primitives=mesh.primitives.map(primitive=>{primitive=_objectSpread2({},primitive);var attributes=primitive.attributes;primitive.attributes={};for(var attribute in attributes){primitive.attributes[attribute]=this.getAccessor(attributes[attribute]);}if(primitive.indices!==undefined){primitive.indices=this.getAccessor(primitive.indices);}if(primitive.material!==undefined){primitive.material=this.getMaterial(primitive.material);}return primitive;});}return mesh;}_resolveMaterial(material,index){material.id=material.id||"material-".concat(index);if(material.normalTexture){material.normalTexture=_objectSpread2({},material.normalTexture);material.normalTexture.texture=this.getTexture(material.normalTexture.index);}if(material.occlusionTexture){material.occlustionTexture=_objectSpread2({},material.occlustionTexture);material.occlusionTexture.texture=this.getTexture(material.occlusionTexture.index);}if(material.emissiveTexture){material.emmisiveTexture=_objectSpread2({},material.emmisiveTexture);material.emissiveTexture.texture=this.getTexture(material.emissiveTexture.index);}if(!material.emissiveFactor){material.emissiveFactor=material.emmisiveTexture?[1,1,1]:[0,0,0];}if(material.pbrMetallicRoughness){material.pbrMetallicRoughness=_objectSpread2({},material.pbrMetallicRoughness);var mr=material.pbrMetallicRoughness;if(mr.baseColorTexture){mr.baseColorTexture=_objectSpread2({},mr.baseColorTexture);mr.baseColorTexture.texture=this.getTexture(mr.baseColorTexture.index);}if(mr.metallicRoughnessTexture){mr.metallicRoughnessTexture=_objectSpread2({},mr.metallicRoughnessTexture);mr.metallicRoughnessTexture.texture=this.getTexture(mr.metallicRoughnessTexture.index);}}return material;}_resolveAccessor(accessor,index){accessor.id=accessor.id||"accessor-".concat(index);if(accessor.bufferView!==undefined){accessor.bufferView=this.getBufferView(accessor.bufferView);}accessor.bytesPerComponent=getBytesFromComponentType(accessor.componentType);accessor.components=getSizeFromAccessorType(accessor.type);accessor.bytesPerElement=accessor.bytesPerComponent*accessor.components;if(accessor.bufferView){var buffer=accessor.bufferView.buffer;var{ArrayType,byteLength}=getAccessorArrayTypeAndLength(accessor,accessor.bufferView);var byteOffset=(accessor.bufferView.byteOffset||0)+(accessor.byteOffset||0)+buffer.byteOffset;var cutBuffer=buffer.arrayBuffer.slice(byteOffset,byteOffset+byteLength);if(accessor.bufferView.byteStride){cutBuffer=this._getValueFromInterleavedBuffer(buffer,byteOffset,accessor.bufferView.byteStride,accessor.bytesPerElement,accessor.count);}accessor.value=new ArrayType(cutBuffer);}return accessor;}_getValueFromInterleavedBuffer(buffer,byteOffset,byteStride,bytesPerElement,count){var result=new Uint8Array(count*bytesPerElement);for(var _i53=0;_i53<count;_i53++){var elementOffset=byteOffset+_i53*byteStride;result.set(new Uint8Array(buffer.arrayBuffer.slice(elementOffset,elementOffset+bytesPerElement)),_i53*bytesPerElement);}return result.buffer;}_resolveTexture(texture,index){texture.id=texture.id||"texture-".concat(index);texture.sampler='sampler'in texture?this.getSampler(texture.sampler):DEFAULT_SAMPLER;texture.source=this.getImage(texture.source);return texture;}_resolveSampler(sampler,index){sampler.id=sampler.id||"sampler-".concat(index);sampler.parameters={};for(var key in sampler){var glEnum=this._enumSamplerParameter(key);if(glEnum!==undefined){sampler.parameters[glEnum]=sampler[key];}}return sampler;}_enumSamplerParameter(key){return SAMPLER_PARAMETER_GLTF_TO_GL[key];}_resolveImage(image,index){image.id=image.id||"image-".concat(index);if(image.bufferView!==undefined){image.bufferView=this.getBufferView(image.bufferView);}var preloadedImage=this.images[index];if(preloadedImage){image.image=preloadedImage;}return image;}_resolveBufferView(bufferView,index){var bufferIndex=bufferView.buffer;var result=_objectSpread2(_objectSpread2({id:"bufferView-".concat(index)},bufferView),{},{buffer:this.buffers[bufferIndex]});var arrayBuffer=this.buffers[bufferIndex].arrayBuffer;var byteOffset=this.buffers[bufferIndex].byteOffset||0;if('byteOffset'in bufferView){byteOffset+=bufferView.byteOffset;}result.data=new Uint8Array(arrayBuffer,byteOffset,bufferView.byteLength);return result;}_resolveCamera(camera,index){camera.id=camera.id||"camera-".concat(index);if(camera.perspective);if(camera.orthographic);return camera;}}function postProcessGLTF(gltf,options){return new GLTFPostProcessor().postProcess(gltf,options);}var MAGIC_glTF=0x676c5446;var GLB_FILE_HEADER_SIZE=12;var GLB_CHUNK_HEADER_SIZE=8;var GLB_CHUNK_TYPE_JSON=0x4e4f534a;var GLB_CHUNK_TYPE_BIN=0x004e4942;var GLB_CHUNK_TYPE_JSON_XVIZ_DEPRECATED=0;var GLB_CHUNK_TYPE_BIX_XVIZ_DEPRECATED=1;var GLB_V1_CONTENT_FORMAT_JSON=0x0;var LE=true;function getMagicString(dataView){var byteOffset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;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)));}function isGLB(arrayBuffer){var byteOffset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var dataView=new DataView(arrayBuffer);var{magic=MAGIC_glTF}=options;var magic1=dataView.getUint32(byteOffset,false);return magic1===magic||magic1===MAGIC_glTF;}function parseGLBSync(glb,arrayBuffer){var byteOffset=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var options=arguments.length>3&&arguments[3]!==undefined?arguments[3]:{};var dataView=new DataView(arrayBuffer);var type=getMagicString(dataView,byteOffset+0);var version=dataView.getUint32(byteOffset+4,LE);var byteLength=dataView.getUint32(byteOffset+8,LE);Object.assign(glb,{header:{byteOffset,byteLength,hasBinChunk:false},type,version,json:{},binChunks:[]});byteOffset+=GLB_FILE_HEADER_SIZE;switch(glb.version){case 1:return parseGLBV1(glb,dataView,byteOffset);case 2:return parseGLBV2(glb,dataView,byteOffset,options={});default:throw new Error("Invalid GLB version ".concat(glb.version,". Only supports v1 and v2."));}}function parseGLBV1(glb,dataView,byteOffset){assert$7(glb.header.byteLength>GLB_FILE_HEADER_SIZE+GLB_CHUNK_HEADER_SIZE);var contentLength=dataView.getUint32(byteOffset+0,LE);var contentFormat=dataView.getUint32(byteOffset+4,LE);byteOffset+=GLB_CHUNK_HEADER_SIZE;assert$7(contentFormat===GLB_V1_CONTENT_FORMAT_JSON);parseJSONChunk(glb,dataView,byteOffset,contentLength);byteOffset+=contentLength;byteOffset+=parseBINChunk(glb,dataView,byteOffset,glb.header.byteLength);return byteOffset;}function parseGLBV2(glb,dataView,byteOffset,options){assert$7(glb.header.byteLength>GLB_FILE_HEADER_SIZE+GLB_CHUNK_HEADER_SIZE);parseGLBChunksSync(glb,dataView,byteOffset,options);return byteOffset+glb.header.byteLength;}function parseGLBChunksSync(glb,dataView,byteOffset,options){while(byteOffset+8<=glb.header.byteLength){var chunkLength=dataView.getUint32(byteOffset+0,LE);var chunkFormat=dataView.getUint32(byteOffset+4,LE);byteOffset+=GLB_CHUNK_HEADER_SIZE;switch(chunkFormat){case GLB_CHUNK_TYPE_JSON:parseJSONChunk(glb,dataView,byteOffset,chunkLength);break;case GLB_CHUNK_TYPE_BIN:parseBINChunk(glb,dataView,byteOffset,chunkLength);break;case GLB_CHUNK_TYPE_JSON_XVIZ_DEPRECATED:if(!options.strict){parseJSONChunk(glb,dataView,byteOffset,chunkLength);}break;case GLB_CHUNK_TYPE_BIX_XVIZ_DEPRECATED:if(!options.strict){parseBINChunk(glb,dataView,byteOffset,chunkLength);}break;}byteOffset+=padToNBytes(chunkLength,4);}return byteOffset;}function parseJSONChunk(glb,dataView,byteOffset,chunkLength){var jsonChunk=new Uint8Array(dataView.buffer,byteOffset,chunkLength);var textDecoder=new TextDecoder('utf8');var jsonText=textDecoder.decode(jsonChunk);glb.json=JSON.parse(jsonText);return padToNBytes(chunkLength,4);}function parseBINChunk(glb,dataView,byteOffset,chunkLength){glb.header.hasBinChunk=true;glb.binChunks.push({byteOffset,byteLength:chunkLength,arrayBuffer:dataView.buffer});return padToNBytes(chunkLength,4);}async function parseGLTF(gltf,arrayBufferOrString){var byteOffset=arguments.length>2&&arguments[2]!==undefined?arguments[2]:0;var options=arguments.length>3?arguments[3]:undefined;var context=arguments.length>4?arguments[4]:undefined;var _options$gltf,_options$gltf2,_options$gltf3,_options$gltf4;parseGLTFContainerSync(gltf,arrayBufferOrString,byteOffset,options);normalizeGLTFV1(gltf,{normalize:options===null||options===void 0?void 0:(_options$gltf=options.gltf)===null||_options$gltf===void 0?void 0:_options$gltf.normalize});preprocessExtensions(gltf,options,context);var promises=[];if(options!==null&&options!==void 0&&(_options$gltf2=options.gltf)!==null&&_options$gltf2!==void 0&&_options$gltf2.loadBuffers&&gltf.json.buffers){await loadBuffers(gltf,options,context);}if(options!==null&&options!==void 0&&(_options$gltf3=options.gltf)!==null&&_options$gltf3!==void 0&&_options$gltf3.loadImages){var _promise=loadImages(gltf,options,context);promises.push(_promise);}var promise=decodeExtensions(gltf,options,context);promises.push(promise);await Promise.all(promises);gltf.json.gltfArrayBuffer=arrayBufferOrString;// !zeg add 兼容gltf
  57068. return options!==null&&options!==void 0&&(_options$gltf4=options.gltf)!==null&&_options$gltf4!==void 0&&_options$gltf4.postProcess?postProcessGLTF(gltf,options):gltf;}function parseGLTFContainerSync(gltf,data,byteOffset,options){if(options.uri){gltf.baseUri=options.uri;}if(data instanceof ArrayBuffer&&!isGLB(data,byteOffset,options)){var textDecoder=new TextDecoder();data=textDecoder.decode(data);}if(typeof data==='string'){gltf.json=parseJSON(data);}else if(data instanceof ArrayBuffer){var glb={};byteOffset=parseGLBSync(glb,data,byteOffset,options.glb);assert$1(glb.type==='glTF',"Invalid GLB magic string ".concat(glb.type));gltf._glb=glb;gltf.json=glb.json;}else {assert$1(false,'GLTF: must be ArrayBuffer or string');}var buffers=gltf.json.buffers||[];gltf.buffers=new Array(buffers.length).fill(null);if(gltf._glb&&gltf._glb.header.hasBinChunk){var{binChunks}=gltf._glb;gltf.buffers[0]={arrayBuffer:binChunks[0].arrayBuffer,byteOffset:binChunks[0].byteOffset,byteLength:binChunks[0].byteLength};}var images=gltf.json.images||[];gltf.images=new Array(images.length).fill({});}async function loadBuffers(gltf,options,context){var buffers=gltf.json.buffers||[];for(var _i54=0;_i54<buffers.length;++_i54){var buffer=buffers[_i54];if(buffer.uri){var _context$fetch,_response$arrayBuffer;var{fetch:_fetch}=context;assert$1(_fetch);var uri=resolveUrl(buffer.uri,options);var 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));var arrayBuffer=await(response===null||response===void 0?void 0:(_response$arrayBuffer=response.arrayBuffer)===null||_response$arrayBuffer===void 0?void 0:_response$arrayBuffer.call(response));gltf.buffers[_i54]={arrayBuffer,byteOffset:0,byteLength:arrayBuffer.byteLength};delete buffer.uri;}}}async function loadImages(gltf,options,context){var imageIndices=getReferencesImageIndices(gltf);var images=gltf.json.images||[];var promises=[];for(var imageIndex of imageIndices){promises.push(loadImage(gltf,images[imageIndex],imageIndex,options,context));}return await Promise.all(promises);}function getReferencesImageIndices(gltf){var imageIndices=new Set();var textures=gltf.json.textures||[];for(var texture of textures){if(texture.source!==undefined){imageIndices.add(texture.source);}}return Array.from(imageIndices).sort();}async function loadImage(gltf,image,index,options,context){var{fetch,parse}=context;var arrayBuffer;if(image.uri){var uri=resolveUrl(image.uri,options);var response=await fetch(uri);arrayBuffer=await response.arrayBuffer();}if(Number.isFinite(image.bufferView)){var array=getTypedArrayForBufferView(gltf.json,gltf.buffers,image.bufferView);arrayBuffer=sliceArrayBuffer(array.buffer,array.byteOffset,array.byteLength);}assert$1(arrayBuffer,'glTF image has no data');var parsedImage=await parse(arrayBuffer,[ImageLoader$1,BasisLoader],{mimeType:image.mimeType,basis:options.basis||{format:selectSupportedBasisFormat()}},context);if(parsedImage&&parsedImage[0]){parsedImage={compressed:true,mipmaps:false,width:parsedImage[0].width,height:parsedImage[0].height,data:parsedImage};}gltf.images=gltf.images||[];gltf.images[index]=parsedImage;}var GLTFLoader$1={name:'glTF',id:'gltf',module:'gltf',version:VERSION$3,extensions:['gltf','glb'],mimeTypes:['model/gltf+json','model/gltf-binary'],text:true,binary:true,tests:['glTF'],parse:parse$1,options:{gltf:{normalize:true,loadBuffers:true,loadImages:true,decompressMeshes:true,postProcess:true},log:console},deprecatedOptions:{fetchImages:'gltf.loadImages',createImages:'gltf.loadImages',decompress:'gltf.decompressMeshes',postProcess:'gltf.postProcess',gltf:{decompress:'gltf.decompressMeshes'}}};async function parse$1(arrayBuffer){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var context=arguments.length>2?arguments[2]:undefined;options=_objectSpread2(_objectSpread2({},GLTFLoader$1.options),options);options.gltf=_objectSpread2(_objectSpread2({},GLTFLoader$1.options.gltf),options.gltf);var{byteOffset=0}=options;var gltf={};return await parseGLTF(gltf,arrayBuffer,byteOffset,options,context);}var GLTF_FORMAT={URI:0,EMBEDDED:1};function parse3DTileGLTFViewSync(tile,arrayBuffer,byteOffset,options){tile.rotateYtoZ=true;var gltfByteLength=tile.byteOffset+tile.byteLength-byteOffset;if(gltfByteLength===0){throw new Error('glTF byte length must be greater than 0.');}tile.gltfUpAxis=options['3d-tiles']&&options['3d-tiles'].assetGltfUpAxis?options['3d-tiles'].assetGltfUpAxis:'Y';tile.gltfArrayBuffer=sliceArrayBuffer(arrayBuffer,byteOffset,gltfByteLength);tile.gltfByteOffset=0;tile.gltfByteLength=gltfByteLength;if(byteOffset%4===0);else {console.warn("".concat(tile.type,": embedded glb is not aligned to a 4-byte boundary."));}return tile.byteOffset+tile.byteLength;}async function extractGLTF(tile,gltfFormat,options,context){var tile3DOptions=options['3d-tiles']||{};extractGLTFBufferOrURL(tile,gltfFormat);if(tile3DOptions.loadGLTF){var{parse:_parse,fetch:_fetch2}=context;if(tile.gltfUrl){tile.gltfArrayBuffer=await _fetch2(tile.gltfUrl,options);tile.gltfByteOffset=0;}if(tile.gltfArrayBuffer){tile.gltf=await _parse(tile.gltfArrayBuffer,GLTFLoader$1,options,context);delete tile.gltfArrayBuffer;delete tile.gltfByteOffset;delete tile.gltfByteLength;}}}function extractGLTFBufferOrURL(tile,gltfFormat,options){switch(gltfFormat){case GLTF_FORMAT.URI:var gltfUrlBytes=new Uint8Array(tile.gltfArrayBuffer,tile.gltfByteOffset);var textDecoder=new TextDecoder();var gltfUrl=textDecoder.decode(gltfUrlBytes);tile.gltfUrl=gltfUrl.replace(/[\s\0]+$/,'');delete tile.gltfArrayBuffer;delete tile.gltfByteOffset;delete tile.gltfByteLength;break;case GLTF_FORMAT.EMBEDDED:break;default:throw new Error('b3dm: Illegal glTF format field');}}async function parseBatchedModel3DTile(tile,arrayBuffer,byteOffset,options,context){var _tile$gltf;byteOffset=parseBatchedModel(tile,arrayBuffer,byteOffset,options);await extractGLTF(tile,GLTF_FORMAT.EMBEDDED,options,context);var extensions=tile===null||tile===void 0?void 0:(_tile$gltf=tile.gltf)===null||_tile$gltf===void 0?void 0:_tile$gltf.extensions;if(extensions&&extensions.CESIUM_RTC){tile.rtcCenter=extensions.CESIUM_RTC.center;}return byteOffset;}function parseBatchedModel(tile,arrayBuffer,byteOffset,options,context){byteOffset=parse3DTileHeaderSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileTablesHeaderSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileTablesSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileGLTFViewSync(tile,arrayBuffer,byteOffset,options);var featureTable=new Tile3DFeatureTable(tile.featureTableJson,tile.featureTableBinary);tile.rtcCenter=featureTable.getGlobalProperty('RTC_CENTER',GL$1.FLOAT,3);return byteOffset;}async function parseInstancedModel3DTile(tile,arrayBuffer,byteOffset,options,context){byteOffset=parseInstancedModel(tile,arrayBuffer,byteOffset,options);await extractGLTF(tile,tile.gltfFormat,options,context);return byteOffset;}function parseInstancedModel(tile,arrayBuffer,byteOffset,options,context){byteOffset=parse3DTileHeaderSync(tile,arrayBuffer,byteOffset);if(tile.version!==1){throw new Error("Instanced 3D Model version ".concat(tile.version," is not supported"));}byteOffset=parse3DTileTablesHeaderSync(tile,arrayBuffer,byteOffset);var view=new DataView(arrayBuffer);tile.gltfFormat=view.getUint32(byteOffset,true);byteOffset+=4;byteOffset=parse3DTileTablesSync(tile,arrayBuffer,byteOffset);byteOffset=parse3DTileGLTFViewSync(tile,arrayBuffer,byteOffset,options);if(tile.featureTableJsonByteLength===0){throw new Error('i3dm parser: featureTableJsonByteLength is zero.');}var featureTable=new Tile3DFeatureTable(tile.featureTableJson,tile.featureTableBinary);var instancesLength=featureTable.getGlobalProperty('INSTANCES_LENGTH');featureTable.featuresLength=instancesLength;if(!Number.isFinite(instancesLength)){throw new Error('i3dm parser: INSTANCES_LENGTH must be defined');}tile.eastNorthUp=featureTable.getGlobalProperty('EAST_NORTH_UP');tile.rtcCenter=featureTable.getGlobalProperty('RTC_CENTER',GL$1.FLOAT,3);var batchTable=new Tile3DBatchTableParser(tile.batchTableJson,tile.batchTableBinary,instancesLength);extractInstancedAttributes(tile,featureTable,batchTable,instancesLength);return byteOffset;}function extractInstancedAttributes(tile,featureTable,batchTable,instancesLength){var collectionOptions={instances:new Array(instancesLength),batchTable:tile._batchTable,cull:false,url:undefined,gltf:undefined,basePath:undefined,incrementallyLoadTextures:false,forwardAxis:[1,0,0]};var instances=collectionOptions.instances;var instancePosition=new Vector3$1();new Vector3$1();new Vector3$1();new Vector3$1();var instanceRotation=new Matrix3$1();var instanceQuaternion=new Quaternion$1();var instanceScale=new Vector3$1();var instanceTranslationRotationScale={};var instanceTransform=new Matrix4$1();var scratch1=[];var scratch2=[];var scratchVector1=new Vector3$1();var scratchVector2=new Vector3$1();for(var _i55=0;_i55<instancesLength;_i55++){var position=void 0;if(featureTable.hasProperty('POSITION')){position=featureTable.getProperty('POSITION',GL$1.FLOAT,3,_i55,instancePosition);}else if(featureTable.hasProperty('POSITION_QUANTIZED')){position=featureTable.getProperty('POSITION_QUANTIZED',GL$1.UNSIGNED_SHORT,3,_i55,instancePosition);var quantizedVolumeOffset=featureTable.getGlobalProperty('QUANTIZED_VOLUME_OFFSET',GL$1.FLOAT,3,scratchVector1);if(!quantizedVolumeOffset){throw new Error('i3dm parser: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.');}var quantizedVolumeScale=featureTable.getGlobalProperty('QUANTIZED_VOLUME_SCALE',GL$1.FLOAT,3,scratchVector2);if(!quantizedVolumeScale){throw new Error('i3dm parser: QUANTIZED_VOLUME_SCALE must be defined for quantized positions.');}var MAX_UNSIGNED_SHORT=65535.0;for(var j=0;j<3;j++){position[j]=position[j]/MAX_UNSIGNED_SHORT*quantizedVolumeScale[j]+quantizedVolumeOffset[j];}}if(!position){throw new Error('i3dm: POSITION or POSITION_QUANTIZED must be defined for each instance.');}instancePosition.copy(position);instanceTranslationRotationScale.translation=instancePosition;tile.normalUp=featureTable.getProperty('NORMAL_UP',GL$1.FLOAT,3,_i55,scratch1);tile.normalRight=featureTable.getProperty('NORMAL_RIGHT',GL$1.FLOAT,3,_i55,scratch2);if(tile.normalUp){if(!tile.normalRight){throw new Error('i3dm: Custom orientation requires both NORMAL_UP and NORMAL_RIGHT.');}tile.hasCustomOrientation=true;}else {tile.octNormalUp=featureTable.getProperty('NORMAL_UP_OCT32P',GL$1.UNSIGNED_SHORT,2,scratch1);tile.octNormalRight=featureTable.getProperty('NORMAL_RIGHT_OCT32P',GL$1.UNSIGNED_SHORT,2,scratch2);if(tile.octNormalUp){if(!tile.octNormalRight){throw new Error('i3dm: oct-encoded orientation requires NORMAL_UP_OCT32P and NORMAL_RIGHT_OCT32P');}throw new Error('i3dm: oct-encoded orientation not implemented');}else if(tile.eastNorthUp){Ellipsoid.WGS84.eastNorthUpToFixedFrame(instancePosition,instanceTransform);instanceTransform.getRotationMatrix3(instanceRotation);}else {instanceRotation.identity();}}instanceQuaternion.fromMatrix3(instanceRotation);instanceTranslationRotationScale.rotation=instanceQuaternion;instanceScale.set(1.0,1.0,1.0);var _scale=featureTable.getProperty('SCALE',GL$1.FLOAT,1,_i55);if(Number.isFinite(_scale)){instanceScale.multiplyByScalar(_scale);}var nonUniformScale=featureTable.getProperty('SCALE_NON_UNIFORM',GL$1.FLOAT,3,_i55,scratch1);if(nonUniformScale){instanceScale.scale(nonUniformScale);}instanceTranslationRotationScale.scale=instanceScale;var batchId=featureTable.getProperty('BATCH_ID',GL$1.UNSIGNED_SHORT,1,_i55);if(batchId===undefined){batchId=_i55;}var rotationMatrix=new Matrix4$1().fromQuaternion(instanceTranslationRotationScale.rotation);instanceTransform.identity();instanceTransform.translate(instanceTranslationRotationScale.translation);instanceTransform.multiplyRight(rotationMatrix);instanceTransform.scale(instanceTranslationRotationScale.scale);var modelMatrix=instanceTransform.clone();instances[_i55]={modelMatrix,batchId};}tile.instances=instances;}async function parseComposite3DTile(tile,arrayBuffer,byteOffset,options,context,parse3DTile){byteOffset=parse3DTileHeaderSync(tile,arrayBuffer,byteOffset);var view=new DataView(arrayBuffer);tile.tilesLength=view.getUint32(byteOffset,true);byteOffset+=4;tile.tiles=[];while(tile.tiles.length<tile.tilesLength&&tile.byteLength-byteOffset>12){var subtile={};tile.tiles.push(subtile);byteOffset=await parse3DTile(arrayBuffer,byteOffset,options,context,subtile);}return byteOffset;}async function parseGltf3DTile(tile,arrayBuffer,options,context){tile.rotateYtoZ=true;tile.gltfUpAxis=options['3d-tiles']&&options['3d-tiles'].assetGltfUpAxis?options['3d-tiles'].assetGltfUpAxis:'Y';var{parse}=context;tile.gltf=await parse(arrayBuffer,GLTFLoader$1,options,context);}async function parse3DTile(arrayBuffer){var byteOffset=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;var options=arguments.length>2?arguments[2]:undefined;var context=arguments.length>3?arguments[3]:undefined;var tile=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};tile.byteOffset=byteOffset;tile.type=getMagicString$1(arrayBuffer,byteOffset);switch(tile.type){case TILE3D_TYPE.COMPOSITE:return await parseComposite3DTile(tile,arrayBuffer,byteOffset,options,context,parse3DTile);case TILE3D_TYPE.BATCHED_3D_MODEL:return await parseBatchedModel3DTile(tile,arrayBuffer,byteOffset,options,context);case TILE3D_TYPE.GLTF:return await parseGltf3DTile(tile,arrayBuffer,options,context);case TILE3D_TYPE.INSTANCED_3D_MODEL:return await parseInstancedModel3DTile(tile,arrayBuffer,byteOffset,options,context);case TILE3D_TYPE.POINT_CLOUD:return await parsePointCloud3DTile(tile,arrayBuffer,byteOffset,options,context);default:throw new Error("3DTileLoader: unknown type ".concat(tile.type));}}var SUBTREE_FILE_MAGIC=0x74627573;var SUBTREE_FILE_VERSION=1;async function parse3DTilesSubtree(data){var magic=new Uint32Array(data.slice(0,4));if(magic[0]!==SUBTREE_FILE_MAGIC){throw new Error('Wrong subtree file magic number');}var version=new Uint32Array(data.slice(4,8));if(version[0]!==SUBTREE_FILE_VERSION){throw new Error('Wrong subtree file verson, must be 1');}var jsonByteLength=parseUint64Value(data.slice(8,16));var stringAttribute=new Uint8Array(data,24,jsonByteLength);var textDecoder=new TextDecoder('utf8');var string=textDecoder.decode(stringAttribute);var subtree=JSON.parse(string);var binaryByteLength=parseUint64Value(data.slice(16,24));var internalBinaryBuffer=new ArrayBuffer(0);if(binaryByteLength){internalBinaryBuffer=data.slice(24+jsonByteLength);}if('bufferView'in subtree.tileAvailability){subtree.tileAvailability.explicitBitstream=await getExplicitBitstream(subtree,'tileAvailability',internalBinaryBuffer);}if('bufferView'in subtree.contentAvailability){subtree.contentAvailability.explicitBitstream=await getExplicitBitstream(subtree,'contentAvailability',internalBinaryBuffer);}if('bufferView'in subtree.childSubtreeAvailability){subtree.childSubtreeAvailability.explicitBitstream=await getExplicitBitstream(subtree,'childSubtreeAvailability',internalBinaryBuffer);}return subtree;}async function getExplicitBitstream(subtree,name,internalBinaryBuffer){var bufferViewIndex=subtree[name].bufferView;var bufferView=subtree.bufferViews[bufferViewIndex];var buffer=subtree.buffers[bufferView.buffer];if(buffer.uri){var response=await fetchFile(buffer.uri);var data=await response.arrayBuffer();return new Uint8Array(data,bufferView.byteOffset,bufferView.byteLength);}return new Uint8Array(internalBinaryBuffer,bufferView.byteOffset,bufferView.byteLength);}function parseUint64Value(buffer){var dataView=new DataView(buffer);var left=dataView.getUint32(0,true);var right=dataView.getUint32(4,true);return left+2**32*right;}var Tile3DSubtreeLoader={id:'3d-tiles-subtree',name:'3D Tiles Subtree',module:'3d-tiles',version:VERSION$5,extensions:['subtree'],mimeTypes:['application/octet-stream'],tests:['subtree'],parse:parse3DTilesSubtree,options:{}};var QUADTREE_DEVISION_COUNT=4;var OCTREE_DEVISION_COUNT=8;var SUBDIVISION_COUNT_MAP={QUADTREE:QUADTREE_DEVISION_COUNT,OCTREE:OCTREE_DEVISION_COUNT};async function parseImplicitTiles(subtree,options){var parentData=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{mortonIndex:0,x:0,y:0,z:0};var childIndex=arguments.length>3&&arguments[3]!==undefined?arguments[3]:0;var level=arguments.length>4&&arguments[4]!==undefined?arguments[4]:0;var globalData=arguments.length>5&&arguments[5]!==undefined?arguments[5]:{level:0,mortonIndex:0,x:0,y:0,z:0};var{subdivisionScheme,subtreeLevels,maximumLevel,contentUrlTemplate,subtreesUriTemplate,basePath}=options;var tile={children:[],lodMetricValue:0,contentUrl:''};var childrenPerTile=SUBDIVISION_COUNT_MAP[subdivisionScheme];var childX=childIndex&0b01;var childY=childIndex>>1&0b01;var childZ=childIndex>>2&0b01;var levelOffset=(childrenPerTile**level-1)/(childrenPerTile-1);var childTileMortonIndex=concatBits(parentData.mortonIndex,childIndex);var tileAvailabilityIndex=levelOffset+childTileMortonIndex;var childTileX=concatBits(parentData.x,childX);var childTileY=concatBits(parentData.y,childY);var childTileZ=concatBits(parentData.z,childZ);var isChildSubtreeAvailable=false;if(level+1>subtreeLevels){isChildSubtreeAvailable=getAvailabilityResult(subtree.childSubtreeAvailability,childTileMortonIndex);}var x=concatBits(globalData.x,childTileX);var y=concatBits(globalData.y,childTileY);var z=concatBits(globalData.z,childTileZ);var lev=level+globalData.level;if(isChildSubtreeAvailable){var subtreePath="".concat(basePath,"/").concat(subtreesUriTemplate);var childSubtreeUrl=replaceContentUrlTemplate(subtreePath,lev,x,y,z);var childSubtree=await load(childSubtreeUrl,Tile3DSubtreeLoader);subtree=childSubtree;globalData.mortonIndex=childTileMortonIndex;globalData.x=childTileX;globalData.y=childTileY;globalData.z=childTileZ;globalData.level=level;childTileMortonIndex=0;tileAvailabilityIndex=0;childTileX=0;childTileY=0;childTileZ=0;level=0;}var isTileAvailable=getAvailabilityResult(subtree.tileAvailability,tileAvailabilityIndex);if(!isTileAvailable||level>maximumLevel){return tile;}var isContentAvailable=getAvailabilityResult(subtree.contentAvailability,tileAvailabilityIndex);if(isContentAvailable){tile.contentUrl=replaceContentUrlTemplate(contentUrlTemplate,lev,x,y,z);}var childTileLevel=level+1;var pData={mortonIndex:childTileMortonIndex,x:childTileX,y:childTileY,z:childTileZ};for(var index=0;index<childrenPerTile;index++){var currentTile=await parseImplicitTiles(subtree,options,pData,index,childTileLevel,globalData);if(currentTile.contentUrl||currentTile.children.length){var globalLevel=lev+1;var childCoordinates={childTileX,childTileY,childTileZ};var formattedTile=formatTileData(currentTile,globalLevel,childCoordinates,options);tile.children.push(formattedTile);}}return tile;}function getAvailabilityResult(availabilityData,index){if('constant'in availabilityData){return Boolean(availabilityData.constant);}if(availabilityData.explicitBitstream){return getBooleanValueFromBitstream(index,availabilityData.explicitBitstream);}return false;}function formatTileData(tile,level,childCoordinates,options){var{basePath,refine,getRefine,lodMetricType,getTileType,rootLodMetricValue,rootBoundingVolume}=options;var uri=tile.contentUrl&&tile.contentUrl.replace("".concat(basePath,"/"),'');var lodMetricValue=rootLodMetricValue/2**level;var boundingVolume=calculateBoundingVolumeForChildTile(level,rootBoundingVolume,childCoordinates);return {children:tile.children,contentUrl:tile.contentUrl,content:{uri},id:tile.contentUrl,refine:getRefine(refine),type:getTileType(tile),lodMetricType,lodMetricValue,boundingVolume};}function calculateBoundingVolumeForChildTile(level,rootBoundingVolume,childCoordinates){if(rootBoundingVolume.region){var{childTileX,childTileY,childTileZ}=childCoordinates;var[west,south,east,north,minimumHeight,maximumHeight]=rootBoundingVolume.region;var boundingVolumesCount=2**level;var sizeX=(east-west)/boundingVolumesCount;var sizeY=(north-south)/boundingVolumesCount;var sizeZ=(maximumHeight-minimumHeight)/boundingVolumesCount;var[childWest,childEast]=[west+sizeX*childTileX,west+sizeX*(childTileX+1)];var[childSouth,childNorth]=[south+sizeY*childTileY,south+sizeY*(childTileY+1)];var[childMinimumHeight,childMaximumHeight]=[minimumHeight+sizeZ*childTileZ,minimumHeight+sizeZ*(childTileZ+1)];return {region:[childWest,childSouth,childEast,childNorth,childMinimumHeight,childMaximumHeight]};}console.warn('Unsupported bounding volume type: ',rootBoundingVolume);return null;}function concatBits(first,second){return parseInt(first.toString(2)+second.toString(2),2);}function replaceContentUrlTemplate(templateUrl,level,x,y,z){var mapUrl=generateMapUrl({level,x,y,z});return templateUrl.replace(/{level}|{x}|{y}|{z}/gi,matched=>mapUrl[matched]);}function generateMapUrl(items){var mapUrl={};for(var key in items){mapUrl["{".concat(key,"}")]=items[key];}return mapUrl;}function getBooleanValueFromBitstream(availabilityIndex,availabilityBuffer){var byteIndex=Math.floor(availabilityIndex/8);var bitIndex=availabilityIndex%8;var bitValue=availabilityBuffer[byteIndex]>>bitIndex&1;return bitValue===1;}function getTileType(tile){if(!tile.contentUrl){return TILE_TYPE.EMPTY;}var contentUrl=tile.contentUrl;var fileExtension=contentUrl.split('.').pop();switch(fileExtension){case'pnts':return TILE_TYPE.POINTCLOUD;case'i3dm':case'b3dm':case'glb':case'gltf':return TILE_TYPE.SCENEGRAPH;default:return fileExtension;}}function getRefine(refine){switch(refine){case'REPLACE':case'replace':return TILE_REFINEMENT.REPLACE;case'ADD':case'add':return TILE_REFINEMENT.ADD;default:return refine;}}function normalizeTileData(tile,options){if(!tile){return null;}if(tile.content){var contentUri=tile.content.uri||tile.content.url;tile.contentUrl="".concat(options.basePath,"/").concat(contentUri);}tile.id=tile.contentUrl;tile.lodMetricType=LOD_METRIC_TYPE.GEOMETRIC_ERROR;tile.lodMetricValue=tile.geometricError;tile.transformMatrix=tile.transform;tile.type=getTileType(tile);tile.refine=getRefine(tile.refine);return tile;}function normalizeTileHeaders(tileset){var basePath=tileset.basePath;var root=normalizeTileData(tileset.root,tileset);var stack=[];stack.push(root);while(stack.length>0){var tile=stack.pop()||{};var children=tile.children||[];for(var childHeader of children){normalizeTileData(childHeader,{basePath});stack.push(childHeader);}}return root;}async function normalizeImplicitTileHeaders(tileset){if(!tileset.root){return null;}var basePath=tileset.basePath;var implicitTilingExtension=tileset.root.extensions['3DTILES_implicit_tiling'];var{subdivisionScheme,maximumLevel,subtreeLevels,subtrees:{uri:subtreesUriTemplate}}=implicitTilingExtension;var subtreeUrl=replaceContentUrlTemplate(subtreesUriTemplate,0,0,0,0);var rootSubtreeUrl="".concat(basePath,"/").concat(subtreeUrl);var rootSubtree=await load(rootSubtreeUrl,Tile3DSubtreeLoader);var contentUrlTemplate="".concat(basePath,"/").concat(tileset.root.content.uri);var refine=tileset.root.refine;var rootLodMetricValue=tileset.root.geometricError;var rootBoundingVolume=tileset.root.boundingVolume;var options={contentUrlTemplate,subtreesUriTemplate,subdivisionScheme,subtreeLevels,maximumLevel,refine,basePath,lodMetricType:LOD_METRIC_TYPE.GEOMETRIC_ERROR,rootLodMetricValue,rootBoundingVolume,getTileType,getRefine};return await normalizeImplicitTileData(tileset.root,rootSubtree,options);}async function normalizeImplicitTileData(tile,rootSubtree,options){if(!tile){return null;}tile.lodMetricType=LOD_METRIC_TYPE.GEOMETRIC_ERROR;tile.lodMetricValue=tile.geometricError;tile.transformMatrix=tile.transform;var{children,contentUrl}=await parseImplicitTiles(rootSubtree,options);if(contentUrl){tile.contentUrl=contentUrl;tile.content={uri:contentUrl.replace("".concat(options.basePath,"/"),'')};}tile.refine=getRefine(tile.refine);tile.type=getTileType(tile);tile.children=children;tile.id=tile.contentUrl;return tile;}var IMPLICIT_TILING_EXTENSION_NAME='3DTILES_implicit_tiling';var Tiles3DLoader={id:'3d-tiles',name:'3D Tiles',module:'3d-tiles',version:VERSION$5,extensions:['cmpt','pnts','b3dm','i3dm'],mimeTypes:['application/octet-stream'],tests:['cmpt','pnts','b3dm','i3dm'],parse,options:{'3d-tiles':{loadGLTF:true,decodeQuantizedPositions:false,isTileset:'auto',assetGltfUpAxis:null}}};function getBaseUri(tileset){return dirname(tileset.url);}async function parseTile(arrayBuffer,options,context){var tile={content:{featureIds:null}};var byteOffset=0;await parse3DTile(arrayBuffer,byteOffset,options,context,tile.content);return tile.content;}async function parseTileset(data,options,context){var _tilesetJson$root;var tilesetJson=JSON.parse(new TextDecoder().decode(data));tilesetJson.loader=options.loader||Tiles3DLoader;tilesetJson.url=context.url;tilesetJson.basePath=getBaseUri(tilesetJson);tilesetJson.root=hasImplicitTilingExtension(tilesetJson)?await normalizeImplicitTileHeaders(tilesetJson):normalizeTileHeaders(tilesetJson);tilesetJson.type=TILESET_TYPE.TILES3D;tilesetJson.lodMetricType=LOD_METRIC_TYPE.GEOMETRIC_ERROR;tilesetJson.lodMetricValue=((_tilesetJson$root=tilesetJson.root)===null||_tilesetJson$root===void 0?void 0:_tilesetJson$root.lodMetricValue)||0;return tilesetJson;}async function parse(data,options,context){var loaderOptions=options['3d-tiles']||{};var isTileset;if(loaderOptions.isTileset==='auto'){isTileset=context.url&&context.url.indexOf('.json')!==-1;}else {isTileset=loaderOptions.isTileset;}if(isTileset){data=await parseTileset(data,options,context);}else {data=await parseTile(data,options,context);}return data;}function hasImplicitTilingExtension(tilesetJson){var _tilesetJson$extensio,_tilesetJson$extensio2;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));}var CESIUM_ION_URL='https://api.cesium.com/v1/assets';async function getIonTilesetMetadata(accessToken,assetId){if(!assetId){var assets=await getIonAssets(accessToken);for(var item of assets.items){if(item.type==='3DTILES'){assetId=item.id;}}}var ionAssetMetadata=await getIonAssetMetadata(accessToken,assetId);var{type,url}=ionAssetMetadata;assert$7(type==='3DTILES'&&url);ionAssetMetadata.headers={Authorization:"Bearer ".concat(ionAssetMetadata.accessToken)};return ionAssetMetadata;}async function getIonAssets(accessToken){assert$7(accessToken);var url=CESIUM_ION_URL;var headers={Authorization:"Bearer ".concat(accessToken)};var response=await fetchFile(url,{fetch:{headers}});if(!response.ok){throw new Error(response.statusText);}return await response.json();}async function getIonAssetMetadata(accessToken,assetId){assert$7(accessToken,assetId);var headers={Authorization:"Bearer ".concat(accessToken)};var url="".concat(CESIUM_ION_URL,"/").concat(assetId);var response=await fetchFile("".concat(url),{fetch:{headers}});if(!response.ok){throw new Error(response.statusText);}var metadata=await response.json();response=await fetchFile("".concat(url,"/endpoint"),{fetch:{headers}});if(!response.ok){throw new Error(response.statusText);}var tilesetInfo=await response.json();metadata=_objectSpread2(_objectSpread2({},metadata),tilesetInfo);return metadata;}async function preload(url){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};options=options['cesium-ion']||{};var{accessToken}=options;var assetId=options.assetId;if(!Number.isFinite(assetId)){var matched=url.match(/\/([0-9]+)\/tileset.json/);assetId=matched&&matched[1];}return getIonTilesetMetadata(accessToken,assetId);}var CesiumIonLoader=_objectSpread2(_objectSpread2({},Tiles3DLoader),{},{id:'cesium-ion',name:'Cesium Ion',preload,parse:async(data,options,context)=>{options=_objectSpread2({},options);options['3d-tiles']=options['cesium-ion'];options.loader=CesiumIonLoader;return Tiles3DLoader.parse(data,options,context);},options:{'cesium-ion':_objectSpread2(_objectSpread2({},Tiles3DLoader.options['3d-tiles']),{},{accessToken:null})}});// From https://github.com/potree/potree/blob/master/src/materials/PointCloudMaterial.js
  57069. function generateGradientTexture(gradient){var size=64;// create canvas
  57070. var canvas=document.createElement('canvas');canvas.width=size;canvas.height=size;// get context
  57071. var context=canvas.getContext('2d');// draw gradient
  57072. context.rect(0,0,size,size);var ctxGradient=context.createLinearGradient(0,0,size,size);for(var _i56=0;_i56<gradient.length;_i56++){var step=gradient[_i56];ctxGradient.addColorStop(step[0],'#'+step[1].getHexString());}context.fillStyle=ctxGradient;context.fill();//let texture = new THREE.Texture(canvas);
  57073. var texture=new CanvasTexture(canvas);texture.needsUpdate=true;texture.minFilter=LinearFilter;texture.wrapS=RepeatWrapping;texture.wrapT=RepeatWrapping;texture.repeat.set(2,2);// textureImage = texture.image;
  57074. return texture;}function _getCameraFrustum(camera){camera.updateMatrix();// make sure camera's local matrix is updated
  57075. camera.updateMatrixWorld();// make sure camera's world matrix is updated
  57076. camera.matrixWorldInverse.copy(camera.matrixWorld).invert();var frustum=new Frustum();frustum.setFromProjectionMatrix(new Matrix4().multiplyMatrices(camera.projectionMatrix,camera.matrixWorldInverse));return frustum;}function loadersPlaneToMesh(plane){var group=new Group();// Create a basic rectangle geometry from math.gl plane
  57077. var planeGeometry=new PlaneGeometry(10,5);// Align the geometry to the plane
  57078. var coplanarPoint=new Vector3(...plane.projectPointOntoPlane([0,0,0]));var normal=new Vector3(plane.normal.x,plane.normal.y,plane.normal.z);var focalPoint=new Vector3().copy(coplanarPoint).add(normal);planeGeometry.lookAt(focalPoint);planeGeometry.translate(coplanarPoint.x,coplanarPoint.y,coplanarPoint.z);// Edges
  57079. /*
  57080. const edges = new EdgesGeometry(planeGeometry)
  57081. var dispPlane = new LineSegments(edges, new LineBasicMaterial({ color: 0x00ffff }))*/ //plane
  57082. var material=new MeshBasicMaterial({color:0x00ffff,side:DoubleSide});var mesh=new Mesh(planeGeometry,material);var arrowHelper=new ArrowHelper(normal,coplanarPoint,5,0xffff00);group.add(arrowHelper);group.add(mesh);return group;}function loadersBoundingBoxToMesh(tile){// Create a basic rectangle geometry from math.gl half-axes
  57083. var boundUntransformed=tile.type=='empty'?tile.boundingVolume:tile.getBoundUntransformed();//empty时没创建好,直接给boundingVolume一样
  57084. /* let redColor = 0;
  57085. if (tile.content) {
  57086. //redColor = Math.min((tile.content.byteLength != void 0 ? tile.content.byteLength : 0) / 500000, 1.0);
  57087. redColor = Math.min( tile.depth / 10 , 1.0); //改
  57088. } */var hue=0;if(tile.content){hue=Math.min(tile.depth/10,1.0);//改
  57089. }var boxColor=new THREE.Color().setHSL(hue,0.9,0.85);//const boxColor = new Color(redColor, 1.0, 0.0);
  57090. var boxGeometry=new BoxGeometry(1,1,1);var boxTransform=new Matrix4();if(boundUntransformed.halfAxes){boxTransform.copy(getMatrix4FromHalfAxes(boundUntransformed.halfAxes));}else if(boundUntransformed.radius){boxGeometry.scale(boundUntransformed.radius*2,boundUntransformed.radius*2,boundUntransformed.radius*2);}boxTransform.premultiply(new Matrix4().setPosition(...boundUntransformed.center));//add
  57091. /* if(tile.type != "empty"){ //root单独处理了
  57092. boxTransform.premultiply((new Matrix4$1()).makeScale(1,1,-1))//xzw 因为mesh倒转了所以box也
  57093. }else{
  57094. console.log('empty')
  57095. } */boxGeometry.applyMatrix4(boxTransform);var edges=new EdgesGeometry(boxGeometry);var dispPlane=new LineSegments(edges,new LineBasicMaterial({color:boxColor,transparent:true}));//dispPlane.position.copy(new Vector3$1(...boundingVolume.center));
  57096. dispPlane.matrixAutoUpdate=false;//add
  57097. var label=new Potree.TextSprite({mat:new THREE.MeshBasicMaterial({transparent:true}),//depthTest:false会导致经常显示不出
  57098. backgroundColor:{r:0,g:0,b:0,a:0.1},textColor:{r:boxColor.r*255,g:boxColor.g*255,b:boxColor.b*255,a:0.9},fontsize:100,//useDepth : true ,
  57099. renderOrder:5,text:tile.id.split('/').pop().split('.b3dm')[0],//Tile_+094_-010.b3dm'
  57100. name:'tile'});label.addEventListener('mouseover',()=>{if(label.sprite.material.opacity<1)return;window.hoverTile=tile;console.log('hoverLabel',tile.id,tile._distanceToCamera);});/* let s = 0.6
  57101. label.scale.set(s,s,s) */var s=tile.tileset.options.maximumScreenSpaceError/400;label.scale.set(s,s,s);dispPlane.add(label);label.position.set(...boundUntransformed.center);//label.position.z *= -1
  57102. /* if(tile.content.byteLength == void 0){
  57103. let oldUpdate = dispPlane.updateMatrixWorld.bind(dispPlane)
  57104. dispPlane.updateMatrixWorld = (a,b)=>{
  57105. oldUpdate(a,b)
  57106. }
  57107. let oldU = dispPlane.updateMatrix.bind(dispPlane)
  57108. dispPlane.updateMatrix = (a,b)=>{
  57109. oldU(a,b)
  57110. }
  57111. } */tile.volumeBox=dispPlane;return dispPlane;}function getMatrix4FromHalfAxes(halfAxes){var m=halfAxes;var rotateMatrix=new Matrix4().fromArray([m[0]*2,m[1]*2,m[2]*2,0,m[3]*2,m[4]*2,m[5]*2,0,m[6]*2,m[7]*2,m[8]*2,0,0,0,0,1]);return rotateMatrix;}/*
  57112. * from https://github.com/tentone/geo-three
  57113. * Tree-shaking did not work, probably due to static class methods
  57114. */function datumsToSpherical(latitude,longitude){var EARTH_RADIUS=6378137;var EARTH_PERIMETER=2*Math.PI*EARTH_RADIUS;var EARTH_ORIGIN=EARTH_PERIMETER/2.0;var x=longitude*EARTH_ORIGIN/180.0;var y=Math.log(Math.tan((90+latitude)*Math.PI/360.0))/(Math.PI/180.0);y=y*EARTH_ORIGIN/180.0;return new Vector2(x,y);}var Gradients$1={// From chroma spectral http://gka.github.io/chroma.js/
  57115. SPECTRAL:[[0,new Color(0.3686,0.3098,0.6353)],[0.1,new Color(0.1961,0.5333,0.7412)],[0.2,new Color(0.4,0.7608,0.6471)],[0.3,new Color(0.6706,0.8667,0.6431)],[0.4,new Color(0.902,0.9608,0.5961)],[0.5,new Color(1.0,1.0,0.749)],[0.6,new Color(0.9961,0.8784,0.5451)],[0.7,new Color(0.9922,0.6824,0.3804)],[0.8,new Color(0.9569,0.4275,0.2627)],[0.9,new Color(0.8353,0.2431,0.3098)],[1,new Color(0.6196,0.0039,0.2588)]],PLASMA:[[0.0,new Color(0.241,0.015,0.61)],[0.1,new Color(0.387,0.001,0.654)],[0.2,new Color(0.524,0.025,0.653)],[0.3,new Color(0.651,0.125,0.596)],[0.4,new Color(0.752,0.227,0.513)],[0.5,new Color(0.837,0.329,0.431)],[0.6,new Color(0.907,0.435,0.353)],[0.7,new Color(0.963,0.554,0.272)],[0.8,new Color(0.992,0.681,0.195)],[0.9,new Color(0.987,0.822,0.144)],[1.0,new Color(0.94,0.975,0.131)]],YELLOW_GREEN:[[0,new Color(0.1647,0.2824,0.3451)],[0.1,new Color(0.1338,0.3555,0.4227)],[0.2,new Color(0.061,0.4319,0.4864)],[0.3,new Color(0.0,0.5099,0.5319)],[0.4,new Color(0.0,0.5881,0.5569)],[0.5,new Color(0.137,0.665,0.5614)],[0.6,new Color(0.2906,0.7395,0.5477)],[0.7,new Color(0.4453,0.8099,0.5201)],[0.8,new Color(0.6102,0.8748,0.485)],[0.9,new Color(0.7883,0.9323,0.4514)],[1,new Color(0.9804,0.9804,0.4314)]],VIRIDIS:[[0.0,new Color(0.267,0.005,0.329)],[0.1,new Color(0.283,0.141,0.458)],[0.2,new Color(0.254,0.265,0.53)],[0.3,new Color(0.207,0.372,0.553)],[0.4,new Color(0.164,0.471,0.558)],[0.5,new Color(0.128,0.567,0.551)],[0.6,new Color(0.135,0.659,0.518)],[0.7,new Color(0.267,0.749,0.441)],[0.8,new Color(0.478,0.821,0.318)],[0.9,new Color(0.741,0.873,0.15)],[1.0,new Color(0.993,0.906,0.144)]],INFERNO:[[0.0,new Color(0.077,0.042,0.206)],[0.1,new Color(0.225,0.036,0.388)],[0.2,new Color(0.373,0.074,0.432)],[0.3,new Color(0.522,0.128,0.42)],[0.4,new Color(0.665,0.182,0.37)],[0.5,new Color(0.797,0.255,0.287)],[0.6,new Color(0.902,0.364,0.184)],[0.7,new Color(0.969,0.516,0.063)],[0.8,new Color(0.988,0.683,0.072)],[0.9,new Color(0.961,0.859,0.298)],[1.0,new Color(0.988,0.998,0.645)]],GRAYSCALE:[[0,new Color(0,0,0)],[1,new Color(1,1,1)]],// 16 samples of the TURBU color scheme
  57116. // values taken from: https://gist.github.com/mikhailov-work/ee72ba4191942acecc03fe6da94fc73f
  57117. // original file licensed under Apache-2.0
  57118. TURBO:[[0.0,new Color(0.18995,0.07176,0.23217)],[0.07,new Color(0.25107,0.25237,0.63374)],[0.13,new Color(0.27628,0.42118,0.89123)],[0.2,new Color(0.25862,0.57958,0.99876)],[0.27,new Color(0.15844,0.73551,0.92305)],[0.33,new Color(0.09267,0.86554,0.7623)],[0.4,new Color(0.19659,0.94901,0.59466)],[0.47,new Color(0.42778,0.99419,0.38575)],[0.53,new Color(0.64362,0.98999,0.23356)],[0.6,new Color(0.80473,0.92452,0.20459)],[0.67,new Color(0.93301,0.81236,0.22667)],[0.73,new Color(0.99314,0.67408,0.20348)],[0.8,new Color(0.9836,0.49291,0.12849)],[0.87,new Color(0.92105,0.31489,0.05475)],[0.93,new Color(0.81608,0.18462,0.01809)],[1.0,new Color(0.66449,0.08436,0.00424)]],RAINBOW:[[0,new Color(0.278,0,0.714)],[1/6,new Color(0,0,1)],[2/6,new Color(0,1,1)],[3/6,new Color(0,1,0)],[4/6,new Color(1,1,0)],[5/6,new Color(1,0.64,0)],[1,new Color(1,0,0)]],CONTOUR:[[0.0,new Color(0,0,0)],[0.03,new Color(0,0,0)],[0.04,new Color(1,1,1)],[1.0,new Color(1,1,1)]]};var PointCloudFS="\n varying vec3 vColor;\n uniform float alpha;\n\n void main() {\n if (vColor == vec3(0.0, 0.0, 0.0)) {\n discard;\n } else {\n gl_FragColor = vec4( vColor, alpha);\n }\n }\n";var PointCloudVS="\n varying vec3 vColor;\n uniform sampler2D gradient;\n uniform sampler2D grayscale;\n attribute float intensity;\n attribute float classification;\n uniform vec3 rootCenter;\n uniform vec3 rootNormal;\n uniform vec2 elevationRange;\n uniform int coloring;\n uniform bool hideGround;\n uniform float maxIntensity;\n uniform float intensityContrast;\n uniform float pointSize;\n\n #ifdef USE_COLOR\n vec3 getRGB() {\n vec3 rgb = color;\n return rgb;\n }\n #endif\n\n vec3 getElevation(){\n vec4 world = modelMatrix * vec4( position, 1.0 );\n float diff = abs(dot(rootNormal, (vec3(world) - rootCenter)));\n float w = max(diff - elevationRange.x,0.0) / max(elevationRange.y - elevationRange.x,1.0);\n vec3 cElevation = texture2D(gradient, vec2(w,1.0-w)).rgb;\n\n return cElevation;\n }\n\n vec3 getIntensity(){\n // TODO: real contrast enhancement. Check https://github.com/yuki-koyama/enhancer/blob/master/shaders/enhancer.fs\n float intmod = pow(intensity, intensityContrast);\n vec3 cIntensity = texture2D(grayscale, vec2(intmod / maxIntensity ,1.0-(intmod / maxIntensity))).rgb;\n return cIntensity;\n }\n\n vec3 getClassification(){\n float classNormalized = classification / 255.0;\n vec3 cClassification = texture2D(gradient, vec2(classNormalized * 5.0,1.0-classNormalized * 5.0)).rgb;\n return cClassification;\n }\n\n vec3 getColor(){\n vec3 color;\n if (hideGround && classification == 2.0) {\n return vec3(0.0, 0.0, 0.0); \n }\n\n if (coloring == 1) {\n color = getIntensity();\n }\n else if (coloring == 2) {\n color = getClassification();\n } else if (coloring == 3) {\n color = getElevation();\n } \n #ifdef USE_COLOR\n else if (coloring == 4) {\n color = getRGB();\n }\n #endif\n else {\n color = vec3(1.0, 1.0, 1.0);\n }\n return color;\n }\n\n void main() {\n vColor = getColor();\n\n gl_PointSize = pointSize;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }\n";/** Types of coloring used when viewing point cloud tiles */var PointCloudColoring;(function(PointCloudColoring){PointCloudColoring[PointCloudColoring["Intensity"]=1]="Intensity";PointCloudColoring[PointCloudColoring["Classification"]=2]="Classification";PointCloudColoring[PointCloudColoring["Elevation"]=3]="Elevation";PointCloudColoring[PointCloudColoring["RGB"]=4]="RGB";PointCloudColoring[PointCloudColoring["White"]=5]="White";})(PointCloudColoring||(PointCloudColoring={}));/** Types of shading used when viewing b3dm (mesh) tiles */var Shading;(function(Shading){Shading[Shading["FlatTexture"]=1]="FlatTexture";Shading[Shading["ShadedTexture"]=2]="ShadedTexture";Shading[Shading["ShadedNoTexture"]=3]="ShadedNoTexture";})(Shading||(Shading={}));var GeoTransform;(function(GeoTransform){GeoTransform[GeoTransform["Reset"]=1]="Reset";GeoTransform[GeoTransform["Mercator"]=2]="Mercator";GeoTransform[GeoTransform["WGS84Cartesian"]=3]="WGS84Cartesian";})(GeoTransform||(GeoTransform={}));var gradient=Gradients$1.RAINBOW;var gradientTexture=typeof document!='undefined'?generateGradientTexture(gradient):null;var grayscale=Gradients$1.GRAYSCALE;var grayscaleTexture=typeof document!='undefined'?generateGradientTexture(grayscale):null;var defaultOptions={throttleRequests:true,maxRequests:64,updateInterval:0.1,maxConcurrency:1,maximumScreenSpaceError:16,maximumMemoryUsage:32,viewDistanceScale:1.0,skipLevelOfDetail:false,updateTransforms:true,shading:Shading.FlatTexture,transparent:false,pointCloudColoring:PointCloudColoring.White,pointSize:1.0,worker:true,wireframe:false,debug:false,basisTranscoderPath:null,dracoDecoderPath:null,material:null,computeNormals:false,shaderCallback:null,geoTransform:GeoTransform.Reset,preloadTilesCount:null};/** 3D Tiles Loader */class Loader3DTiles{/**
  57119. * Loads a tileset of 3D Tiles according to the given {@link LoaderProps}
  57120. * @public
  57121. *
  57122. * @param props - Properties for this load call {@link LoaderProps}.
  57123. * @returns An object containing the 3D Model to be added to the scene
  57124. * and a runtime engine to be updated every frame.
  57125. */static load(props){return __awaiter(this,void 0,void 0,function*(){var options=Object.assign(Object.assign({},defaultOptions),props.options);var{url}=props;var UPDATE_INTERVAL=options.updateInterval;var MAX_DEPTH_FOR_ORIENTATION=5;var loadersGLOptions={};if(options.cesiumIONToken){loadersGLOptions['cesium-ion']={accessToken:options.cesiumIONToken};var metadata=yield CesiumIonLoader.preload(url,loadersGLOptions);loadersGLOptions['fetch']={headers:metadata.headers};}if(props.loadingManager){props.loadingManager.itemStart(url);}var tilesetJson=yield load(url,Tiles3DLoader,Object.assign({},loadersGLOptions));var renderMap={};var boxMap={};var unloadQueue=[];var root=new Group();var tileBoxes=new Group();tileBoxes.matrixAutoUpdate=false;//add
  57126. if(!options.debug){tileBoxes.visible=false;}else {options.parent.add(tileBoxes);//add
  57127. }var pointcloudUniforms={pointSize:{type:'f',value:options.pointSize},gradient:{type:'t',value:gradientTexture},grayscale:{type:'t',value:grayscaleTexture},rootCenter:{type:'vec3',value:new Vector3()},rootNormal:{type:'vec3',value:new Vector3()},coloring:{type:'i',value:options.pointCloudColoring},hideGround:{type:'b',value:true},elevationRange:{type:'vec2',value:new Vector2(0,400)},maxIntensity:{type:'f',value:1.0},intensityContrast:{type:'f',value:1.0},alpha:{type:'f',value:1.0}};var pointcloudMaterial=new ShaderMaterial({uniforms:pointcloudUniforms,vertexShader:PointCloudVS,fragmentShader:PointCloudFS,transparent:options.transparent,vertexColors:true});var cameraReference=null;var rendererReference=null;var gltfLoader=props.gltfLoader||new GLTFLoader();//xzw改
  57128. var ktx2Loader=undefined;var dracoLoader=undefined;if(options.basisTranscoderPath){ktx2Loader=new KTX2Loader();ktx2Loader.detectSupport(props.renderer);ktx2Loader.setTranscoderPath(options.basisTranscoderPath+'/');ktx2Loader.setWorkerLimit(1);gltfLoader.setKTX2Loader(ktx2Loader);}if(options.dracoDecoderPath){dracoLoader=new DRACOLoader();dracoLoader.setDecoderPath(options.dracoDecoderPath+'/');dracoLoader.setWorkerLimit(options.maxConcurrency);gltfLoader.setDRACOLoader(dracoLoader);}var unlitMaterial=new MeshBasicMaterial({transparent:options.transparent});var tileOptions={is4dkkModel:options.is4dkkModel,//add
  57129. maximumMemoryUsage:options.maximumMemoryUsage,maximumScreenSpaceError:options.maximumScreenSpaceError,initialMaxSSE:options.maximumScreenSpaceError,viewDistanceScale:options.viewDistanceScale,skipLevelOfDetail:options.skipLevelOfDetail,updateTransforms:options.updateTransforms,throttleRequests:options.throttleRequests,maxRequests:options.maxRequests,updateTime:options.updateTime||0,//add
  57130. //maxDepth: options.maxDepth || 50, // !zeg改
  57131. contentLoader:tile=>__awaiter(this,void 0,void 0,function*(){var tileContent=null;switch(tile.type){case TILE_TYPE.POINTCLOUD:{tileContent=createPointNodes(tile,pointcloudMaterial,options,rootTransformInverse);break;}case TILE_TYPE.SCENEGRAPH:case TILE_TYPE.MESH:{tileContent=yield createGLTFNodes(gltfLoader,tile,unlitMaterial,options,rootTransformInverse);break;}}if(tileContent){tileContent.visible=false;renderMap[tile.id]=tileContent;tileContent.name=tile.id;//add
  57132. tileContent.tile=tile;//add
  57133. changeModelPointCount(tile,'add');if(options.is4dkkModel){// !zeg改 addTile
  57134. //root.addTile(tile.floorIndex, tileContent)//this.floors.getOrMakeFloor(floorIndex).addTile(tileContent)
  57135. getOrMakeFloor(tile.floorIndex).add(tileContent);}else {root.add(tileContent);}if(options.debug){var box=loadersBoundingBoxToMesh(tile);tileBoxes.add(box);boxMap[tile.id]=box;}//xzw :
  57136. tileset.dispatchEvent({type:'tileLoaded',tileContent});//每一个tile加载完要更改透明度等
  57137. }}),onTileLoad:tile=>__awaiter(this,void 0,void 0,function*(){if(tileset){if(!orientationDetected&&(tile===null||tile===void 0?void 0:tile.depth)<=MAX_DEPTH_FOR_ORIENTATION){detectOrientation(tile);}tileset._frameNumber++;tilesetUpdate(tileset,renderMap,rendererReference,cameraReference);}}),onTileUnload:tile=>{unloadQueue.push(tile);},onTileError:(tile,message)=>{console.error('Tile error',tile.id,message);}};var tileset=new Tileset3D(tilesetJson,Object.assign(Object.assign({},tileOptions),{loadOptions:Object.assign(Object.assign({},loadersGLOptions),{maxConcurrency:options.maxConcurrency,worker:options.worker,gltf:{loadImages:false},'3d-tiles':{loadGLTF:false}})}));var getOrMakeFloor=function getOrMakeFloor(floorIndex){//xzw add
  57138. if(!root.floors)root.floors={};var floor=root.floors[floorIndex];if(!floor){floor=new Group();//new Floor(this.model, floorIndex)
  57139. floor.name='floor_'+floorIndex;floor.floorIndex=floorIndex;root.add(floor);root.floors[floorIndex]=floor;}return floor;};if(options.is4dkkModel){tileset.currentFloor='all';root.goFloor=function(floorIndex){tileset.currentFloor=floorIndex;root.children.forEach(e=>Potree.Utils.updateVisible(e,'goFloor',floorIndex=='all'||e.floorIndex==floorIndex));tileset.nextForceUpdate=true;};}tileset.boxMap=boxMap;//add
  57140. // transformations
  57141. var threeMat=new Matrix4();var tileTransform=new Matrix4();var rootCenter=new Vector3();var orientationDetected=false;if(tileset.root.boundingVolume){if(tileset.root.header.boundingVolume.region){// TODO: Handle region type bounding volumes
  57142. // https://github.com/visgl/loaders.gl/issues/1994
  57143. console.warn("Cannot apply a model matrix to bounding volumes of type region. Tileset stays in original geo-coordinates.");options.geoTransform=GeoTransform.WGS84Cartesian;}tileTransform.setPosition(tileset.root.boundingVolume.center[0],tileset.root.boundingVolume.center[1],tileset.root.boundingVolume.center[2]);}else {console.warn("Bounding volume not found, no transformations applied");}if(options.debug){var box=loadersBoundingBoxToMesh(tileset.root);tileBoxes.add(box);boxMap[tileset.root.id]=box;}var disposeFlag=false;var loadingEnded=false;pointcloudUniforms.rootCenter.value.copy(rootCenter);pointcloudUniforms.rootNormal.value.copy(new Vector3(0,0,1).normalize());// Extra stats
  57144. tileset.stats.get('Loader concurrency').count=options.maxConcurrency;tileset.stats.get('Maximum SSE').count=options.maximumScreenSpaceError;tileset.stats.get('Maximum mem usage').count=options.maximumMemoryUsage;var timer=0;var lastCameraTransform=null;var lastCameraAspect=null;var lastCameraPosition=new Vector3(Infinity,Infinity,Infinity);var sseDenominator=null;root.updateMatrixWorld(true);var lastRootTransform=new Matrix4().copy(root.matrixWorld);var rootTransformInverse=new Matrix4().copy(lastRootTransform).invert();tileset.lastRootTransform=lastRootTransform;//add
  57145. detectOrientation(tileset.root);updateResetTransform();if(options.debug){boxMap[tileset.root.id].applyMatrix4(threeMat);tileBoxes.matrixWorld.copy(root.matrixWorld);}if(options.geoTransform==GeoTransform.Mercator){var coords=datumsToSpherical(tileset.cartographicCenter[1],tileset.cartographicCenter[0]);rootCenter.set(coords.x,0,-coords.y);root.position.copy(rootCenter);root.rotation.set(-Math.PI/2,0,0);root.updateMatrixWorld(true);}else if(options.geoTransform==GeoTransform.WGS84Cartesian){root.applyMatrix4(tileTransform);root.updateMatrixWorld(true);rootCenter.copy(root.position);}function detectOrientation(tile){if(!tile.boundingVolume.halfAxes){return;}var halfAxes=tile.boundingVolume.halfAxes;var orientationMatrix=new Matrix4().extractRotation(getMatrix4FromHalfAxes(halfAxes)).premultiply(new Matrix4().extractRotation(rootTransformInverse));var rotation=new Euler().setFromRotationMatrix(orientationMatrix);if(!rotation.equals(new Euler())){orientationDetected=true;var pos=new Vector3(tileTransform.elements[12],tileTransform.elements[13],tileTransform.elements[14]);tileTransform.extractRotation(orientationMatrix);tileTransform.setPosition(pos);updateResetTransform();}}function updateResetTransform(){if(options.geoTransform!=GeoTransform.WGS84Cartesian){// Reset the current model matrix and apply our own transformation
  57146. //threeMat.copy(tileTransform).invert();
  57147. //threeMat.premultiply(lastRootTransform); //xzw删 被下面copy这句覆盖了
  57148. var tileTransInvert=new Matrix4().copy(tileTransform).invert();threeMat.copy(lastRootTransform).multiply(tileTransInvert);tileset.modelMatrix=new Matrix4$1(threeMat.toArray());//console.log('update tileset ModelMatrix', tileset.modelMatrix.elements)
  57149. tileset.tileTransInvert=tileTransInvert.toArray();// add for volumebox
  57150. }}// 更新瓦片显隐和瓦片迭代更新
  57151. function tilesetUpdate(tileset,renderMap,renderer,camera){if(disposeFlag||options.pauseTilesetUpdate){// !zeg改 pauseTilesetUpdate
  57152. return;}// Assumes camera fov, near and far are not changing
  57153. if(!sseDenominator||camera.aspect!=lastCameraAspect){var loadersFrustum=new PerspectiveFrustum({fov:camera.fov/180*Math.PI,aspectRatio:camera.aspect,near:camera.near,far:camera.far});sseDenominator=loadersFrustum.sseDenominator;lastCameraAspect=camera.aspect;if(camera.aspect==0)return;//add
  57154. if(options.debug){console.log('Updated sse denonimator:',sseDenominator);}}var frustum=_getCameraFrustum(camera);var planes=frustum.planes.map(plane=>new Plane$1(plane.normal.toArray(),plane.constant));var cullingVolume=new CullingVolume(planes);var rendererSize=new Vector2();renderer.getSize(rendererSize);var frameState={camera:{position:lastCameraPosition.toArray()},height:rendererSize.y,frameNumber:tileset._frameNumber,sseDenominator:sseDenominator,cullingVolume:cullingVolume,viewport:{id:0}};tileset._cache.reset();tileset._traverser.traverse(tileset.root,frameState,tileset.options);for(var tile of tileset.tiles){if(tile.selected){if(!renderMap[tile.id]){console.error('TILE SELECTED BUT NOT LOADED!!',tile.id);}else {// Make sure it's visible
  57155. if(!renderMap[tile.id].visible){if(viewer.visiVertexCount<maxVertexVisi){renderMap[tile.id].visible=true;viewer.visiVertexCount+=tile.posCount;//renderMap[tile.id].vertexCount //xzw add
  57156. options.debug&&(boxMap[tile.id].material.opacity=1,boxMap[tile.id].children[0].sprite.material.opacity=1);}else {//console.log('超出', visiVertexCount)
  57157. }}/* if(!renderMap[tile.id].realVisible()){
  57158. console.error('!realVisible')
  57159. } */}}else {if(renderMap[tile.id]){if(renderMap[tile.id].visible){renderMap[tile.id].visible=false;options.debug&&(boxMap[tile.id].material.opacity=0.1,boxMap[tile.id].children[0].sprite.material.opacity=0.1);viewer.visiVertexCount-=tile.posCount;//renderMap[tile.id].vertexCount //xzw add
  57160. }}}}while(unloadQueue.length>0){var _tile=unloadQueue.pop();if(renderMap[_tile.id]&&_tile.contentState==TILE_CONTENT_STATE.UNLOADED){//console.log('removevisi', renderMap[tile.id].visible) 如果是true,visiVertexCount要减
  57161. root.remove(renderMap[_tile.id]);disposeNode(renderMap[_tile.id]);delete renderMap[_tile.id];}if(boxMap[_tile.id]){disposeNode(boxMap[_tile.id]);tileBoxes.remove(boxMap[_tile.id]);delete boxMap[_tile.id];}}var tilesLoaded=tileset.stats.get('Tiles Loaded').count;var tilesLoading=tileset.stats.get('Tiles Loading').count;if(props.onProgress){props.onProgress(tilesLoaded,tilesLoaded+tilesLoading);}if(props.loadingManager&&!loadingEnded){if(tilesLoading==0&&(options.preloadTilesCount==null||tilesLoaded>=options.preloadTilesCount)){loadingEnded=true;props.loadingManager.itemEnd(props.url);}}return frameState;}return {model:root,runtime:{getTileset:()=>{return tileset;},getStats:()=>{return tileset.stats;},showTiles:visible=>{tileBoxes.visible=visible;},setWireframe:wireframe=>{options.wireframe=wireframe;root.traverse(object=>{if(object instanceof Mesh){object.material.wireframe=wireframe;}});},setDebug:debug=>{options.debug=debug;tileBoxes.visible=debug;},setShading:shading=>{options.shading=shading;},getTileBoxes:()=>{return tileBoxes;},setViewDistanceScale:scale=>{tileset.options.viewDistanceScale=scale;tileset._frameNumber++;tilesetUpdate(tileset,renderMap,rendererReference,cameraReference);},setHideGround:enabled=>{pointcloudUniforms.hideGround.value=enabled;},setPointCloudColoring:selection=>{pointcloudUniforms.coloring.value=selection;},setElevationRange:range=>{pointcloudUniforms.elevationRange.value.set(range[0],range[1]);},setMaxIntensity:intensity=>{pointcloudUniforms.maxIntensity.value=intensity;},setIntensityContrast:contrast=>{pointcloudUniforms.intensityContrast.value=contrast;},setPointAlpha:alpha=>{pointcloudUniforms.alpha.value=alpha;},getLatLongHeightFromPosition:position=>{var cartographicPosition=tileset.ellipsoid.cartesianToCartographic(new Vector3().copy(position).applyMatrix4(new Matrix4().copy(threeMat).invert()).toArray());return {lat:cartographicPosition[1],long:cartographicPosition[0],height:cartographicPosition[2]};},getPositionFromLatLongHeight:coord=>{var cartesianPosition=tileset.ellipsoid.cartographicToCartesian([coord.long,coord.lat,coord.height]);return new Vector3(...cartesianPosition).applyMatrix4(threeMat);},getCameraFrustum:camera=>{var frustum=_getCameraFrustum(camera);var meshes=frustum.planes.map(plane=>new Plane$1(plane.normal.toArray(),plane.constant)).map(loadersPlane=>loadersPlaneToMesh(loadersPlane));var model=new Group();for(var mesh of meshes)model.add(mesh);return model;},update:function update(dt,renderer,camera,ifForce){cameraReference=camera;rendererReference=renderer;timer+=dt;//updateQuality()
  57162. if(!ifForce)ifForce=tileset.nextForceUpdate;tileset.nextForceUpdate=false;if(tileset.needRenderNext){//必须在下一帧渲染刷新否则无法显示
  57163. viewer.dispatchEvent('content_changed');}tileset.needRenderNext=ifForce;if(tileset&&(timer>=UPDATE_INTERVAL||ifForce)){if(!lastRootTransform.equals(root.matrixWorld)){timer=0;lastRootTransform.copy(root.matrixWorld);updateResetTransform();var _rootCenter=new Vector3().setFromMatrixPosition(lastRootTransform);pointcloudUniforms.rootCenter.value.copy(_rootCenter);pointcloudUniforms.rootNormal.value.copy(new Vector3(0,0,1).applyMatrix4(lastRootTransform).normalize());rootTransformInverse.copy(lastRootTransform).invert();if(options.debug){/* console.log('move', tileset.root.id, boxMap[tileset.root.id].matrix.elements, boxMap[tileset.root.id].matrixWorld.elements)
  57164. boxMap[tileset.root.id].matrix.copy(root.matrixWorld);
  57165. boxMap[tileset.root.id].matrixWorld.copy(root.matrixWorld); */ //boxMap[tileset.root.id].applyMatrix4(threeMat);
  57166. tileBoxes.matrix.copy(root.matrixWorld);//boxMap[tileset.root.id].matrixWorld.copy(threeMat);
  57167. //boxMap[tileset.root.id].applyMatrix4(lastRootTransform);//boxMap[tileset.root.id].applyMatrix4(lastRootTransform);
  57168. //boxMap[tileset.root.id].updateWorldMatrix()
  57169. }}if(this.lastCameraTransform==null){this.lastCameraTransform=new Matrix4().copy(camera.matrixWorld);}else {var cameraChanged=!camera.matrixWorld.equals(this.lastCameraTransform)||!(camera.aspect==lastCameraAspect);if(cameraChanged||ifForce){timer=0;tileset._frameNumber++;camera.getWorldPosition(lastCameraPosition);this.lastCameraTransform.copy(camera.matrixWorld);tilesetUpdate(tileset,renderMap,renderer,camera);}}}},dispose:function dispose(){disposeFlag=true;tileset._destroy();while(root.children.length>0){var obj=root.children[0];disposeNode(obj);root.remove(obj);}while(tileBoxes.children.length>0){var _obj=tileBoxes.children[0];tileBoxes.remove(_obj);_obj.geometry.dispose();_obj.material.dispose();}if(ktx2Loader){ktx2Loader.dispose();}if(dracoLoader){dracoLoader.dispose();}},limit2lowestDepth:isLowest=>{//zeg add 设置是否限制为最低精度tile深度
  57170. maxDepth=isLowest?1:100;//影响到shouldRefine, 检查方法:可以看到当maxDepth降低了之后viewer.objs.children[0].runtime.getTileset().tiles.filter(e=> e.tileContent.visible)变少
  57171. if(cameraReference){tileset._frameNumber++;tilesetUpdate(tileset,renderMap,rendererReference,cameraReference);}}}};});}}function createGLTFNodes(gltfLoader,tile,unlitMaterial,options,rootTransformInverse){return __awaiter(this,void 0,void 0,function*(){return new Promise((resolve,reject)=>{var _a;var rotateX=new Matrix4().makeRotationAxis(new Vector3(1,0,0),Math.PI/2);var shouldRotate=((_a=tile.tileset.asset)===null||_a===void 0?void 0:_a.gltfUpAxis)!=="Z";// The computed trasnform already contains the root's transform, so we have to invert it
  57172. //const contentTransform = new Matrix4$1().fromArray(tile.computedTransform).premultiply(tileMatrix)//.premultiply(rootTransformInverse); //xzw 删。原先的会造成移动后tiles错乱
  57173. //const contentTransform = new Matrix4$1().fromArray(tile.computedTransform).premultiply(tile.tileset.modelMatrix).premultiply(rootTransformInverse)
  57174. // 这句同tile.computedTransform左乘tileTransform。 因为tileTransform拿不到所以使用modelMatrix。modelMatrix为tileTransform左乘rootTransform, 所以再左乘rootTransformInverse
  57175. //改动:contentTransform中的computedTransform 去掉左乘 root.modelMatrixWorld , 因为移动过后这个computedTransform没更新
  57176. gltfLoader.parse(tile.content.type=='glTF'?tile.content.gltf.gltfArrayBuffer:tile.content.gltfArrayBuffer,//tile.content.gltfArrayBuffer,
  57177. tile.contentUrl?tile.contentUrl.substr(0,tile.contentUrl.lastIndexOf('/')+1):'',gltf=>{var tileContent=gltf.scenes[0];//tileContent.vertexCount = 0 //xzw add
  57178. tile.tileContent=tileContent;//xzw add
  57179. var needUpdate;if(tile.rtcCenterState!=!!tile.content.rtcCenter){// 等mesh加载好才知道rtcCenter,每个mesh坐标都不一样
  57180. needUpdate=true;//console.error('rtcCenter有变化?!')
  57181. }tile.rtcCenterState=rtcCenterGlobal=!!tile.content.rtcCenter;var translate=tile.content.rtcCenter||tile.header.boundingVolume.sphere;//大部分模型无 rtcCenter
  57182. var contentTransform=tile.getContentTransform(needUpdate);if(translate){//需要位移后才和boundingVolume一样
  57183. var tranM=new Matrix4();tranM.makeTranslation(...translate);contentTransform.multiply(tranM);}if(needUpdate){tile._updateBoundingVolume(tile.header);//add 重新更新
  57184. }if(shouldRotate){//大部分模型 无需 Rotate
  57185. contentTransform.multiply(rotateX);// convert from GLTF Y-up to Z-up
  57186. }tileContent.applyMatrix4(contentTransform);//'https://testgis.4dage.com/LVBADUI_qp/tileset.json', //村庄 这个案例是 要rotateX 且有rtcCenter的。boundingVolume已经是转换这两者后的值所以getContentTransform不加这个
  57187. //tile总共要左乘的矩阵 rotateX -> tileTransInvert * computedTransform -> 对geometry的tranM修改 -> 整个模型的matrixWorld
  57188. tileContent.traverse(object=>{if(object.type=="Mesh"){var mesh=object;//mesh.tileId = tile.id//add
  57189. var originalMaterial=mesh.material;var originalMap=originalMaterial.map;if(options.material){mesh.material=options.material.clone();originalMaterial.dispose();}else if(options.shading==Shading.FlatTexture){mesh.material=unlitMaterial.clone();originalMaterial.dispose();}if(options.shading!=Shading.ShadedNoTexture){if(mesh.material.type=="ShaderMaterial"&&!(mesh.material instanceof MeshBasicMaterial)){//改
  57190. mesh.material.uniforms.map={value:originalMap};}else {mesh.material.map=originalMap;}}else {if(originalMap){originalMap.dispose();}mesh.material.map=null;}if(options.shaderCallback){mesh.onBeforeRender=options.shaderCallback;}mesh.material.wireframe=options.wireframe;if(options.computeNormals){mesh.geometry.computeVertexNormals();}//xzw add:
  57191. //tileContent.vertexCount += mesh.geometry.attributes.position.count
  57192. //------------------add on 2023.1.16----zeg
  57193. //mesh.geometry.applyMatrix4(contentTransform)
  57194. /* if (tile.content.rtcCenter) {
  57195. // 有些b3dm模型会将坐标写在源码的rtcCenter里 如https://testgis.4dage.com/LVBADUI_qp/tileset.json
  57196. mesh.geometry.translate(tile.content.rtcCenter[0], tile.content.rtcCenter[1], tile.content.rtcCenter[2])
  57197. } else {
  57198. mesh.geometry.scale(1, 1, -1) // 调整缩放,对应box也要进行变换(scaleZ对应box[2])
  57199. } */ //---------------------
  57200. }});resolve(tileContent);},e=>{reject(new Error("error parsing gltf in tile ".concat(tile.id,": ").concat(e)));});});});}function createPointNodes(tile,pointcloudMaterial,options,rootTransformInverse){var d={rtc_center:tile.content.rtcCenter,points:tile.content.attributes.positions,intensities:tile.content.attributes.intensity,classifications:tile.content.attributes.classification,rgb:null,rgba:null};var{colors}=tile.content.attributes;if(colors&&colors.size===3){d.rgb=colors.value;}if(colors&&colors.size===4){d.rgba=colors.value;}var geometry=new BufferGeometry();geometry.setAttribute('position',new Float32BufferAttribute(d.points,3));var contentTransform=new Matrix4().fromArray(tile.computedTransform).premultiply(rootTransformInverse);if(d.rgba){geometry.setAttribute('color',new Float32BufferAttribute(d.rgba,4));}else if(d.rgb){geometry.setAttribute('color',new Uint8BufferAttribute(d.rgb,3,true));}if(d.intensities){geometry.setAttribute('intensity',// Handles both 16bit or 8bit intensity values
  57201. new BufferAttribute(d.intensities,1,true));}if(d.classifications){geometry.setAttribute('classification',new Uint8BufferAttribute(d.classifications,1,false));}var tileContent=new Points(geometry,options.material||pointcloudMaterial);if(d.rtc_center){var c=d.rtc_center;contentTransform.multiply(new Matrix4().makeTranslation(c[0],c[1],c[2]));}tileContent.applyMatrix4(contentTransform);return tileContent;}function disposeMaterial(material){var _a,_b,_c,_d;if((_a=material===null||material===void 0?void 0:material.uniforms)===null||_a===void 0?void 0:_a.map){(_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();}else if(material.map){(_d=material.map)===null||_d===void 0?void 0:_d.dispose();}material.dispose();}function disposeNode(node){node.traverse(object=>{if(object.isMesh){object.geometry.dispose();if(object.material.isMaterial){disposeMaterial(object.material);}else {// an array of materials
  57202. for(var material of object.material){disposeMaterial(material);}}}});for(var _i57=node.children.length-1;_i57>=0;_i57--){var obj=node.children[_i57];node.remove(obj);}}/*
  57203. 关键搜寻:
  57204. Loader3DTiles : const tileset = new Tileset3D
  57205. tileset.dispatchEvent({type:'tileLoaded',tileContent})
  57206. createGLTFNodes(gltfLoader 创建tile
  57207. executeTraversal(root, frameState) 遍历root
  57208. lastRootTransform rootTransformInverse
  57209. tileset._loadTiles 依次加载tiles
  57210. _getPriority 加载优先级 加了一句
  57211. 笔记:
  57212. 主要类:
  57213. class tileset3D 最外层整体。 获取方法: viewer.objs.children[index].runtime.getTileset()。 .tiles包含所有tiles
  57214. class tileHeader 也就是tileset里面的一个个tile 。 其上有.tileset
  57215. _initializeTileSet(tilesetJson)
  57216. _initializeTileHeaders(tilesetJson, parentTileHeader) //json里tile初始化
  57217. tileset里算的tileTransform之后是不会改变的, tile.transform也是,是json里的。
  57218. tileset.modelMatrix (通常这个值很大) 会随着位移改变
  57219. tile.computedTransform 被我修改了,之前左乘了tileset.modelMatrix,现只包含了transform信息 _updateTransform(parentTransfor 其中有_updateBoundingVolume,这个影响可见性, 在computeVisibilityWithPlaneMask中计算
  57220. tileset._cache.trim(), 然后再update //可以将所有不可见的tiles dispose
  57221. 相机靠近容易缺块的bug暂时修改如下: _visible是由computeVisibilityWithPlaneMask计算得
  57222. get isVisibleAndInRequestVolume() {
  57223. return this._inRequestVolume; //去掉了_visible ||
  57224. }
  57225. 显示所有tile似乎也不会卡顿. 但好像影响了加载顺序从而变慢了。visiVertexCount过量。 怀疑应该还是文件的bound有问题。
  57226. 原本会消失的地方虽然不会消失了但一直是模糊的
  57227. 被隐藏的tiles对应的mesh也是仅隐藏,并未删除
  57228. =========
  57229. 访问所有tile:
  57230. viewer.objs.children[0].runtime.getTileset().tiles
  57231. 它的mesh: tile.tileContent
  57232. 或者直接得到所有mesh: viewer.objs.children[0].children
  57233. tile.depth最低为1 , root是0
  57234. ===============
  57235. 带坐标osgb参考ces初始化位置 (用付费软件转的那个)特点:tileset.json里的boundingVolume有sphere而非box,无transform
  57236. 用另一个工程 3DTilesRendererJS 也显示不出来。 改了很多代码才显示对。
  57237. 思路:把json里的sphere.center提取出来,作为最后默认的position,这样模型就在原点上,很多变量都是000了,简化很多。
  57238. 和box型的不同的是,需要手动将children里的也按照其sphere.center(减去外层的原始center)位移。box的似乎geo里已经位移好了。
  57239. 然后会看到模型是斜的,如案例港湾一号的mesh,因cesium中地球正面为经纬度0,0的位置,在非洲左侧,对应x轴正向,右侧为y轴正向。
  57240. 模型位于地球右侧靠后上一点,朝向地心。所以把它转正一下就行了。 (现在写进了rotGeoToZeroMat)
  57241. 原始center为cesium坐标,要转化为经纬度再用:
  57242. let lonlat = Potree.sdk.cesMath.fromCes(center, true)
  57243. let pos = viewer.transform.lonlatToLocal.forward(lonlat) // {x:113.5933488,y:22.36711151}
  57244. model.position.copy(pos)
  57245. cesium显示:http://192.168.0.59:1234/examples/tomcat/allTest/Cesium-3dTiles/index-sphere.html
  57246. tile.header.boundingVolume.sphere 应用上变换才是 tile.boundingVolume.center
  57247. -.-.-.-.--.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
  57248. 用另一个开源代码转的是box型的,这样对准位置:
  57249. let center = new THREE.Vector3().fromArray([-2361896.965580558 ,//json的transform的后面三位
  57250. 5407880.606769544 ,
  57251. 2412064.492022378
  57252. ])
  57253. let pos = Potree.sdk.cesMath.fromCes(center)
  57254. viewer.modules.MergeEditor.selected.position.copy(pos)
  57255. //let lonlat = Potree.sdk.cesMath.fromCes(center,true)
  57256. //let pos = viewer.transform.lonlatToLocal.forward(lonlat)
  57257. //viewer.modules.MergeEditor.moveBoundCenterTo( viewer.modules.MergeEditor.selected, new THREE.Vector3().fromArray(pos) )
  57258. //因为bound中心在原点所以上面两句都可以
  57259. viewer.modules.MergeEditor.selected.updateMatrixWorld()
  57260. viewer.modules.MergeEditor.getBoundCenter(viewer.modules.MergeEditor.selected)
  57261. ==============
  57262. 3dtiles在四维看看和激光里摆放不同,这里的需要位移一段距离才能和四维看看一样,也就是和无transform后的点云一样。
  57263. 见load4dkkPanos函数
  57264. 且四维看看场景里所有坐标导入这里都要转换下,用posRot1MatrixInvert等矩阵。
  57265. */
  57266. var OBJLoader = function () {
  57267. // o object_name | g group_name
  57268. var object_pattern = /^[og]\s*(.+)?/;
  57269. // mtllib file_reference
  57270. var material_library_pattern = /^mtllib /;
  57271. // usemtl material_name
  57272. var material_use_pattern = /^usemtl /;
  57273. // usemap map_name
  57274. var map_use_pattern = /^usemap /;
  57275. var vA = new Vector3();
  57276. var vB = new Vector3();
  57277. var vC = new Vector3();
  57278. var ab = new Vector3();
  57279. var cb = new Vector3();
  57280. function ParserState() {
  57281. var state = {
  57282. objects: [],
  57283. object: {},
  57284. vertices: [],
  57285. normals: [],
  57286. colors: [],
  57287. uvs: [],
  57288. materials: {},
  57289. materialLibraries: [],
  57290. startObject: function startObject(name, fromDeclaration) {
  57291. // If the current object (initial from reset) is not from a g/o declaration in the parsed
  57292. // file. We need to use it for the first parsed g/o to keep things in sync.
  57293. if (this.object && this.object.fromDeclaration === false) {
  57294. this.object.name = name;
  57295. this.object.fromDeclaration = fromDeclaration !== false;
  57296. return;
  57297. }
  57298. var previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined;
  57299. if (this.object && typeof this.object._finalize === 'function') {
  57300. this.object._finalize(true);
  57301. }
  57302. this.object = {
  57303. name: name || '',
  57304. fromDeclaration: fromDeclaration !== false,
  57305. geometry: {
  57306. vertices: [],
  57307. normals: [],
  57308. colors: [],
  57309. uvs: [],
  57310. hasUVIndices: false
  57311. },
  57312. materials: [],
  57313. smooth: true,
  57314. startMaterial: function startMaterial(name, libraries) {
  57315. var previous = this._finalize(false);
  57316. // New usemtl declaration overwrites an inherited material, except if faces were declared
  57317. // after the material, then it must be preserved for proper MultiMaterial continuation.
  57318. if (previous && (previous.inherited || previous.groupCount <= 0)) {
  57319. this.materials.splice(previous.index, 1);
  57320. }
  57321. var material = {
  57322. index: this.materials.length,
  57323. name: name || '',
  57324. mtllib: Array.isArray(libraries) && libraries.length > 0 ? libraries[libraries.length - 1] : '',
  57325. smooth: previous !== undefined ? previous.smooth : this.smooth,
  57326. groupStart: previous !== undefined ? previous.groupEnd : 0,
  57327. groupEnd: -1,
  57328. groupCount: -1,
  57329. inherited: false,
  57330. clone: function clone(index) {
  57331. var cloned = {
  57332. index: typeof index === 'number' ? index : this.index,
  57333. name: this.name,
  57334. mtllib: this.mtllib,
  57335. smooth: this.smooth,
  57336. groupStart: 0,
  57337. groupEnd: -1,
  57338. groupCount: -1,
  57339. inherited: false
  57340. };
  57341. cloned.clone = this.clone.bind(cloned);
  57342. return cloned;
  57343. }
  57344. };
  57345. this.materials.push(material);
  57346. return material;
  57347. },
  57348. currentMaterial: function currentMaterial() {
  57349. if (this.materials.length > 0) {
  57350. return this.materials[this.materials.length - 1];
  57351. }
  57352. return undefined;
  57353. },
  57354. _finalize: function _finalize(end) {
  57355. var lastMultiMaterial = this.currentMaterial();
  57356. if (lastMultiMaterial && lastMultiMaterial.groupEnd === -1) {
  57357. lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
  57358. lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
  57359. lastMultiMaterial.inherited = false;
  57360. }
  57361. // Ignore objects tail materials if no face declarations followed them before a new o/g started.
  57362. if (end && this.materials.length > 1) {
  57363. for (var mi = this.materials.length - 1; mi >= 0; mi--) {
  57364. if (this.materials[mi].groupCount <= 0) {
  57365. this.materials.splice(mi, 1);
  57366. }
  57367. }
  57368. }
  57369. // Guarantee at least one empty material, this makes the creation later more straight forward.
  57370. if (end && this.materials.length === 0) {
  57371. this.materials.push({
  57372. name: '',
  57373. smooth: this.smooth
  57374. });
  57375. }
  57376. return lastMultiMaterial;
  57377. }
  57378. };
  57379. // Inherit previous objects material.
  57380. // Spec tells us that a declared material must be set to all objects until a new material is declared.
  57381. // If a usemtl declaration is encountered while this new object is being parsed, it will
  57382. // overwrite the inherited material. Exception being that there was already face declarations
  57383. // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
  57384. if (previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function') {
  57385. var declared = previousMaterial.clone(0);
  57386. declared.inherited = true;
  57387. this.object.materials.push(declared);
  57388. }
  57389. this.objects.push(this.object);
  57390. },
  57391. finalize: function finalize() {
  57392. if (this.object && typeof this.object._finalize === 'function') {
  57393. this.object._finalize(true);
  57394. }
  57395. },
  57396. parseVertexIndex: function parseVertexIndex(value, len) {
  57397. var index = parseInt(value, 10);
  57398. return (index >= 0 ? index - 1 : index + len / 3) * 3;
  57399. },
  57400. parseNormalIndex: function parseNormalIndex(value, len) {
  57401. var index = parseInt(value, 10);
  57402. return (index >= 0 ? index - 1 : index + len / 3) * 3;
  57403. },
  57404. parseUVIndex: function parseUVIndex(value, len) {
  57405. var index = parseInt(value, 10);
  57406. return (index >= 0 ? index - 1 : index + len / 2) * 2;
  57407. },
  57408. addVertex: function addVertex(a, b, c) {
  57409. var src = this.vertices;
  57410. var dst = this.object.geometry.vertices;
  57411. dst.push(src[a + 0], src[a + 1], src[a + 2]);
  57412. dst.push(src[b + 0], src[b + 1], src[b + 2]);
  57413. dst.push(src[c + 0], src[c + 1], src[c + 2]);
  57414. },
  57415. addVertexPoint: function addVertexPoint(a) {
  57416. var src = this.vertices;
  57417. var dst = this.object.geometry.vertices;
  57418. dst.push(src[a + 0], src[a + 1], src[a + 2]);
  57419. },
  57420. addVertexLine: function addVertexLine(a) {
  57421. var src = this.vertices;
  57422. var dst = this.object.geometry.vertices;
  57423. dst.push(src[a + 0], src[a + 1], src[a + 2]);
  57424. },
  57425. addNormal: function addNormal(a, b, c) {
  57426. var src = this.normals;
  57427. var dst = this.object.geometry.normals;
  57428. dst.push(src[a + 0], src[a + 1], src[a + 2]);
  57429. dst.push(src[b + 0], src[b + 1], src[b + 2]);
  57430. dst.push(src[c + 0], src[c + 1], src[c + 2]);
  57431. },
  57432. addFaceNormal: function addFaceNormal(a, b, c) {
  57433. var src = this.vertices;
  57434. var dst = this.object.geometry.normals;
  57435. vA.fromArray(src, a);
  57436. vB.fromArray(src, b);
  57437. vC.fromArray(src, c);
  57438. cb.subVectors(vC, vB);
  57439. ab.subVectors(vA, vB);
  57440. cb.cross(ab);
  57441. cb.normalize();
  57442. dst.push(cb.x, cb.y, cb.z);
  57443. dst.push(cb.x, cb.y, cb.z);
  57444. dst.push(cb.x, cb.y, cb.z);
  57445. },
  57446. addColor: function addColor(a, b, c) {
  57447. var src = this.colors;
  57448. var dst = this.object.geometry.colors;
  57449. if (src[a] !== undefined) dst.push(src[a + 0], src[a + 1], src[a + 2]);
  57450. if (src[b] !== undefined) dst.push(src[b + 0], src[b + 1], src[b + 2]);
  57451. if (src[c] !== undefined) dst.push(src[c + 0], src[c + 1], src[c + 2]);
  57452. },
  57453. addUV: function addUV(a, b, c) {
  57454. var src = this.uvs;
  57455. var dst = this.object.geometry.uvs;
  57456. dst.push(src[a + 0], src[a + 1]);
  57457. dst.push(src[b + 0], src[b + 1]);
  57458. dst.push(src[c + 0], src[c + 1]);
  57459. },
  57460. addDefaultUV: function addDefaultUV() {
  57461. var dst = this.object.geometry.uvs;
  57462. dst.push(0, 0);
  57463. dst.push(0, 0);
  57464. dst.push(0, 0);
  57465. },
  57466. addUVLine: function addUVLine(a) {
  57467. var src = this.uvs;
  57468. var dst = this.object.geometry.uvs;
  57469. dst.push(src[a + 0], src[a + 1]);
  57470. },
  57471. addFace: function addFace(a, b, c, ua, ub, uc, na, nb, nc) {
  57472. var vLen = this.vertices.length;
  57473. var ia = this.parseVertexIndex(a, vLen);
  57474. var ib = this.parseVertexIndex(b, vLen);
  57475. var ic = this.parseVertexIndex(c, vLen);
  57476. this.addVertex(ia, ib, ic);
  57477. this.addColor(ia, ib, ic);
  57478. // normals
  57479. if (na !== undefined && na !== '') {
  57480. var nLen = this.normals.length;
  57481. ia = this.parseNormalIndex(na, nLen);
  57482. ib = this.parseNormalIndex(nb, nLen);
  57483. ic = this.parseNormalIndex(nc, nLen);
  57484. this.addNormal(ia, ib, ic);
  57485. } else {
  57486. this.addFaceNormal(ia, ib, ic);
  57487. }
  57488. // uvs
  57489. if (ua !== undefined && ua !== '') {
  57490. var uvLen = this.uvs.length;
  57491. ia = this.parseUVIndex(ua, uvLen);
  57492. ib = this.parseUVIndex(ub, uvLen);
  57493. ic = this.parseUVIndex(uc, uvLen);
  57494. this.addUV(ia, ib, ic);
  57495. this.object.geometry.hasUVIndices = true;
  57496. } else {
  57497. // add placeholder values (for inconsistent face definitions)
  57498. this.addDefaultUV();
  57499. }
  57500. },
  57501. addPointGeometry: function addPointGeometry(vertices) {
  57502. this.object.geometry.type = 'Points';
  57503. var vLen = this.vertices.length;
  57504. for (var vi = 0, l = vertices.length; vi < l; vi++) {
  57505. var index = this.parseVertexIndex(vertices[vi], vLen);
  57506. this.addVertexPoint(index);
  57507. this.addColor(index);
  57508. }
  57509. },
  57510. addLineGeometry: function addLineGeometry(vertices, uvs) {
  57511. this.object.geometry.type = 'Line';
  57512. var vLen = this.vertices.length;
  57513. var uvLen = this.uvs.length;
  57514. for (var vi = 0, l = vertices.length; vi < l; vi++) {
  57515. this.addVertexLine(this.parseVertexIndex(vertices[vi], vLen));
  57516. }
  57517. for (var uvi = 0, l = uvs.length; uvi < l; uvi++) {
  57518. this.addUVLine(this.parseUVIndex(uvs[uvi], uvLen));
  57519. }
  57520. }
  57521. };
  57522. state.startObject('', false);
  57523. return state;
  57524. }
  57525. //
  57526. function OBJLoader(manager) {
  57527. Loader.call(this, manager);
  57528. this.materials = null;
  57529. }
  57530. OBJLoader.prototype = Object.assign(Object.create(Loader.prototype), {
  57531. constructor: OBJLoader,
  57532. load: function load(url, onLoad, onProgress, onError) {
  57533. var scope = this;
  57534. var loader = new FileLoader(this.manager);
  57535. loader.setPath(this.path);
  57536. loader.setRequestHeader(this.requestHeader);
  57537. loader.setWithCredentials(this.withCredentials);
  57538. loader.load(url, function (text, total) {
  57539. // xzw add total
  57540. try {
  57541. onLoad(scope.parse(text), total);
  57542. } catch (e) {
  57543. if (onError) {
  57544. onError(e);
  57545. } else {
  57546. console.error(e);
  57547. }
  57548. scope.manager.itemError(url);
  57549. }
  57550. }, onProgress, onError);
  57551. },
  57552. setMaterials: function setMaterials(materials) {
  57553. this.materials = materials;
  57554. return this;
  57555. },
  57556. parse: function parse(text) {
  57557. var state = new ParserState();
  57558. if (text.indexOf('\r\n') !== -1) {
  57559. // This is faster than String.split with regex that splits on both
  57560. text = text.replace(/\r\n/g, '\n');
  57561. }
  57562. if (text.indexOf('\\\n') !== -1) {
  57563. // join lines separated by a line continuation character (\)
  57564. text = text.replace(/\\\n/g, '');
  57565. }
  57566. var lines = text.split('\n');
  57567. var line = '',
  57568. lineFirstChar = '';
  57569. var lineLength = 0;
  57570. var result = [];
  57571. // Faster to just trim left side of the line. Use if available.
  57572. var trimLeft = typeof ''.trimLeft === 'function';
  57573. for (var i = 0, l = lines.length; i < l; i++) {
  57574. line = lines[i];
  57575. line = trimLeft ? line.trimLeft() : line.trim();
  57576. lineLength = line.length;
  57577. if (lineLength === 0) continue;
  57578. lineFirstChar = line.charAt(0);
  57579. // @todo invoke passed in handler if any
  57580. if (lineFirstChar === '#') continue;
  57581. if (lineFirstChar === 'v') {
  57582. var data = line.split(/\s+/);
  57583. switch (data[0]) {
  57584. case 'v':
  57585. state.vertices.push(parseFloat(data[1]), parseFloat(data[2]), parseFloat(data[3]));
  57586. if (data.length >= 7) {
  57587. state.colors.push(parseFloat(data[4]), parseFloat(data[5]), parseFloat(data[6]));
  57588. } else {
  57589. // if no colors are defined, add placeholders so color and vertex indices match
  57590. state.colors.push(undefined, undefined, undefined);
  57591. }
  57592. break;
  57593. case 'vn':
  57594. state.normals.push(parseFloat(data[1]), parseFloat(data[2]), parseFloat(data[3]));
  57595. break;
  57596. case 'vt':
  57597. state.uvs.push(parseFloat(data[1]), parseFloat(data[2]));
  57598. break;
  57599. }
  57600. } else if (lineFirstChar === 'f') {
  57601. var lineData = line.substr(1).trim();
  57602. var vertexData = lineData.split(/\s+/);
  57603. var faceVertices = [];
  57604. // Parse the face vertex data into an easy to work with format
  57605. for (var j = 0, jl = vertexData.length; j < jl; j++) {
  57606. var vertex = vertexData[j];
  57607. if (vertex.length > 0) {
  57608. var vertexParts = vertex.split('/');
  57609. faceVertices.push(vertexParts);
  57610. }
  57611. }
  57612. // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
  57613. var v1 = faceVertices[0];
  57614. for (var j = 1, jl = faceVertices.length - 1; j < jl; j++) {
  57615. var v2 = faceVertices[j];
  57616. var v3 = faceVertices[j + 1];
  57617. state.addFace(v1[0], v2[0], v3[0], v1[1], v2[1], v3[1], v1[2], v2[2], v3[2]);
  57618. }
  57619. } else if (lineFirstChar === 'l') {
  57620. var lineParts = line.substring(1).trim().split(' ');
  57621. var lineVertices = [],
  57622. lineUVs = [];
  57623. if (line.indexOf('/') === -1) {
  57624. lineVertices = lineParts;
  57625. } else {
  57626. for (var li = 0, llen = lineParts.length; li < llen; li++) {
  57627. var parts = lineParts[li].split('/');
  57628. if (parts[0] !== '') lineVertices.push(parts[0]);
  57629. if (parts[1] !== '') lineUVs.push(parts[1]);
  57630. }
  57631. }
  57632. state.addLineGeometry(lineVertices, lineUVs);
  57633. } else if (lineFirstChar === 'p') {
  57634. var lineData = line.substr(1).trim();
  57635. var pointData = lineData.split(' ');
  57636. state.addPointGeometry(pointData);
  57637. } else if ((result = object_pattern.exec(line)) !== null) {
  57638. // o object_name
  57639. // or
  57640. // g group_name
  57641. // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
  57642. // var name = result[ 0 ].substr( 1 ).trim();
  57643. var name = (' ' + result[0].substr(1).trim()).substr(1);
  57644. state.startObject(name);
  57645. } else if (material_use_pattern.test(line)) {
  57646. // material
  57647. state.object.startMaterial(line.substring(7).trim(), state.materialLibraries);
  57648. } else if (material_library_pattern.test(line)) {
  57649. // mtl file
  57650. state.materialLibraries.push(line.substring(7).trim());
  57651. } else if (map_use_pattern.test(line)) {
  57652. // the line is parsed but ignored since the loader assumes textures are defined MTL files
  57653. // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
  57654. console.warn('THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.');
  57655. } else if (lineFirstChar === 's') {
  57656. result = line.split(' ');
  57657. // smooth shading
  57658. // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
  57659. // but does not define a usemtl for each face set.
  57660. // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
  57661. // This requires some care to not create extra material on each smooth value for "normal" obj files.
  57662. // where explicit usemtl defines geometry groups.
  57663. // Example asset: examples/models/obj/cerberus/Cerberus.obj
  57664. /*
  57665. * http://paulbourke.net/dataformats/obj/
  57666. * or
  57667. * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
  57668. *
  57669. * From chapter "Grouping" Syntax explanation "s group_number":
  57670. * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
  57671. * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
  57672. * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
  57673. * than 0."
  57674. */
  57675. if (result.length > 1) {
  57676. var value = result[1].trim().toLowerCase();
  57677. state.object.smooth = value !== '0' && value !== 'off';
  57678. } else {
  57679. // ZBrush can produce "s" lines #11707
  57680. state.object.smooth = true;
  57681. }
  57682. var material = state.object.currentMaterial();
  57683. if (material) material.smooth = state.object.smooth;
  57684. } else {
  57685. // Handle null terminated files without exception
  57686. if (line === '\0') continue;
  57687. console.warn('THREE.OBJLoader: Unexpected line: "' + line + '"');
  57688. }
  57689. }
  57690. state.finalize();
  57691. var container = new Group();
  57692. container.materialLibraries = [].concat(state.materialLibraries);
  57693. var hasPrimitives = !(state.objects.length === 1 && state.objects[0].geometry.vertices.length === 0);
  57694. if (hasPrimitives === true) {
  57695. for (var i = 0, l = state.objects.length; i < l; i++) {
  57696. var object = state.objects[i];
  57697. var geometry = object.geometry;
  57698. var materials = object.materials;
  57699. var isLine = geometry.type === 'Line';
  57700. var isPoints = geometry.type === 'Points';
  57701. var hasVertexColors = false;
  57702. // Skip o/g line declarations that did not follow with any faces
  57703. if (geometry.vertices.length === 0) continue;
  57704. var buffergeometry = new BufferGeometry();
  57705. buffergeometry.setAttribute('position', new Float32BufferAttribute(geometry.vertices, 3));
  57706. if (geometry.normals.length > 0) {
  57707. buffergeometry.setAttribute('normal', new Float32BufferAttribute(geometry.normals, 3));
  57708. }
  57709. if (geometry.colors.length > 0) {
  57710. hasVertexColors = true;
  57711. buffergeometry.setAttribute('color', new Float32BufferAttribute(geometry.colors, 3));
  57712. }
  57713. if (geometry.hasUVIndices === true) {
  57714. buffergeometry.setAttribute('uv', new Float32BufferAttribute(geometry.uvs, 2));
  57715. }
  57716. // Create materials
  57717. var createdMaterials = [];
  57718. for (var mi = 0, miLen = materials.length; mi < miLen; mi++) {
  57719. var sourceMaterial = materials[mi];
  57720. var materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
  57721. var material = state.materials[materialHash];
  57722. if (this.materials !== null) {
  57723. material = this.materials.create(sourceMaterial.name);
  57724. // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
  57725. if (isLine && material && !(material instanceof LineBasicMaterial)) {
  57726. var materialLine = new LineBasicMaterial();
  57727. Material.prototype.copy.call(materialLine, material);
  57728. materialLine.color.copy(material.color);
  57729. material = materialLine;
  57730. } else if (isPoints && material && !(material instanceof PointsMaterial)) {
  57731. var materialPoints = new PointsMaterial({
  57732. size: 10,
  57733. sizeAttenuation: false
  57734. });
  57735. Material.prototype.copy.call(materialPoints, material);
  57736. materialPoints.color.copy(material.color);
  57737. materialPoints.map = material.map;
  57738. material = materialPoints;
  57739. }
  57740. }
  57741. if (material === undefined) {
  57742. if (isLine) {
  57743. material = new LineBasicMaterial();
  57744. } else if (isPoints) {
  57745. material = new PointsMaterial({
  57746. size: 1,
  57747. sizeAttenuation: false
  57748. });
  57749. } else {
  57750. material = new MeshPhongMaterial();
  57751. }
  57752. material.name = sourceMaterial.name;
  57753. material.flatShading = sourceMaterial.smooth ? false : true;
  57754. material.vertexColors = hasVertexColors;
  57755. state.materials[materialHash] = material;
  57756. }
  57757. createdMaterials.push(material);
  57758. }
  57759. // Create mesh
  57760. var mesh;
  57761. if (createdMaterials.length > 1) {
  57762. for (var mi = 0, miLen = materials.length; mi < miLen; mi++) {
  57763. var sourceMaterial = materials[mi];
  57764. buffergeometry.addGroup(sourceMaterial.groupStart, sourceMaterial.groupCount, mi);
  57765. }
  57766. if (isLine) {
  57767. mesh = new LineSegments(buffergeometry, createdMaterials);
  57768. } else if (isPoints) {
  57769. mesh = new Points(buffergeometry, createdMaterials);
  57770. } else {
  57771. mesh = new Mesh(buffergeometry, createdMaterials);
  57772. }
  57773. } else {
  57774. if (isLine) {
  57775. mesh = new LineSegments(buffergeometry, createdMaterials[0]);
  57776. } else if (isPoints) {
  57777. mesh = new Points(buffergeometry, createdMaterials[0]);
  57778. } else {
  57779. mesh = new Mesh(buffergeometry, createdMaterials[0]);
  57780. }
  57781. }
  57782. mesh.name = object.name;
  57783. container.add(mesh);
  57784. }
  57785. } else {
  57786. // if there is only the default parser state object with no geometry data, interpret data as point cloud
  57787. if (state.vertices.length > 0) {
  57788. var material = new PointsMaterial({
  57789. size: 1,
  57790. sizeAttenuation: false
  57791. });
  57792. var buffergeometry = new BufferGeometry();
  57793. buffergeometry.setAttribute('position', new Float32BufferAttribute(state.vertices, 3));
  57794. if (state.colors.length > 0 && state.colors[0] !== undefined) {
  57795. buffergeometry.setAttribute('color', new Float32BufferAttribute(state.colors, 3));
  57796. material.vertexColors = true;
  57797. }
  57798. var points = new Points(buffergeometry, material);
  57799. container.add(points);
  57800. }
  57801. }
  57802. return container;
  57803. }
  57804. });
  57805. return OBJLoader;
  57806. }();
  57807. /**
  57808. * Loads a Wavefront .mtl file specifying materials
  57809. */
  57810. var MTLLoader = function MTLLoader(manager) {
  57811. Loader.call(this, manager);
  57812. };
  57813. MTLLoader.prototype = Object.assign(Object.create(Loader.prototype), {
  57814. constructor: MTLLoader,
  57815. /**
  57816. * Loads and parses a MTL asset from a URL.
  57817. *
  57818. * @param {String} url - URL to the MTL file.
  57819. * @param {Function} [onLoad] - Callback invoked with the loaded object.
  57820. * @param {Function} [onProgress] - Callback for download progress.
  57821. * @param {Function} [onError] - Callback for download errors.
  57822. *
  57823. * @see setPath setResourcePath
  57824. *
  57825. * @note In order for relative texture references to resolve correctly
  57826. * you must call setResourcePath() explicitly prior to load.
  57827. */
  57828. load: function load(url, onLoad, onProgress, onError) {
  57829. var scope = this;
  57830. var path = this.path === '' ? LoaderUtils.extractUrlBase(url) : this.path;
  57831. var loader = new FileLoader(this.manager);
  57832. loader.setPath(this.path);
  57833. loader.setRequestHeader(this.requestHeader);
  57834. loader.setWithCredentials(this.withCredentials);
  57835. loader.load(url, function (text) {
  57836. try {
  57837. onLoad(scope.parse(text, path));
  57838. } catch (e) {
  57839. if (onError) {
  57840. onError(e);
  57841. } else {
  57842. console.error(e);
  57843. }
  57844. scope.manager.itemError(url);
  57845. }
  57846. }, onProgress, onError);
  57847. },
  57848. setMaterialOptions: function setMaterialOptions(value) {
  57849. this.materialOptions = value;
  57850. return this;
  57851. },
  57852. /**
  57853. * Parses a MTL file.
  57854. *
  57855. * @param {String} text - Content of MTL file
  57856. * @return {MTLLoader.MaterialCreator}
  57857. *
  57858. * @see setPath setResourcePath
  57859. *
  57860. * @note In order for relative texture references to resolve correctly
  57861. * you must call setResourcePath() explicitly prior to parse.
  57862. */
  57863. parse: function parse(text, path) {
  57864. var lines = text.split('\n');
  57865. var info = {};
  57866. var delimiter_pattern = /\s+/;
  57867. var materialsInfo = {};
  57868. for (var i = 0; i < lines.length; i++) {
  57869. var line = lines[i];
  57870. line = line.trim();
  57871. if (line.length === 0 || line.charAt(0) === '#') {
  57872. // Blank line or comment ignore
  57873. continue;
  57874. }
  57875. var pos = line.indexOf(' ');
  57876. var key = pos >= 0 ? line.substring(0, pos) : line;
  57877. key = key.toLowerCase();
  57878. var value = pos >= 0 ? line.substring(pos + 1) : '';
  57879. value = value.trim();
  57880. if (key === 'newmtl') {
  57881. // New material
  57882. info = {
  57883. name: value
  57884. };
  57885. materialsInfo[value] = info;
  57886. } else {
  57887. if (key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke') {
  57888. var ss = value.split(delimiter_pattern, 3);
  57889. info[key] = [parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])];
  57890. } else {
  57891. info[key] = value;
  57892. }
  57893. }
  57894. }
  57895. var materialCreator = new MTLLoader.MaterialCreator(this.resourcePath || path, this.materialOptions);
  57896. materialCreator.setCrossOrigin(this.crossOrigin);
  57897. materialCreator.setManager(this.manager);
  57898. materialCreator.setMaterials(materialsInfo);
  57899. return materialCreator;
  57900. }
  57901. });
  57902. /**
  57903. * Create a new MTLLoader.MaterialCreator
  57904. * @param baseUrl - Url relative to which textures are loaded
  57905. * @param options - Set of options on how to construct the materials
  57906. * side: Which side to apply the material
  57907. * FrontSide (default), THREE.BackSide, THREE.DoubleSide
  57908. * wrap: What type of wrapping to apply for textures
  57909. * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
  57910. * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
  57911. * Default: false, assumed to be already normalized
  57912. * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
  57913. * Default: false
  57914. * @constructor
  57915. */
  57916. MTLLoader.MaterialCreator = function (baseUrl, options) {
  57917. this.baseUrl = baseUrl || '';
  57918. this.options = options;
  57919. this.materialsInfo = {};
  57920. this.materials = {};
  57921. this.materialsArray = [];
  57922. this.nameLookup = {};
  57923. this.side = this.options && this.options.side ? this.options.side : FrontSide;
  57924. this.wrap = this.options && this.options.wrap ? this.options.wrap : RepeatWrapping;
  57925. };
  57926. MTLLoader.MaterialCreator.prototype = {
  57927. constructor: MTLLoader.MaterialCreator,
  57928. crossOrigin: 'anonymous',
  57929. setCrossOrigin: function setCrossOrigin(value) {
  57930. this.crossOrigin = value;
  57931. return this;
  57932. },
  57933. setManager: function setManager(value) {
  57934. this.manager = value;
  57935. },
  57936. setMaterials: function setMaterials(materialsInfo) {
  57937. this.materialsInfo = this.convert(materialsInfo);
  57938. this.materials = {};
  57939. this.materialsArray = [];
  57940. this.nameLookup = {};
  57941. },
  57942. convert: function convert(materialsInfo) {
  57943. if (!this.options) return materialsInfo;
  57944. var converted = {};
  57945. for (var mn in materialsInfo) {
  57946. // Convert materials info into normalized form based on options
  57947. var mat = materialsInfo[mn];
  57948. var covmat = {};
  57949. converted[mn] = covmat;
  57950. for (var prop in mat) {
  57951. var save = true;
  57952. var value = mat[prop];
  57953. var lprop = prop.toLowerCase();
  57954. switch (lprop) {
  57955. case 'kd':
  57956. case 'ka':
  57957. case 'ks':
  57958. // Diffuse color (color under white light) using RGB values
  57959. if (this.options && this.options.normalizeRGB) {
  57960. value = [value[0] / 255, value[1] / 255, value[2] / 255];
  57961. }
  57962. if (this.options && this.options.ignoreZeroRGBs) {
  57963. if (value[0] === 0 && value[1] === 0 && value[2] === 0) {
  57964. // ignore
  57965. save = false;
  57966. }
  57967. }
  57968. break;
  57969. default:
  57970. break;
  57971. }
  57972. if (save) {
  57973. covmat[lprop] = value;
  57974. }
  57975. }
  57976. }
  57977. return converted;
  57978. },
  57979. preload: function preload() {
  57980. for (var mn in this.materialsInfo) {
  57981. this.create(mn);
  57982. }
  57983. },
  57984. getIndex: function getIndex(materialName) {
  57985. return this.nameLookup[materialName];
  57986. },
  57987. getAsArray: function getAsArray() {
  57988. var index = 0;
  57989. for (var mn in this.materialsInfo) {
  57990. this.materialsArray[index] = this.create(mn);
  57991. this.nameLookup[mn] = index;
  57992. index++;
  57993. }
  57994. return this.materialsArray;
  57995. },
  57996. create: function create(materialName) {
  57997. if (this.materials[materialName] === undefined) {
  57998. this.createMaterial_(materialName);
  57999. }
  58000. return this.materials[materialName];
  58001. },
  58002. createMaterial_: function createMaterial_(materialName) {
  58003. // Create material
  58004. var scope = this;
  58005. var mat = this.materialsInfo[materialName];
  58006. var params = {
  58007. name: materialName,
  58008. side: this.side
  58009. };
  58010. function resolveURL(baseUrl, url) {
  58011. if (typeof url !== 'string' || url === '') return '';
  58012. // Absolute URL
  58013. if (/^https?:\/\//i.test(url)) return url;
  58014. return baseUrl + url;
  58015. }
  58016. function setMapForType(mapType, value) {
  58017. if (params[mapType]) return; // Keep the first encountered texture
  58018. var texParams = scope.getTextureParams(value, params);
  58019. var map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
  58020. map.repeat.copy(texParams.scale);
  58021. map.offset.copy(texParams.offset);
  58022. map.wrapS = scope.wrap;
  58023. map.wrapT = scope.wrap;
  58024. params[mapType] = map;
  58025. }
  58026. for (var prop in mat) {
  58027. var value = mat[prop];
  58028. var n;
  58029. if (value === '') continue;
  58030. switch (prop.toLowerCase()) {
  58031. // Ns is material specular exponent
  58032. case 'kd':
  58033. // Diffuse color (color under white light) using RGB values
  58034. params.color = new Color().fromArray(value);
  58035. break;
  58036. case 'ks':
  58037. // Specular color (color when light is reflected from shiny surface) using RGB values
  58038. //params.specular = new Color().fromArray( value );
  58039. //console.log('specular',value)
  58040. break;
  58041. case 'ke':
  58042. // Emissive using RGB values
  58043. params.emissive = new Color().fromArray(value);
  58044. break;
  58045. case 'map_kd':
  58046. // Diffuse texture map
  58047. setMapForType('map', value);
  58048. break;
  58049. case 'map_ks':
  58050. // Specular map
  58051. setMapForType('specularMap', value);
  58052. break;
  58053. case 'map_ke':
  58054. // Emissive map
  58055. setMapForType('emissiveMap', value);
  58056. break;
  58057. case 'norm':
  58058. setMapForType('normalMap', value);
  58059. break;
  58060. case 'map_bump':
  58061. case 'bump':
  58062. // Bump texture map
  58063. setMapForType('bumpMap', value);
  58064. break;
  58065. case 'map_d':
  58066. // Alpha map
  58067. setMapForType('alphaMap', value);
  58068. params.transparent = true;
  58069. break;
  58070. case 'ns':
  58071. // The specular exponent (defines the focus of the specular highlight)
  58072. // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
  58073. //params.shininess = parseFloat( value );
  58074. //console.log('shininess',value)
  58075. break;
  58076. case 'd':
  58077. n = parseFloat(value);
  58078. if (n < 1) {
  58079. params.opacity = n;
  58080. params.transparent = true;
  58081. }
  58082. break;
  58083. case 'tr':
  58084. n = parseFloat(value);
  58085. if (this.options && this.options.invertTrProperty) n = 1 - n;
  58086. if (n > 0) {
  58087. params.opacity = 1 - n;
  58088. params.transparent = true;
  58089. }
  58090. break;
  58091. default:
  58092. break;
  58093. }
  58094. }
  58095. this.materials[materialName] = new MeshStandardMaterial(params); //MeshPhongMaterial( params );
  58096. return this.materials[materialName];
  58097. },
  58098. getTextureParams: function getTextureParams(value, matParams) {
  58099. var texParams = {
  58100. scale: new Vector2(1, 1),
  58101. offset: new Vector2(0, 0)
  58102. };
  58103. var items = value.split(/\s+/);
  58104. var pos;
  58105. pos = items.indexOf('-bm');
  58106. if (pos >= 0) {
  58107. matParams.bumpScale = parseFloat(items[pos + 1]);
  58108. items.splice(pos, 2);
  58109. }
  58110. pos = items.indexOf('-s');
  58111. if (pos >= 0) {
  58112. texParams.scale.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
  58113. items.splice(pos, 4); // we expect 3 parameters here!
  58114. }
  58115. pos = items.indexOf('-o');
  58116. if (pos >= 0) {
  58117. texParams.offset.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
  58118. items.splice(pos, 4); // we expect 3 parameters here!
  58119. }
  58120. texParams.url = items.join(' ').trim();
  58121. return texParams;
  58122. },
  58123. loadTexture: function loadTexture(url, mapping, onLoad, onProgress, onError) {
  58124. var texture;
  58125. var manager = this.manager !== undefined ? this.manager : DefaultLoadingManager;
  58126. var loader = manager.getHandler(url);
  58127. if (loader === null) {
  58128. loader = new TextureLoader(manager);
  58129. }
  58130. if (loader.setCrossOrigin) loader.setCrossOrigin(this.crossOrigin);
  58131. texture = loader.load(url, onLoad, onProgress, onError);
  58132. if (mapping !== undefined) texture.mapping = mapping;
  58133. return texture;
  58134. }
  58135. };
  58136. /**
  58137. * Description: A THREE loader for PLY ASCII files (known as the Polygon
  58138. * File Format or the Stanford Triangle Format).
  58139. *
  58140. * Limitations: ASCII decoding assumes file is UTF-8.
  58141. *
  58142. * Usage:
  58143. * var loader = new PLYLoader();
  58144. * loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {
  58145. *
  58146. * scene.add( new THREE.Mesh( geometry ) );
  58147. *
  58148. * } );
  58149. *
  58150. * If the PLY file uses non standard property names, they can be mapped while
  58151. * loading. For example, the following maps the properties
  58152. * “diffuse_(red|green|blue)” in the file to standard color names.
  58153. *
  58154. * loader.setPropertyNameMapping( {
  58155. * diffuse_red: 'red',
  58156. * diffuse_green: 'green',
  58157. * diffuse_blue: 'blue'
  58158. * } );
  58159. *
  58160. */
  58161. var PLYLoader = function PLYLoader(manager) {
  58162. Loader.call(this, manager);
  58163. this.propertyNameMapping = {};
  58164. };
  58165. PLYLoader.prototype = Object.assign(Object.create(Loader.prototype), {
  58166. constructor: PLYLoader,
  58167. load: function load(url, onLoad, onProgress, onError) {
  58168. var scope = this;
  58169. var loader = new FileLoader(this.manager);
  58170. loader.setPath(this.path);
  58171. loader.setResponseType('arraybuffer');
  58172. loader.setRequestHeader(this.requestHeader);
  58173. loader.setWithCredentials(this.withCredentials);
  58174. loader.load(url, function (text) {
  58175. try {
  58176. onLoad(scope.parse(text));
  58177. } catch (e) {
  58178. if (onError) {
  58179. onError(e);
  58180. } else {
  58181. console.error(e);
  58182. }
  58183. scope.manager.itemError(url);
  58184. }
  58185. }, onProgress, onError);
  58186. },
  58187. setPropertyNameMapping: function setPropertyNameMapping(mapping) {
  58188. this.propertyNameMapping = mapping;
  58189. },
  58190. parse: function parse(data) {
  58191. function parseHeader(data) {
  58192. var patternHeader = /ply([\s\S]*)end_header\r?\n/;
  58193. var headerText = '';
  58194. var headerLength = 0;
  58195. var result = patternHeader.exec(data);
  58196. if (result !== null) {
  58197. headerText = result[1];
  58198. headerLength = new Blob([result[0]]).size;
  58199. }
  58200. var header = {
  58201. comments: [],
  58202. elements: [],
  58203. headerLength: headerLength,
  58204. objInfo: ''
  58205. };
  58206. var lines = headerText.split('\n');
  58207. var currentElement;
  58208. var lineType, lineValues;
  58209. function make_ply_element_property(propertValues, propertyNameMapping) {
  58210. var property = {
  58211. type: propertValues[0]
  58212. };
  58213. if (property.type === 'list') {
  58214. property.name = propertValues[3];
  58215. property.countType = propertValues[1];
  58216. property.itemType = propertValues[2];
  58217. } else {
  58218. property.name = propertValues[1];
  58219. }
  58220. if (property.name in propertyNameMapping) {
  58221. property.name = propertyNameMapping[property.name];
  58222. }
  58223. return property;
  58224. }
  58225. for (var i = 0; i < lines.length; i++) {
  58226. var line = lines[i];
  58227. line = line.trim();
  58228. if (line === '') continue;
  58229. lineValues = line.split(/\s+/);
  58230. lineType = lineValues.shift();
  58231. line = lineValues.join(' ');
  58232. switch (lineType) {
  58233. case 'format':
  58234. header.format = lineValues[0];
  58235. header.version = lineValues[1];
  58236. break;
  58237. case 'comment':
  58238. header.comments.push(line);
  58239. break;
  58240. case 'element':
  58241. if (currentElement !== undefined) {
  58242. header.elements.push(currentElement);
  58243. }
  58244. currentElement = {};
  58245. currentElement.name = lineValues[0];
  58246. currentElement.count = parseInt(lineValues[1]);
  58247. currentElement.properties = [];
  58248. break;
  58249. case 'property':
  58250. currentElement.properties.push(make_ply_element_property(lineValues, scope.propertyNameMapping));
  58251. break;
  58252. case 'obj_info':
  58253. header.objInfo = line;
  58254. break;
  58255. default:
  58256. console.log('unhandled', lineType, lineValues);
  58257. }
  58258. }
  58259. if (currentElement !== undefined) {
  58260. header.elements.push(currentElement);
  58261. }
  58262. return header;
  58263. }
  58264. function parseASCIINumber(n, type) {
  58265. switch (type) {
  58266. case 'char':
  58267. case 'uchar':
  58268. case 'short':
  58269. case 'ushort':
  58270. case 'int':
  58271. case 'uint':
  58272. case 'int8':
  58273. case 'uint8':
  58274. case 'int16':
  58275. case 'uint16':
  58276. case 'int32':
  58277. case 'uint32':
  58278. return parseInt(n);
  58279. case 'float':
  58280. case 'double':
  58281. case 'float32':
  58282. case 'float64':
  58283. return parseFloat(n);
  58284. }
  58285. }
  58286. function parseASCIIElement(properties, line) {
  58287. var values = line.split(/\s+/);
  58288. var element = {};
  58289. for (var i = 0; i < properties.length; i++) {
  58290. if (properties[i].type === 'list') {
  58291. var list = [];
  58292. var n = parseASCIINumber(values.shift(), properties[i].countType);
  58293. for (var j = 0; j < n; j++) {
  58294. list.push(parseASCIINumber(values.shift(), properties[i].itemType));
  58295. }
  58296. element[properties[i].name] = list;
  58297. } else {
  58298. element[properties[i].name] = parseASCIINumber(values.shift(), properties[i].type);
  58299. }
  58300. }
  58301. return element;
  58302. }
  58303. function parseASCII(data, header) {
  58304. // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
  58305. var buffer = {
  58306. indices: [],
  58307. vertices: [],
  58308. normals: [],
  58309. uvs: [],
  58310. faceVertexUvs: [],
  58311. colors: []
  58312. };
  58313. var result;
  58314. var patternBody = /end_header\s([\s\S]*)$/;
  58315. var body = '';
  58316. if ((result = patternBody.exec(data)) !== null) {
  58317. body = result[1];
  58318. }
  58319. var lines = body.split('\n');
  58320. var currentElement = 0;
  58321. var currentElementCount = 0;
  58322. for (var i = 0; i < lines.length; i++) {
  58323. var line = lines[i];
  58324. line = line.trim();
  58325. if (line === '') {
  58326. continue;
  58327. }
  58328. if (currentElementCount >= header.elements[currentElement].count) {
  58329. currentElement++;
  58330. currentElementCount = 0;
  58331. }
  58332. var element = parseASCIIElement(header.elements[currentElement].properties, line);
  58333. handleElement(buffer, header.elements[currentElement].name, element);
  58334. currentElementCount++;
  58335. }
  58336. return postProcess(buffer);
  58337. }
  58338. function postProcess(buffer) {
  58339. var geometry = new BufferGeometry();
  58340. // mandatory buffer data
  58341. if (buffer.indices.length > 0) {
  58342. geometry.setIndex(buffer.indices);
  58343. }
  58344. geometry.setAttribute('position', new Float32BufferAttribute(buffer.vertices, 3));
  58345. // optional buffer data
  58346. if (buffer.normals.length > 0) {
  58347. geometry.setAttribute('normal', new Float32BufferAttribute(buffer.normals, 3));
  58348. }
  58349. if (buffer.uvs.length > 0) {
  58350. geometry.setAttribute('uv', new Float32BufferAttribute(buffer.uvs, 2));
  58351. }
  58352. if (buffer.colors.length > 0) {
  58353. geometry.setAttribute('color', new Float32BufferAttribute(buffer.colors, 3));
  58354. }
  58355. if (buffer.faceVertexUvs.length > 0) {
  58356. geometry = geometry.toNonIndexed();
  58357. geometry.setAttribute('uv', new Float32BufferAttribute(buffer.faceVertexUvs, 2));
  58358. }
  58359. geometry.computeBoundingSphere();
  58360. return geometry;
  58361. }
  58362. function handleElement(buffer, elementName, element) {
  58363. if (elementName === 'vertex') {
  58364. buffer.vertices.push(element.x, element.y, element.z);
  58365. if ('nx' in element && 'ny' in element && 'nz' in element) {
  58366. buffer.normals.push(element.nx, element.ny, element.nz);
  58367. }
  58368. if ('s' in element && 't' in element) {
  58369. buffer.uvs.push(element.s, element.t);
  58370. }
  58371. if ('red' in element && 'green' in element && 'blue' in element) {
  58372. buffer.colors.push(element.red / 255.0, element.green / 255.0, element.blue / 255.0);
  58373. }
  58374. } else if (elementName === 'face') {
  58375. var vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338
  58376. var texcoord = element.texcoord;
  58377. if (vertex_indices.length === 3) {
  58378. buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[2]);
  58379. if (texcoord && texcoord.length === 6) {
  58380. buffer.faceVertexUvs.push(texcoord[0], texcoord[1]);
  58381. buffer.faceVertexUvs.push(texcoord[2], texcoord[3]);
  58382. buffer.faceVertexUvs.push(texcoord[4], texcoord[5]);
  58383. }
  58384. } else if (vertex_indices.length === 4) {
  58385. buffer.indices.push(vertex_indices[0], vertex_indices[1], vertex_indices[3]);
  58386. buffer.indices.push(vertex_indices[1], vertex_indices[2], vertex_indices[3]);
  58387. }
  58388. }
  58389. }
  58390. function binaryRead(dataview, at, type, little_endian) {
  58391. switch (type) {
  58392. // corespondences for non-specific length types here match rply:
  58393. case 'int8':
  58394. case 'char':
  58395. return [dataview.getInt8(at), 1];
  58396. case 'uint8':
  58397. case 'uchar':
  58398. return [dataview.getUint8(at), 1];
  58399. case 'int16':
  58400. case 'short':
  58401. return [dataview.getInt16(at, little_endian), 2];
  58402. case 'uint16':
  58403. case 'ushort':
  58404. return [dataview.getUint16(at, little_endian), 2];
  58405. case 'int32':
  58406. case 'int':
  58407. return [dataview.getInt32(at, little_endian), 4];
  58408. case 'uint32':
  58409. case 'uint':
  58410. return [dataview.getUint32(at, little_endian), 4];
  58411. case 'float32':
  58412. case 'float':
  58413. return [dataview.getFloat32(at, little_endian), 4];
  58414. case 'float64':
  58415. case 'double':
  58416. return [dataview.getFloat64(at, little_endian), 8];
  58417. }
  58418. }
  58419. function binaryReadElement(dataview, at, properties, little_endian) {
  58420. var element = {};
  58421. var result,
  58422. read = 0;
  58423. for (var i = 0; i < properties.length; i++) {
  58424. if (properties[i].type === 'list') {
  58425. var list = [];
  58426. result = binaryRead(dataview, at + read, properties[i].countType, little_endian);
  58427. var n = result[0];
  58428. read += result[1];
  58429. for (var j = 0; j < n; j++) {
  58430. result = binaryRead(dataview, at + read, properties[i].itemType, little_endian);
  58431. list.push(result[0]);
  58432. read += result[1];
  58433. }
  58434. element[properties[i].name] = list;
  58435. } else {
  58436. result = binaryRead(dataview, at + read, properties[i].type, little_endian);
  58437. element[properties[i].name] = result[0];
  58438. read += result[1];
  58439. }
  58440. }
  58441. return [element, read];
  58442. }
  58443. function parseBinary(data, header) {
  58444. var buffer = {
  58445. indices: [],
  58446. vertices: [],
  58447. normals: [],
  58448. uvs: [],
  58449. faceVertexUvs: [],
  58450. colors: []
  58451. };
  58452. var little_endian = header.format === 'binary_little_endian';
  58453. var body = new DataView(data, header.headerLength);
  58454. var result,
  58455. loc = 0;
  58456. for (var currentElement = 0; currentElement < header.elements.length; currentElement++) {
  58457. for (var currentElementCount = 0; currentElementCount < header.elements[currentElement].count; currentElementCount++) {
  58458. result = binaryReadElement(body, loc, header.elements[currentElement].properties, little_endian);
  58459. loc += result[1];
  58460. var element = result[0];
  58461. handleElement(buffer, header.elements[currentElement].name, element);
  58462. }
  58463. }
  58464. return postProcess(buffer);
  58465. }
  58466. //
  58467. var geometry;
  58468. var scope = this;
  58469. if (data instanceof ArrayBuffer) {
  58470. var text = LoaderUtils.decodeText(new Uint8Array(data));
  58471. var header = parseHeader(text);
  58472. geometry = header.format === 'ascii' ? parseASCII(text, header) : parseBinary(data, header);
  58473. } else {
  58474. geometry = parseASCII(data, parseHeader(data));
  58475. }
  58476. return geometry;
  58477. }
  58478. });
  58479. var _Stats = function Stats() {
  58480. var mode = 0;
  58481. var container = document.createElement('div');
  58482. container.style.cssText = 'position:fixed;top:0;left:60px;cursor:pointer;opacity:0.9;z-index:10000';
  58483. container.addEventListener('click', function (event) {
  58484. event.preventDefault();
  58485. showPanel(++mode % container.children.length);
  58486. }, false);
  58487. //
  58488. function addPanel(panel) {
  58489. container.appendChild(panel.dom);
  58490. return panel;
  58491. }
  58492. function showPanel(id) {
  58493. for (var i = 0; i < container.children.length; i++) {
  58494. container.children[i].style.display = i === id ? 'block' : 'none';
  58495. }
  58496. mode = id;
  58497. }
  58498. //
  58499. var beginTime = (performance || Date).now(),
  58500. prevTime = beginTime,
  58501. frames = 0;
  58502. var fpsPanel = addPanel(new _Stats.Panel('FPS', '#0ff', '#002'));
  58503. var msPanel = addPanel(new _Stats.Panel('MS', '#0f0', '#020'));
  58504. if (self.performance && self.performance.memory) {
  58505. var memPanel = addPanel(new _Stats.Panel('MB', '#f08', '#201'));
  58506. }
  58507. showPanel(0);
  58508. return {
  58509. REVISION: 16,
  58510. dom: container,
  58511. addPanel: addPanel,
  58512. showPanel: showPanel,
  58513. begin: function begin() {
  58514. beginTime = (performance || Date).now();
  58515. },
  58516. end: function end() {
  58517. frames++;
  58518. var time = (performance || Date).now();
  58519. msPanel.update(time - beginTime, 200);
  58520. if (time >= prevTime + 1000) {
  58521. fpsPanel.update(frames * 1000 / (time - prevTime), 100);
  58522. prevTime = time;
  58523. frames = 0;
  58524. if (memPanel) {
  58525. var memory = performance.memory;
  58526. memPanel.update(memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576);
  58527. }
  58528. }
  58529. return time;
  58530. },
  58531. update: function update() {
  58532. beginTime = this.end();
  58533. },
  58534. // Backwards Compatibility
  58535. domElement: container,
  58536. setMode: showPanel
  58537. };
  58538. };
  58539. _Stats.Panel = function (name, fg, bg) {
  58540. var min = Infinity,
  58541. max = 0,
  58542. round = Math.round;
  58543. var PR = round(window.devicePixelRatio || 1);
  58544. var WIDTH = 80 * PR,
  58545. HEIGHT = 48 * PR,
  58546. TEXT_X = 3 * PR,
  58547. TEXT_Y = 2 * PR,
  58548. GRAPH_X = 3 * PR,
  58549. GRAPH_Y = 15 * PR,
  58550. GRAPH_WIDTH = 74 * PR,
  58551. GRAPH_HEIGHT = 30 * PR;
  58552. var canvas = document.createElement('canvas');
  58553. canvas.width = WIDTH;
  58554. canvas.height = HEIGHT;
  58555. canvas.style.cssText = 'width:80px;height:48px';
  58556. var context = canvas.getContext('2d');
  58557. context.font = 'bold ' + 9 * PR + 'px Helvetica,Arial,sans-serif';
  58558. context.textBaseline = 'top';
  58559. context.fillStyle = bg;
  58560. context.fillRect(0, 0, WIDTH, HEIGHT);
  58561. context.fillStyle = fg;
  58562. context.fillText(name, TEXT_X, TEXT_Y);
  58563. context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
  58564. context.fillStyle = bg;
  58565. context.globalAlpha = 0.9;
  58566. context.fillRect(GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT);
  58567. return {
  58568. dom: canvas,
  58569. update: function update(value, maxValue) {
  58570. min = Math.min(min, value);
  58571. max = Math.max(max, value);
  58572. context.fillStyle = bg;
  58573. context.globalAlpha = 1;
  58574. context.fillRect(0, 0, WIDTH, GRAPH_Y);
  58575. context.fillStyle = fg;
  58576. context.fillText(round(value) + ' ' + name + ' (' + round(min) + '-' + round(max) + ')', TEXT_X, TEXT_Y);
  58577. context.drawImage(canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT);
  58578. context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT);
  58579. context.fillStyle = bg;
  58580. context.globalAlpha = 0.9;
  58581. context.fillRect(GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round((1 - value / maxValue) * GRAPH_HEIGHT));
  58582. }
  58583. };
  58584. };
  58585. var depthMatProp = {
  58586. //为了防止拉远后因放大而一半嵌入墙。
  58587. useDepth: true,
  58588. startClipDis: 0.5,
  58589. clipDistance: 1,
  58590. //消失距离
  58591. startOcclusDis: 0.5,
  58592. occlusionDistance: 0.9,
  58593. //变为backColor距离
  58594. maxOcclusionFactor: 0.7,
  58595. maxClipFactor: 1
  58596. };
  58597. var planeGeo$3 = new PlaneBufferGeometry(1, 1);
  58598. var texLoader$8 = new TextureLoader();
  58599. var lineMat, dragPointMat$1;
  58600. var defaultLineLength = 1;
  58601. var defaultSpotScale = 0.35;
  58602. var titleHeight = {
  58603. uponSpot: 0.1
  58604. }; //title底部和spot顶端间隔
  58605. var Vectors$2 = {
  58606. UP: new Vector3(0, 1, 0),
  58607. ZERO: new Vector3()
  58608. };
  58609. class Tag extends Shim.FollowRootObject {
  58610. constructor(o) {
  58611. super(o.root);
  58612. this.title = o.title;
  58613. this.fontsize = o.fontsize;
  58614. this.lineLength = o.lineLength != void 0 ? o.lineLength : defaultLineLength;
  58615. this.position.copy(o.position);
  58616. this.normal = o.normal != void 0 ? o.normal : new Vector3(0, 0, 1);
  58617. this.build(o);
  58618. this.bindEvent();
  58619. this.dragEnable = true;
  58620. }
  58621. set dragEnable(state) {
  58622. this.lineDragPoint.visible = state;
  58623. }
  58624. get dragEnable() {
  58625. return this.lineDragPoint.visible;
  58626. }
  58627. build(o) {
  58628. lineMat || (lineMat = LineDraw.createFatLineMat(Object.assign({}, depthMatProp, {
  58629. color: '#ffffff',
  58630. useDepth: true,
  58631. lineWidth: 1
  58632. })));
  58633. var group = new Object3D();
  58634. this.spot = new Mesh(planeGeo$3, new DepthBasicMaterial(Object.assign({}, depthMatProp, {
  58635. transparent: true
  58636. })));
  58637. this.spot.name = 'spot';
  58638. this.spot.scale.set(defaultSpotScale, defaultSpotScale, defaultSpotScale);
  58639. this.spot.renderOrder = this.spot.pickOrder = Potree.config.renderOrders.tag.spot;
  58640. Potree.settings.isOfficial || this.changeMap(Potree.resourcePath + '/textures/spot_default.png');
  58641. this.line = LineDraw.createFatLine([], {
  58642. mat: lineMat
  58643. });
  58644. this.line.name = 'tagLine';
  58645. this.line.renderOrder = this.line.pickOrder = Potree.config.renderOrders.tag.line;
  58646. this.titleLabel = new TextSprite$2(Object.assign({}, depthMatProp, {
  58647. root: group,
  58648. text: '',
  58649. sizeInfo: {
  58650. width2d: 150
  58651. },
  58652. textColor: {
  58653. r: 255,
  58654. g: 255,
  58655. b: 255,
  58656. a: 1.0
  58657. },
  58658. backgroundColor: {
  58659. r: 0,
  58660. g: 0,
  58661. b: 0,
  58662. a: 0.7
  58663. },
  58664. borderRadius: 6,
  58665. fontsize: this.fontsize || 14,
  58666. fontWeight: '',
  58667. //thick
  58668. renderOrder: Potree.config.renderOrders.tag.label,
  58669. pickOrder: Potree.config.renderOrders.tag.label,
  58670. useDepth: true,
  58671. maxLineWidth: 300,
  58672. transform2Dpercent: {
  58673. x: 0,
  58674. y: 0.5
  58675. },
  58676. //向上移动一半
  58677. textAlign: Potree.settings.isOfficial && 'left'
  58678. })); //更新sprite时,实际更新的是root: spot的矩阵
  58679. this.setTitle(this.title);
  58680. this.updateTitlePos();
  58681. group.add(this.titleLabel);
  58682. group.add(this.spot);
  58683. this.add(group);
  58684. this.add(this.line);
  58685. viewer.tags.add(this);
  58686. if (!dragPointMat$1) {
  58687. var map = texLoader$8.load(Potree.resourcePath + '/textures/whiteCircle.png', () => {});
  58688. dragPointMat$1 = {
  58689. default: new MeshBasicMaterial({
  58690. map,
  58691. transparent: true,
  58692. color: '#0fe',
  58693. opacity: 0,
  58694. depthTest: false
  58695. }),
  58696. hover: new MeshBasicMaterial({
  58697. map,
  58698. transparent: true,
  58699. color: '#0fe',
  58700. opacity: 0.4,
  58701. depthTest: false
  58702. })
  58703. };
  58704. }
  58705. this.lineDragPoint = new Mesh(planeGeo$3, dragPointMat$1.default); //修改线高度时出现的小圆点
  58706. this.lineDragPoint.scale.set(0.15, 0.15, 0.15);
  58707. this.lineDragPoint.name = 'lineDragPoint';
  58708. this.lineDragPoint.renderOrder = this.lineDragPoint.pickOrder = Potree.config.renderOrders.tag.spot + 3;
  58709. group.add(this.lineDragPoint);
  58710. this.updatePose();
  58711. }
  58712. bindEvent() {
  58713. var hoverState = {},
  58714. grabbingObject;
  58715. var setDragPointState = state => {
  58716. this.lineDragPoint.material = state ? dragPointMat$1.hover : dragPointMat$1.default;
  58717. this.spot.material.opacity = state ? 0.5 : 1;
  58718. this.titleLabel.sprite.material.opacity = state ? 0.5 : 1;
  58719. };
  58720. {
  58721. //因为只有有intersect时才能拖拽,所以写得比较麻烦
  58722. var cursor = {
  58723. hoverGrab: 0,
  58724. grabbing: 0
  58725. };
  58726. var setCursor = (name, action) => {
  58727. var state = action == 'add' ? 1 : 0;
  58728. if (state != cursor[name]) {
  58729. cursor[name] = state;
  58730. viewer.dispatchEvent({
  58731. type: "CursorChange",
  58732. action,
  58733. name
  58734. });
  58735. }
  58736. };
  58737. [this.line, this.spot, this.lineDragPoint].forEach(e => e.addEventListener('mousemove', e => {
  58738. hoverState[e.target.name] = 1;
  58739. if (this.dragEnable && (viewer.inputHandler.intersect || hoverState['lineDragPoint'])) {
  58740. //能拖拽时
  58741. setCursor('hoverGrab', 'add');
  58742. } else {
  58743. setCursor('hoverGrab', 'remove');
  58744. }
  58745. }));
  58746. [this.line, this.spot, this.lineDragPoint].forEach(e => e.addEventListener('mouseleave', e => {
  58747. hoverState[e.target.name] = 0;
  58748. if (!Object.values(hoverState).some(e => e)) {
  58749. //都没hover才取消
  58750. setCursor('hoverGrab', 'remove');
  58751. }
  58752. /* if(!hoverState.line && !hoverState.spot && !hoverState.label){
  58753. this.dispatchEvent('mouseleave')
  58754. } */
  58755. }));
  58756. [this.line, this.spot, this.lineDragPoint].forEach(e => e.addEventListener('drag', e => {
  58757. if (this.dragEnable && cursor.grabbing) {
  58758. if (e.target.name == 'lineDragPoint') {
  58759. this.dragLineLen(e);
  58760. } else {
  58761. var info = viewer.tagTool.getPoseByIntersect(e);
  58762. info && this.changePos(info);
  58763. }
  58764. }
  58765. }));
  58766. [this.line, this.spot, this.lineDragPoint].forEach(e => e.addEventListener('startDragging', e => {
  58767. this.dragEnable && (viewer.inputHandler.intersect || e.target.name == 'lineDragPoint') && setCursor('grabbing', 'add');
  58768. grabbingObject = e.target.name;
  58769. grabbingObject == 'lineDragPoint' && setDragPointState(true);
  58770. }));
  58771. [this.line, this.spot, this.lineDragPoint].forEach(e => e.addEventListener('drop', e => {
  58772. this.dragEnable && setCursor('grabbing', 'remove');
  58773. grabbingObject = null;
  58774. hoverState['lineDragPoint'] || setDragPointState(false);
  58775. }));
  58776. //拖拽线来移动。虽然理想方式是拟真,拖拽时不改变在线上的位置,使之平移,但仔细想想似乎办不到。因为墙面normal是不固定的,尤其在交界处难以确定。不知鼠标在空中的位置,即使是平行镜头移动也无法满足所有情况。matterport是加了底座,移动也是改变底座中心。
  58777. }
  58778. {
  58779. var mouseover = e => {
  58780. this.dispatchEvent('mouseover');
  58781. };
  58782. var mouseleave = e => {
  58783. //if(!hoverState.line && !hoverState.spot && !hoverState.label){
  58784. this.dispatchEvent('mouseleave');
  58785. //}
  58786. };
  58787. var click = e => {
  58788. this.dispatchEvent('click');
  58789. };
  58790. this.spot.addEventListener('mouseover', mouseover);
  58791. this.spot.addEventListener('mouseleave', mouseleave);
  58792. this.titleLabel.addEventListener('mouseover', mouseover);
  58793. this.titleLabel.addEventListener('mouseleave', mouseleave);
  58794. this.spot.addEventListener('click', click);
  58795. this.titleLabel.addEventListener('click', click);
  58796. }
  58797. this.titleLabel.sprite.addEventListener('spriteUpdated', () => {
  58798. this.updateDepthParams();
  58799. });
  58800. //-----------set line length
  58801. // CursorDeal
  58802. this.lineDragPoint.addEventListener('mouseover', e => {
  58803. grabbingObject || setDragPointState(true);
  58804. });
  58805. this.lineDragPoint.addEventListener('mouseleave', e => {
  58806. grabbingObject != 'lineDragPoint' && setDragPointState(false);
  58807. });
  58808. }
  58809. updateDepthParams() {
  58810. //为了避免热点嵌入墙壁,实时根据其大小更新材质系数。 但是在倾斜的角度看由于遮挡距离很大肯定会嵌入的
  58811. var s = this.titleLabel.parent.scale.x;
  58812. var names = ['clipDistance', 'occlusionDistance', 'startClipDis', 'startOcclusDis'];
  58813. var titleSize = Math.max(this.titleLabel.sprite.scale.x, this.titleLabel.sprite.scale.y) * s;
  58814. names.forEach(name => {
  58815. this.titleLabel.sprite.material.uniforms[name].value = depthMatProp[name] * titleSize;
  58816. });
  58817. if (this.onMesh) {
  58818. //not sprite,还原。 大概能不被崎岖的3dtiles地面遮住就行
  58819. names.forEach(name => {
  58820. this.spot.material.uniforms[name].value = depthMatProp[name];
  58821. });
  58822. } else {
  58823. var spotSize = this.spot.scale.x * s;
  58824. names.forEach(name => {
  58825. this.spot.material.uniforms[name].value = depthMatProp[name] * spotSize;
  58826. });
  58827. }
  58828. }
  58829. updatePose() {
  58830. var endPos = this.normal.clone().multiplyScalar(this.lineLength);
  58831. LineDraw.updateLine(this.line, [new Vector3(0, 0, 0), endPos]);
  58832. this.titleLabel.parent.position.copy(endPos);
  58833. this.titleLabel.updatePose();
  58834. viewer.dispatchEvent('content_changed');
  58835. }
  58836. changeLineLen(len) {
  58837. if (len == this.lineLength) return;
  58838. this.lineLength = parseFloat(len);
  58839. this.updatePose();
  58840. }
  58841. dragLineLen(e) {
  58842. //拖拽线的顶端修改线长度
  58843. var endPos = this.normal.clone().multiplyScalar(this.lineLength).applyMatrix4(this.matrixWorld);
  58844. var normal = this.normal.clone().applyQuaternion(this.getWorldQuaternion(new Quaternion()));
  58845. var projected = endPos.clone().project(e.drag.dragViewport.camera);
  58846. projected.x = e.pointer.x;
  58847. projected.y = e.pointer.y;
  58848. var unprojected = projected.clone().unproject(e.drag.dragViewport.camera);
  58849. var moveVec = new Vector3().subVectors(unprojected, endPos);
  58850. moveVec = moveVec.projectOnVector(normal);
  58851. var newLength = Math.max(0, this.lineLength + moveVec.dot(normal));
  58852. //console.log(moveVec,newLength)
  58853. this.changeLineLen(newLength);
  58854. this.dispatchEvent('dragLineLen');
  58855. }
  58856. changePos(info) {
  58857. //注:onMesh时在非平地上拖拽,热点旋转会一直变
  58858. this.position.copy(info.position);
  58859. this.normal.copy(info.normal);
  58860. var root = this.root;
  58861. this.root = info.root;
  58862. root != this.root && this.updateMatrixWorld(); //防止拖动到另一个scale不同的模型上时sprite会缩放闪烁
  58863. this.setNorQua();
  58864. this.updatePose();
  58865. this.dispatchEvent('posChanged');
  58866. viewer.dispatchEvent('content_changed');
  58867. }
  58868. changeOnMesh(onMesh) {
  58869. //是否贴在mesh上
  58870. //if(this.title == 'single2') debugger
  58871. this.onMesh = onMesh;
  58872. if (onMesh) {
  58873. //贴mesh上时不是sprite,且可设置旋转值
  58874. this.add(this.spot);
  58875. this.titleLabel.position.y = 0;
  58876. this.spot.position.set(0, 0, 0.01); //在mesh之上偏移一点
  58877. this.setNorQua();
  58878. this.spot.renderOrder = Potree.config.renderOrders.tag.onMesh.spot; // 防止遮住线
  58879. this.line.renderOrder = Potree.config.renderOrders.tag.onMesh.line;
  58880. } else {
  58881. this.titleLabel.parent.add(this.spot);
  58882. this.updateTitlePos();
  58883. this.spot.position.set(0, 0, 0);
  58884. this.spot.quaternion.set(0, 0, 0, 1); //this.titleLabel.waitUpdate()
  58885. this.realFaceAngle = 0;
  58886. this.spot.renderOrder = Potree.config.renderOrders.tag.spot; //还原
  58887. this.line.renderOrder = Potree.config.renderOrders.tag.line;
  58888. }
  58889. Potree.Utils.updateVisible(this.line, 'hideTitle', !this.titleLabel.visible && onMesh ? false : true);
  58890. this.updateDepthParams();
  58891. viewer.dispatchEvent('content_changed');
  58892. }
  58893. setFaceAngle() {
  58894. var faceAngle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  58895. //if(this.title == 'single2') debugger
  58896. this.faceAngle = faceAngle; //先记录,但非onMesh时不会用
  58897. if (!this.onMesh) return;
  58898. var delta = faceAngle - (this.realFaceAngle || 0);
  58899. //this.plane.quaternion.setFromAxisAngle(new THREE.Vector3(0, 0, 1), THREE.MathUtils.degToRad(-faceAngle))
  58900. this.spot.rotateOnAxis(new Vector3(0, 0, 1), MathUtils.degToRad(delta));
  58901. //this.updateLabelPose()
  58902. this.realFaceAngle = faceAngle;
  58903. viewer.dispatchEvent('content_changed');
  58904. }
  58905. setNorQua() {
  58906. if (!this.onMesh) return;
  58907. this.spot.quaternion.setFromRotationMatrix(new Matrix4().lookAt(this.normal, Vectors$2.ZERO, Vectors$2.UP)); //重算quaternion
  58908. this.realFaceAngle = 0; //quaternion被重置了,所以再设置一下faceAngle
  58909. this.setFaceAngle(this.faceAngle);
  58910. }
  58911. /*
  58912. 如果要像四维看看那样,在地面上时保持初始转向镜头的话,需要矫正且保存quaternion。且要根据世界normal判断是否在地面, 会随着模型改变, 所以也没法仅保存normal去矫正。
  58913. 要不然就要直接改变faceAngle
  58914. */
  58915. setTitle() {
  58916. var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  58917. this.titleLabel.setText(title);
  58918. this.setTitleVisi(title instanceof Array || title.trim() != '', 'noText');
  58919. viewer.dispatchEvent('content_changed');
  58920. }
  58921. setTitleVisi(v) {
  58922. var reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  58923. Potree.Utils.updateVisible(this.titleLabel, 'hideTitle-' + reason, v);
  58924. //tag.onMesh && Potree.Utils.updateVisible(tag.line, 'hideTitle-'+reason, v)
  58925. //line的可见性比较复杂,所以干脆跟随title的,reason不记录那么多
  58926. this.onMesh && Potree.Utils.updateVisible(this.line, 'hideTitle', this.titleLabel.visible);
  58927. viewer.dispatchEvent('content_changed');
  58928. }
  58929. setFontSize(fontsize) {
  58930. this.titleLabel.fontsize = this.fontsize = fontsize;
  58931. this.titleLabel.updateTexture();
  58932. //this.updateTitlePos()
  58933. viewer.dispatchEvent('content_changed');
  58934. }
  58935. changeSpotScale(s) {
  58936. s *= defaultSpotScale;
  58937. this.spot.scale.set(s, s, s);
  58938. this.updateTitlePos();
  58939. viewer.dispatchEvent('content_changed');
  58940. }
  58941. updateTitlePos() {
  58942. this.onMesh || (this.titleLabel.position.y = titleHeight.uponSpot + this.spot.scale.x / 2);
  58943. }
  58944. changeMap(url) {
  58945. var map = texLoader$8.load(url, () => {
  58946. viewer.dispatchEvent('content_changed');
  58947. });
  58948. this.spot.material.map = map;
  58949. }
  58950. dispose() {
  58951. var _this$titleLabel;
  58952. this.parent.remove(this);
  58953. (_this$titleLabel = this.titleLabel) === null || _this$titleLabel === void 0 || _this$titleLabel.dispose();
  58954. viewer.dispatchEvent('content_changed');
  58955. }
  58956. }
  58957. class TagTool extends EventDispatcher {
  58958. constructor(viewer) {
  58959. super();
  58960. this.viewer = viewer;
  58961. viewer.tags = new Object3D();
  58962. viewer.scene.overlayScene.add(viewer.tags);
  58963. this.viewer.addEventListener('start_inserting_tag', e => {
  58964. this.viewer.dispatchEvent({
  58965. type: 'cancel_insertions'
  58966. });
  58967. });
  58968. }
  58969. createTagFromData(data) {
  58970. var tag = new Tag(data);
  58971. return tag;
  58972. }
  58973. getPoseByIntersect(e) {
  58974. var _e$intersect, _e$intersect$localNor;
  58975. if (!((_e$intersect = e.intersect) !== null && _e$intersect !== void 0 && _e$intersect.location)) return;
  58976. var root = e.intersect.pointcloud || e.intersect.object;
  58977. var position = Potree.Utils.datasetPosTransform({
  58978. toDataset: true,
  58979. pointcloud: e.intersect.pointcloud,
  58980. object: e.intersect.object,
  58981. position: e.intersect.location
  58982. });
  58983. var normal = (_e$intersect$localNor = e.intersect.localNormal) === null || _e$intersect$localNor === void 0 ? void 0 : _e$intersect$localNor.clone();
  58984. if (!normal) {
  58985. normal = e.intersect.normal.clone().applyMatrix4(root.rotateInvMatrix);
  58986. }
  58987. return {
  58988. root,
  58989. normal,
  58990. position
  58991. };
  58992. }
  58993. startInsertion() {
  58994. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  58995. var callback = arguments.length > 1 ? arguments[1] : undefined;
  58996. var cancelFun = arguments.length > 2 ? arguments[2] : undefined;
  58997. var deferred = $.Deferred();
  58998. this.viewer.dispatchEvent({
  58999. type: 'start_inserting_tag'
  59000. });
  59001. this.adding = true;
  59002. var cancel = () => {
  59003. end();
  59004. };
  59005. var end = () => {
  59006. this.adding = false;
  59007. viewer.dispatchEvent({
  59008. type: "endTagMove"
  59009. });
  59010. this.viewer.removeEventListener('global_click', click);
  59011. };
  59012. var click = e => {
  59013. var info = this.getPoseByIntersect(e);
  59014. if (!info) return;
  59015. info.title = '1';
  59016. var tag = new Tag(info);
  59017. end();
  59018. e.consume && e.consume();
  59019. deferred.resolve(tag);
  59020. return {
  59021. stopContinue: true
  59022. };
  59023. };
  59024. this.viewer.addEventListener('global_click', click, {
  59025. importance: 10
  59026. });
  59027. return deferred.promise();
  59028. }
  59029. }
  59030. var initDir = new Vector3(0, 1, 0); //指南针模型的北方向 向屏幕里
  59031. class Compass extends EventDispatcher {
  59032. constructor(dom, viewport) {
  59033. super();
  59034. this.angle = 0;
  59035. this.show = false;
  59036. if (dom) {
  59037. this.dom = $(dom);
  59038. }
  59039. this.viewport = viewport;
  59040. this.init();
  59041. }
  59042. init() {
  59043. var width = 100,
  59044. height = 100;
  59045. if (!this.dom) {
  59046. this.dom = $('<div name="compass"></div>');
  59047. $(viewer.renderArea).append(this.dom);
  59048. }
  59049. this.dom.css({
  59050. display: "none",
  59051. position: "absolute",
  59052. right: "1%",
  59053. top: "60px",
  59054. width: width + "px",
  59055. height: height + "px",
  59056. "z-index": 100,
  59057. "pointer-events": "none"
  59058. });
  59059. var child = $("<div class='dirText north'><span>" + /* (config.lang=='zh'? */'N' /* :'N') */ + "</span></div><div class='center'></div>");
  59060. this.dom.append(child);
  59061. this.dom.find(".dirText").css({
  59062. textAlign: "center",
  59063. "font-size": "10px",
  59064. "position": "absolute",
  59065. width: "100%",
  59066. height: "25px",
  59067. "line-height": "25px"
  59068. });
  59069. this.dom.find(".north").css({
  59070. "color": "#02a0e9",
  59071. "top": "0"
  59072. });
  59073. this.dom.find(".south").css({
  59074. "color": "#ff1414",
  59075. "bottom": "0"
  59076. });
  59077. this.dom.find(".center").css({
  59078. //"background":`url(${config.getStaticResource('img')}/dire.png)`,
  59079. width: width / 2 + "px",
  59080. height: height / 2 + "px",
  59081. "background-size": "contain",
  59082. "background-position": "center",
  59083. left: "50%",
  59084. top: "50%",
  59085. transform: "translate(-50%,-50%)",
  59086. position: "absolute"
  59087. });
  59088. this.dom.find(".dirText").css({
  59089. "text-align": "center",
  59090. "font-size": "10px",
  59091. "color": "rgb(255, 255, 255)",
  59092. "position": "absolute",
  59093. "top": "50%",
  59094. "left": "50%",
  59095. "width": "45%",
  59096. "height": "0px",
  59097. "transform-origin": "left center"
  59098. });
  59099. this.dom.find(".dirText span").css({
  59100. display: "block",
  59101. position: "absolute",
  59102. right: "5px",
  59103. top: "0",
  59104. width: "20px",
  59105. height: "20px",
  59106. "line-height": "20px",
  59107. // "font-size": ".75rem ",
  59108. "margin-top": "-10px"
  59109. });
  59110. try {
  59111. this.renderer = new WebGLRenderer({
  59112. antialias: true,
  59113. alpha: true
  59114. }); //许钟文 添加个抗锯齿,否则添加的线条锯齿严重,
  59115. this.renderer.autoClear = !0;
  59116. this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
  59117. this.renderer.domElement.setAttribute('name', 'compass');
  59118. this.renderer.setClearAlpha(0.0);
  59119. //xst修改
  59120. //this.renderer.setSize(width/2, height/2, false, window.devicePixelRatio ? window.devicePixelRatio : 1);
  59121. //xst修改
  59122. //this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
  59123. //this.renderer.setSize(width/2, height/2);
  59124. //xst修改
  59125. this.renderer.setDrawingBufferSize(width / 2, height / 2, window.devicePixelRatio ? window.devicePixelRatio : 1);
  59126. //this.emit(SceneRendererEvents.ContextCreated)
  59127. } catch (e) {
  59128. viewer.dispatchEvent('webglError', {
  59129. msg: e
  59130. });
  59131. }
  59132. this.dom.find(".center")[0].appendChild(this.renderer.domElement);
  59133. this.renderer.domElement.style.width = this.renderer.domElement.style.height = '100%';
  59134. this.camera = new PerspectiveCamera();
  59135. this.camera.fov = 50;
  59136. this.camera.updateProjectionMatrix();
  59137. this.scene = new Scene(), this.scene.add(this.camera);
  59138. this.createCompass();
  59139. viewer.addEventListener('camera_changed', e => {
  59140. if (e.viewport == this.viewport && e.changeInfo.quaternionChanged /* || e.changeInfo.quaternionChanged */) {
  59141. this.update();
  59142. }
  59143. });
  59144. this.setDomPos();
  59145. if (this.viewport) this.setDisplay(true);
  59146. }
  59147. createCompass() {
  59148. //ConeBufferGeometry(radius : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
  59149. var height = 2;
  59150. var geometry1 = new ConeBufferGeometry(0.7, height, 4, true);
  59151. var geometry2 = new ConeBufferGeometry(0.7, height, 4, true);
  59152. var material = new MeshBasicMaterial({
  59153. vertexColors: true
  59154. });
  59155. //指南针由两个四棱锥拼成,为了渐变颜色,采用指定vertexColor的方式。
  59156. var setColor = function setColor(geometry, color1, color2) {
  59157. var colors = [];
  59158. for (var i = 0, n = geometry.attributes.position.count; i < n; ++i) {
  59159. colors.push(1, 1, 1);
  59160. }
  59161. var set = function set(index, color) {
  59162. //设置第index个点的颜色
  59163. colors[index * 3 + 0] = color[0];
  59164. colors[index * 3 + 1] = color[1];
  59165. colors[index * 3 + 2] = color[2];
  59166. };
  59167. var mid = [(color1[0] + color2[0]) / 2, (color1[1] + color2[1]) / 2, (color1[2] + color2[2]) / 2];
  59168. set(1, color1);
  59169. set(5, color1);
  59170. set(6, color1);
  59171. set(2, mid);
  59172. set(3, mid);
  59173. set(7, mid);
  59174. set(4, color2);
  59175. set(8, color2);
  59176. set(9, color2);
  59177. geometry.setAttribute("color", new BufferAttribute(new Float32Array(colors), 3));
  59178. };
  59179. var blue1 = [1 / 255, 238 / 255, 245 / 255]; //逐渐变深
  59180. var blue2 = [20 / 255, 146 / 255, 170 / 255];
  59181. var blue3 = [40 / 255, 60 / 255, 103 / 255];
  59182. setColor(geometry1, blue1, blue2);
  59183. setColor(geometry2, blue2, blue3);
  59184. /* 朝箭头方向看点构成如下 虽然geometry.attributes.position.count = 19 只有1-9设置的颜色是有效的 另外为什么7决定了上下两边的颜色呢…… 5、9可将其分成上下两个颜色
  59185. 6
  59186. /|\
  59187. / | \
  59188. 7 /_2|1_\ 5
  59189. \ 3|4 / 9
  59190. \ | /
  59191. \|/
  59192. 8
  59193. */
  59194. var cone = new Mesh(geometry1, material);
  59195. cone.position.setY(height / 2);
  59196. geometry1.computeVertexNormals(); //computeFaceNormals
  59197. geometry2.computeVertexNormals();
  59198. var cones = new Object3D();
  59199. cones.add(cone);
  59200. var cone2 = new Mesh(geometry2, material);
  59201. cone2.rotation.x = Math.PI;
  59202. cone2.position.setY(-height / 2);
  59203. cones.add(cone2);
  59204. //cones.rotation.x = Math.PI / 2;//转向initDir的方向
  59205. //cones.rotation.z = Math.PI / 2;
  59206. cones.rotation.z = Math.PI; //转向initDir的方向
  59207. cones.scale.set(0.7, 0.7, 0.7);
  59208. this.scene.add(cones);
  59209. this.cones = cones;
  59210. }
  59211. setNorth(angle) {
  59212. //设置北方向,这决定了指南针自身的朝向。
  59213. if (angle === this.angle) return;
  59214. this.angle = angle;
  59215. this.cones.rotation.z = -MathUtils.degToRad(angle);
  59216. this.update();
  59217. }
  59218. update(quaternion) {
  59219. if (!this.show) return;
  59220. if (!quaternion) quaternion = this.viewport.camera.quaternion.clone();
  59221. this.updateCamera(quaternion);
  59222. this.updateLabel(quaternion);
  59223. this.render();
  59224. }
  59225. updateLabel(quaternion) {
  59226. //更新北标签
  59227. var deg = MathUtils.radToDeg(this.viewport.view.yaw) - 90 + this.angle;
  59228. this.dom.find(".dirText").css("transform", "rotate(" + deg + "deg)");
  59229. this.dom.find(".dirText span").css("transform", "rotate(" + -deg + "deg)");
  59230. }
  59231. updateCamera(quaternion) {
  59232. //更新canvas中的指南针表现,也就是更新相机,和场景中的相机朝向一致。
  59233. var radius = 5; //相机距离
  59234. this.camera.quaternion.copy(quaternion);
  59235. var dir = this.viewport.view.direction; //相机朝向
  59236. this.camera.position.copy(dir.multiplyScalar(radius).negate()); //相机绕着指南针中心(000)转动
  59237. }
  59238. changeViewport(viewport) {
  59239. this.viewport = viewport;
  59240. this.update(); //因相机更新了
  59241. }
  59242. render() {
  59243. this.renderer.render(this.scene, this.camera);
  59244. }
  59245. setDisplay(state) {
  59246. this.show = !!state;
  59247. if (this.show) {
  59248. this.update();
  59249. this.dom.fadeIn(100);
  59250. } else {
  59251. this.dom.fadeOut(100);
  59252. }
  59253. }
  59254. setAutoDisplay(state) {
  59255. //被直接改变了dom的显示
  59256. if (this.autoJudgeShow == state) return;
  59257. this.autoJudgeShow = state;
  59258. if (state) {
  59259. this._autoDisplayEvent = () => {
  59260. var oldShow = this.show;
  59261. this.show = !!this.renderer.domElement.clientHeight;
  59262. if (oldShow != this.show) {
  59263. this.update();
  59264. }
  59265. };
  59266. viewer.addEventListener('update_start', this._autoDisplayEvent);
  59267. } else {
  59268. viewer.removeEventListener('update_start', this._autoDisplayEvent);
  59269. }
  59270. }
  59271. setDomPos() {
  59272. if (!this.viewport) return;
  59273. var right = this.viewport.left + this.viewport.width;
  59274. this.dom.css({
  59275. 'right': (1 - right) * 100 + 1 + '%'
  59276. });
  59277. }
  59278. }
  59279. var planeGeo$4 = new PlaneGeometry(1.6, 1.6, 1, 1);
  59280. var texLoader$9 = new TextureLoader();
  59281. var lastQ = new Quaternion();
  59282. class FloorCompass extends Object3D {
  59283. constructor(viewer) {
  59284. super();
  59285. this.angle = 0;
  59286. this.build();
  59287. Potree.Utils.updateVisible(this, 'isAtPano', false);
  59288. viewer.scene.scene.add(this);
  59289. viewer.addEventListener('camera_changed', e => {
  59290. if (e.viewport == viewer.mainViewport && e.changeInfo.quaternionChanged) {
  59291. this.updateRot();
  59292. }
  59293. });
  59294. var init = () => {
  59295. var setPano = pano => {
  59296. this.position.copy(pano.floorPosition);
  59297. this.position.z += 0.05;
  59298. Potree.Utils.updateVisible(this, 'isAtPano', true);
  59299. };
  59300. if (viewer.images360.currentPano) {
  59301. setPano(viewer.images360.currentPano);
  59302. }
  59303. viewer.images360.addEventListener('flyToPano', e => {
  59304. //console.log('floorcompass set pano',e.toPano.pano.id)
  59305. setPano(e.toPano.pano);
  59306. });
  59307. };
  59308. if (viewer.allLoaded) {
  59309. init();
  59310. } else {
  59311. viewer.addEventListener('allLoaded', e => {
  59312. init();
  59313. });
  59314. }
  59315. this.addEventListener('isVisible', e => {
  59316. //visi change
  59317. if (this.visible) this.updateRot();
  59318. viewer.dispatchEvent('content_changed');
  59319. });
  59320. }
  59321. build() {
  59322. var count = 0;
  59323. var loaded = tex => {
  59324. count++;
  59325. if (count == 2) {
  59326. this.underLayer = new Mesh(planeGeo$4, new MeshBasicMaterial({
  59327. map: compassMap,
  59328. transparent: true,
  59329. side: undefined,
  59330. depthTest: false
  59331. }));
  59332. this.underLayer.name = 'underLayer';
  59333. this.underLayer.renderOrder = 2;
  59334. this.arrow = new Mesh(planeGeo$4, new MeshBasicMaterial({
  59335. map: arrowMap,
  59336. transparent: true,
  59337. side: undefined,
  59338. depthTest: false
  59339. }));
  59340. this.arrow.name = 'compassArrow';
  59341. this.arrow.position.set(0, 0, 0.01);
  59342. this.arrow.renderOrder = 3;
  59343. this.add(this.underLayer);
  59344. this.add(this.arrow);
  59345. this.updateRot();
  59346. //this.setAngle()
  59347. //done && done()
  59348. }
  59349. };
  59350. var arrowMap = texLoader$9.load(Potree.resourcePath + '/textures/compass_arrow.png', loaded);
  59351. var compassMap = texLoader$9.load(Potree.resourcePath + '/textures/compass_floor.png', loaded);
  59352. }
  59353. setAngle(angle) {
  59354. if (angle === this.angle) return;
  59355. this.angle = angle;
  59356. this.rotation.set(0, 0, -MathUtils.degToRad(angle));
  59357. viewer.dispatchEvent('content_changed');
  59358. }
  59359. updateRot() {
  59360. /* rotation = new THREE.Euler(0, 0, yaw - this.firstLogo.rotation.z)
  59361. this.compassArrow1.rotation.copy(rotation) */
  59362. if (!this.arrow || !this.visible) return;
  59363. this.arrow.rotation.z = viewer.mainViewport.view.yaw - this.rotation.z;
  59364. }
  59365. }
  59366. class AxisViewer extends ViewerBase {
  59367. constructor(listenViewport, parentArea) {
  59368. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  59369. var domElement = $("<div name=\"Axisdom\" viewport=".concat(listenViewport.name, "></div>"));
  59370. $(parentArea).append(domElement);
  59371. var posInfo = Object.assign({
  59372. //default:
  59373. right: 0,
  59374. top: 0,
  59375. width: '100px',
  59376. height: '100px'
  59377. }, options.domStyle, {
  59378. position: 'absolute'
  59379. });
  59380. if (options.domStyle) {
  59381. if (options.domStyle.bottom != void 0) {
  59382. delete posInfo.top;
  59383. }
  59384. if (options.domStyle.left != void 0) {
  59385. delete posInfo.right;
  59386. }
  59387. }
  59388. domElement.css(posInfo);
  59389. super(domElement[0], {
  59390. name: 'axis',
  59391. antialias: true
  59392. });
  59393. this.listenViewport = listenViewport;
  59394. Object.defineProperty(listenViewport, 'axis', {
  59395. value: this,
  59396. writable: true,
  59397. // 可写(可选)
  59398. enumerable: false,
  59399. // 不可枚举
  59400. configurable: true // 可配置(可选)
  59401. });
  59402. this.scene = new Scene();
  59403. //this.camera = new THREE.PerspectiveCamera(30, 1, 1, this.radius*3);
  59404. var w = 50;
  59405. this.camera = new OrthographicCamera(-w / 2, w / 2, w / 2, -w / 2, 1, w * 4);
  59406. this.camera.zoom = 2.7; //(domElement.clientWidth || 300) / w * 1.267//zoom越大视野越小
  59407. this.camera.updateProjectionMatrix();
  59408. this.view = new ExtendView();
  59409. this.view.radius = 70;
  59410. this.viewports = [new Viewport(this.view, this.camera, {
  59411. left: 0,
  59412. bottom: 0,
  59413. width: 1,
  59414. height: 1,
  59415. name: 'axis'
  59416. })];
  59417. this.updateScreenSize();
  59418. this.createAxis();
  59419. var updateCamera = e => {
  59420. if (e.viewport == listenViewport && e.changeInfo.quaternionChanged) {
  59421. this.update();
  59422. }
  59423. };
  59424. viewer.addEventListener('camera_changed', updateCamera);
  59425. var repos = () => {
  59426. if (!listenViewport.active || listenViewport.width == 0 || listenViewport.height == 0) {
  59427. return domElement.css('visibility', 'hidden');
  59428. }
  59429. domElement.css('visibility', 'visible');
  59430. var props = [['left', 'right', 'width'], ['bottom', 'top', 'height']];
  59431. var set = prop => {
  59432. var str;
  59433. var name = posInfo[prop[1]] != void 0 ? prop[1] : prop[0];
  59434. var percent = posInfo[prop[1]] != void 0 ? 1 - listenViewport[prop[0]] - listenViewport[prop[2]] : listenViewport[prop[0]];
  59435. if (posInfo[name] == 0 || posInfo[name].includes('%')) {
  59436. str = parseFloat(posInfo[name]) + percent * 100 + '%';
  59437. } else {
  59438. //px
  59439. str = 'calc(' + percent * 100 + '% + ' + posInfo[name] + ')';
  59440. }
  59441. domElement.css(name, str);
  59442. };
  59443. set(props[0]);
  59444. set(props[1]);
  59445. };
  59446. this.listenViewport.addEventListener('resize', repos);
  59447. this.addEventListener('dispose', () => {
  59448. viewer.removeEventListener('camera_changed', updateCamera);
  59449. viewer.removeEventListener('resize', repos);
  59450. });
  59451. repos();
  59452. this.update();
  59453. }
  59454. createAxis() {
  59455. var axis = new Object3D();
  59456. ['x', 'y', 'z'].forEach(axisText => {
  59457. var color = new Color().set(Potree.config.axis[axisText].color);
  59458. var group = new Object3D();
  59459. var line = LineDraw.createLine([new Vector3(), new Vector3(0, 0, 7)], {
  59460. color
  59461. });
  59462. var label = this.createLabel(axisText, color);
  59463. label.position.set(0, 0, 11 /* + this.renderArea.clientWidth/200 */);
  59464. if (axisText == 'y') {
  59465. group.rotation.x = -Math.PI / 2;
  59466. } else if (axisText == 'x') {
  59467. group.rotation.y = Math.PI / 2;
  59468. }
  59469. group.add(line);
  59470. group.add(label);
  59471. axis.add(group);
  59472. });
  59473. this.axis = axis;
  59474. this.scene.add(this.axis);
  59475. }
  59476. createLabel(text, color) {
  59477. var fontsize = this.renderArea.clientWidth / 5; //20//Math.round( Potree.math.linearClamp(this.renderArea.clientWidth, [80,500],[12,50]))
  59478. var s = 3100 / this.renderArea.clientWidth;
  59479. console.log('fontsize', fontsize);
  59480. var label = new TextSprite$2({
  59481. backgroundColor: {
  59482. r: 0,
  59483. g: 0,
  59484. b: 0,
  59485. a: 0
  59486. },
  59487. textColor: {
  59488. r: color.r * 255,
  59489. g: color.g * 255,
  59490. b: color.b * 255,
  59491. a: 1
  59492. },
  59493. fontsize,
  59494. //useDepth : true ,
  59495. renderOrder: 5,
  59496. // pickOrder:5,
  59497. fontWeight: 'Lighter',
  59498. text,
  59499. name: 'axis',
  59500. viewports: this.viewports
  59501. });
  59502. label.scale.set(s, s, s);
  59503. return label;
  59504. }
  59505. update() {
  59506. this.updateCamera();
  59507. this.render();
  59508. }
  59509. updateCamera() {
  59510. var view = this.listenViewport.view;
  59511. this.view.yaw = view.yaw;
  59512. this.view.pitch = view.pitch;
  59513. var dir = view.direction; //相机朝向
  59514. this.view.position.copy(dir.multiplyScalar(this.view.radius).negate()); //相机绕着指南针中心(000)转动
  59515. this.view.applyToCamera(this.camera);
  59516. }
  59517. render() {
  59518. viewer.dispatchEvent({
  59519. type: "render.begin",
  59520. viewport: this.viewports[0]
  59521. }); //update sprite
  59522. this.renderer.render(this.scene, this.camera);
  59523. }
  59524. dispose() {
  59525. this.axis.traverse(child => {
  59526. if (child instanceof TextSprite$2) {
  59527. child.dispose();
  59528. } else if (child instanceof LineSegments) {
  59529. child.material.dispose();
  59530. child.geometry.dispose();
  59531. }
  59532. });
  59533. super.dispose();
  59534. delete this.listenViewport.axis;
  59535. }
  59536. }
  59537. function exitFullScreen() {
  59538. if (document.fullscreenElement && document.fullscreenElement.tagName === 'VIDEO' && document.fullscreenElement.getAttribute('unfullscreen')) {
  59539. if (document.exitFullscreen) {
  59540. document.exitFullscreen();
  59541. } else if (document.msExitFullscreen) {
  59542. document.msExitFullscreen();
  59543. } else if (document.mozCancelFullScreen) {
  59544. document.mozCancelFullScreen();
  59545. } else if (document.oRequestFullscreen) {
  59546. document.oCancelFullScreen();
  59547. } else if (document.webkitExitFullscreen) {
  59548. document.webkitExitFullscreen();
  59549. } else if (document.webkitCancelFullScreen) {
  59550. document.webkitCancelFullScreen();
  59551. }
  59552. setTimeout(() => {
  59553. exitFullScreen();
  59554. }, 250);
  59555. }
  59556. }
  59557. if (browser.detectAndroidMobile()) {
  59558. //针对Android横屏时video会自动全屏播放的bug #39505 #43421
  59559. window.addEventListener('resize', () => {
  59560. //resize时如果全屏元素为video, 退出全屏
  59561. setTimeout(() => {
  59562. exitFullScreen();
  59563. }, 500); //太快可能检测不到document.fullscreenElement
  59564. });
  59565. window.addEventListener('orientationchange', e => {
  59566. // 空间视频横屏时会触发自动全屏
  59567. if (window.orientation == 0 || window.orientation == 180) {
  59568. //竖屏
  59569. var videos = document.querySelectorAll('video[box]'); //只针对有box属性的video标签(空间视频)
  59570. videos.forEach(item => {
  59571. item.remove();
  59572. });
  59573. setTimeout(() => {
  59574. videos.forEach(i => {
  59575. document.body.appendChild(i);
  59576. i.play();
  59577. });
  59578. }, 500);
  59579. } else {
  59580. // 横屏
  59581. var _videos = document.querySelectorAll('video[box]');
  59582. _videos.forEach(item => {
  59583. item.remove();
  59584. });
  59585. setTimeout(() => {
  59586. _videos.forEach(i => {
  59587. document.body.appendChild(i);
  59588. i.play();
  59589. });
  59590. }, 500);
  59591. }
  59592. });
  59593. }
  59594. class FlvVideoPlayerBase {
  59595. constructor(player) {
  59596. this.player = player;
  59597. this.instances = new Map();
  59598. this.video = null;
  59599. }
  59600. //overlay info -- [metadata.overlay]
  59601. addVideo(url) {
  59602. var instance = this._createVideo(url);
  59603. this.instances.set(url, instance);
  59604. instance.videoElement.masters = []; //一个video可以对应多个主体,因为它们链接一样
  59605. return instance;
  59606. }
  59607. getVideo(url, master) {
  59608. var instance = this.instances.get(url);
  59609. if (!instance) {
  59610. instance = this.addVideo(url);
  59611. }
  59612. var video = instance.videoElement;
  59613. master && video.masters.push(master);
  59614. video.onloadedmetadata = () => {
  59615. video.canPlayed = true;
  59616. video.masters.forEach(m => {
  59617. m.dispatchEvent({
  59618. type: 'loadedmetadata'
  59619. });
  59620. });
  59621. };
  59622. return video;
  59623. }
  59624. _getVideoPath(sid) {
  59625. //在子类中扩展
  59626. }
  59627. _createVideo(url) {
  59628. var video = document.createElement('video');
  59629. video.setAttribute('crossOrigin', 'anonymous');
  59630. video.setAttribute('playsinline', 'true');
  59631. video.setAttribute('webkit-playsinline', 'true');
  59632. video.setAttribute('controls', 'true');
  59633. video.setAttribute('unfullscreen', 'true');
  59634. video.autoplay = false;
  59635. video.muted = true;
  59636. video.loop = true;
  59637. video.style.position = 'fixed';
  59638. video.style.left = '0';
  59639. video.style.top = '0';
  59640. video.style.zIndex = '0';
  59641. video.style.width = '1px';
  59642. // video.style.display = 'none'
  59643. //video.isFirstPlay = true;
  59644. video.style.opacity = '0';
  59645. document.body.appendChild(video);
  59646. video.player = this;
  59647. var player = flvjs.createPlayer({
  59648. type: 'flv',
  59649. url: url
  59650. });
  59651. player.videoElement = video;
  59652. player.attachMediaElement(video);
  59653. player.on(flvjs.Events.ERROR, () => {
  59654. this._onPlayerError();
  59655. console.log('尝试使用mp4链接进行播放');
  59656. video.src = url.replace('.flv', '.mp4');
  59657. });
  59658. player.load();
  59659. return player;
  59660. }
  59661. _onPlayerError() {
  59662. console.warn('视频加载失败');
  59663. }
  59664. }
  59665. class H5VideoPlayerBase {
  59666. constructor() {
  59667. this.video = null;
  59668. this.videos = new Map();
  59669. }
  59670. //overlay info -- [metadata.overlay]
  59671. addVideo(url) {
  59672. var video = this._createVideoElement(url);
  59673. this.videos.set(url, video);
  59674. video.masters = [];
  59675. return video;
  59676. }
  59677. getVideo(url, master) {
  59678. var video = this.videos.get(url);
  59679. if (!video) {
  59680. video = this.addVideo(url);
  59681. }
  59682. master && video.masters.push(master);
  59683. video.onloadedmetadata = () => {
  59684. video.canPlayed = true;
  59685. video.masters.forEach(m => {
  59686. m.dispatchEvent({
  59687. type: 'loadedmetadata'
  59688. });
  59689. });
  59690. };
  59691. return video;
  59692. }
  59693. _createVideoElement(src) {
  59694. var video = document.createElement('video');
  59695. video.setAttribute('crossOrigin', 'anonymous');
  59696. video.setAttribute('playsinline', 'true');
  59697. video.setAttribute('x5-playsinline', 'true');
  59698. video.setAttribute('webkit-playsinline', 'true');
  59699. video.setAttribute('x5-video-player-type', 'h5');
  59700. video.setAttribute('controls', 'true');
  59701. video.setAttribute('x-webkit-airplay', 'allow');
  59702. video.autoplay = true;
  59703. video.muted = true;
  59704. video.loop = true;
  59705. video.src = src;
  59706. video.style.position = 'fixed';
  59707. video.style.left = '0';
  59708. video.style.top = '0';
  59709. video.style.zIndex = '1000';
  59710. video.style.width = '300px';
  59711. video.style.height = '300px';
  59712. //video.style.display = browser.urlHasValue('debug') ? 'block' : 'none'
  59713. //document.body.appendChild(video)
  59714. return video;
  59715. }
  59716. }
  59717. var planeGeometry = new PlaneGeometry(1, 1);
  59718. var testUrl = 'https://newcntv.qcloudcdn.com/asp/hls/4000/0303000a/3/default/d907ef756138493e9fe5b35b4ab69642/4000.m3u8';
  59719. var videoPlayer = Potree.browser.nonsupportH5Video ? new FlvVideoPlayerBase() : new H5VideoPlayerBase();
  59720. var normalColor = new Color(1, 1, 1);
  59721. var hoverColor = new Color(2, 2, 2);
  59722. var vec1 = new Vector3(),
  59723. vec2 = new Vector3(),
  59724. vec3 = new Vector3(),
  59725. quat1 = new Quaternion(),
  59726. quat2 = new Quaternion();
  59727. var cameraModel, loadingCamModel;
  59728. //测试场景: http://192.168.0.25/mix3d/#/home/671 潘少 Aa123456 http://192.168.0.25/epg.html?m=YZL-jm-lrZcWxzPaPJ#/tag
  59729. //接收4dkk的监控 暂不支持修改 可以直接加到模型上,注意所附模型旋转90度后角度才对。
  59730. class Monitor extends Object3D {
  59731. constructor(data, model) {
  59732. super();
  59733. this.isMonitor = true;
  59734. this.external = external; //全景时不换材质
  59735. warnHls();
  59736. data.showScope == void 0 && (data.showScope = true);
  59737. data.video = testUrl;
  59738. this.data = data;
  59739. /* for(let i in data){
  59740. this[i] = data[i]
  59741. } */
  59742. this.fov = data.data.fov;
  59743. this.cylinderNear = data.data.near || 0.03;
  59744. this.cylinderFar = data.data.far || 3;
  59745. model.add(this);
  59746. var videoUrl = this.getVideoSrc();
  59747. this.video = videoPlayer.getVideo(videoUrl, this);
  59748. if (data.video) {
  59749. //console.error('createVideo', this.videoSrc, this.sid)
  59750. /* this.video.onloadedmetadata = () => {
  59751. this.video.canPlayed = true
  59752. this.video.masters.forEach(v => { //一个video可以对应多个camera,因为它们链接一样
  59753. v.dispatchEvent({ type: 'loadedmetadata' })
  59754. })
  59755. } */
  59756. var canPlayed = e => {
  59757. //this.player.$app.Camera.emit('SecurityCamera.videoActive', this.sid)
  59758. this.videoActive = true;
  59759. //this.updateInfo(true)
  59760. };
  59761. if (this.video.canPlayed) {
  59762. canPlayed();
  59763. } else {
  59764. this.addEventListener('loadedmetadata', canPlayed);
  59765. }
  59766. if (Hls.isSupported() && data.urlType == 1) {
  59767. //似乎Hls不支持就无法播放
  59768. var hls = new Hls();
  59769. hls.loadSource(videoUrl);
  59770. hls.attachMedia(this.video);
  59771. hls.on(Hls.Events.ERROR, (event, data) => {
  59772. console.log('HLS加载失败', data.name, event, data);
  59773. });
  59774. this.hlsVideoPlayer = hls;
  59775. }
  59776. this.play(); // ios需要
  59777. this.pause();
  59778. }
  59779. this.obj3d = new Group();
  59780. this.add(this.obj3d);
  59781. // 投射体材质
  59782. this.normalMat = new BasicMaterial({
  59783. color: new Color(0x00c8af),
  59784. transparent: true,
  59785. opacity: 0.1,
  59786. side: DoubleSide,
  59787. depthTest: false,
  59788. visible: !!data.showScope
  59789. });
  59790. // 监控视频材质
  59791. this.videoMat = new BasicMaterial({
  59792. map: new VideoTexture(this.video),
  59793. side: DoubleSide,
  59794. depthTest: false,
  59795. transparent: true
  59796. });
  59797. // 摄像头
  59798. if (!cameraModel) {
  59799. if (!loadingCamModel) {
  59800. loadingCamModel = true;
  59801. viewer.loadModel({
  59802. fileType: 'glb',
  59803. url: "".concat(Potree.resourcePath, "/models/glb/monitor.glb")
  59804. }, model => {
  59805. cameraModel = model.children[0].children[0];
  59806. cameraModel.geometry.translate(30, 50, -10);
  59807. cameraModel.quaternion.setFromEuler(new Euler(Math.PI / 2 + 0.24, Math.PI, 0));
  59808. cameraModel.name = 'cameraModel';
  59809. console.log('load monitor glb', cameraModel.uuid);
  59810. model.parent.remove(model);
  59811. viewer.scene.monitors.forEach(e => e.modelLoaded());
  59812. loadingCamModel = false;
  59813. });
  59814. }
  59815. } else {
  59816. this.modelLoaded();
  59817. }
  59818. this.updateAspect();
  59819. if (data.showTitle) {
  59820. var group = new Shim.FollowRootObject(this); //透明有问题,只有放到overlayScene里渲染了 (大小好像还是跟随模型了
  59821. this.titleLabel = new TextSprite$2({
  59822. text: data.name,
  59823. backgroundColor: {
  59824. r: 255,
  59825. g: 255,
  59826. b: 255,
  59827. a: 0
  59828. },
  59829. textColor: {
  59830. r: 255,
  59831. g: 255,
  59832. b: 255,
  59833. a: 1
  59834. },
  59835. textshadowColor: '#666',
  59836. borderRadius: 2,
  59837. fontsize: 34,
  59838. renderOrder: 5,
  59839. margin: {
  59840. x: 12,
  59841. y: 10
  59842. },
  59843. sizeInfo: {
  59844. scale: 0.4,
  59845. nearBound: 3
  59846. }
  59847. });
  59848. this.titleLabel.sprite.material.depthTest = this.titleLabel.sprite.material.depthWrite = true;
  59849. this.titleLabel.position.set(0, -0.2, 0.1);
  59850. group.add(this.titleLabel);
  59851. viewer.scene.overlayScene.add(group);
  59852. group.name = 'monitorLabel';
  59853. this.addEventListener('isVisible', () => {
  59854. Potree.Utils.updateVisible(group, 'follow', this.realVisible());
  59855. });
  59856. this.parent.addEventListener('isVisible', () => {
  59857. Potree.Utils.updateVisible(group, 'follow', this.realVisible());
  59858. });
  59859. }
  59860. {
  59861. var _model$props$baseRota;
  59862. this.posOri = new Vector3(parseFloat(data.data['posOri-x']), parseFloat(data.data['posOri-y']), parseFloat(data.data['posOri-z'])), this.posOffset = new Vector3(parseFloat(data.data['posOffset-x']), parseFloat(data.data['posOffset-y']), parseFloat(data.data['posOffset-z'])),
  59863. // data.position && this.position.copy(data.position)
  59864. this.position.copy(this.posOri).add(this.posOffset);
  59865. this.position.copy(Potree.Utils.tran4dkkVecInModel(this.position, model));
  59866. // target的优先级大于rotation
  59867. if (data.data.target) {
  59868. this.target = Potree.Utils.tran4dkkVecInModel(data.data.target, model);
  59869. this.lookAt(data.data.target);
  59870. } else {
  59871. data.data.rotation && this.quaternion.setFromEuler(data.data.rotation);
  59872. this.target = new Vector3(0, 0, -1).applyQuaternion(this.quaternion).add(this.position);
  59873. }
  59874. this.roll = 0;
  59875. data.data.pitch && (this.pitch = data.data.pitch);
  59876. data.data.yaw && (this.yaw = data.data.yaw);
  59877. data.data.roll && this.setRoll(this.data.data.roll);
  59878. if (((_model$props$baseRota = model.props.baseRotation) === null || _model$props$baseRota === void 0 ? void 0 : _model$props$baseRota.x) == 0) {
  59879. //该模型已经矫正,无需旋转90度,但是场景的数据需要,导致monitor和模型不匹配,需要再旋转
  59880. this.quaternion.copy(Potree.math.convertQuaternion.YupToZup(this.quaternion));
  59881. }
  59882. }
  59883. //this.updateInfo(true)
  59884. this.events = {
  59885. setSize: (width, height) => {
  59886. if (this.isWatching) {
  59887. this.updateAspect();
  59888. }
  59889. },
  59890. update: () => {
  59891. if (!this.video.paused) {
  59892. viewer.dispatchEvent('content_changed');
  59893. }
  59894. }
  59895. };
  59896. viewer.addEventListener('viewerResize', this.events.setSize);
  59897. viewer.addEventListener('update', this.events.update);
  59898. window.monitor = this;
  59899. Potree.Utils.setObjectLayers(this, 'dontIntersect');
  59900. Potree.Utils.setObjectLayers(this.cylinder.bottom, 'monitor');
  59901. this.cameraModel && Potree.Utils.setObjectLayers(this.cameraModel, 'sceneObjects');
  59902. }
  59903. getVideoSrc() {
  59904. if (this.data.urlType === 2) {
  59905. var a = this.parent.props.raw.surveillancePath.split('/'); //用户上传的文件
  59906. a.pop();
  59907. return a.join('/') + '/' + this.data.fileName;
  59908. } else {
  59909. return this.data.playUrl;
  59910. }
  59911. }
  59912. modelLoaded() {
  59913. this.cameraModel = cameraModel.clone();
  59914. this.cameraModel.material = cameraModel.material.clone();
  59915. this.obj3d.add(this.cameraModel);
  59916. this.cameraModel.addEventListener('mouseover', () => {
  59917. CursorDeal.add('hoverMonitor');
  59918. this.highlight(true);
  59919. });
  59920. this.cameraModel.addEventListener('mouseleave', () => {
  59921. CursorDeal.remove('hoverMonitor');
  59922. this.highlight(false);
  59923. });
  59924. this.cameraModel.addEventListener('click', () => {
  59925. if (viewer.scene.monitors.some(e => e.isWatching)) return;
  59926. this.watch();
  59927. });
  59928. }
  59929. watch() {
  59930. if (!this.videoActive) {
  59931. console.log('monitorError src:', this.video.src);
  59932. return viewer.dispatchEvent('monitorError');
  59933. }
  59934. var camera = viewer.mainViewport.camera;
  59935. this.updateAspect();
  59936. this.isWatching = true;
  59937. //this.target.set(0, 0, -1).applyQuaternion(this.quaternion).add(this.position)
  59938. viewer.mainViewport.view.cancelFlying();
  59939. this.oldState = {
  59940. fov: camera.fov,
  59941. position: camera.position.clone(),
  59942. quaternion: camera.quaternion.clone()
  59943. };
  59944. this.data.showScope && this.showVideo(true);
  59945. this.video.pause(); //先显示出画面
  59946. setTimeout(() => {
  59947. this.data.showScope || this.showVideo(true);
  59948. viewer.mainViewport.cameraLayers = ['monitor']; //hide others
  59949. viewer.scene.monitors.forEach(e => Potree.Utils.updateVisible(e, 'watch', e == this));
  59950. }, 800);
  59951. viewer.mainViewport.view.setRotMode('free');
  59952. viewer.mainViewport.view.setView({
  59953. position: this.getWorldPosition(new Vector3()),
  59954. quaternion: this.getWorldQuaternion(new Quaternion()),
  59955. onUpdate: percent => {
  59956. camera.fov = this.fov * percent + this.oldState.fov * (1 - percent);
  59957. camera.updateProjectionMatrix();
  59958. },
  59959. callback: () => {
  59960. this.video.play();
  59961. viewer.dispatchEvent({
  59962. type: 'watchMonitor',
  59963. monitor: this
  59964. });
  59965. },
  59966. duration: 1500
  59967. });
  59968. viewer.renderArea.style['pointer-events'] = 'none';
  59969. }
  59970. leave() {
  59971. // 停止观看监控
  59972. var camera = viewer.mainViewport.camera;
  59973. this.isWatching = false;
  59974. this.cameraModel.material.color.copy(normalColor);
  59975. viewer.mainViewport.view.cancelFlying();
  59976. viewer.mainViewport.cameraLayers = null;
  59977. viewer.scene.monitors.forEach(e => Potree.Utils.updateVisible(e, 'watch', true));
  59978. this.data.showScope || this.showVideo(false);
  59979. this.video.pause();
  59980. viewer.mainViewport.view.setView({
  59981. position: this.oldState.position,
  59982. quaternion: this.oldState.quaternion,
  59983. onUpdate: percent => {
  59984. camera.fov = this.fov * (1 - percent) + this.oldState.fov * percent;
  59985. camera.updateProjectionMatrix();
  59986. },
  59987. callback: () => {
  59988. viewer.renderArea.style['pointer-events'] = '';
  59989. this.data.showScope && this.showVideo(false);
  59990. viewer.mainViewport.view.setRotMode('standard');
  59991. },
  59992. duration: 1000
  59993. });
  59994. viewer.dispatchEvent({
  59995. type: 'exitWatchMonitor',
  59996. monitor: this
  59997. });
  59998. }
  59999. // 显示监控视频或显示投射体
  60000. showVideo(isShow) {
  60001. //console.warn('showVideo', this.info.sid, isShow )
  60002. if (!this.videoActive) return;
  60003. if (isShow) {
  60004. /* if (browser.detectIOS()) {
  60005. this.player.domElement.addEventListener('touchstart', this.events.onDomElementTouchStart, true)
  60006. } */
  60007. this.play();
  60008. this.normalMat.opacity = 0;
  60009. Potree.Utils.updateVisible(this.cylinder, 'watch', true, 1, 'add');
  60010. this.cylinder.bottom.material = this.videoMat;
  60011. //this.cylinder.bottom.renderOrder = RenderOrder.monitorPlane
  60012. } else {
  60013. this.pause();
  60014. this.normalMat.opacity = 0.08;
  60015. Potree.Utils.updateVisible(this.cylinder, 'watch', false, 1, 'cancel');
  60016. this.cylinder.bottom.material = this.normalMat;
  60017. //this.cylinder.bottom.renderOrder = RenderOrder.visibleFloor
  60018. }
  60019. }
  60020. play() {
  60021. //console.log('play monitor', this.sid, this.videoSrc)
  60022. this.shouldPlay = true;
  60023. if (Potree.browser.detectWeixin()) {
  60024. //用微信平台的 WeixinJSBridge 越过 Autoplay Policy
  60025. try {
  60026. top.WeixinJSBridge && top.WeixinJSBridge.invoke('getNetworkType', {}, e => {
  60027. this.video.play();
  60028. }, false);
  60029. } catch (error) {
  60030. this.video.play();
  60031. }
  60032. } else {
  60033. this.video.play();
  60034. if (this.video.paused) {
  60035. console.log('播放不了');
  60036. /* this.player.once('pointerStart', () => {
  60037. this.play()
  60038. }) */
  60039. }
  60040. }
  60041. }
  60042. pause() {
  60043. this.shouldPlay = false;
  60044. this.video.pause();
  60045. }
  60046. dispose() {
  60047. var _this$titleLabel;
  60048. var index = viewer.scene.monitors.indexOf(this);
  60049. if (index == -1) return;
  60050. viewer.scene.monitors.splice(index, 1);
  60051. viewer.removeEventListener("viewerResize", this.events.setSize);
  60052. viewer.removeEventListener("update", this.events.update);
  60053. transitions.cancelById('cameraHighlight_' + this.sid);
  60054. /* this.tag.geometry.dispose()
  60055. this.tag.material.dispose()
  60056. this.cylinder.line.geometry.dispose()
  60057. this.cylinder.line.material.dispose()
  60058. this.cylinder.geometry.dispose() */
  60059. viewer.removeModel(this);
  60060. this.normalMat.dispose();
  60061. this.videoMat.dispose();
  60062. (_this$titleLabel = this.titleLabel) === null || _this$titleLabel === void 0 || _this$titleLabel.dispose();
  60063. this.hlsVideoPlayer && this.hlsVideoPlayer.destroy();
  60064. }
  60065. highlight(state) {
  60066. //相机hover高亮
  60067. if (this.hightlighted == state) return;
  60068. this.hightlighted = state;
  60069. transitions.cancelById('cameraHighlight_' + this.sid);
  60070. transitions.start(lerp.color(this.cameraModel.material.color, state ? hoverColor : normalColor), 100, null, null, null, null, 'cameraHighlight_' + this.sid);
  60071. }
  60072. updateAspect() {
  60073. //更新aspect且修改geometry
  60074. var aspect = viewer.mainViewport.camera.aspect;
  60075. if (aspect != this.aspect) {
  60076. this.aspect = aspect;
  60077. this.updateMesh();
  60078. }
  60079. }
  60080. updateMesh() {
  60081. var nearHeight, nearWidth, farHeight, farWidth;
  60082. nearHeight = Math.tan(MathUtils.degToRad(this.fov / 2)) * this.cylinderNear;
  60083. nearWidth = nearHeight * this.aspect; //根据canvas比例调整视频面的比例,保持和canvas一致。
  60084. farHeight = Math.tan(MathUtils.degToRad(this.fov / 2)) * this.cylinderFar;
  60085. farWidth = farHeight * this.aspect;
  60086. var firstBuild = !this.cylinder;
  60087. if (this.data.showScope) {
  60088. // 投射体(底面以外)
  60089. var vertices = [],
  60090. bottomVertices = [];
  60091. vertices.push(-nearWidth, nearHeight, -this.cylinderNear);
  60092. vertices.push(nearWidth, nearHeight, -this.cylinderNear);
  60093. vertices.push(nearWidth, -nearHeight, -this.cylinderNear);
  60094. vertices.push(-nearWidth, -nearHeight, -this.cylinderNear);
  60095. bottomVertices.push(-farWidth, farHeight, -this.cylinderFar);
  60096. bottomVertices.push(farWidth, farHeight, -this.cylinderFar);
  60097. bottomVertices.push(farWidth, -farHeight, -this.cylinderFar);
  60098. bottomVertices.push(-farWidth, -farHeight, -this.cylinderFar);
  60099. vertices = vertices.concat(bottomVertices);
  60100. if (firstBuild) {
  60101. var uvs = [];
  60102. uvs.push(0, 1, 1, 1, 1, 0, 0, 0);
  60103. uvs.push(0, 1, 1, 1, 1, 0, 0, 0);
  60104. var indexs = [];
  60105. indexs.push(0, 1, 3, 2, 3, 1);
  60106. indexs.push(0, 1, 4, 5, 4, 1);
  60107. indexs.push(1, 2, 5, 6, 5, 2);
  60108. indexs.push(2, 3, 6, 7, 6, 3);
  60109. indexs.push(3, 0, 7, 4, 7, 0);
  60110. // indexs.push(4, 7, 5, 6, 5, 7)
  60111. var cylinderGeo = new BufferGeometry();
  60112. cylinderGeo.setAttribute('uv', new BufferAttribute(new Float32Array(uvs), 2));
  60113. cylinderGeo.setIndex(new BufferAttribute(new Uint16Array(indexs), 1));
  60114. this.cylinder = new Mesh(cylinderGeo, this.normalMat);
  60115. //if (this.control.player.$app.config.mobile) this.cylinder.rotateZ(-Math.PI / 2) //用户自己旋转屏幕吧
  60116. this.obj3d.add(this.cylinder);
  60117. }
  60118. this.cylinder.geometry.setAttribute('position', new BufferAttribute(new Float32Array(vertices), 3));
  60119. } else if (!this.cylinder) {
  60120. this.cylinder = new Group();
  60121. this.obj3d.add(this.cylinder);
  60122. }
  60123. // 投射体底面 (视频)
  60124. var bottomGeo = new PlaneGeometry(farWidth * 2, farHeight * 2);
  60125. if (firstBuild) {
  60126. this.cylinder.bottom = new Mesh(bottomGeo, this.normalMat);
  60127. this.cylinder.add(this.cylinder.bottom);
  60128. } else {
  60129. this.cylinder.bottom.geometry.dispose();
  60130. this.cylinder.bottom.geometry = bottomGeo;
  60131. }
  60132. this.cylinder.bottom.position.set(0, 0, this.cylinderNear - this.cylinderFar);
  60133. if (this.data.showScope) {
  60134. // 投射体线框
  60135. if (firstBuild) {
  60136. this.cylinder.line = new LineSegments(new EdgesGeometry(this.cylinder.geometry), new LineBasicMaterial({
  60137. color: 0xffffff,
  60138. opacity: 0.6,
  60139. transparent: true
  60140. }));
  60141. this.cylinder.add(this.cylinder.line);
  60142. } else {
  60143. this.cylinder.line.geometry.dispose();
  60144. this.cylinder.line.geometry = new EdgesGeometry(this.cylinder.geometry);
  60145. }
  60146. }
  60147. }
  60148. set pitch(pitch) {
  60149. pitch = Math.min(Math.max(pitch, -89.9), 89.9); // 防止万向锁
  60150. var yaw = this.yaw < 0 ? this.yaw + 360 : this.yaw;
  60151. var upDir = vec1.set(0, 1, 0);
  60152. var rightDir = vec2.set(1, 0, 0); //.applyQuaternion(this.quaternion)
  60153. var yawQuat = quat1.setFromAxisAngle(upDir, MathUtils.degToRad(yaw));
  60154. var pitchQuat = quat2.setFromAxisAngle(rightDir, MathUtils.degToRad(pitch));
  60155. this.quaternion.multiplyQuaternions(yawQuat, pitchQuat);
  60156. //this.updateTarget()
  60157. }
  60158. set yaw(yaw) {
  60159. var pitch = this.pitch; // 要先计算pitch,防止窜数据
  60160. var upDir = vec1.set(0, 1, 0);
  60161. var rightDir = vec2.set(1, 0, 0);
  60162. var yawQuat = quat1.setFromAxisAngle(upDir, MathUtils.degToRad(yaw));
  60163. var pitchQuat = quat2.setFromAxisAngle(rightDir, MathUtils.degToRad(pitch));
  60164. this.quaternion.multiplyQuaternions(yawQuat, pitchQuat);
  60165. //this.updateTarget()
  60166. }
  60167. // 横滚角
  60168. setRoll(angle) {
  60169. //因加在子物体上,非0时播放视频是歪的(4dkk也这样)
  60170. this.roll = angle % 360;
  60171. this.obj3d.quaternion.setFromAxisAngle(vec1.set(0, 0, -1), MathUtils.degToRad(angle));
  60172. }
  60173. get pitch() {
  60174. // 上下转角
  60175. return this.data.data.pitch; //xzw改
  60176. var lookAt = vec1.copy(this.cylinder.bottom.position).applyQuaternion(this.quaternion);
  60177. var projectVec = vec2.copy(lookAt).projectOnPlane(vec3.set(0, 1, 0));
  60178. var pitch = MathUtils.radToDeg(lookAt.angleTo(projectVec) * Math.sign(lookAt.y)) % 180;
  60179. if (pitch > 90) pitch = 90 - pitch;
  60180. return pitch;
  60181. }
  60182. get yaw() {
  60183. // 左右转角
  60184. return this.data.data.yaw; //xzw改 原先的计算不对,0变180
  60185. var lookAt = vec1.copy(this.cylinder.bottom.position).applyQuaternion(this.quaternion);
  60186. var lookAtXZ = lookAt.setY(0);
  60187. var frontDir = vec2.set(0, 0, 1);
  60188. var frontCross = vec3.set(1, 0, 0);
  60189. var angle = (MathUtils.radToDeg(lookAtXZ.angleTo(frontDir) * Math.sign(lookAtXZ.dot(frontCross))) + 180) % 360;
  60190. if (angle > 180) angle = angle - 360;
  60191. return angle;
  60192. }
  60193. }
  60194. function warnHls() {
  60195. var _window$Hls;
  60196. if (!window.Hls) {
  60197. console.error('没加载Hls.js文件!');
  60198. }
  60199. if (!((_window$Hls = window.Hls) !== null && _window$Hls !== void 0 && _window$Hls.isSupported())) {
  60200. //在融合页面导入hls文件
  60201. console.error('Hls is not Supported, 部分监控视频可能不支持'); //iphoneX不支持 小米Civi 1S支持。
  60202. }
  60203. }
  60204. /*
  60205. viewer.addMonitor(undefined, viewer.objs.children[0])
  60206. viewer.scene.monitors[0].leave()
  60207. */
  60208. //
  60209. // Algorithm by Christian Boucheny
  60210. // shader code taken and adapted from CloudCompare
  60211. //
  60212. // see
  60213. // https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
  60214. // http://www.kitware.com/source/home/post/9
  60215. // https://tel.archives-ouvertes.fr/tel-00438464/document p. 115+ (french)
  60216. class ExtendEyeDomeLightingMaterial extends EyeDomeLightingMaterial {
  60217. constructor() {
  60218. var parameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  60219. super(parameters);
  60220. delete this.uniforms.screenWidth;
  60221. delete this.uniforms.screenHeight;
  60222. this.uniforms.resolution = {
  60223. type: 'v2',
  60224. value: new Vector2()
  60225. };
  60226. this.uniforms.useEDL = {
  60227. type: 'i',
  60228. value: 1
  60229. };
  60230. var defines = this.getDefines();
  60231. var {
  60232. vs,
  60233. fs
  60234. } = Common$1.changeShaderToWebgl2(defines + Shaders['edl_new.vs'], defines + Shaders['edl_new.fs'], 'RawShaderMaterial');
  60235. this.glslVersion = Potree.settings.isWebgl2 && '300 es';
  60236. this.vertexShader = vs;
  60237. this.fragmentShader = fs;
  60238. /* this.vertexShader = this.getDefines() + Shaders['edl_new.vs'] //改
  60239. this.fragmentShader = this.getDefines() + Shaders['edl_new.fs'] //改 */
  60240. }
  60241. }
  60242. var copyShader = {
  60243. uniforms: {
  60244. tDiffuse: {
  60245. type: "t",
  60246. value: null
  60247. },
  60248. opacity: {
  60249. type: "f",
  60250. value: 1
  60251. },
  60252. depthTex: {
  60253. type: "t",
  60254. value: null
  60255. }
  60256. },
  60257. vertexShader: " \n varying vec2 vUv;\n void main() {\n vUv = uv; \n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }\n ",
  60258. fragmentShader: "\n #extension GL_EXT_frag_depth : enable\n uniform float opacity;\n uniform sampler2D tDiffuse;\n #if defined(GL_EXT_frag_depth) && defined(useDepth) \n uniform sampler2D depthTex;\n #endif\n \n varying vec2 vUv;\n void main() { \n #if defined(GL_EXT_frag_depth) && defined(useDepth) \n float depth = texture2D(depthTex, vUv).r;\n /* if(depth >= 1.0){ //\u8D85\u7EA7\u8FDC\uFF08\u4F46\u662F\u5728modelTex\u91CC\u6211\u628A\u5929\u7A7A\u8DDD\u79BB\u8D85\u51FAfar\u4E86\uFF0C\u6240\u4EE5\u4E0D\u5220\uFF09\n discard;\n } */\n gl_FragDepthEXT = depth; \n #endif\n \n \n \n vec4 texel = texture2D( tDiffuse, vUv );\n gl_FragColor = opacity * texel; \n \n \n } \n "
  60259. };
  60260. //import DepthTexSampler from "../custom/utils/DepthTexSampler.js";
  60261. class EDLRenderer {
  60262. //Eye-Dome Lighting 眼罩照明
  60263. constructor(viewer) {
  60264. this.viewer = viewer;
  60265. this.edlMaterial = null;
  60266. //this.rtRegular;
  60267. this.rtEDLs = new Map();
  60268. this.gl = viewer.renderer.getContext();
  60269. //反正也没用到,注释了:
  60270. //this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
  60271. viewer.addEventListener('resize', this.resize.bind(this));
  60272. this.initEDL(viewer);
  60273. }
  60274. initEDL(viewer) {
  60275. if (this.edlMaterial != null || !Features.EXT_DEPTH.isSupported()) {
  60276. return;
  60277. }
  60278. this.edlMaterial = new ExtendEyeDomeLightingMaterial();
  60279. this.edlMaterial.depthTest = true;
  60280. this.edlMaterial.depthWrite = true;
  60281. this.edlMaterial.transparent = true;
  60282. var copyUniforms = UniformsUtils.clone(copyShader.uniforms);
  60283. var {
  60284. vs,
  60285. fs
  60286. } = Common$1.changeShaderToWebgl2(copyShader.vertexShader, copyShader.fragmentShader, 'ShaderMaterial');
  60287. this.recoverToScreenMat = new ShaderMaterial({
  60288. uniforms: copyUniforms,
  60289. vertexShader: vs,
  60290. fragmentShader: fs,
  60291. transparent: true,
  60292. defines: {
  60293. useDepth: true //开启后,其他物体才能被遮挡
  60294. }
  60295. });
  60296. /* let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
  60297. this.copyMaterial = new THREE.ShaderMaterial( {
  60298. uniforms: copyUniforms,
  60299. vertexShader: copyShader.vertexShader,
  60300. fragmentShader: copyShader.fragmentShader,
  60301. //premultipliedAlpha: true,
  60302. transparent: true,
  60303. //blending: THREE.AdditiveBlending,
  60304. depthTest: false,
  60305. depthWrite: false
  60306. }); */
  60307. if (Potree.settings.useRTskybox != Potree.settings.useRTPoint) {
  60308. //如果两个只开了一个
  60309. viewer.images360.addEventListener('endChangeMode', () => {
  60310. this.resize({
  60311. viewport: viewer.mainViewport
  60312. });
  60313. });
  60314. }
  60315. //this.depthTexSampler = new DepthTexSampler(this);
  60316. }
  60317. resize(e) {
  60318. if (Features.EXT_DEPTH.isSupported()) {
  60319. var viewport = e.viewport;
  60320. var size = (Potree.settings.displayMode == 'showPanos' ? Potree.settings.useRTskybox : Potree.settings.useRTPoint) ? viewport.resolution2 : viewport.resolution; //若要渲染skybox,需要和设备一样精度的rt
  60321. this.getRtEDL(viewport).setSize(size.x, size.y); //理论上可以是任意尺寸,但会影响精度,且aspect最好和渲染的一致
  60322. }
  60323. }
  60324. clearTargets() {
  60325. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  60326. var viewer = this.viewer;
  60327. var {
  60328. renderer
  60329. } = viewer;
  60330. var oldTarget = renderer.getRenderTarget();
  60331. if (params.target) {
  60332. //add
  60333. renderer.setRenderTarget(params.target);
  60334. renderer.clear();
  60335. }
  60336. if (Features.EXT_DEPTH.isSupported()) {
  60337. var rtEDL = params.rtEDL || this.getRtEDL(params.viewport);
  60338. if (rtEDL) {
  60339. renderer.setRenderTarget(rtEDL);
  60340. var oldAlpha = renderer.getClearAlpha();
  60341. renderer.setClearAlpha(0);
  60342. renderer.clear(true, true, true);
  60343. renderer.setClearAlpha(oldAlpha);
  60344. }
  60345. }
  60346. //renderer.setRenderTarget( this.rtRegular );
  60347. //renderer.clear( true, true, false );
  60348. renderer.setRenderTarget(oldTarget);
  60349. }
  60350. getRtEDL(viewport) {
  60351. //根据不同viewport返回rtEDL的texture
  60352. if (!viewport) {
  60353. console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!');
  60354. viewport = viewer.mainViewport;
  60355. }
  60356. var rtEDL = this.rtEDLs.get(viewport);
  60357. if (!rtEDL) {
  60358. if (Features.EXT_DEPTH.isSupported()) {
  60359. rtEDL = new WebGLRenderTarget(viewport.resolution.x, viewport.resolution.y, {
  60360. minFilter: NearestFilter,
  60361. magFilter: NearestFilter,
  60362. format: RGBAFormat,
  60363. type: FloatType,
  60364. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  60365. });
  60366. //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
  60367. this.rtEDLs.set(viewport, rtEDL);
  60368. }
  60369. }
  60370. //注:当pc窗口缩小,deviceRatio变小后,resolution2会小于resolution,然后遮挡会出现精度损失而有细微不准,是正常现象。
  60371. return rtEDL;
  60372. }
  60373. renderShadowMap(visiblePointClouds, camera, lights) {
  60374. var {
  60375. viewer
  60376. } = this;
  60377. var doShadows = lights.length > 0 && !lights[0].disableShadowUpdates;
  60378. if (doShadows) {
  60379. var light = lights[0];
  60380. this.shadowMap.setLight(light);
  60381. var originalAttributes = new Map();
  60382. for (var pointcloud of viewer.scene.pointclouds) {
  60383. // TODO IMPORTANT !!! check
  60384. originalAttributes.set(pointcloud, pointcloud.material.activeAttributeName);
  60385. pointcloud.material.disableEvents();
  60386. pointcloud.material.activeAttributeName = "depth";
  60387. //pointcloud.material.pointColorType = PointColorType.DEPTH;
  60388. }
  60389. this.shadowMap.render(viewer.scene.scenePointCloud, camera);
  60390. for (var _pointcloud of visiblePointClouds) {
  60391. var originalAttribute = originalAttributes.get(_pointcloud);
  60392. // TODO IMPORTANT !!! check
  60393. _pointcloud.material.activeAttributeName = originalAttribute;
  60394. _pointcloud.material.enableEvents();
  60395. }
  60396. viewer.shadowTestCam.updateMatrixWorld();
  60397. viewer.shadowTestCam.matrixWorldInverse.copy(viewer.shadowTestCam.matrixWorld).invert();
  60398. viewer.shadowTestCam.updateProjectionMatrix();
  60399. }
  60400. }
  60401. getIfRtEDL_() {
  60402. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  60403. return (Potree.settings.pointEnableRT && Potree.settings.displayMode == 'showPointCloud' || Potree.settings.displayMode == 'showPanos' /* && viewer.images360.currentPano.pointcloud.hasDepthTex */ || viewer.useEDL) && Features.EXT_DEPTH.isSupported() && params.camera.type != "OrthographicCamera" && !params.dontRenderRtEDL && (params.rtEDL || this.getRtEDL(params.viewport)); // 平面相机不用depthTex直接打开depthTest?且不使用edl
  60404. }
  60405. getIfuseEdl() {
  60406. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  60407. return viewer.useEDL && Potree.settings.displayMode != 'showPanos';
  60408. }
  60409. canUseRTPoint() {
  60410. return Potree.settings.useRTPoint && !viewer.scene.pointclouds.some(e => e.visible && e.material.opacity < 1) && !viewer.objs.children.some(e => e.opacity < 1); //透明mesh发黑,透明无效
  60411. }
  60412. render() {
  60413. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  60414. var viewer = this.viewer;
  60415. var camera = params.camera ? params.camera : viewer.scene.getActiveCamera();
  60416. var rtEDL = this.getIfRtEDL_(params);
  60417. var useEDL = rtEDL && this.getIfuseEdl(params);
  60418. var target = params.target || null;
  60419. var resolution = rtEDL && Potree.settings.useRTPoint ? new Vector2(rtEDL.width, rtEDL.height) : params.target ? new Vector2(params.target.width, params.target.height) : params.viewport ? params.viewport.resolution2 : this.viewer.renderer.getSize(new Vector2()); //截图时需要用target的大小
  60420. var renderer = params.renderer || viewer.renderer;
  60421. var pRenderer = params.pRenderer || viewer.pRenderer;
  60422. renderer.setRenderTarget(target);
  60423. //viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
  60424. var lights = [];
  60425. /* viewer.scene.scene.traverse(node => {
  60426. if(node.type === "SpotLight"){
  60427. lights.push(node);
  60428. }
  60429. }); */
  60430. //skybox 全景图
  60431. if (!params.magnifier) {
  60432. if (Potree.settings.displayMode == 'showPanos' || Potree.settings.testCube) {
  60433. Potree.Utils.setCameraLayers(camera, ['skybox']); //注:model等也可能是skybox
  60434. if (Potree.settings.displayMode == 'showPanos' && (viewer.images360.currentPano.pointcloud.hasDepthTex || Potree.settings.modelSkybox && viewer.images360.currentPano.pointcloud.is4dkkModel) && rtEDL) {
  60435. //渲染深度图
  60436. renderer.setRenderTarget(rtEDL); //将带有深度图的skybox画在rtEDL一下,这样就不需要绘制后边的点云了
  60437. renderer.render(viewer.scene.scene, camera);
  60438. renderer.setRenderTarget(target);
  60439. if (Potree.settings.useRTskybox) {
  60440. //直接使用rtEDL,但是会失去抗锯齿,不知在skybox上需要抗锯齿吗
  60441. this.recoverToScreenMat.uniforms.depthTex.value = rtEDL.depthTexture;
  60442. this.recoverToScreenMat.uniforms.tDiffuse.value = rtEDL.texture;
  60443. Utils.screenPass.render(renderer, this.recoverToScreenMat, target);
  60444. } else {
  60445. renderer.render(viewer.scene.scene, camera);
  60446. }
  60447. } else {
  60448. renderer.render(viewer.scene.scene, camera);
  60449. }
  60450. if (Potree.settings.displayMode == 'showPanos') {
  60451. if (Potree.settings.fastTran && viewer.images360.fastTranMaskPass.enabled) {
  60452. viewer.images360.fastTranMaskPass.render();
  60453. }
  60454. //if( viewer.objs.children.length == 0 || !params.useModelOnRT ) return //没有模型需要绘制遮挡
  60455. //if(viewer.objs.children.filter(e=>!e.is4dkkModel && e.visible).length == 0)return //需要绘制遮挡的小物体(layers为model)的个数为0
  60456. } //直接绘制吧,is4dkkModel的还有monitor要绘制
  60457. }
  60458. }
  60459. var pointclouds = viewer.scene.pointclouds.filter(pc => !pc.isSplat);
  60460. var visiblePointClouds2 = pointclouds.filter(pc => pc.visible /* Potree.Utils.getObjVisiByReason(pc,'datasetSelection') */); //需要绘制到rtEDL的
  60461. var showPointClouds = params.magnifier ? visiblePointClouds2.length > 0 : pointclouds.some(e => e.visible); //是否有需要绘制到屏幕的
  60462. /* visiblePointClouds2.forEach(e=>{//为了绘制到depthTexture,先显示(展示全景图时隐藏了点云,所以需要显示下 )
  60463. e.oldVisi = e.visible
  60464. e.visible = true;
  60465. }) */
  60466. //好难写- -,太多东西了,无depTex时要把不显示的点云和模型绘制到rt上,但是rt又可能直接绘制到画面。有的模型是要在全景模式显示的
  60467. //所以决定去掉不显示的点云,无深度图的话就无遮挡 http://192.168.0.21/index.php?m=bug&f=view&bugID=49575
  60468. Potree.Utils.setCameraLayers(camera, ['pointcloud']); //设置多少都会渲染出来,因为渲染里没有sort
  60469. //camera.layers.set(Potree.config.renderLayers.pointcloud);
  60470. //TODO adapt to multiple lights
  60471. //this.renderShadowMap(visiblePointClouds2, camera, lights); //???????
  60472. {
  60473. for (var pointcloud of visiblePointClouds2) {
  60474. var material = pointcloud.material;
  60475. var octreeSize = pointcloud.pcoGeometry.boundingBox.getSize(new Vector3()).x;
  60476. material.fov = MathUtils.degToRad(camera.fov);
  60477. material.resolution = resolution;
  60478. material.spacing = pointcloud.pcoGeometry.spacing; // * Math.max(this.scale.x, this.scale.y, this.scale.z);
  60479. material.near = camera.near;
  60480. material.far = camera.far;
  60481. material.uniforms.octreeSize.value = octreeSize;
  60482. if (useEDL) {
  60483. material.useEDL = true;
  60484. //material.fakeEDL = false; //add
  60485. } else {
  60486. material.useEDL = false;
  60487. //material.fakeEDL = true; //add 使也输出深度
  60488. }
  60489. }
  60490. if (rtEDL) {
  60491. //借用rtEDL存储深度信息
  60492. renderer.setRenderTarget(rtEDL);
  60493. if (visiblePointClouds2.length > 0) {
  60494. //渲染scenePointCloud到rtEDL
  60495. pRenderer.render(viewer.scene.scenePointCloud, camera, rtEDL, {
  60496. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  60497. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume$1),
  60498. transparent: false,
  60499. // 因透明时不写深度,所以不透明。 这也导致透明时不能直接使用rtEDL绘制到屏幕
  60500. notAdditiveBlending: Potree.settings.notAdditiveBlending
  60501. });
  60502. }
  60503. if (Potree.settings.intersectOnObjs) {
  60504. Potree.Utils.setCameraLayers(camera, ['model', 'light']);
  60505. viewer.objs.traverse(e => {
  60506. if (e.material) e._OlddepthWrite = e.material.depthWrite, e.material.depthWrite = true;
  60507. }); //否则半透明的mesh无法遮住测量线
  60508. viewer.dispatchEvent({
  60509. type: "render.begin2",
  60510. viewer,
  60511. viewport: params.viewport
  60512. });
  60513. renderer.render(viewer.scene.scene, camera);
  60514. viewer.objs.traverse(e => {
  60515. if (e.material) e.material.depthWrite = e._OlddepthWrite;
  60516. });
  60517. }
  60518. }
  60519. }
  60520. //渲染到rtEDL完毕
  60521. viewer.dispatchEvent({
  60522. type: "render.pass.scene",
  60523. viewer: viewer
  60524. });
  60525. renderer.setRenderTarget(target);
  60526. /* if(!params.magnifier)visiblePointClouds2.forEach(e=>{//放大镜显示点云
  60527. e.visible = e.oldVisi
  60528. }) */
  60529. {
  60530. //绘制点云到画布
  60531. if (useEDL) {
  60532. //设置edlMaterial //Features.EXT_DEPTH不支持的话不会到这一块
  60533. if (showPointClouds) {
  60534. var uniforms = this.edlMaterial.uniforms;
  60535. uniforms.resolution.value.copy(resolution);
  60536. uniforms.edlStrength.value = viewer.edlStrength;
  60537. uniforms.radius.value = viewer.edlRadius;
  60538. uniforms.useEDL.value = 1; //add
  60539. var proj = camera.projectionMatrix;
  60540. var projArray = new Float32Array(16);
  60541. projArray.set(proj.elements);
  60542. uniforms.uProj.value = projArray;
  60543. uniforms.uEDLColor.value = rtEDL.texture;
  60544. uniforms.opacity.value = viewer.edlOpacity; // HACK
  60545. Utils.screenPass.render(renderer, this.edlMaterial, target); //相当于一个描边后期特效。 缺点: 因为target上的没有抗锯齿,所以点云在晃动镜头时会不稳定地闪烁1px位置。优点:比不打开edl少绘制一次点云,更流畅了?!
  60546. }
  60547. } else if (this.canUseRTPoint() && rtEDL) {
  60548. //半透明点云在clearAlpha为非1的状态下截图 或 在useRTPoints时绘制到屏幕上透明度不对,亮度变低 。深度值遮挡也不对。 只能在半透明时关闭一下useRTPoint
  60549. this.recoverToScreenMat.uniforms.tDiffuse.value = rtEDL.texture;
  60550. if (this.recoverToScreenMat.defines.useDepth) {
  60551. this.recoverToScreenMat.uniforms.depthTex.value = rtEDL.depthTexture;
  60552. }
  60553. Utils.screenPass.render(renderer, this.recoverToScreenMat, target /* , Potree.settings.useFxaa && viewer.composer2 */);
  60554. //这时候 params_.useModelOnRT 应该和 Potree.settings.intersectOnObjs 相等 否则出错
  60555. } else {
  60556. //渲染点云 (直接用rtEDL上的会失去抗锯齿, 导致频闪、密集时出现条纹, 自己写抗锯齿也要渲染好几次。另外透明度也要处理下)
  60557. if (showPointClouds) {
  60558. var prop = {
  60559. shadowMaps: lights.length > 0 ? [this.shadowMap] : null,
  60560. clipSpheres: viewer.scene.volumes.filter(v => v instanceof SphereVolume$1),
  60561. notAdditiveBlending: Potree.settings.notAdditiveBlending //add 否则透明的点云会挡住后面的模型。 加上这句后竟然透明不会叠加了!
  60562. };
  60563. pRenderer.render(viewer.scene.scenePointCloud, camera, null, prop);
  60564. }
  60565. }
  60566. }
  60567. /* visiblePointClouds2.forEach(e=>{
  60568. e.visible = e.oldVisi
  60569. }) */
  60570. //viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
  60571. }
  60572. /*
  60573. 渲染顺序:
  60574. 底层:背景 -> skybox(也可中间)
  60575. 中间层(含有深度信息):1 点云、marker等mesh,
  60576. 2 测量线(现在被做成借用depthTex
  60577. 顶层:maginifier
  60578. magnifier的贴图渲染不需要顶层、中间层只需要点云。
  60579. */
  60580. }
  60581. class NavigationCube extends Object3D {
  60582. constructor(viewer) {
  60583. super();
  60584. this.viewer = viewer;
  60585. var createPlaneMaterial = img => {
  60586. var material = new MeshBasicMaterial({
  60587. depthTest: true,
  60588. depthWrite: true,
  60589. side: DoubleSide
  60590. });
  60591. new TextureLoader().load(exports.resourcePath + '/textures/navigation/' + img, function (texture) {
  60592. texture.anisotropy = viewer.renderer.capabilities.getMaxAnisotropy();
  60593. material.map = texture;
  60594. material.needsUpdate = true;
  60595. });
  60596. return material;
  60597. };
  60598. var planeGeometry = new PlaneGeometry(1, 1);
  60599. this.front = new Mesh(planeGeometry, createPlaneMaterial('F.png'));
  60600. this.front.position.y = -0.5;
  60601. this.front.rotation.x = Math.PI / 2.0;
  60602. this.front.updateMatrixWorld();
  60603. this.front.name = "F";
  60604. this.add(this.front);
  60605. this.back = new Mesh(planeGeometry, createPlaneMaterial('B.png'));
  60606. this.back.position.y = 0.5;
  60607. this.back.rotation.x = Math.PI / 2.0;
  60608. this.back.updateMatrixWorld();
  60609. this.back.name = "B";
  60610. this.add(this.back);
  60611. this.left = new Mesh(planeGeometry, createPlaneMaterial('L.png'));
  60612. this.left.position.x = -0.5;
  60613. this.left.rotation.y = Math.PI / 2.0;
  60614. this.left.updateMatrixWorld();
  60615. this.left.name = "L";
  60616. this.add(this.left);
  60617. this.right = new Mesh(planeGeometry, createPlaneMaterial('R.png'));
  60618. this.right.position.x = 0.5;
  60619. this.right.rotation.y = Math.PI / 2.0;
  60620. this.right.updateMatrixWorld();
  60621. this.right.name = "R";
  60622. this.add(this.right);
  60623. this.bottom = new Mesh(planeGeometry, createPlaneMaterial('D.png'));
  60624. this.bottom.position.z = -0.5;
  60625. this.bottom.updateMatrixWorld();
  60626. this.bottom.name = "D";
  60627. this.add(this.bottom);
  60628. this.top = new Mesh(planeGeometry, createPlaneMaterial('U.png'));
  60629. this.top.position.z = 0.5;
  60630. this.top.updateMatrixWorld();
  60631. this.top.name = "U";
  60632. this.add(this.top);
  60633. this.width = 150; // in px
  60634. this.camera = new OrthographicCamera(-1, 1, 1, -1, -1, 1);
  60635. this.camera.position.copy(new Vector3(0, 0, 0));
  60636. this.camera.lookAt(new Vector3(0, 1, 0));
  60637. this.camera.updateMatrixWorld();
  60638. this.camera.rotation.order = "ZXY";
  60639. var onMouseDown = event => {
  60640. if (!this.visible) {
  60641. return;
  60642. }
  60643. this.pickedFace = null;
  60644. var mouse = new Vector2();
  60645. mouse.x = event.clientX - (window.innerWidth - this.width);
  60646. mouse.y = event.clientY;
  60647. if (mouse.x < 0 || mouse.y > this.width) return;
  60648. mouse.x = mouse.x / this.width * 2 - 1;
  60649. mouse.y = -(mouse.y / this.width) * 2 + 1;
  60650. var raycaster = new Raycaster();
  60651. raycaster.setFromCamera(mouse, this.camera);
  60652. raycaster.ray.origin.sub(this.camera.getWorldDirection(new Vector3()));
  60653. var intersects = raycaster.intersectObjects(this.children);
  60654. var minDistance = 1000;
  60655. for (var i = 0; i < intersects.length; i++) {
  60656. if (intersects[i].distance < minDistance) {
  60657. this.pickedFace = intersects[i].object.name;
  60658. minDistance = intersects[i].distance;
  60659. }
  60660. }
  60661. if (this.pickedFace) {
  60662. this.viewer.setView(this.pickedFace);
  60663. }
  60664. };
  60665. this.viewer.renderer.domElement.addEventListener('mousedown', onMouseDown, false);
  60666. }
  60667. update(rotation) {
  60668. this.camera.rotation.copy(rotation);
  60669. this.visible && this.camera.updateMatrixWorld();
  60670. }
  60671. }
  60672. /**
  60673. *
  60674. * @author sigeom sa / http://sigeom.ch
  60675. * @author Ioda-Net Sàrl / https://www.ioda-net.ch/
  60676. * @author Markus Schütz / http://potree.org
  60677. *
  60678. */
  60679. class GeoJSONExporter {
  60680. static measurementToFeatures(measurement) {
  60681. var coords = measurement.points.map(e => e.position.toArray());
  60682. var features = [];
  60683. if (coords.length === 1) {
  60684. var feature = {
  60685. type: 'Feature',
  60686. geometry: {
  60687. type: 'Point',
  60688. coordinates: coords[0]
  60689. },
  60690. properties: {
  60691. name: measurement.name
  60692. }
  60693. };
  60694. features.push(feature);
  60695. } else if (coords.length > 1 && !measurement.closed) {
  60696. var object = {
  60697. 'type': 'Feature',
  60698. 'geometry': {
  60699. 'type': 'LineString',
  60700. 'coordinates': coords
  60701. },
  60702. 'properties': {
  60703. name: measurement.name
  60704. }
  60705. };
  60706. features.push(object);
  60707. } else if (coords.length > 1 && measurement.closed) {
  60708. var _object = {
  60709. 'type': 'Feature',
  60710. 'geometry': {
  60711. 'type': 'Polygon',
  60712. 'coordinates': [[...coords, coords[0]]]
  60713. },
  60714. 'properties': {
  60715. name: measurement.name
  60716. }
  60717. };
  60718. features.push(_object);
  60719. }
  60720. if (measurement.showDistances) {
  60721. measurement.edgeLabels.forEach(label => {
  60722. var labelPoint = {
  60723. type: 'Feature',
  60724. geometry: {
  60725. type: 'Point',
  60726. coordinates: label.position.toArray()
  60727. },
  60728. properties: {
  60729. distance: label.text
  60730. }
  60731. };
  60732. features.push(labelPoint);
  60733. });
  60734. }
  60735. if (measurement.showArea) {
  60736. var point = measurement.areaLabel.position;
  60737. var labelArea = {
  60738. type: 'Feature',
  60739. geometry: {
  60740. type: 'Point',
  60741. coordinates: point.toArray()
  60742. },
  60743. properties: {
  60744. area: measurement.areaLabel.text
  60745. }
  60746. };
  60747. features.push(labelArea);
  60748. }
  60749. return features;
  60750. }
  60751. static toString(measurements) {
  60752. if (!(measurements instanceof Array)) {
  60753. measurements = [measurements];
  60754. }
  60755. measurements = measurements.filter(m => m instanceof Measure);
  60756. var features = [];
  60757. for (var measure of measurements) {
  60758. var f = GeoJSONExporter.measurementToFeatures(measure);
  60759. features = features.concat(f);
  60760. }
  60761. var geojson = {
  60762. 'type': 'FeatureCollection',
  60763. 'features': features
  60764. };
  60765. return JSON.stringify(geojson, null, '\t');
  60766. }
  60767. }
  60768. /**
  60769. *
  60770. * @author sigeom sa / http://sigeom.ch
  60771. * @author Ioda-Net Sàrl / https://www.ioda-net.ch/
  60772. * @author Markus Schuetz / http://potree.org
  60773. *
  60774. */
  60775. class DXFExporter {
  60776. static measurementPointSection(measurement) {
  60777. var position = measurement.points[0].position;
  60778. if (!position) {
  60779. return '';
  60780. }
  60781. var dxfSection = "0\nCIRCLE\n8\nlayer_point\n10\n".concat(position.x, "\n20\n").concat(position.y, "\n30\n").concat(position.z, "\n40\n1.0\n");
  60782. return dxfSection;
  60783. }
  60784. static measurementPolylineSection(measurement) {
  60785. // bit code for polygons/polylines:
  60786. // https://www.autodesk.com/techpubs/autocad/acad2000/dxf/polyline_dxf_06.htm
  60787. var geomCode = 8;
  60788. if (measurement.closed) {
  60789. geomCode += 1;
  60790. }
  60791. var dxfSection = "0\nPOLYLINE\n8\nlayer_polyline\n62\n1\n66\n1\n10\n0.0\n20\n0.0\n30\n0.0\n70\n".concat(geomCode, "\n");
  60792. var xMax = 0.0;
  60793. var yMax = 0.0;
  60794. var zMax = 0.0;
  60795. for (var point of measurement.points) {
  60796. point = point.position;
  60797. xMax = Math.max(xMax, point.x);
  60798. yMax = Math.max(yMax, point.y);
  60799. zMax = Math.max(zMax, point.z);
  60800. dxfSection += "0\nVERTEX\n8\n0\n10\n".concat(point.x, "\n20\n").concat(point.y, "\n30\n").concat(point.z, "\n70\n32\n");
  60801. }
  60802. dxfSection += "0\nSEQEND\n";
  60803. return dxfSection;
  60804. }
  60805. static measurementSection(measurement) {
  60806. // if(measurement.points.length <= 1){
  60807. // return "";
  60808. // }
  60809. if (measurement.points.length === 0) {
  60810. return '';
  60811. } else if (measurement.points.length === 1) {
  60812. return DXFExporter.measurementPointSection(measurement);
  60813. } else if (measurement.points.length >= 2) {
  60814. return DXFExporter.measurementPolylineSection(measurement);
  60815. }
  60816. }
  60817. static toString(measurements) {
  60818. if (!(measurements instanceof Array)) {
  60819. measurements = [measurements];
  60820. }
  60821. measurements = measurements.filter(m => m instanceof Measure);
  60822. var points = measurements.filter(m => m instanceof Measure).map(m => m.points).reduce((a, v) => a.concat(v)).map(p => p.position);
  60823. var min = new Vector3(Infinity, Infinity, Infinity);
  60824. var max = new Vector3(-Infinity, -Infinity, -Infinity);
  60825. for (var point of points) {
  60826. min.min(point);
  60827. max.max(point);
  60828. }
  60829. var dxfHeader = "999\nDXF created from potree\n0\nSECTION\n2\nHEADER\n9\n$ACADVER\n1\nAC1006\n9\n$INSBASE\n10\n0.0\n20\n0.0\n30\n0.0\n9\n$EXTMIN\n10\n".concat(min.x, "\n20\n").concat(min.y, "\n30\n").concat(min.z, "\n9\n$EXTMAX\n10\n").concat(max.x, "\n20\n").concat(max.y, "\n30\n").concat(max.z, "\n0\nENDSEC\n");
  60830. var dxfBody = "0\nSECTION\n2\nENTITIES\n";
  60831. for (var measurement of measurements) {
  60832. dxfBody += DXFExporter.measurementSection(measurement);
  60833. }
  60834. dxfBody += "0\nENDSEC\n";
  60835. var dxf = dxfHeader + dxfBody + '0\nEOF';
  60836. return dxf;
  60837. }
  60838. }
  60839. class HandleSvg extends EventDispatcher {
  60840. constructor(position, color) {
  60841. super();
  60842. this.position = position;
  60843. this.color = '#' + new Color(color).getHexString();
  60844. this.svg = this.create();
  60845. this.visible_ = true;
  60846. var update = () => {
  60847. this.update();
  60848. };
  60849. viewer.addEventListener("camera_changed", update);
  60850. this.addEventListener('dispose', () => {
  60851. viewer.removeEventListener("camera_changed", update);
  60852. });
  60853. }
  60854. create() {
  60855. var svgns = "http://www.w3.org/2000/svg";
  60856. var svg = document.createElementNS(svgns, "svg");
  60857. svg.setAttribute("width", "2em");
  60858. svg.setAttribute("height", "2em");
  60859. svg.setAttribute("position", "absolute");
  60860. svg.style.left = "50px";
  60861. svg.style.top = "50px";
  60862. svg.style.position = "absolute";
  60863. svg.style.zIndex = "10000";
  60864. svg.style.cursor = 'grab';
  60865. svg.style.transform = 'translate(-50%,-50%)';
  60866. var circle = document.createElementNS(svgns, 'circle');
  60867. circle.setAttributeNS(null, 'cx', "1em");
  60868. circle.setAttributeNS(null, 'cy', "1em");
  60869. circle.setAttributeNS(null, 'r', "0.5em");
  60870. circle.setAttributeNS(null, 'style', 'fill: ' + this.color + '; stroke: black; stroke-width: 0.2em;');
  60871. svg.appendChild(circle);
  60872. var element = viewer.renderer.domElement.parentElement;
  60873. element.appendChild(svg);
  60874. var startDrag = evt => {
  60875. /* if(evt.button === THREE.MOUSE.RIGHT){
  60876. return
  60877. } */
  60878. this.selectedElement = svg;
  60879. document.addEventListener("mousemove", drag);
  60880. };
  60881. var endDrag = evt => {
  60882. this.selectedElement = null;
  60883. document.removeEventListener("mousemove", drag);
  60884. };
  60885. var drag = evt => {
  60886. if (this.selectedElement) {
  60887. evt.preventDefault();
  60888. var rect = viewer.renderer.domElement.getBoundingClientRect();
  60889. var x = evt.clientX - rect.x;
  60890. var y = evt.clientY - rect.y;
  60891. var {
  60892. width,
  60893. height
  60894. } = viewer.renderer.getSize(new Vector2());
  60895. var camera = viewer.scene.getActiveCamera();
  60896. var projected = this.position.clone().project(camera);
  60897. projected.x = (x / width - 0.5) / 0.5;
  60898. projected.y = (-(y - height) / height - 0.5) / 0.5;
  60899. var unprojected = projected.clone().unproject(camera);
  60900. this.position.set(unprojected.x, unprojected.y, unprojected.z);
  60901. this.update();
  60902. this.dispatchEvent({
  60903. type: 'dragged',
  60904. position: this.position
  60905. });
  60906. }
  60907. };
  60908. svg.addEventListener('mousedown', startDrag);
  60909. svg.addEventListener('mouseup', endDrag);
  60910. svg.style.display = this.visible ? "" : "none";
  60911. this.addEventListener('dispose', () => {
  60912. svg.removeEventListener('mousedown', startDrag);
  60913. svg.removeEventListener('mouseup', endDrag);
  60914. });
  60915. return svg;
  60916. }
  60917. set visible(v) {
  60918. this.visible_ = v;
  60919. if (v) {
  60920. this.update();
  60921. } else {
  60922. this.svg.style.display = "none";
  60923. }
  60924. }
  60925. get visible() {
  60926. return this.visible_;
  60927. }
  60928. update() {
  60929. if (!this.visible) return;
  60930. var camera = viewer.scene.getActiveCamera();
  60931. var p = Potree.Utils.getPos2d(this.position, viewer.mainViewport, viewer.renderArea);
  60932. if (!p.trueSide) {
  60933. return this.svg.style.display = 'none';
  60934. }
  60935. this.svg.style.left = p.posInViewport.x;
  60936. this.svg.style.top = p.posInViewport.y;
  60937. this.svg.style.display = '';
  60938. }
  60939. dispose() {
  60940. this.svg.remove();
  60941. this.dispatchEvent('dispose');
  60942. }
  60943. }
  60944. /*
  60945. 两种拖拽方式:
  60946. 1 只依附在点云上
  60947. 2 平行于镜头view移动 */
  60948. var geo$1 = new PlaneBufferGeometry(1, 1);
  60949. class HandleSprite extends Sprite$2 {
  60950. constructor(position) {
  60951. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  60952. options.sizeInfo = {
  60953. width2d: 60
  60954. };
  60955. super(options);
  60956. this.position.copy(position);
  60957. this.dragStyle = options.dragStyle || 'default'; //'default'||'onPointCloud'
  60958. this.bindEvent();
  60959. }
  60960. bindEvent() {
  60961. var projectedStart, pointerStart;
  60962. var drag = e => {
  60963. /* if(e.hoverViewport != e.drag.dragViewport){//不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
  60964. viewer.dispatchEvent({
  60965. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  60966. })
  60967. return
  60968. } */
  60969. var camera = viewer.scene.getActiveCamera();
  60970. if (projectedStart) {
  60971. var move2d = new Vector2().subVectors(e.pointer, pointerStart);
  60972. var projectNow = projectedStart.clone();
  60973. projectNow.x += move2d.x;
  60974. projectNow.y += move2d.y;
  60975. var unprojected = projectNow.clone().unproject(camera);
  60976. this.position.set(unprojected.x, unprojected.y, unprojected.z);
  60977. } else {
  60978. projectedStart = this.position.clone().project(camera);
  60979. pointerStart = e.pointer.clone();
  60980. }
  60981. this.update();
  60982. this.dispatchEvent({
  60983. type: 'dragged',
  60984. position: this.position
  60985. });
  60986. };
  60987. var drop = e => {
  60988. projectedStart = null, pointerStart = null;
  60989. };
  60990. var mouseover = e => {
  60991. viewer.dispatchEvent({
  60992. type: "CursorChange",
  60993. action: "add",
  60994. name: "markerMove"
  60995. });
  60996. };
  60997. var mouseleave = e => {
  60998. viewer.dispatchEvent({
  60999. type: "CursorChange",
  61000. action: "remove",
  61001. name: "markerMove"
  61002. });
  61003. };
  61004. this.addEventListener('drag', drag);
  61005. this.addEventListener('drop', drop);
  61006. this.addEventListener('mouseover', mouseover);
  61007. this.addEventListener('mouseleave', mouseleave);
  61008. }
  61009. }
  61010. var sphere = new Mesh(new SphereBufferGeometry(0.08, 0.08, 3, 2), new MeshBasicMaterial({
  61011. color: '#f88'
  61012. }));
  61013. class CurveCtrl extends Object3D {
  61014. constructor(points, lineMat, color, name) {
  61015. var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  61016. super();
  61017. this.curve = new CatmullRomCurve3(points, false, options.tension == void 0 ? "centripetal" : 'catmullrom', options.tension);
  61018. this.name = name || 'curveNode';
  61019. this.handleMat = options.handleMat;
  61020. this.lineMat = lineMat;
  61021. this.createPath();
  61022. this.color = color;
  61023. this.handles = [];
  61024. this.wholeLength = 0;
  61025. this.viewports = options.viewports || [viewer.mainViewport]; //for HandleSprite
  61026. for (var i = 0, j = this.points.length; i < j; i++) {
  61027. this.handles.push(this.createHandle(this.points[i]));
  61028. }
  61029. this.visible_ = true;
  61030. if (Potree.settings.isTest) {
  61031. this.spheres = new Object3D();
  61032. /* let i = Count+1;
  61033. while(i>0){
  61034. this.spheres.add(sphere.clone());
  61035. i--;
  61036. } */
  61037. this.add(this.spheres);
  61038. }
  61039. this.updatePath();
  61040. }
  61041. addPoint(position, index, ifUpdate) {
  61042. var length = this.points.length;
  61043. if (index == void 0) {
  61044. index = length;
  61045. }
  61046. var handle = this.createHandle(position);
  61047. this.handles = [...this.handles.slice(0, index), handle, ...this.handles.slice(index, length)];
  61048. this.points = [...this.points.slice(0, index), position, ...this.points.slice(index, length)];
  61049. ifUpdate && (this.updatePath(), this.updateHandle(index));
  61050. }
  61051. removePoint(index) {
  61052. var handle = this.handles[index];
  61053. handle.dispose();
  61054. this.handles.splice(index, 1);
  61055. this.points.splice(index, 1);
  61056. this.updatePath();
  61057. }
  61058. createPath() {
  61059. var line = LineDraw.createFatLine([], this.lineMat);
  61060. this.line = line;
  61061. this.add(line);
  61062. }
  61063. updatePath() {
  61064. this.curve.needsUpdate = true; //如果不更新,得到的点不均匀,开头点少。
  61065. var points,
  61066. length = this.points.length;
  61067. this.wholeLength = this.points.reduce((total, currentValue, currentIndex, arr) => {
  61068. //所有端点的距离总和
  61069. if (currentIndex == 0) return 0;
  61070. return total + currentValue.distanceTo(arr[currentIndex - 1]);
  61071. }, 0);
  61072. if (length > 1) {
  61073. var count = MathUtils.clamp(Math.ceil(this.wholeLength * 5), 30, 500);
  61074. points = this.curve.getSpacedPoints(count);
  61075. if (this.needsPercent) {
  61076. //获取每个节点在整条中的百分比,便于定位(但不精确)
  61077. this.pointsPercent = [0];
  61078. var sums = [0];
  61079. var sum = 0,
  61080. last = points[0];
  61081. for (var i = 1; i < length; i++) {
  61082. var point = this.points[i];
  61083. sum += point.distanceTo(last); //参考getLengths函数,根据长度得到百分比
  61084. last = point;
  61085. sums.push(sum);
  61086. }
  61087. for (var _i = 1; _i < length; _i++) {
  61088. this.pointsPercent.push(sum == 0 ? _i / length : sums[_i] / sum);
  61089. }
  61090. }
  61091. if (Potree.settings.isTest) {
  61092. this.spheres.children.forEach(e => e.visible = false);
  61093. points.forEach((e, i) => {
  61094. var sphere1 = this.spheres.children[i];
  61095. if (!sphere1) {
  61096. sphere1 = sphere.clone();
  61097. this.spheres.add(sphere1);
  61098. }
  61099. sphere1.position.copy(e);
  61100. sphere1.visible = true;
  61101. });
  61102. }
  61103. } else {
  61104. points = [];
  61105. }
  61106. LineDraw.updateLine(this.line, points);
  61107. this.dispatchEvent('updatePath');
  61108. }
  61109. createHandle(position) {
  61110. if (this.handleMat) {
  61111. var handle = new HandleSprite(position, {
  61112. mat: this.handleMat,
  61113. viewports: this.viewports
  61114. });
  61115. this.add(handle);
  61116. } else {
  61117. var handle = new HandleSvg(position, this.color);
  61118. }
  61119. handle.visible = this.visible;
  61120. handle.addEventListener('dragged', e => {
  61121. var index = this.handles.indexOf(handle);
  61122. this.points[index].copy(e.position);
  61123. this.updatePath();
  61124. this.dispatchEvent({
  61125. type: 'dragCurvePoint',
  61126. index
  61127. });
  61128. });
  61129. return handle;
  61130. }
  61131. updateHandle(index) {
  61132. if (!this.visible) return;
  61133. this.handles[index].update();
  61134. }
  61135. updateHandles() {
  61136. this.handles.forEach((handle, index) => {
  61137. this.updateHandle(index);
  61138. });
  61139. }
  61140. update() {
  61141. this.updateHandles();
  61142. this.updatePath();
  61143. }
  61144. set visible(v) {
  61145. if (v != this.visible_) {
  61146. this.visible_ = v;
  61147. this.visible = v;
  61148. if (this.handles) {
  61149. this.handles.forEach(e => e.visible = v);
  61150. if (v) this.updateHandles(); //因为不可见时没更新位置
  61151. }
  61152. }
  61153. }
  61154. get visible() {
  61155. return this.visible_;
  61156. }
  61157. /* set visible(v){
  61158. this.handles.forEach(e=>e.svg.style.display = v ? "" : "none" )
  61159. if(v) this.updateHandles() //因为不可见时没更新位置
  61160. } */
  61161. get points() {
  61162. return this.curve.points;
  61163. }
  61164. set points(points) {
  61165. this.curve.points = points;
  61166. }
  61167. getPointAt(t) {
  61168. return this.curve.getPointAt(t);
  61169. }
  61170. getSpacedPoints(t) {
  61171. return this.curve.getSpacedPoints(t);
  61172. }
  61173. dispose() {
  61174. this.parent && this.parent.remove(this);
  61175. this.handles.forEach(e => e.dispose());
  61176. this.line.geometry && this.line.geometry.dispose();
  61177. }
  61178. }
  61179. var colors$1 = {
  61180. position: 'red',
  61181. target: 'blue'
  61182. };
  61183. var lastQuaternion;
  61184. var lineMats;
  61185. var getLineMat = function getLineMat(name) {
  61186. if (!lineMats) {
  61187. lineMats = {
  61188. position: LineDraw.createFatLineMat({
  61189. color: colors$1.position,
  61190. lineWidth: 3
  61191. }),
  61192. target: LineDraw.createFatLineMat({
  61193. color: colors$1.target,
  61194. lineWidth: 3
  61195. }),
  61196. frustum: LineDraw.createFatLineMat({
  61197. color: colors$1.position,
  61198. lineWidth: 2
  61199. }),
  61200. aimAtTarget: new LineBasicMaterial({
  61201. color: colors$1.target,
  61202. depthTest: false
  61203. })
  61204. };
  61205. }
  61206. return lineMats[name];
  61207. };
  61208. class CameraAnimation$1 extends EventDispatcher {
  61209. constructor(viewer, tension) {
  61210. super();
  61211. this.viewer = viewer;
  61212. this.selectedElement = null;
  61213. //this.controlPoints = [];
  61214. this.uuid = MathUtils.generateUUID();
  61215. this.node = new Object3D();
  61216. this.node.name = "camera animation";
  61217. this.viewer.scene.scene.add(this.node);
  61218. this.frustum = this.createFrustum();
  61219. this.node.add(this.frustum);
  61220. this.name = "Camera Animation";
  61221. // "centripetal", "chordal", "catmullrom"
  61222. this.curveType = "centripetal";
  61223. this.visible = true;
  61224. this.targets = [];
  61225. this.createPath(tension);
  61226. this.duration = 5;
  61227. this.percent = 0;
  61228. this.currentIndex = 0;
  61229. this.durations = [];
  61230. this.quaternions = [];
  61231. if (!Potree.settings.isTest && Potree.settings.isOfficial) {
  61232. this.setVisible(false);
  61233. }
  61234. this.addEventListener('dispose', () => {
  61235. this.dispose();
  61236. });
  61237. this.targetLines = new Object3D();
  61238. this.node.add(this.targetLines);
  61239. }
  61240. static defaultFromView(viewer) {
  61241. var animation = new CameraAnimation$1(viewer);
  61242. var camera = viewer.scene.getActiveCamera();
  61243. var target = viewer.scene.view.getPivot();
  61244. var cpCenter = new Vector3(0.3 * camera.position.x + 0.7 * target.x, 0.3 * camera.position.y + 0.7 * target.y, 0.3 * camera.position.z + 0.7 * target.z);
  61245. var targetCenter = new Vector3(0.05 * camera.position.x + 0.95 * target.x, 0.05 * camera.position.y + 0.95 * target.y, 0.05 * camera.position.z + 0.95 * target.z);
  61246. var r = 2; //camera.position.distanceTo(target) * 0.3;
  61247. //const dir = target.clone().sub(camera.position).normalize();
  61248. var angle = Utils.computeAzimuth(camera.position, target);
  61249. var n = 5;
  61250. for (var i = 0; i < n; i++) {
  61251. var u = 1.5 * Math.PI * (i / n) + angle;
  61252. var dx = r * Math.cos(u);
  61253. var dy = r * Math.sin(u);
  61254. var cpPos = new Vector3(cpCenter.x + dx, cpCenter.y + dy, cpCenter.z);
  61255. var targetPos = new Vector3(targetCenter.x + dx * 0.1, targetCenter.y + dy * 0.1, targetCenter.z);
  61256. animation.createControlPoint(null, {
  61257. position: cpPos,
  61258. target: targetPos
  61259. });
  61260. }
  61261. animation.changeCallback();
  61262. return animation;
  61263. }
  61264. createControlPoint(index, posInfo) {
  61265. var length = this.posCurve.points.length;
  61266. var position = new Vector3();
  61267. var target = new Vector3();
  61268. if (index == void 0) {
  61269. index = length;
  61270. }
  61271. if (!posInfo) {
  61272. if (length >= 2 && index === 0) {
  61273. var dir = new Vector3().subVectors(this.posCurve.points[0], this.posCurve.points[1]);
  61274. position.copy(this.posCurve.points[0]).add(dir);
  61275. var tDir = new Vector3().subVectors(this.targets[0].position, this.targets[1].position);
  61276. target.copy(this.targets[0].position).add(dir);
  61277. } else if (length >= 2 && index === length) {
  61278. var _dir = new Vector3().subVectors(this.posCurve.points[length - 1], this.posCurve.points[length - 2]);
  61279. position.copy(this.posCurve.points[length - 2]).add(_dir);
  61280. var _tDir = new Vector3().subVectors(this.targets[length - 1].position, this.targets[length - 2].position);
  61281. target.copy(this.targets[length - 2].position).add(_dir);
  61282. } else if (length >= 2) {
  61283. position.copy(this.posCurve.points[index - 1].clone().add(this.posCurve.points[index]).multiplyScalar(0.5));
  61284. target.copy(this.targets[index - 1].position.clone().add(this.targets[index].position).multiplyScalar(0.5));
  61285. }
  61286. } else {
  61287. position.copy(posInfo.position);
  61288. target.copy(posInfo.target);
  61289. }
  61290. this.posCurve.addPoint(position, index /* , true */);
  61291. //this.targetCurve.addPoint(target, index/* , true */)
  61292. var targetSvg = new HandleSvg(target, colors$1.target);
  61293. targetSvg.visible = this.visible;
  61294. this.targets = [...this.targets.slice(0, index), targetSvg, ...this.targets.slice(index, length)];
  61295. if (this.useDurSlice) {
  61296. //不使用全局的duration,而是分段的
  61297. this.durations = [...this.durations.slice(0, index), posInfo.duration, ...this.durations.slice(index, length)];
  61298. }
  61299. this.dispatchEvent({
  61300. type: "controlpoint_added",
  61301. index
  61302. });
  61303. {
  61304. var targetLine = LineDraw.createLine([position, target], {
  61305. mat: getLineMat('aimAtTarget')
  61306. });
  61307. this.targetLines.children = [...this.targetLines.children.slice(0, index), targetLine, ...this.targetLines.children.slice(index, length)];
  61308. this.targets[index].addEventListener('dragged', e => {
  61309. this.updatePathCallback();
  61310. this.dragPointCallback(e);
  61311. });
  61312. }
  61313. }
  61314. dragPointCallback(e) {
  61315. var index = e.index;
  61316. if (e.index == void 0) {
  61317. index = this.targets.indexOf(e.target);
  61318. }
  61319. LineDraw.moveLine(this.targetLines.children[index], [this.posCurve.points[index], this.targets[index].position]);
  61320. viewer.dispatchEvent('content_changed');
  61321. this.updateFrustum();
  61322. }
  61323. updatePathCallback() {
  61324. {
  61325. this.quaternions = [];
  61326. var length = this.posCurve.points.length;
  61327. for (var i = 0; i < length; i++) {
  61328. var quaternion = math.getQuaFromPosAim(this.posCurve.points[i], this.targets[i].position);
  61329. this.quaternions.push(quaternion);
  61330. }
  61331. }
  61332. this.reMapCurvePercent();
  61333. }
  61334. removeControlPoint(index) {
  61335. this.posCurve.removePoint(index);
  61336. //this.targetCurve.removePoint(index)
  61337. this.targets[index].dispose();
  61338. this.targets.splice(index, 1);
  61339. this.dispatchEvent({
  61340. type: "controlpoint_removed",
  61341. index
  61342. });
  61343. this.targetLines.remove(this.targetLines.children[index]);
  61344. if (this.useDurSlice) {
  61345. this.durations.splice(index, 1);
  61346. }
  61347. }
  61348. createPath(tension) {
  61349. this.posCurve = new CurveCtrl([], getLineMat('position'), colors$1.position, 'posCurve', {
  61350. tension
  61351. });
  61352. //this.targetCurve = new CurveCtrl([], getLineMat('target'), colors.target, 'targetCurve', {noLine:true});
  61353. this.posCurve.needsPercent = true;
  61354. this.node.add(this.posCurve);
  61355. //this.node.add(this.targetCurve)
  61356. this.posCurve.addEventListener('dragCurvePoint', this.dragPointCallback.bind(this));
  61357. this.posCurve.addEventListener('updatePath', this.updatePathCallback.bind(this));
  61358. }
  61359. createFrustum() {
  61360. var f = 0.3;
  61361. var positions = [new Vector3(0, 0, 0), new Vector3(-f, -f, +1), new Vector3(0, 0, 0), new Vector3(f, -f, +1), new Vector3(0, 0, 0), new Vector3(f, f, +1), new Vector3(0, 0, 0), new Vector3(-f, f, +1), new Vector3(-f, -f, +1), new Vector3(f, -f, +1), new Vector3(f, -f, +1), new Vector3(f, f, +1), new Vector3(f, f, +1), new Vector3(-f, f, +1), new Vector3(-f, f, +1), new Vector3(-f, -f, +1)];
  61362. positions.forEach(e => e.z *= -1); //因为得到的rotation是camera的,作用在物体上要反向,所以这里反向一下
  61363. //geometry.computeBoundingSphere();//?
  61364. var line = LineDraw.createFatLine(positions, {
  61365. mat: getLineMat('frustum')
  61366. });
  61367. //line.scale.set(20, 20, 20);
  61368. line.visible = false;
  61369. return line;
  61370. }
  61371. reMapCurvePercent() {
  61372. //因在不同点在相同位置旋转,由于间隔仅和位置距离相关,导致时间间隔为0,采取重新调整间隔的策略。
  61373. var length = this.posCurve.points.length;
  61374. if (length < 2) {
  61375. return this.newPointsPercents = [];
  61376. }
  61377. var newPercents = [0];
  61378. if (this.useDurSlice) {
  61379. //已经设定好了每一段的duration的话
  61380. var sums = [0];
  61381. var sum = 0,
  61382. last;
  61383. for (var i = 0; i < length - 1; i++) {
  61384. //去掉最后一个duration,因为已到终点
  61385. var duration = this.durations[i];
  61386. sum += duration;
  61387. last = duration;
  61388. sums.push(sum);
  61389. }
  61390. for (var _i = 1; _i < length; _i++) {
  61391. newPercents.push(sum == 0 ? _i / length : sums[_i] / sum);
  61392. }
  61393. } else {
  61394. var maxSpaceDur = this.duration / length; //每两点之间修改间隔时间后,最大时间
  61395. var durPerRad = 0.8; //每弧度应该占用的时间
  61396. var minSpaceDur = Math.min(0.8, maxSpaceDur); //每两点之间修改间隔时间后,最小时间
  61397. var maxAngleSpaceDur = MathUtils.clamp(durPerRad * Math.PI, minSpaceDur, maxSpaceDur); // 最大可能差距是180度
  61398. var percents = this.posCurve.pointsPercent;
  61399. for (var _i2 = 1; _i2 < length; _i2++) {
  61400. var diff = (percents[_i2] - percents[_i2 - 1]) * this.duration; //间隔时间
  61401. var percent = void 0;
  61402. var curMin = minSpaceDur;
  61403. if (diff < maxAngleSpaceDur) {
  61404. //若小于最大旋转时间
  61405. var rad = this.quaternions[_i2].angleTo(this.quaternions[_i2 - 1]);
  61406. curMin = MathUtils.clamp(rad * durPerRad, minSpaceDur, maxSpaceDur);
  61407. }
  61408. diff = Math.max(diff, curMin);
  61409. percent = newPercents[_i2 - 1] + diff / this.duration; //得到新的percent
  61410. newPercents.push(percent);
  61411. }
  61412. var maxPercent = newPercents[length - 1]; //最后一个,若扩充过时间,就会>1
  61413. if (!math.closeTo(maxPercent, 1)) {
  61414. var scale = 1 / maxPercent; //需要压缩的比例 <1 这一步会让实际得到的间隔更小
  61415. newPercents = newPercents.map(e => e *= scale);
  61416. }
  61417. }
  61418. this.newPointsPercents = newPercents;
  61419. //console.log(newPercents)
  61420. }
  61421. at(originPercent, delta, transitionRatio) {
  61422. originPercent = MathUtils.clamp(originPercent, 0, 1);
  61423. //修改第一层:起始时间
  61424. var percent = originPercent;
  61425. /* const easePercent = 0.3; //缓动占比 //如果能在所有从静止到运动的中间加缓动就好了呀:lastPos * 0.9 + currentPos * 0.1 ?
  61426. if(originPercent < easePercent){
  61427. console.log('easeIn')
  61428. percent = easing.easeInSine(originPercent, 0, easePercent, easePercent) //currentTime, startY, wholeY, duration 选了一个衔接时接近斜率1的缓动函数
  61429. }else if(originPercent > 1-easePercent){
  61430. console.log('easeOut')
  61431. percent = easing.easeOutSine(originPercent-(1-easePercent), 1-easePercent, easePercent, easePercent)
  61432. } */
  61433. var quaternion, position;
  61434. if (this.quaFromCurveTan) {
  61435. //沿着curve行走,目视curve前方
  61436. position = this.posCurve.getPointAt(percent);
  61437. var percent2 = percent + (this.tangentDt || 0.001);
  61438. if (percent2 <= 1) {
  61439. var position2 = this.posCurve.getPointAt(percent2);
  61440. quaternion = math.getQuaFromPosAim(position, position2);
  61441. } else {
  61442. quaternion = lastQuaternion;
  61443. }
  61444. } else {
  61445. if (percent < 1) {
  61446. //修改第二层:使用每个点的重定位的 newPointsPercents
  61447. this.currentIndex = this.newPointsPercents.findIndex(e => e > percent) - 1;
  61448. //假设每个节点的百分比是精确的,那么:
  61449. var curIndexPercent = this.newPointsPercents[this.currentIndex];
  61450. var nextIndexPercent = this.newPointsPercents[this.currentIndex + 1];
  61451. var progress = (percent - curIndexPercent) / (nextIndexPercent - curIndexPercent); //在这两个节点间的百分比
  61452. var endQuaternion = this.quaternions[this.currentIndex + 1];
  61453. var startQuaternion = this.quaternions[this.currentIndex];
  61454. quaternion = new Quaternion().copy(startQuaternion);
  61455. lerp.quaternion(quaternion, endQuaternion)(progress);
  61456. //投影到原本的 posCurve.pointsPercent上:
  61457. var curIndexOriPercent = this.posCurve.pointsPercent[this.currentIndex];
  61458. var nextIndexOriPercent = this.posCurve.pointsPercent[this.currentIndex + 1];
  61459. percent = curIndexOriPercent + (nextIndexOriPercent - curIndexOriPercent) * progress;
  61460. /* if(this.posInterpolate){
  61461. let endPos = this.posCurve.points[this.currentIndex+1]
  61462. let startPos = this.posCurve.points[this.currentIndex]
  61463. position = (new THREE.Vector3()).copy(startPos)
  61464. lerp.vector(position, endPos)(progress)
  61465. } */
  61466. position = this.posCurve.getPointAt(percent); // 需要this.posCurve.points.length>1 否则报错
  61467. } else {
  61468. this.currentIndex = this.posCurve.points.length - 1;
  61469. quaternion = this.quaternions[this.currentIndex];
  61470. position = this.posCurve.points[this.currentIndex];
  61471. }
  61472. }
  61473. lastQuaternion = quaternion;
  61474. //console.log(this.currentIndex, originPercent)
  61475. //缓动:
  61476. var aimQua, aimPos;
  61477. if (delta != void 0) {
  61478. if (Potree.settings.tourTestCameraMove) {
  61479. aimQua = this.frustum.quaternion.clone();
  61480. aimPos = this.frustum.position.clone();
  61481. } else {
  61482. var camera = viewer.scene.getActiveCamera();
  61483. aimQua = camera.quaternion.clone();
  61484. aimPos = camera.position.clone();
  61485. }
  61486. transitionRatio = transitionRatio || 1 / (this.cameraAniSmoothRatio || Potree.settings.cameraAniSmoothRatio); //渐变系数,越小缓动程度越高,越平滑
  61487. transitionRatio *= delta * 60; //假设标准帧率为60fps,当帧率低时(delta大时) 降低缓动。速度快时缓动太高会偏移路径
  61488. //console.log(transitionRatio, delta) //画面ui变化会使delta变大
  61489. transitionRatio = MathUtils.clamp(transitionRatio, 0, 1);
  61490. lerp.quaternion(aimQua, quaternion)(transitionRatio); //每次只改变一点点
  61491. lerp.vector(aimPos, position)(transitionRatio);
  61492. } else {
  61493. aimQua = quaternion;
  61494. aimPos = position;
  61495. }
  61496. var rotation = new Euler().setFromQuaternion(aimQua);
  61497. var frame = {
  61498. position: aimPos,
  61499. rotation
  61500. };
  61501. return frame;
  61502. }
  61503. set(percent) {
  61504. this.percent = percent;
  61505. }
  61506. setVisible(visible) {
  61507. this.node.visible = visible;
  61508. this.posCurve.visible = visible;
  61509. this.targets.forEach(e => e.visible = visible);
  61510. this.visible = visible;
  61511. }
  61512. setDuration(duration) {
  61513. if (duration != this.duration) {
  61514. this.duration = duration;
  61515. if (this.quaternions.length == this.posCurve.points.length) this.reMapCurvePercent();
  61516. }
  61517. }
  61518. getDuration(duration) {
  61519. return this.duration;
  61520. }
  61521. play() {
  61522. var startOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  61523. if (this.onUpdate) {
  61524. return console.error('已经开始播放');
  61525. }
  61526. var startPercent = 0,
  61527. currentIndex = 0;
  61528. if (startOptions.percent != void 0) {
  61529. startPercent = startOptions.percent;
  61530. } else if (startOptions.index) {
  61531. currentIndex = index;
  61532. //startPercent = index/(this.posCurve.points.length-1)
  61533. startPercent = this.posCurve.pointsPercent[index];
  61534. }
  61535. //const tStart = performance.now();
  61536. var duration = this.duration;
  61537. this.originalyVisible = this.visible;
  61538. Potree.settings.tourTestCameraMove || this.setVisible(false);
  61539. var tStart,
  61540. startTransitionRatio = 0.2;
  61541. var startDelay = 1 / startTransitionRatio / 20; //s 因为缓动所以延迟开始,前面前都是at(0),使过渡到开始点位(但是依旧不能准确停在起始点,因为缓动是乘百分比有残留。所以直接平滑衔接到开始后的位置)
  61542. var hasPlayedTime = 0;
  61543. var finishDelay = Potree.settings.cameraAniSmoothRatio / 60 * 3; //结束后还需要多久时间才能大致达到缓动的最终目标
  61544. var hasStoppedTime = 0;
  61545. this.onUpdate = e => {
  61546. if (this.posCurve.points.length < 2) {
  61547. if (this.posCurve.points.length == 1) {
  61548. viewer.scene.view.position.copy(this.posCurve.points[0]);
  61549. viewer.scene.view.rotation = new Euler().setFromQuaternion(this.quaternions[0]);
  61550. }
  61551. this.pause();
  61552. return;
  61553. }
  61554. var percent, transitionRatio;
  61555. if (tStart) {
  61556. var tNow = performance.now();
  61557. var elapsed = (tNow - tStart) / 1000;
  61558. percent = elapsed / duration + startPercent;
  61559. } else {
  61560. //从当前位置过渡到开始位置
  61561. percent = 0; //因为at函数里有缓动措施,所以只需要设置位置在初始点即可。
  61562. hasPlayedTime += e.delta;
  61563. transitionRatio = startTransitionRatio;
  61564. // console.log('延迟开始')
  61565. if (hasPlayedTime > startDelay) {
  61566. tStart = performance.now();
  61567. }
  61568. }
  61569. this.set(percent);
  61570. var frame = this.at(percent, e.delta, transitionRatio);
  61571. if (currentIndex != this.currentIndex) {
  61572. currentIndex = this.currentIndex;
  61573. console.log('updateCurrentIndex', currentIndex);
  61574. this.dispatchEvent({
  61575. type: 'updateCurrentIndex',
  61576. currentIndex
  61577. });
  61578. }
  61579. if (!Potree.settings.tourTestCameraMove) {
  61580. viewer.scene.view.position.copy(frame.position);
  61581. //viewer.scene.view.lookAt(frame.target);
  61582. viewer.scene.view.rotation = frame.rotation;
  61583. }
  61584. this.updateFrustum(frame);
  61585. if (percent >= 1) {
  61586. if (hasStoppedTime > finishDelay) {
  61587. this.pause();
  61588. } else {
  61589. hasStoppedTime += e.delta;
  61590. //console.log('延迟结束')
  61591. }
  61592. }
  61593. };
  61594. this.viewer.addEventListener("update", this.onUpdate);
  61595. }
  61596. pause() {
  61597. this.setVisible(this.originalyVisible);
  61598. this.viewer.removeEventListener("update", this.onUpdate);
  61599. this.dispatchEvent('playDone');
  61600. this.onUpdate = null;
  61601. }
  61602. updateFrustum(frame) {
  61603. var frustum = this.frustum;
  61604. if (this.posCurve.points.length > 1) {
  61605. frustum.visible = true;
  61606. } else {
  61607. frustum.visible = false;
  61608. return;
  61609. }
  61610. frame = frame || this.at(this.percent);
  61611. frustum.position.copy(frame.position);
  61612. //frustum.lookAt(...frame.target.toArray());
  61613. frustum.rotation.copy(frame.rotation);
  61614. viewer.dispatchEvent('content_changed');
  61615. }
  61616. changeCallback(i) {
  61617. this.posCurve.update();
  61618. //this.targets.forEach(e=>e.update())
  61619. this.updatePathCallback();
  61620. if (i == void 0) {
  61621. var length = this.posCurve.points.length;
  61622. for (var _i3 = 0; _i3 < length; _i3++) {
  61623. this.dragPointCallback({
  61624. index: _i3
  61625. });
  61626. }
  61627. } else this.dragPointCallback({
  61628. index: i
  61629. });
  61630. this.updateFrustum();
  61631. }
  61632. dispose() {
  61633. //add
  61634. this.posCurve.dispose();
  61635. //this.targetCurve.dispatchEvent({type:'dispose'})
  61636. this.targets.forEach(e => e.dispose());
  61637. this.durations = [];
  61638. this.node.parent.remove(this.node);
  61639. }
  61640. }
  61641. //scene.removeCameraAnimation
  61642. //修改:不使用targetCurve作为target曲线,因为播放时posCuve的节点和targetCurve并没有对应,且使用target的曲线会使角度变化大的情况过渡生硬。
  61643. // 改完旋转了。但是位置也有问题。速度完全和路程相关,当在同一位置设置多点时,这段的总时长为0. (是否要设置最小时长?不过也做不到 - -)
  61644. class MeasurePanel {
  61645. constructor(viewer, measurement, propertiesPanel) {
  61646. this.viewer = viewer;
  61647. this.measurement = measurement;
  61648. this.propertiesPanel = propertiesPanel;
  61649. this._update = () => {
  61650. this.update();
  61651. };
  61652. }
  61653. createCoordinatesTable(points) {
  61654. var _this = this;
  61655. var table = $("\n\t\t\t<table class=\"measurement_value_table\">\n\t\t\t\t<tr>\n\t\t\t\t\t<th>x</th>\n\t\t\t\t\t<th>y</th>\n\t\t\t\t\t<th>z</th>\n\t\t\t\t\t<th></th>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t");
  61656. var copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  61657. var _loop = function _loop(point) {
  61658. var x = Utils.addCommas(point.x.toFixed(3));
  61659. var y = Utils.addCommas(point.y.toFixed(3));
  61660. var z = Utils.addCommas(point.z.toFixed(3));
  61661. var row = $("\n\t\t\t\t<tr>\n\t\t\t\t\t<td><span>".concat(x, "</span></td>\n\t\t\t\t\t<td><span>").concat(y, "</span></td>\n\t\t\t\t\t<td><span>").concat(z, "</span></td>\n\t\t\t\t\t<td align=\"right\" style=\"width: 25%\">\n\t\t\t\t\t\t<img name=\"copy\" title=\"copy\" class=\"button-icon\" src=\"").concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t"));
  61662. _this.elCopy = row.find("img[name=copy]");
  61663. _this.elCopy.click(() => {
  61664. var msg = point.toArray().map(c => c.toFixed(3)).join(", ");
  61665. Utils.clipboardCopy(msg);
  61666. _this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  61667. duration: 3000
  61668. });
  61669. });
  61670. table.append(row);
  61671. };
  61672. for (var point of points) {
  61673. _loop(point);
  61674. }
  61675. return table;
  61676. }
  61677. createAttributesTable() {
  61678. var elTable = $('<table class="measurement_value_table"></table>');
  61679. var point = this.measurement.points[0];
  61680. /* for(let attributeName of Object.keys(point)){
  61681. if(attributeName === "position"){
  61682. }else if(attributeName === "rgba"){
  61683. let color = point.rgba;
  61684. let text = color.join(', ');
  61685. elTable.append($(`
  61686. <tr>
  61687. <td>rgb</td>
  61688. <td>${text}</td>
  61689. </tr>
  61690. `));
  61691. }else{
  61692. let value = point[attributeName];
  61693. let text = value.join(', ');
  61694. elTable.append($(`
  61695. <tr>
  61696. <td>${attributeName}</td>
  61697. <td>${text}</td>
  61698. </tr>
  61699. `));
  61700. }
  61701. } */
  61702. return elTable;
  61703. }
  61704. update() {}
  61705. }
  61706. ;
  61707. class DistancePanel extends MeasurePanel {
  61708. constructor(viewer, measurement, propertiesPanel) {
  61709. super(viewer, measurement, propertiesPanel);
  61710. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61711. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<table id=\"distances_table\" class=\"measurement_value_table\"></table>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<input type=\"button\" name=\"make_profile\" value=\"profile from measure\" />\n\t\t\t\t\t</span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61712. this.elRemove = this.elContent.find("img[name=remove]");
  61713. this.elRemove.click(() => {
  61714. this.viewer.scene.removeMeasurement(measurement);
  61715. });
  61716. this.elMakeProfile = this.elContent.find("input[name=make_profile]");
  61717. this.elMakeProfile.click(() => {
  61718. //measurement.points;
  61719. var profile = new Profile();
  61720. profile.name = measurement.name;
  61721. profile.width = measurement.getTotalDistance() / 50;
  61722. for (var point of measurement.points) {
  61723. profile.addMarker(point.position.clone());
  61724. }
  61725. this.viewer.scene.addProfile(profile);
  61726. });
  61727. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61728. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61729. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61730. this.update();
  61731. }
  61732. update() {
  61733. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61734. elCoordiantesContainer.empty();
  61735. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61736. var positions = this.measurement.points.map(p => p.position);
  61737. var distances = [];
  61738. for (var i = 0; i < positions.length - 1; i++) {
  61739. var d = positions[i].distanceTo(positions[i + 1]);
  61740. distances.push(d.toFixed(3));
  61741. }
  61742. var totalDistance = this.measurement.getTotalDistance().toFixed(3);
  61743. var elDistanceTable = this.elContent.find("#distances_table");
  61744. elDistanceTable.empty();
  61745. for (var _i = 0; _i < distances.length; _i++) {
  61746. var label = _i === 0 ? 'Distances: ' : '';
  61747. var distance = distances[_i];
  61748. var elDistance = $("\n\t\t\t\t<tr>\n\t\t\t\t\t<th>".concat(label, "</th>\n\t\t\t\t\t<td style=\"width: 100%; padding-left: 10px\">").concat(distance, "</td>\n\t\t\t\t</tr>"));
  61749. elDistanceTable.append(elDistance);
  61750. }
  61751. var elTotal = $("\n\t\t\t<tr>\n\t\t\t\t<th>Total: </td><td style=\"width: 100%; padding-left: 10px\">".concat(totalDistance, "</th>\n\t\t\t</tr>"));
  61752. elDistanceTable.append(elTotal);
  61753. }
  61754. }
  61755. ;
  61756. class PointPanel extends MeasurePanel {
  61757. constructor(viewer, measurement, propertiesPanel) {
  61758. super(viewer, measurement, propertiesPanel);
  61759. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61760. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<span class=\"attributes_table_container\"></span>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61761. this.elRemove = this.elContent.find("img[name=remove]");
  61762. this.elRemove.click(() => {
  61763. this.viewer.scene.removeMeasurement(measurement);
  61764. });
  61765. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61766. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61767. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61768. this.update();
  61769. }
  61770. update() {
  61771. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61772. elCoordiantesContainer.empty();
  61773. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  61774. var elAttributesContainer = this.elContent.find('.attributes_table_container');
  61775. elAttributesContainer.empty();
  61776. elAttributesContainer.append(this.createAttributesTable());
  61777. }
  61778. }
  61779. ;
  61780. class AreaPanel extends MeasurePanel {
  61781. constructor(viewer, measurement, propertiesPanel) {
  61782. super(viewer, measurement, propertiesPanel);
  61783. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61784. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<span style=\"font-weight: bold\">Area: </span>\n\t\t\t\t<span id=\"measurement_area\"></span>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  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. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61796. elCoordiantesContainer.empty();
  61797. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  61798. var elArea = this.elContent.find("#measurement_area");
  61799. elArea.html(this.measurement.area.value.toFixed(3));
  61800. }
  61801. }
  61802. ;
  61803. class AnglePanel extends MeasurePanel {
  61804. constructor(viewer, measurement, propertiesPanel) {
  61805. super(viewer, measurement, propertiesPanel);
  61806. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61807. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<table class=\"measurement_value_table\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>\u03B1</th>\n\t\t\t\t\t\t<th>\u03B2</th>\n\t\t\t\t\t\t<th>\u03B3</th>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_alpha\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_betta\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_gamma\" style=\"width: 33%\"></td>\n\t\t\t\t\t</tr>\n\t\t\t\t</table>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61808. this.elRemove = this.elContent.find("img[name=remove]");
  61809. this.elRemove.click(() => {
  61810. this.viewer.scene.removeMeasurement(measurement);
  61811. });
  61812. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61813. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61814. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61815. this.update();
  61816. }
  61817. update() {
  61818. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61819. elCoordiantesContainer.empty();
  61820. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61821. var angles = [];
  61822. for (var i = 0; i < this.measurement.points.length; i++) {
  61823. angles.push(this.measurement.getAngle(i) * (180.0 / Math.PI));
  61824. }
  61825. angles = angles.map(a => a.toFixed(1) + '\u00B0');
  61826. var elAlpha = this.elContent.find("#angle_cell_alpha");
  61827. var elBetta = this.elContent.find("#angle_cell_betta");
  61828. var elGamma = this.elContent.find("#angle_cell_gamma");
  61829. elAlpha.html(angles[0]);
  61830. elBetta.html(angles[1]);
  61831. elGamma.html(angles[2]);
  61832. }
  61833. }
  61834. ;
  61835. class CirclePanel extends MeasurePanel {
  61836. constructor(viewer, measurement, propertiesPanel) {
  61837. super(viewer, measurement, propertiesPanel);
  61838. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61839. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<table id=\"infos_table\" class=\"measurement_value_table\"></table>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61840. this.elRemove = this.elContent.find("img[name=remove]");
  61841. this.elRemove.click(() => {
  61842. this.viewer.scene.removeMeasurement(measurement);
  61843. });
  61844. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61845. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61846. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61847. this.update();
  61848. }
  61849. update() {
  61850. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61851. elCoordiantesContainer.empty();
  61852. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61853. var elInfos = this.elContent.find("#infos_table");
  61854. if (this.measurement.points.length !== 3) {
  61855. elInfos.empty();
  61856. return;
  61857. }
  61858. var A = this.measurement.points[0].position;
  61859. var B = this.measurement.points[1].position;
  61860. var C = this.measurement.points[2].position;
  61861. var center = Potree.Utils.computeCircleCenter(A, B, C);
  61862. var radius = center.distanceTo(A);
  61863. var circumference = 2 * Math.PI * radius;
  61864. var format = number => {
  61865. return Potree.Utils.addCommas(number.toFixed(3));
  61866. };
  61867. var txtCenter = "".concat(format(center.x), " ").concat(format(center.y), " ").concat(format(center.z));
  61868. var txtRadius = format(radius);
  61869. var txtCircumference = format(circumference);
  61870. var thStyle = "style=\"text-align: left\"";
  61871. var tdStyle = "style=\"width: 100%; padding: 5px;\"";
  61872. elInfos.html("\n\t\t\t<tr>\n\t\t\t\t<th ".concat(thStyle, ">Center: </th>\n\t\t\t\t<td ").concat(tdStyle, "></td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td ").concat(tdStyle, " colspan=\"2\">\n\t\t\t\t\t").concat(txtCenter, "\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<th ").concat(thStyle, ">Radius: </th>\n\t\t\t\t<td ").concat(tdStyle, ">").concat(txtRadius, "</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<th ").concat(thStyle, ">Circumference: </th>\n\t\t\t\t<td ").concat(tdStyle, ">").concat(txtCircumference, "</td>\n\t\t\t</tr>\n\t\t"));
  61873. }
  61874. }
  61875. ;
  61876. class HeightPanel extends MeasurePanel {
  61877. constructor(viewer, measurement, propertiesPanel) {
  61878. super(viewer, measurement, propertiesPanel);
  61879. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61880. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<span id=\"height_label\">Height: </span><br>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61881. this.elRemove = this.elContent.find("img[name=remove]");
  61882. this.elRemove.click(() => {
  61883. this.viewer.scene.removeMeasurement(measurement);
  61884. });
  61885. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  61886. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  61887. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  61888. this.update();
  61889. }
  61890. update() {
  61891. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  61892. elCoordiantesContainer.empty();
  61893. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
  61894. {
  61895. var points = this.measurement.points;
  61896. var sorted = points.slice().sort((a, b) => a.position.z - b.position.z);
  61897. var lowPoint = sorted[0].position.clone();
  61898. var highPoint = sorted[sorted.length - 1].position.clone();
  61899. var min = lowPoint.z;
  61900. var max = highPoint.z;
  61901. var height = max - min;
  61902. height = height.toFixed(3);
  61903. this.elHeightLabel = this.elContent.find("#height_label");
  61904. this.elHeightLabel.html("<b>Height:</b> ".concat(height));
  61905. }
  61906. }
  61907. }
  61908. ;
  61909. class VolumePanel extends MeasurePanel {
  61910. constructor(viewer, measurement, propertiesPanel) {
  61911. super(viewer, measurement, propertiesPanel);
  61912. var copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  61913. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  61914. var lblLengthText = new Map([[BoxVolume, "length"], [SphereVolume$1, "rx"]]).get(measurement.constructor);
  61915. var lblWidthText = new Map([[BoxVolume, "width"], [SphereVolume$1, "ry"]]).get(measurement.constructor);
  61916. var lblHeightText = new Map([[BoxVolume, "height"], [SphereVolume$1, "rz"]]).get(measurement.constructor);
  61917. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\n\t\t\t\t<table class=\"measurement_value_table\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>\u03B1</th>\n\t\t\t\t\t\t<th>\u03B2</th>\n\t\t\t\t\t\t<th>\u03B3</th>\n\t\t\t\t\t\t<th></th>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_alpha\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_betta\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"angle_cell_gamma\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"right\" style=\"width: 25%\">\n\t\t\t\t\t\t\t<img name=\"copyRotation\" title=\"copy\" class=\"button-icon\" src=\"".concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</table>\n\n\t\t\t\t<table class=\"measurement_value_table\">\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>").concat(lblLengthText, "</th>\n\t\t\t\t\t\t<th>").concat(lblWidthText, "</th>\n\t\t\t\t\t\t<th>").concat(lblHeightText, "</th>\n\t\t\t\t\t\t<th></th>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td align=\"center\" id=\"cell_length\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"cell_width\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"center\" id=\"cell_height\" style=\"width: 33%\"></td>\n\t\t\t\t\t\t<td align=\"right\" style=\"width: 25%\">\n\t\t\t\t\t\t\t<img name=\"copyScale\" title=\"copy\" class=\"button-icon\" src=\"").concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</table>\n\n\t\t\t\t<br>\n\t\t\t\t<span style=\"font-weight: bold\">Volume: </span>\n\t\t\t\t<span id=\"measurement_volume\"></span>\n\n\t\t\t\t<!--\n\t\t\t\t<li>\n\t\t\t\t\t<label style=\"whitespace: nowrap\">\n\t\t\t\t\t\t<input id=\"volume_show\" type=\"checkbox\"/>\n\t\t\t\t\t\t<span>show volume</span>\n\t\t\t\t\t</label>\n\t\t\t\t</li>-->\n\n\t\t\t\t<li>\n\t\t\t\t\t<label style=\"whitespace: nowrap\">\n\t\t\t\t\t\t<input id=\"volume_clip\" type=\"checkbox\"/>\n\t\t\t\t\t\t<span>make clip volume</span>\n\t\t\t\t\t</label>\n\t\t\t\t</li>\n\n\t\t\t\t<li style=\"margin-top: 10px\">\n\t\t\t\t\t<input name=\"download_volume\" type=\"button\" value=\"prepare download\" style=\"width: 100%\" />\n\t\t\t\t\t<div name=\"download_message\"></div>\n\t\t\t\t</li>\n\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<li style=\"display: grid; grid-template-columns: auto auto; grid-column-gap: 5px; margin-top: 10px\">\n\t\t\t\t\t<input id=\"volume_reset_orientation\" type=\"button\" value=\"reset orientation\"/>\n\t\t\t\t\t<input id=\"volume_make_uniform\" type=\"button\" value=\"make uniform\"/>\n\t\t\t\t</li>\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"").concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  61918. {
  61919. // download
  61920. this.elDownloadButton = this.elContent.find("input[name=download_volume]");
  61921. if (this.propertiesPanel.viewer.server) {
  61922. this.elDownloadButton.click(() => this.download());
  61923. } else {
  61924. this.elDownloadButton.hide();
  61925. }
  61926. }
  61927. this.elCopyRotation = this.elContent.find("img[name=copyRotation]");
  61928. this.elCopyRotation.click(() => {
  61929. var rotation = this.measurement.rotation.toArray().slice(0, 3);
  61930. var msg = rotation.map(c => c.toFixed(3)).join(", ");
  61931. Utils.clipboardCopy(msg);
  61932. this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  61933. duration: 3000
  61934. });
  61935. });
  61936. this.elCopyScale = this.elContent.find("img[name=copyScale]");
  61937. this.elCopyScale.click(() => {
  61938. var scale = this.measurement.scale.toArray();
  61939. var msg = scale.map(c => c.toFixed(3)).join(", ");
  61940. Utils.clipboardCopy(msg);
  61941. this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  61942. duration: 3000
  61943. });
  61944. });
  61945. this.elRemove = this.elContent.find("img[name=remove]");
  61946. this.elRemove.click(() => {
  61947. this.viewer.scene.removeVolume(measurement);
  61948. });
  61949. this.elContent.find("#volume_reset_orientation").click(() => {
  61950. measurement.rotation.set(0, 0, 0);
  61951. });
  61952. this.elContent.find("#volume_make_uniform").click(() => {
  61953. var mean = (measurement.scale.x + measurement.scale.y + measurement.scale.z) / 3;
  61954. measurement.scale.set(mean, mean, mean);
  61955. });
  61956. this.elCheckClip = this.elContent.find('#volume_clip');
  61957. this.elCheckClip.click(event => {
  61958. this.measurement.clip = event.target.checked;
  61959. });
  61960. this.elCheckShow = this.elContent.find('#volume_show');
  61961. this.elCheckShow.click(event => {
  61962. this.measurement.visible = event.target.checked;
  61963. });
  61964. this.propertiesPanel.addVolatileListener(measurement, "position_changed", this._update);
  61965. this.propertiesPanel.addVolatileListener(measurement, "orientation_changed", this._update);
  61966. this.propertiesPanel.addVolatileListener(measurement, "scale_changed", this._update);
  61967. this.propertiesPanel.addVolatileListener(measurement, "clip_changed", this._update);
  61968. this.update();
  61969. }
  61970. async download() {
  61971. var clipBox = this.measurement;
  61972. var regions = [];
  61973. //for(let clipBox of boxes){
  61974. {
  61975. var toClip = clipBox.matrixWorld;
  61976. var px = new Vector3(+0.5, 0, 0).applyMatrix4(toClip);
  61977. var nx = new Vector3(-0.5, 0, 0).applyMatrix4(toClip);
  61978. var py = new Vector3(0, +0.5, 0).applyMatrix4(toClip);
  61979. var ny = new Vector3(0, -0.5, 0).applyMatrix4(toClip);
  61980. var pz = new Vector3(0, 0, +0.5).applyMatrix4(toClip);
  61981. var nz = new Vector3(0, 0, -0.5).applyMatrix4(toClip);
  61982. var pxN = new Vector3().subVectors(nx, px).normalize();
  61983. var nxN = pxN.clone().multiplyScalar(-1);
  61984. var pyN = new Vector3().subVectors(ny, py).normalize();
  61985. var nyN = pyN.clone().multiplyScalar(-1);
  61986. var pzN = new Vector3().subVectors(nz, pz).normalize();
  61987. var nzN = pzN.clone().multiplyScalar(-1);
  61988. var planes = [new Plane().setFromNormalAndCoplanarPoint(pxN, px), new Plane().setFromNormalAndCoplanarPoint(nxN, nx), new Plane().setFromNormalAndCoplanarPoint(pyN, py), new Plane().setFromNormalAndCoplanarPoint(nyN, ny), new Plane().setFromNormalAndCoplanarPoint(pzN, pz), new Plane().setFromNormalAndCoplanarPoint(nzN, nz)];
  61989. var planeQueryParts = [];
  61990. for (var plane of planes) {
  61991. var part = [plane.normal.toArray(), plane.constant].join(",");
  61992. part = "[".concat(part, "]");
  61993. planeQueryParts.push(part);
  61994. }
  61995. var region = "[" + planeQueryParts.join(",") + "]";
  61996. regions.push(region);
  61997. }
  61998. var regionsArg = regions.join(",");
  61999. var pointcloudArgs = [];
  62000. for (var pointcloud of this.viewer.scene.pointclouds) {
  62001. if (!pointcloud.visible) {
  62002. continue;
  62003. }
  62004. var offset = pointcloud.pcoGeometry.offset.clone();
  62005. var negateOffset = new Matrix4().makeTranslation(...offset.multiplyScalar(-1).toArray());
  62006. var matrixWorld = pointcloud.matrixWorld;
  62007. var transform = new Matrix4().multiplyMatrices(matrixWorld, negateOffset);
  62008. var path = "".concat(window.location.pathname, "/../").concat(pointcloud.pcoGeometry.url);
  62009. var arg = {
  62010. path: path,
  62011. transform: transform.elements
  62012. };
  62013. var argString = JSON.stringify(arg);
  62014. pointcloudArgs.push(argString);
  62015. }
  62016. var pointcloudsArg = pointcloudArgs.join(",");
  62017. var elMessage = this.elContent.find("div[name=download_message]");
  62018. var error = message => {
  62019. elMessage.html("<div style=\"color: #ff0000\">ERROR: ".concat(message, "</div>"));
  62020. };
  62021. var info = message => {
  62022. elMessage.html("".concat(message));
  62023. };
  62024. var handle = null;
  62025. {
  62026. // START FILTER
  62027. var url = "".concat(viewer.server, "/create_regions_filter?pointclouds=[").concat(pointcloudsArg, "]&regions=[").concat(regionsArg, "]");
  62028. //console.log(url);
  62029. info("estimating results ...");
  62030. var response = await fetch(url);
  62031. var jsResponse = await response.json();
  62032. //console.log(jsResponse);
  62033. if (!jsResponse.handle) {
  62034. error(jsResponse.message);
  62035. return;
  62036. } else {
  62037. handle = jsResponse.handle;
  62038. }
  62039. }
  62040. {
  62041. // WAIT, CHECK PROGRESS, HANDLE FINISH
  62042. var _url = "".concat(viewer.server, "/check_regions_filter?handle=").concat(handle);
  62043. var sleep = function sleep(duration) {
  62044. return new Promise((res, rej) => {
  62045. setTimeout(() => {
  62046. res();
  62047. }, duration);
  62048. });
  62049. };
  62050. var handleFiltering = jsResponse => {
  62051. var {
  62052. progress,
  62053. estimate
  62054. } = jsResponse;
  62055. var progressFract = progress["processed points"] / estimate.points;
  62056. var progressPercents = parseInt(progressFract * 100);
  62057. info("progress: ".concat(progressPercents, "%"));
  62058. };
  62059. var handleFinish = jsResponse => {
  62060. var message = "downloads ready: <br>";
  62061. message += "<ul>";
  62062. for (var i = 0; i < jsResponse.pointclouds.length; i++) {
  62063. var _url2 = "".concat(viewer.server, "/download_regions_filter_result?handle=").concat(handle, "&index=").concat(i);
  62064. message += "<li><a href=\"".concat(_url2, "\">result_").concat(i, ".las</a> </li>\n");
  62065. }
  62066. var reportURL = "".concat(viewer.server, "/download_regions_filter_report?handle=").concat(handle);
  62067. message += "<li> <a href=\"".concat(reportURL, "\">report.json</a> </li>\n");
  62068. message += "</ul>";
  62069. info(message);
  62070. };
  62071. var handleUnexpected = jsResponse => {
  62072. var message = "Unexpected Response. <br>status: ".concat(jsResponse.status, " <br>message: ").concat(jsResponse.message);
  62073. info(message);
  62074. };
  62075. var handleError = jsResponse => {
  62076. var message = "ERROR: ".concat(jsResponse.message);
  62077. error(message);
  62078. throw new Error(message);
  62079. };
  62080. var start = Date.now();
  62081. while (true) {
  62082. var _response = await fetch(_url);
  62083. var _jsResponse = await _response.json();
  62084. if (_jsResponse.status === "ERROR") {
  62085. handleError(_jsResponse);
  62086. } else if (_jsResponse.status === "FILTERING") {
  62087. handleFiltering(_jsResponse);
  62088. } else if (_jsResponse.status === "FINISHED") {
  62089. handleFinish(_jsResponse);
  62090. break;
  62091. } else {
  62092. handleUnexpected(_jsResponse);
  62093. }
  62094. var durationS = (Date.now() - start) / 1000;
  62095. var sleepAmountMS = durationS < 10 ? 100 : 1000;
  62096. await sleep(sleepAmountMS);
  62097. }
  62098. }
  62099. }
  62100. update() {
  62101. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  62102. elCoordiantesContainer.empty();
  62103. elCoordiantesContainer.append(this.createCoordinatesTable([this.measurement.position]));
  62104. {
  62105. var angles = this.measurement.rotation.toVector3();
  62106. angles = angles.toArray();
  62107. //angles = [angles.z, angles.x, angles.y];
  62108. angles = angles.map(v => 180 * v / Math.PI);
  62109. angles = angles.map(a => a.toFixed(1) + '\u00B0');
  62110. var elAlpha = this.elContent.find("#angle_cell_alpha");
  62111. var elBetta = this.elContent.find("#angle_cell_betta");
  62112. var elGamma = this.elContent.find("#angle_cell_gamma");
  62113. elAlpha.html(angles[0]);
  62114. elBetta.html(angles[1]);
  62115. elGamma.html(angles[2]);
  62116. }
  62117. {
  62118. var dimensions = this.measurement.scale.toArray();
  62119. dimensions = dimensions.map(v => Utils.addCommas(v.toFixed(2)));
  62120. var elLength = this.elContent.find("#cell_length");
  62121. var elWidth = this.elContent.find("#cell_width");
  62122. var elHeight = this.elContent.find("#cell_height");
  62123. elLength.html(dimensions[0]);
  62124. elWidth.html(dimensions[1]);
  62125. elHeight.html(dimensions[2]);
  62126. }
  62127. {
  62128. var elVolume = this.elContent.find("#measurement_volume");
  62129. var volume = this.measurement.getVolume();
  62130. elVolume.html(Utils.addCommas(volume.toFixed(2)));
  62131. }
  62132. this.elCheckClip.prop("checked", this.measurement.clip);
  62133. this.elCheckShow.prop("checked", this.measurement.visible);
  62134. }
  62135. }
  62136. ;
  62137. class ProfilePanel extends MeasurePanel {
  62138. constructor(viewer, measurement, propertiesPanel) {
  62139. super(viewer, measurement, propertiesPanel);
  62140. var removeIconPath = Potree.resourcePath + '/icons/remove.svg';
  62141. this.elContent = $("\n\t\t\t<div class=\"measurement_content selectable\">\n\t\t\t\t<span class=\"coordinates_table_container\"></span>\n\t\t\t\t<br>\n\t\t\t\t<span style=\"display:flex\">\n\t\t\t\t\t<span style=\"display:flex; align-items: center; padding-right: 10px\">Width: </span>\n\t\t\t\t\t<input id=\"sldProfileWidth\" name=\"sldProfileWidth\" value=\"5.06\" style=\"flex-grow: 1; width:100%\">\n\t\t\t\t</span>\n\t\t\t\t<br>\n\n\t\t\t\t<li style=\"margin-top: 10px\">\n\t\t\t\t\t<input name=\"download_profile\" type=\"button\" value=\"prepare download\" style=\"width: 100%\" />\n\t\t\t\t\t<div name=\"download_message\"></div>\n\t\t\t\t</li>\n\n\t\t\t\t<br>\n\n\t\t\t\t<input type=\"button\" id=\"show_2d_profile\" value=\"show 2d profile\" style=\"width: 100%\"/>\n\n\t\t\t\t<!-- ACTIONS -->\n\t\t\t\t<div style=\"display: flex; margin-top: 12px\">\n\t\t\t\t\t<span></span>\n\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t<img name=\"remove\" class=\"button-icon\" src=\"".concat(removeIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t"));
  62142. this.elRemove = this.elContent.find("img[name=remove]");
  62143. this.elRemove.click(() => {
  62144. this.viewer.scene.removeProfile(measurement);
  62145. });
  62146. {
  62147. // download
  62148. this.elDownloadButton = this.elContent.find("input[name=download_profile]");
  62149. if (this.propertiesPanel.viewer.server) {
  62150. this.elDownloadButton.click(() => this.download());
  62151. } else {
  62152. this.elDownloadButton.hide();
  62153. }
  62154. }
  62155. {
  62156. // width spinner
  62157. var elWidthSlider = this.elContent.find("#sldProfileWidth");
  62158. elWidthSlider.spinner({
  62159. min: 0,
  62160. max: 10 * 1000 * 1000,
  62161. step: 0.01,
  62162. numberFormat: 'n',
  62163. start: () => {},
  62164. spin: (event, ui) => {
  62165. var value = elWidthSlider.spinner('value');
  62166. measurement.setWidth(value);
  62167. },
  62168. change: (event, ui) => {
  62169. var value = elWidthSlider.spinner('value');
  62170. measurement.setWidth(value);
  62171. },
  62172. stop: (event, ui) => {
  62173. var value = elWidthSlider.spinner('value');
  62174. measurement.setWidth(value);
  62175. },
  62176. incremental: count => {
  62177. var value = elWidthSlider.spinner('value');
  62178. var step = elWidthSlider.spinner('option', 'step');
  62179. var delta = value * 0.05;
  62180. var increments = Math.max(1, parseInt(delta / step));
  62181. return increments;
  62182. }
  62183. });
  62184. elWidthSlider.spinner('value', measurement.getWidth());
  62185. elWidthSlider.spinner('widget').css('width', '100%');
  62186. var widthListener = event => {
  62187. var value = elWidthSlider.spinner('value');
  62188. if (value !== measurement.getWidth()) {
  62189. elWidthSlider.spinner('value', measurement.getWidth());
  62190. }
  62191. };
  62192. this.propertiesPanel.addVolatileListener(measurement, "width_changed", widthListener);
  62193. }
  62194. var elShow2DProfile = this.elContent.find("#show_2d_profile");
  62195. elShow2DProfile.click(() => {
  62196. this.propertiesPanel.viewer.profileWindow.show();
  62197. this.propertiesPanel.viewer.profileWindowController.setProfile(measurement);
  62198. });
  62199. this.propertiesPanel.addVolatileListener(measurement, "marker_added", this._update);
  62200. this.propertiesPanel.addVolatileListener(measurement, "marker_removed", this._update);
  62201. this.propertiesPanel.addVolatileListener(measurement, "marker_moved", this._update);
  62202. this.update();
  62203. }
  62204. update() {
  62205. var elCoordiantesContainer = this.elContent.find('.coordinates_table_container');
  62206. elCoordiantesContainer.empty();
  62207. elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points));
  62208. }
  62209. async download() {
  62210. var profile = this.measurement;
  62211. var regions = [];
  62212. {
  62213. var segments = profile.getSegments();
  62214. var width = profile.width;
  62215. for (var segment of segments) {
  62216. var start = segment.start.clone().multiply(new Vector3(1, 1, 0));
  62217. var end = segment.end.clone().multiply(new Vector3(1, 1, 0));
  62218. var center = new Vector3().addVectors(start, end).multiplyScalar(0.5);
  62219. var startEndDir = new Vector3().subVectors(end, start).normalize();
  62220. var endStartDir = new Vector3().subVectors(start, end).normalize();
  62221. var upDir = new Vector3(0, 0, 1);
  62222. var rightDir = new Vector3().crossVectors(startEndDir, upDir);
  62223. var leftDir = new Vector3().crossVectors(endStartDir, upDir);
  62224. console.log(leftDir);
  62225. var right = rightDir.clone().multiplyScalar(width * 0.5).add(center);
  62226. var left = leftDir.clone().multiplyScalar(width * 0.5).add(center);
  62227. var planes = [new Plane().setFromNormalAndCoplanarPoint(startEndDir, start), new Plane().setFromNormalAndCoplanarPoint(endStartDir, end), new Plane().setFromNormalAndCoplanarPoint(leftDir, right), new Plane().setFromNormalAndCoplanarPoint(rightDir, left)];
  62228. var planeQueryParts = [];
  62229. for (var plane of planes) {
  62230. var part = [plane.normal.toArray(), plane.constant].join(",");
  62231. part = "[".concat(part, "]");
  62232. planeQueryParts.push(part);
  62233. }
  62234. var region = "[" + planeQueryParts.join(",") + "]";
  62235. regions.push(region);
  62236. }
  62237. }
  62238. var regionsArg = regions.join(",");
  62239. var pointcloudArgs = [];
  62240. for (var pointcloud of this.viewer.scene.pointclouds) {
  62241. if (!pointcloud.visible) {
  62242. continue;
  62243. }
  62244. var offset = pointcloud.pcoGeometry.offset.clone();
  62245. var negateOffset = new Matrix4().makeTranslation(...offset.multiplyScalar(-1).toArray());
  62246. var matrixWorld = pointcloud.matrixWorld;
  62247. var transform = new Matrix4().multiplyMatrices(matrixWorld, negateOffset);
  62248. var path = "".concat(window.location.pathname, "/../").concat(pointcloud.pcoGeometry.url);
  62249. var arg = {
  62250. path: path,
  62251. transform: transform.elements
  62252. };
  62253. var argString = JSON.stringify(arg);
  62254. pointcloudArgs.push(argString);
  62255. }
  62256. var pointcloudsArg = pointcloudArgs.join(",");
  62257. var elMessage = this.elContent.find("div[name=download_message]");
  62258. var error = message => {
  62259. elMessage.html("<div style=\"color: #ff0000\">ERROR: ".concat(message, "</div>"));
  62260. };
  62261. var info = message => {
  62262. elMessage.html("".concat(message));
  62263. };
  62264. var handle = null;
  62265. {
  62266. // START FILTER
  62267. var url = "".concat(viewer.server, "/create_regions_filter?pointclouds=[").concat(pointcloudsArg, "]&regions=[").concat(regionsArg, "]");
  62268. //console.log(url);
  62269. info("estimating results ...");
  62270. var response = await fetch(url);
  62271. var jsResponse = await response.json();
  62272. //console.log(jsResponse);
  62273. if (!jsResponse.handle) {
  62274. error(jsResponse.message);
  62275. return;
  62276. } else {
  62277. handle = jsResponse.handle;
  62278. }
  62279. }
  62280. {
  62281. // WAIT, CHECK PROGRESS, HANDLE FINISH
  62282. var _url = "".concat(viewer.server, "/check_regions_filter?handle=").concat(handle);
  62283. var sleep = function sleep(duration) {
  62284. return new Promise((res, rej) => {
  62285. setTimeout(() => {
  62286. res();
  62287. }, duration);
  62288. });
  62289. };
  62290. var handleFiltering = jsResponse => {
  62291. var {
  62292. progress,
  62293. estimate
  62294. } = jsResponse;
  62295. var progressFract = progress["processed points"] / estimate.points;
  62296. var progressPercents = parseInt(progressFract * 100);
  62297. info("progress: ".concat(progressPercents, "%"));
  62298. };
  62299. var handleFinish = jsResponse => {
  62300. var message = "downloads ready: <br>";
  62301. message += "<ul>";
  62302. for (var i = 0; i < jsResponse.pointclouds.length; i++) {
  62303. var _url2 = "".concat(viewer.server, "/download_regions_filter_result?handle=").concat(handle, "&index=").concat(i);
  62304. message += "<li><a href=\"".concat(_url2, "\">result_").concat(i, ".las</a> </li>\n");
  62305. }
  62306. var reportURL = "".concat(viewer.server, "/download_regions_filter_report?handle=").concat(handle);
  62307. message += "<li> <a href=\"".concat(reportURL, "\">report.json</a> </li>\n");
  62308. message += "</ul>";
  62309. info(message);
  62310. };
  62311. var handleUnexpected = jsResponse => {
  62312. var message = "Unexpected Response. <br>status: ".concat(jsResponse.status, " <br>message: ").concat(jsResponse.message);
  62313. info(message);
  62314. };
  62315. var handleError = jsResponse => {
  62316. var message = "ERROR: ".concat(jsResponse.message);
  62317. error(message);
  62318. throw new Error(message);
  62319. };
  62320. var _start = Date.now();
  62321. while (true) {
  62322. var _response = await fetch(_url);
  62323. var _jsResponse = await _response.json();
  62324. if (_jsResponse.status === "ERROR") {
  62325. handleError(_jsResponse);
  62326. } else if (_jsResponse.status === "FILTERING") {
  62327. handleFiltering(_jsResponse);
  62328. } else if (_jsResponse.status === "FINISHED") {
  62329. handleFinish(_jsResponse);
  62330. break;
  62331. } else {
  62332. handleUnexpected(_jsResponse);
  62333. }
  62334. var durationS = (Date.now() - _start) / 1000;
  62335. var sleepAmountMS = durationS < 10 ? 100 : 1000;
  62336. await sleep(sleepAmountMS);
  62337. }
  62338. }
  62339. }
  62340. }
  62341. ;
  62342. class CameraPanel {
  62343. constructor(viewer, propertiesPanel) {
  62344. this.viewer = viewer;
  62345. this.propertiesPanel = propertiesPanel;
  62346. this._update = () => {
  62347. this.update();
  62348. };
  62349. var copyIconPath = Potree.resourcePath + '/icons/copy.svg';
  62350. this.elContent = $("\n\t\t<div class=\"propertypanel_content\">\n\t\t\t<table>\n\t\t\t\t<tr>\n\t\t\t\t\t<th colspan=\"3\">position</th>\n\t\t\t\t\t<th></th>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td align=\"center\" id=\"camera_position_x\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"camera_position_y\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"camera_position_z\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"right\" id=\"copy_camera_position\" style=\"width: 25%\">\n\t\t\t\t\t\t<img name=\"copyPosition\" title=\"copy\" class=\"button-icon\" src=\"".concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<th colspan=\"3\">target</th>\n\t\t\t\t\t<th></th>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td align=\"center\" id=\"camera_target_x\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"camera_target_y\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"camera_target_z\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"right\" id=\"copy_camera_target\" style=\"width: 25%\">\n\t\t\t\t\t\t<img name=\"copyTarget\" title=\"copy\" class=\"button-icon\" src=\"").concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</div>\n\t\t"));
  62351. this.elCopyPosition = this.elContent.find("img[name=copyPosition]");
  62352. this.elCopyPosition.click(() => {
  62353. var pos = this.viewer.scene.getActiveCamera().position.toArray();
  62354. var msg = pos.map(c => c.toFixed(3)).join(", ");
  62355. Utils.clipboardCopy(msg);
  62356. this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  62357. duration: 3000
  62358. });
  62359. });
  62360. this.elCopyTarget = this.elContent.find("img[name=copyTarget]");
  62361. this.elCopyTarget.click(() => {
  62362. var pos = this.viewer.scene.view.getPivot().toArray();
  62363. var msg = pos.map(c => c.toFixed(3)).join(", ");
  62364. Utils.clipboardCopy(msg);
  62365. this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  62366. duration: 3000
  62367. });
  62368. });
  62369. this.propertiesPanel.addVolatileListener(viewer, "camera_changed", this._update);
  62370. this.update();
  62371. }
  62372. update() {
  62373. //console.log("updating camera panel");
  62374. var camera = this.viewer.scene.getActiveCamera();
  62375. var view = this.viewer.scene.view;
  62376. var pos = camera.position.toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62377. this.elContent.find("#camera_position_x").html(pos[0]);
  62378. this.elContent.find("#camera_position_y").html(pos[1]);
  62379. this.elContent.find("#camera_position_z").html(pos[2]);
  62380. var target = view.getPivot().toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62381. this.elContent.find("#camera_target_x").html(target[0]);
  62382. this.elContent.find("#camera_target_y").html(target[1]);
  62383. this.elContent.find("#camera_target_z").html(target[2]);
  62384. }
  62385. }
  62386. ;
  62387. class AnnotationPanel {
  62388. constructor(viewer, propertiesPanel, annotation) {
  62389. this.viewer = viewer;
  62390. this.propertiesPanel = propertiesPanel;
  62391. this.annotation = annotation;
  62392. this._update = () => {
  62393. this.update();
  62394. };
  62395. var copyIconPath = "".concat(Potree.resourcePath, "/icons/copy.svg");
  62396. this.elContent = $("\n\t\t<div class=\"propertypanel_content\">\n\t\t\t<table>\n\t\t\t\t<tr>\n\t\t\t\t\t<th colspan=\"3\">position</th>\n\t\t\t\t\t<th></th>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td align=\"center\" id=\"annotation_position_x\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"annotation_position_y\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"center\" id=\"annotation_position_z\" style=\"width: 25%\"></td>\n\t\t\t\t\t<td align=\"right\" id=\"copy_annotation_position\" style=\"width: 25%\">\n\t\t\t\t\t\t<img name=\"copyPosition\" title=\"copy\" class=\"button-icon\" src=\"".concat(copyIconPath, "\" style=\"width: 16px; height: 16px\"/>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\n\t\t\t</table>\n\n\t\t\t<div>\n\n\t\t\t\t<div class=\"heading\">Title</div>\n\t\t\t\t<div id=\"annotation_title\" contenteditable=\"true\">\n\t\t\t\t\tAnnotation Title\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"heading\">Description</div>\n\t\t\t\t<div id=\"annotation_description\" contenteditable=\"true\">\n\t\t\t\t\tA longer description of this annotation. \n\t\t\t\t\t\tCan be multiple lines long. TODO: the user should be able\n\t\t\t\t\t\tto modify title and description. \n\t\t\t\t</div>\n\n\t\t\t</div>\n\n\t\t</div>\n\t\t"));
  62397. this.elCopyPosition = this.elContent.find("img[name=copyPosition]");
  62398. this.elCopyPosition.click(() => {
  62399. var pos = this.annotation.position.toArray();
  62400. var msg = pos.map(c => c.toFixed(3)).join(", ");
  62401. Utils.clipboardCopy(msg);
  62402. this.viewer.postMessage("Copied value to clipboard: <br>'".concat(msg, "'"), {
  62403. duration: 3000
  62404. });
  62405. });
  62406. this.elTitle = this.elContent.find("#annotation_title").html(annotation.title);
  62407. this.elDescription = this.elContent.find("#annotation_description").html(annotation.description);
  62408. this.elTitle[0].addEventListener("input", () => {
  62409. var title = this.elTitle.html();
  62410. annotation.title = title;
  62411. }, false);
  62412. this.elDescription[0].addEventListener("input", () => {
  62413. var description = this.elDescription.html();
  62414. annotation.description = description;
  62415. }, false);
  62416. this.update();
  62417. }
  62418. update() {
  62419. var {
  62420. annotation,
  62421. elContent,
  62422. elTitle,
  62423. elDescription
  62424. } = this;
  62425. var pos = annotation.position.toArray().map(c => Utils.addCommas(c.toFixed(3)));
  62426. elContent.find("#annotation_position_x").html(pos[0]);
  62427. elContent.find("#annotation_position_y").html(pos[1]);
  62428. elContent.find("#annotation_position_z").html(pos[2]);
  62429. elTitle.html(annotation.title);
  62430. elDescription.html(annotation.description);
  62431. }
  62432. }
  62433. ;
  62434. class CameraAnimationPanel {
  62435. constructor(viewer, propertiesPanel, animation) {
  62436. this.viewer = viewer;
  62437. this.propertiesPanel = propertiesPanel;
  62438. this.animation = animation;
  62439. this.elContent = $("\n\t\t\t<div class=\"propertypanel_content\">\n\t\t\t\t<span id=\"animation_keyframes\"></span>\n\n\t\t\t\t<span>\n\n\t\t\t\t\t<span style=\"display:flex\">\n\t\t\t\t\t\t<span style=\"display:flex; align-items: center; padding-right: 10px\">Duration: </span>\n\t\t\t\t\t\t<input name=\"spnDuration\" value=\"5.0\" style=\"flex-grow: 1; width:100%\">\n\t\t\t\t\t</span>\n\n\t\t\t\t\t<span>Time: </span><span id=\"lblTime\"></span> <div id=\"sldTime\"></div>\n\n\t\t\t\t\t<input name=\"play\" type=\"button\" value=\"play\"/>\n\t\t\t\t\t<input name=\"pause\" type=\"button\" value=\"pause\"/>\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t");
  62440. var elPlay = this.elContent.find("input[name=play]");
  62441. elPlay.click(() => {
  62442. animation.play();
  62443. });
  62444. var elPause = this.elContent.find("input[name=pause]");
  62445. elPause.click(() => {
  62446. animation.pause();
  62447. });
  62448. var elSlider = this.elContent.find('#sldTime');
  62449. elSlider.slider({
  62450. value: 0,
  62451. min: 0,
  62452. max: 1,
  62453. step: 0.001,
  62454. slide: (event, ui) => {
  62455. animation.set(ui.value);
  62456. animation.updateFrustum();
  62457. }
  62458. });
  62459. var elDuration = this.elContent.find("input[name=spnDuration]");
  62460. elDuration.spinner({
  62461. min: 0,
  62462. max: 300,
  62463. step: 0.01,
  62464. numberFormat: 'n',
  62465. start: () => {},
  62466. spin: (event, ui) => {
  62467. var value = elDuration.spinner('value');
  62468. animation.setDuration(value);
  62469. },
  62470. change: (event, ui) => {
  62471. var value = elDuration.spinner('value');
  62472. animation.setDuration(value);
  62473. },
  62474. stop: (event, ui) => {
  62475. var value = elDuration.spinner('value');
  62476. animation.setDuration(value);
  62477. },
  62478. incremental: count => {
  62479. var value = elDuration.spinner('value');
  62480. var step = elDuration.spinner('option', 'step');
  62481. var delta = value * 0.05;
  62482. var increments = Math.max(1, parseInt(delta / step));
  62483. return increments;
  62484. }
  62485. });
  62486. elDuration.spinner('value', animation.getDuration());
  62487. elDuration.spinner('widget').css('width', '100%');
  62488. var elKeyframes = this.elContent.find("#animation_keyframes");
  62489. var updateKeyframes = () => {
  62490. elKeyframes.empty();
  62491. //let index = 0;
  62492. // <span style="flex-grow: 0;">
  62493. // <img name="add" src="${Potree.resourcePath}/icons/add.svg" style="width: 1.5em; height: 1.5em"/>
  62494. // </span>
  62495. var addNewKeyframeItem = index => {
  62496. var elNewKeyframe = $("\n\t\t\t\t\t<div style=\"display: flex; margin: 0.2em 0em\">\n\t\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t\t<input type=\"button\" name=\"add\" value=\"insert control point\" />\n\t\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t</div>\n\t\t\t\t");
  62497. var elAdd = elNewKeyframe.find("input[name=add]");
  62498. elAdd.click(() => {
  62499. animation.createControlPoint(index, {
  62500. position: viewer.scene.view.position,
  62501. target: viewer.scene.view.getPivot()
  62502. });
  62503. animation.changeCallback();
  62504. });
  62505. elKeyframes.append(elNewKeyframe);
  62506. };
  62507. var addKeyframeItem = index => {
  62508. var elKeyframe = $("\n\t\t\t\t\t<div style=\"display: flex; margin: 0.2em 0em\">\n\t\t\t\t\t\t<span style=\"flex-grow: 0;\">\n\t\t\t\t\t\t\t<img name=\"assign\" src=\"".concat(Potree.resourcePath, "/icons/assign.svg\" style=\"width: 1.5em; height: 1.5em\"/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span style=\"flex-grow: 0;\">\n\t\t\t\t\t\t\t<img name=\"move\" src=\"").concat(Potree.resourcePath, "/icons/circled_dot.svg\" style=\"width: 1.5em; height: 1.5em\"/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span style=\"flex-grow: 0; width: 1.5em; height: 1.5em\"></span>\n\t\t\t\t\t\t<span style=\"flex-grow: 0; font-size: 1.5em\">keyframe</span>\n\t\t\t\t\t\t<span style=\"flex-grow: 1\"></span>\n\t\t\t\t\t\t<span style=\"flex-grow: 0;\">\n\t\t\t\t\t\t\t<img name=\"delete\" src=\"").concat(Potree.resourcePath, "/icons/remove.svg\" style=\"width: 1.5em; height: 1.5em\"/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t"));
  62509. var elAssign = elKeyframe.find("img[name=assign]");
  62510. var elMove = elKeyframe.find("img[name=move]");
  62511. var elDelete = elKeyframe.find("img[name=delete]");
  62512. elAssign.click(() => {
  62513. //修改
  62514. animation.posCurve.points[index].copy(viewer.scene.view.position);
  62515. animation.targets[index].position.copy(viewer.scene.view.getPivot());
  62516. animation.changeCallback(index);
  62517. });
  62518. elMove.click(() => {
  62519. viewer.scene.view.position.copy(animation.posCurve.points[index]);
  62520. viewer.scene.view.lookAt(animation.targets[index].position);
  62521. });
  62522. elDelete.click(() => {
  62523. animation.removeControlPoint(index);
  62524. animation.changeCallback();
  62525. });
  62526. elKeyframes.append(elKeyframe);
  62527. };
  62528. var index = 0;
  62529. addNewKeyframeItem(index);
  62530. animation.posCurve.points.forEach(e => {
  62531. addKeyframeItem(index);
  62532. index++;
  62533. addNewKeyframeItem(index);
  62534. });
  62535. };
  62536. updateKeyframes();
  62537. animation.addEventListener("controlpoint_added", updateKeyframes);
  62538. animation.addEventListener("controlpoint_removed", updateKeyframes);
  62539. // this._update = () => { this.update(); };
  62540. // this.update();
  62541. }
  62542. update() {}
  62543. }
  62544. ;
  62545. class PropertiesPanel {
  62546. constructor(container, viewer) {
  62547. this.container = container;
  62548. this.viewer = viewer;
  62549. this.object = null;
  62550. this.cleanupTasks = [];
  62551. this.scene = null;
  62552. }
  62553. setScene(scene) {
  62554. this.scene = scene;
  62555. }
  62556. set(object) {
  62557. if (this.object === object) {
  62558. return;
  62559. }
  62560. this.object = object;
  62561. for (var task of this.cleanupTasks) {
  62562. task();
  62563. }
  62564. this.cleanupTasks = [];
  62565. this.container.empty();
  62566. if (object instanceof PointCloudTree) {
  62567. this.setPointCloud(object);
  62568. } else if (object instanceof Measure || object instanceof Profile || object instanceof Volume) {
  62569. this.setMeasurement(object);
  62570. } else if (object instanceof Camera) {
  62571. this.setCamera(object);
  62572. } else if (object instanceof Annotation) {
  62573. this.setAnnotation(object);
  62574. } else if (object instanceof CameraAnimation$1) {
  62575. //改
  62576. this.setCameraAnimation(object);
  62577. }
  62578. }
  62579. //
  62580. // Used for events that should be removed when the property object changes.
  62581. // This is for listening to materials, scene, point clouds, etc.
  62582. // not required for DOM listeners, since they are automatically cleared by removing the DOM subtree.
  62583. //
  62584. addVolatileListener(target, type, callback) {
  62585. target.addEventListener(type, callback);
  62586. this.cleanupTasks.push(() => {
  62587. target.removeEventListener(type, callback);
  62588. });
  62589. }
  62590. setPointCloud(pointcloud) {
  62591. var material = pointcloud.material;
  62592. var panel = $("\n\t\t\t<div class=\"scene_content selectable\">\n\t\t\t\t<ul class=\"pv-menu-list\">\n\n\t\t\t\t<li>\n\t\t\t\t<span data-i18n=\"appearance.point_size\"></span>:&nbsp;<span id=\"lblPointSize\"></span> <div id=\"sldPointSize\"></div>\n\t\t\t\t</li>\n\t\t\t\t<li>\n\t\t\t\t<span data-i18n=\"appearance.min_point_size\"></span>:&nbsp;<span id=\"lblMinPointSize\"></span> <div id=\"sldMinPointSize\"></div>\n\t\t\t\t</li>\n\n\t\t\t\t<!-- SIZE TYPE -->\n\t\t\t\t<li>\n\t\t\t\t\t<label for=\"optPointSizing\" class=\"pv-select-label\" data-i18n=\"appearance.point_size_type\">Point Sizing </label>\n\t\t\t\t\t<select id=\"optPointSizing\" name=\"optPointSizing\">\n\t\t\t\t\t\t<option>FIXED</option>\n\t\t\t\t\t\t<option>ATTENUATED</option>\n\t\t\t\t\t\t<option>ADAPTIVE</option>\n\t\t\t\t\t</select>\n\t\t\t\t</li>\n\n\t\t\t\t<!-- SHAPE -->\n\t\t\t\t<li>\n\t\t\t\t\t<label for=\"optShape\" class=\"pv-select-label\" data-i18n=\"appearance.point_shape\"></label><br>\n\t\t\t\t\t<select id=\"optShape\" name=\"optShape\">\n\t\t\t\t\t\t<option>SQUARE</option>\n\t\t\t\t\t\t<option>CIRCLE</option>\n\t\t\t\t\t\t<option>PARABOLOID</option>\n\t\t\t\t\t</select>\n\t\t\t\t</li>\n\n\t\t\t\t<li id=\"materials_backface_container\">\n\t\t\t\t<label><input id=\"set_backface_culling\" type=\"checkbox\" /><span data-i18n=\"appearance.backface_culling\"></span></label>\n\t\t\t\t</li>\n\t\t\t\t\n\t\t\t\t<!-- OPACITY -->\n\t\t\t\t<li><span data-i18n=\"appearance.point_opacity\"></span>:<span id=\"lblOpacity\"></span><div id=\"sldOpacity\"></div></li>\n\n\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t<span>Attribute</span>\n\t\t\t\t</div>\n\n\t\t\t\t<li>\n\t\t\t\t\t<select id=\"optMaterial\" name=\"optMaterial\"></select>\n\t\t\t\t</li>\n\n\t\t\t\t<div id=\"materials.composite_weight_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Attribute Weights</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li>RGB: <span id=\"lblWeightRGB\"></span> <div id=\"sldWeightRGB\"></div>\t</li>\n\t\t\t\t\t<li>Intensity: <span id=\"lblWeightIntensity\"></span> <div id=\"sldWeightIntensity\"></div>\t</li>\n\t\t\t\t\t<li>Elevation: <span id=\"lblWeightElevation\"></span> <div id=\"sldWeightElevation\"></div>\t</li>\n\t\t\t\t\t<li>Classification: <span id=\"lblWeightClassification\"></span> <div id=\"sldWeightClassification\"></div>\t</li>\n\t\t\t\t\t<li>Return Number: <span id=\"lblWeightReturnNumber\"></span> <div id=\"sldWeightReturnNumber\"></div>\t</li>\n\t\t\t\t\t<li>Source ID: <span id=\"lblWeightSourceID\"></span> <div id=\"sldWeightSourceID\"></div>\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.rgb_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>RGB</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li>Gamma: <span id=\"lblRGBGamma\"></span> <div id=\"sldRGBGamma\"></div>\t</li>\n\t\t\t\t\t<li>Brightness: <span id=\"lblRGBBrightness\"></span> <div id=\"sldRGBBrightness\"></div>\t</li>\n\t\t\t\t\t<li>Contrast: <span id=\"lblRGBContrast\"></span> <div id=\"sldRGBContrast\"></div>\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.extra_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Extra Attribute</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li><span data-i18n=\"appearance.extra_range\"></span>: <span id=\"lblExtraRange\"></span> <div id=\"sldExtraRange\"></div></li>\n\n\t\t\t\t\t<li>Gamma: <span id=\"lblExtraGamma\"></span> <div id=\"sldExtraGamma\"></div></li>\n\t\t\t\t\t<li>Brightness: <span id=\"lblExtraBrightness\"></span> <div id=\"sldExtraBrightness\"></div></li>\n\t\t\t\t\t<li>Contrast: <span id=\"lblExtraContrast\"></span> <div id=\"sldExtraContrast\"></div></li>\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div id=\"materials.matcap_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>MATCAP</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<div id=\"matcap_scheme_selection\" style=\"display: flex; flex-wrap: wrap;\"> </div>\n\t\t\t\t\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.color_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Color</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<input id=\"materials.color.picker\" />\n\t\t\t\t</div>\n\n\n\t\t\t\t<div id=\"materials.elevation_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Elevation</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li><span data-i18n=\"appearance.elevation_range\"></span>: <span id=\"lblHeightRange\"></span> <div id=\"sldHeightRange\"></div>\t</li>\n\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<selectgroup id=\"gradient_repeat_option\">\n\t\t\t\t\t\t\t<option id=\"gradient_repeat_clamp\" value=\"CLAMP\">Clamp</option>\n\t\t\t\t\t\t\t<option id=\"gradient_repeat_repeat\" value=\"REPEAT\">Repeat</option>\n\t\t\t\t\t\t\t<option id=\"gradient_repeat_mirrored_repeat\" value=\"MIRRORED_REPEAT\">Mirrored Repeat</option>\n\t\t\t\t\t\t</selectgroup>\n\t\t\t\t\t</li>\n\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<span>Gradient Scheme:</span>\n\t\t\t\t\t\t<div id=\"elevation_gradient_scheme_selection\" style=\"display: flex; padding: 1em 0em\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.transition_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Transition</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li>transition: <span id=\"lblTransition\"></span> <div id=\"sldTransition\"></div>\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.intensity_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Intensity</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<li>Range: <span id=\"lblIntensityRange\"></span> <div id=\"sldIntensityRange\"></div>\t</li>\n\t\t\t\t\t<li>Gamma: <span id=\"lblIntensityGamma\"></span> <div id=\"sldIntensityGamma\"></div>\t</li>\n\t\t\t\t\t<li>Brightness: <span id=\"lblIntensityBrightness\"></span> <div id=\"sldIntensityBrightness\"></div>\t</li>\n\t\t\t\t\t<li>Contrast: <span id=\"lblIntensityContrast\"></span> <div id=\"sldIntensityContrast\"></div>\t</li>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"materials.gpstime_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>GPS Time</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t</div>\n\t\t\t\t\n\t\t\t\t<div id=\"materials.index_container\">\n\t\t\t\t\t<div class=\"divider\">\n\t\t\t\t\t\t<span>Indices</span>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t");
  62593. panel.i18n();
  62594. this.container.append(panel);
  62595. {
  62596. // POINT SIZE
  62597. var sldPointSize = panel.find("#sldPointSize");
  62598. var lblPointSize = panel.find("#lblPointSize");
  62599. sldPointSize.slider({
  62600. value: material.size,
  62601. min: 0,
  62602. max: 3,
  62603. step: 0.01,
  62604. slide: function slide(event, ui) {
  62605. material.size = ui.value;
  62606. }
  62607. });
  62608. var update = e => {
  62609. lblPointSize.html(material.size.toFixed(2));
  62610. sldPointSize.slider({
  62611. value: material.size
  62612. });
  62613. };
  62614. this.addVolatileListener(material, "point_size_changed", update);
  62615. update();
  62616. }
  62617. {
  62618. // MINIMUM POINT SIZE
  62619. var sldMinPointSize = panel.find("#sldMinPointSize");
  62620. var lblMinPointSize = panel.find("#lblMinPointSize");
  62621. sldMinPointSize.slider({
  62622. value: material.size,
  62623. min: 0,
  62624. max: 3,
  62625. step: 0.01,
  62626. slide: function slide(event, ui) {
  62627. material.minSize = ui.value;
  62628. }
  62629. });
  62630. var _update = e => {
  62631. lblMinPointSize.html(material.minSize.toFixed(2));
  62632. sldMinPointSize.slider({
  62633. value: material.minSize
  62634. });
  62635. };
  62636. this.addVolatileListener(material, "point_size_changed", _update);
  62637. _update();
  62638. }
  62639. {
  62640. // POINT SIZING
  62641. var strSizeType = Object.keys(PointSizeType)[material.pointSizeType];
  62642. var opt = panel.find("#optPointSizing");
  62643. opt.selectmenu();
  62644. opt.val(strSizeType).selectmenu('refresh');
  62645. opt.selectmenu({
  62646. change: (event, ui) => {
  62647. material.pointSizeType = PointSizeType[ui.item.value];
  62648. }
  62649. });
  62650. }
  62651. {
  62652. // SHAPE
  62653. var _opt = panel.find("#optShape");
  62654. _opt.selectmenu({
  62655. change: (event, ui) => {
  62656. var value = ui.item.value;
  62657. material.shape = PointShape$1[value];
  62658. }
  62659. });
  62660. var _update2 = () => {
  62661. var typename = Object.keys(PointShape$1)[material.shape];
  62662. _opt.selectmenu().val(typename).selectmenu('refresh');
  62663. };
  62664. this.addVolatileListener(material, "point_shape_changed", _update2);
  62665. _update2();
  62666. }
  62667. {
  62668. // BACKFACE CULLING
  62669. var _opt2 = panel.find("#set_backface_culling");
  62670. _opt2.click(() => {
  62671. material.backfaceCulling = _opt2.prop("checked");
  62672. });
  62673. var _update3 = () => {
  62674. var value = material.backfaceCulling;
  62675. _opt2.prop("checked", value);
  62676. };
  62677. this.addVolatileListener(material, "backface_changed", _update3);
  62678. _update3();
  62679. var blockBackface = $('#materials_backface_container');
  62680. blockBackface.css('display', 'none');
  62681. var pointAttributes = pointcloud.pcoGeometry.pointAttributes;
  62682. var hasNormals = pointAttributes.hasNormals ? pointAttributes.hasNormals() : false;
  62683. if (hasNormals) {
  62684. blockBackface.css('display', 'block');
  62685. }
  62686. /*
  62687. opt.checkboxradio({
  62688. clicked: (event, ui) => {
  62689. // let value = ui.item.value;
  62690. let value = ui.item.checked;
  62691. console.log(value);
  62692. material.backfaceCulling = value; // $('#set_freeze').prop("checked");
  62693. }
  62694. });
  62695. */
  62696. }
  62697. {
  62698. // OPACITY
  62699. var sldOpacity = panel.find("#sldOpacity");
  62700. var lblOpacity = panel.find("#lblOpacity");
  62701. sldOpacity.slider({
  62702. value: material.opacity,
  62703. min: 0,
  62704. max: 1,
  62705. step: 0.001,
  62706. slide: function slide(event, ui) {
  62707. material.opacity = ui.value;
  62708. }
  62709. });
  62710. var _update4 = e => {
  62711. lblOpacity.html(material.opacity.toFixed(2));
  62712. sldOpacity.slider({
  62713. value: material.opacity
  62714. });
  62715. };
  62716. this.addVolatileListener(material, "opacity_changed", _update4);
  62717. _update4();
  62718. }
  62719. {
  62720. var attributes = pointcloud.pcoGeometry.pointAttributes.attributes;
  62721. var options = [];
  62722. options.push(...attributes.map(a => a.name));
  62723. var intensityIndex = options.indexOf("intensity");
  62724. if (intensityIndex >= 0) {
  62725. options.splice(intensityIndex + 1, 0, "intensity gradient");
  62726. }
  62727. options.push("elevation", "color", 'matcap', 'indices', 'level of detail', 'composite');
  62728. var blacklist = ["POSITION_CARTESIAN", "position"];
  62729. options = options.filter(o => !blacklist.includes(o));
  62730. var attributeSelection = panel.find('#optMaterial');
  62731. for (var option of options) {
  62732. var elOption = $("<option>".concat(option, "</option>"));
  62733. attributeSelection.append(elOption);
  62734. }
  62735. var updateMaterialPanel = (event, ui) => {
  62736. var selectedValue = attributeSelection.selectmenu().val();
  62737. material.activeAttributeName = selectedValue;
  62738. var attribute = pointcloud.getAttribute(selectedValue);
  62739. if (selectedValue === "intensity gradient") {
  62740. attribute = pointcloud.getAttribute("intensity");
  62741. }
  62742. var isIntensity = attribute ? ["intensity", "intensity gradient"].includes(attribute.name) : false;
  62743. if (isIntensity) {
  62744. if (pointcloud.material.intensityRange[0] === Infinity) {
  62745. pointcloud.material.intensityRange = attribute.range;
  62746. }
  62747. var [min, max] = attribute.range;
  62748. panel.find('#sldIntensityRange').slider({
  62749. range: true,
  62750. min: min,
  62751. max: max,
  62752. step: 0.01,
  62753. values: [min, max],
  62754. slide: (event, ui) => {
  62755. var min = ui.values[0];
  62756. var max = ui.values[1];
  62757. material.intensityRange = [min, max];
  62758. }
  62759. });
  62760. } else if (attribute) {
  62761. var [_min, _max] = attribute.range;
  62762. var selectedRange = material.getRange(attribute.name);
  62763. if (!selectedRange) {
  62764. selectedRange = [...attribute.range];
  62765. }
  62766. var minMaxAreNumbers = typeof _min === "number" && typeof _max === "number";
  62767. if (minMaxAreNumbers) {
  62768. panel.find('#sldExtraRange').slider({
  62769. range: true,
  62770. min: _min,
  62771. max: _max,
  62772. step: 0.01,
  62773. values: selectedRange,
  62774. slide: (event, ui) => {
  62775. var [a, b] = ui.values;
  62776. material.setRange(attribute.name, [a, b]);
  62777. }
  62778. });
  62779. }
  62780. }
  62781. var blockWeights = $('#materials\\.composite_weight_container');
  62782. var blockElevation = $('#materials\\.elevation_container');
  62783. var blockRGB = $('#materials\\.rgb_container');
  62784. var blockExtra = $('#materials\\.extra_container');
  62785. var blockColor = $('#materials\\.color_container');
  62786. var blockIntensity = $('#materials\\.intensity_container');
  62787. var blockIndex = $('#materials\\.index_container');
  62788. var blockTransition = $('#materials\\.transition_container');
  62789. var blockGps = $('#materials\\.gpstime_container');
  62790. var blockMatcap = $('#materials\\.matcap_container');
  62791. blockIndex.css('display', 'none');
  62792. blockIntensity.css('display', 'none');
  62793. blockElevation.css('display', 'none');
  62794. blockRGB.css('display', 'none');
  62795. blockExtra.css('display', 'none');
  62796. blockColor.css('display', 'none');
  62797. blockWeights.css('display', 'none');
  62798. blockTransition.css('display', 'none');
  62799. blockMatcap.css('display', 'none');
  62800. blockGps.css('display', 'none');
  62801. if (selectedValue === 'composite') {
  62802. blockWeights.css('display', 'block');
  62803. blockElevation.css('display', 'block');
  62804. blockRGB.css('display', 'block');
  62805. blockIntensity.css('display', 'block');
  62806. } else if (selectedValue === 'elevation') {
  62807. blockElevation.css('display', 'block');
  62808. } else if (selectedValue === 'RGB and Elevation') {
  62809. blockRGB.css('display', 'block');
  62810. blockElevation.css('display', 'block');
  62811. } else if (selectedValue === 'rgba') {
  62812. blockRGB.css('display', 'block');
  62813. } else if (selectedValue === 'color') {
  62814. blockColor.css('display', 'block');
  62815. } else if (selectedValue === 'intensity') {
  62816. blockIntensity.css('display', 'block');
  62817. } else if (selectedValue === 'intensity gradient') {
  62818. blockIntensity.css('display', 'block');
  62819. } else if (selectedValue === "indices") {
  62820. blockIndex.css('display', 'block');
  62821. } else if (selectedValue === "matcap") {
  62822. blockMatcap.css('display', 'block');
  62823. } else if (selectedValue === "classification") {
  62824. // add classification color selctor?
  62825. } else if (selectedValue === "gps-time") {
  62826. blockGps.css('display', 'block');
  62827. } else if (selectedValue === "number of returns") {} else if (selectedValue === "return number") {} else if (["source id", "point source id"].includes(selectedValue)) {} else {
  62828. blockExtra.css('display', 'block');
  62829. }
  62830. };
  62831. attributeSelection.selectmenu({
  62832. change: updateMaterialPanel
  62833. });
  62834. var _update5 = () => {
  62835. attributeSelection.val(material.activeAttributeName).selectmenu('refresh');
  62836. };
  62837. this.addVolatileListener(material, "point_color_type_changed", _update5);
  62838. this.addVolatileListener(material, "active_attribute_changed", _update5);
  62839. _update5();
  62840. updateMaterialPanel();
  62841. }
  62842. {
  62843. var schemes = Object.keys(Potree.Gradients).map(name => ({
  62844. name: name,
  62845. values: Gradients[name]
  62846. }));
  62847. var elSchemeContainer = panel.find("#elevation_gradient_scheme_selection");
  62848. var _loop = function _loop(scheme) {
  62849. var elScheme = $("\n\t\t\t\t\t<span style=\"flex-grow: 1;\">\n\t\t\t\t\t</span>\n\t\t\t\t");
  62850. var svg = Potree.Utils.createSvgGradient(scheme.values);
  62851. svg.setAttributeNS(null, "class", "button-icon");
  62852. elScheme.append($(svg));
  62853. elScheme.click(() => {
  62854. material.gradient = Gradients[scheme.name];
  62855. });
  62856. elSchemeContainer.append(elScheme);
  62857. };
  62858. for (var scheme of schemes) {
  62859. _loop(scheme);
  62860. }
  62861. }
  62862. {
  62863. var matcaps = [{
  62864. name: "Normals",
  62865. icon: "".concat(Potree.resourcePath, "/icons/matcap/check_normal+y.jpg")
  62866. }, {
  62867. name: "Basic 1",
  62868. icon: "".concat(Potree.resourcePath, "/icons/matcap/basic_1.jpg")
  62869. }, {
  62870. name: "Basic 2",
  62871. icon: "".concat(Potree.resourcePath, "/icons/matcap/basic_2.jpg")
  62872. }, {
  62873. name: "Basic Dark",
  62874. icon: "".concat(Potree.resourcePath, "/icons/matcap/basic_dark.jpg")
  62875. }, {
  62876. name: "Basic Side",
  62877. icon: "".concat(Potree.resourcePath, "/icons/matcap/basic_side.jpg")
  62878. }, {
  62879. name: "Ceramic Dark",
  62880. icon: "".concat(Potree.resourcePath, "/icons/matcap/ceramic_dark.jpg")
  62881. }, {
  62882. name: "Ceramic Lightbulb",
  62883. icon: "".concat(Potree.resourcePath, "/icons/matcap/ceramic_lightbulb.jpg")
  62884. }, {
  62885. name: "Clay Brown",
  62886. icon: "".concat(Potree.resourcePath, "/icons/matcap/clay_brown.jpg")
  62887. }, {
  62888. name: "Clay Muddy",
  62889. icon: "".concat(Potree.resourcePath, "/icons/matcap/clay_muddy.jpg")
  62890. }, {
  62891. name: "Clay Studio",
  62892. icon: "".concat(Potree.resourcePath, "/icons/matcap/clay_studio.jpg")
  62893. }, {
  62894. name: "Resin",
  62895. icon: "".concat(Potree.resourcePath, "/icons/matcap/resin.jpg")
  62896. }, {
  62897. name: "Skin",
  62898. icon: "".concat(Potree.resourcePath, "/icons/matcap/skin.jpg")
  62899. }, {
  62900. name: "Jade",
  62901. icon: "".concat(Potree.resourcePath, "/icons/matcap/jade.jpg")
  62902. }, {
  62903. name: "Metal_ Anisotropic",
  62904. icon: "".concat(Potree.resourcePath, "/icons/matcap/metal_anisotropic.jpg")
  62905. }, {
  62906. name: "Metal Carpaint",
  62907. icon: "".concat(Potree.resourcePath, "/icons/matcap/metal_carpaint.jpg")
  62908. }, {
  62909. name: "Metal Lead",
  62910. icon: "".concat(Potree.resourcePath, "/icons/matcap/metal_lead.jpg")
  62911. }, {
  62912. name: "Metal Shiny",
  62913. icon: "".concat(Potree.resourcePath, "/icons/matcap/metal_shiny.jpg")
  62914. }, {
  62915. name: "Pearl",
  62916. icon: "".concat(Potree.resourcePath, "/icons/matcap/pearl.jpg")
  62917. }, {
  62918. name: "Toon",
  62919. icon: "".concat(Potree.resourcePath, "/icons/matcap/toon.jpg")
  62920. }, {
  62921. name: "Check Rim Light",
  62922. icon: "".concat(Potree.resourcePath, "/icons/matcap/check_rim_light.jpg")
  62923. }, {
  62924. name: "Check Rim Dark",
  62925. icon: "".concat(Potree.resourcePath, "/icons/matcap/check_rim_dark.jpg")
  62926. }, {
  62927. name: "Contours 1",
  62928. icon: "".concat(Potree.resourcePath, "/icons/matcap/contours_1.jpg")
  62929. }, {
  62930. name: "Contours 2",
  62931. icon: "".concat(Potree.resourcePath, "/icons/matcap/contours_2.jpg")
  62932. }, {
  62933. name: "Contours 3",
  62934. icon: "".concat(Potree.resourcePath, "/icons/matcap/contours_3.jpg")
  62935. }, {
  62936. name: "Reflection Check Horizontal",
  62937. icon: "".concat(Potree.resourcePath, "/icons/matcap/reflection_check_horizontal.jpg")
  62938. }, {
  62939. name: "Reflection Check Vertical",
  62940. icon: "".concat(Potree.resourcePath, "/icons/matcap/reflection_check_vertical.jpg")
  62941. }];
  62942. var elMatcapContainer = panel.find("#matcap_scheme_selection");
  62943. var _loop2 = function _loop2(matcap) {
  62944. var elMatcap = $("\n\t\t\t\t\t\t<img src=\"".concat(matcap.icon, "\" class=\"button-icon\" style=\"width: 25%;\" />\n\t\t\t\t"));
  62945. elMatcap.click(() => {
  62946. material.matcap = matcap.icon.substring(matcap.icon.lastIndexOf('/'));
  62947. });
  62948. elMatcapContainer.append(elMatcap);
  62949. };
  62950. for (var matcap of matcaps) {
  62951. _loop2(matcap);
  62952. }
  62953. }
  62954. {
  62955. panel.find('#sldRGBGamma').slider({
  62956. value: material.rgbGamma,
  62957. min: 0,
  62958. max: 4,
  62959. step: 0.01,
  62960. slide: (event, ui) => {
  62961. material.rgbGamma = ui.value;
  62962. }
  62963. });
  62964. panel.find('#sldRGBContrast').slider({
  62965. value: material.rgbContrast,
  62966. min: -1,
  62967. max: 1,
  62968. step: 0.01,
  62969. slide: (event, ui) => {
  62970. material.rgbContrast = ui.value;
  62971. }
  62972. });
  62973. panel.find('#sldRGBBrightness').slider({
  62974. value: material.rgbBrightness,
  62975. min: -1,
  62976. max: 1,
  62977. step: 0.01,
  62978. slide: (event, ui) => {
  62979. material.rgbBrightness = ui.value;
  62980. }
  62981. });
  62982. panel.find('#sldExtraGamma').slider({
  62983. value: material.extraGamma,
  62984. min: 0,
  62985. max: 4,
  62986. step: 0.01,
  62987. slide: (event, ui) => {
  62988. material.extraGamma = ui.value;
  62989. }
  62990. });
  62991. panel.find('#sldExtraBrightness').slider({
  62992. value: material.extraBrightness,
  62993. min: -1,
  62994. max: 1,
  62995. step: 0.01,
  62996. slide: (event, ui) => {
  62997. material.extraBrightness = ui.value;
  62998. }
  62999. });
  63000. panel.find('#sldExtraContrast').slider({
  63001. value: material.extraContrast,
  63002. min: -1,
  63003. max: 1,
  63004. step: 0.01,
  63005. slide: (event, ui) => {
  63006. material.extraContrast = ui.value;
  63007. }
  63008. });
  63009. panel.find('#sldHeightRange').slider({
  63010. range: true,
  63011. min: 0,
  63012. max: 1000,
  63013. step: 0.01,
  63014. values: [0, 1000],
  63015. slide: (event, ui) => {
  63016. material.heightMin = ui.values[0];
  63017. material.heightMax = ui.values[1];
  63018. }
  63019. });
  63020. panel.find('#sldIntensityGamma').slider({
  63021. value: material.intensityGamma,
  63022. min: 0,
  63023. max: 4,
  63024. step: 0.01,
  63025. slide: (event, ui) => {
  63026. material.intensityGamma = ui.value;
  63027. }
  63028. });
  63029. panel.find('#sldIntensityContrast').slider({
  63030. value: material.intensityContrast,
  63031. min: -1,
  63032. max: 1,
  63033. step: 0.01,
  63034. slide: (event, ui) => {
  63035. material.intensityContrast = ui.value;
  63036. }
  63037. });
  63038. panel.find('#sldIntensityBrightness').slider({
  63039. value: material.intensityBrightness,
  63040. min: -1,
  63041. max: 1,
  63042. step: 0.01,
  63043. slide: (event, ui) => {
  63044. material.intensityBrightness = ui.value;
  63045. }
  63046. });
  63047. panel.find('#sldWeightRGB').slider({
  63048. value: material.weightRGB,
  63049. min: 0,
  63050. max: 1,
  63051. step: 0.01,
  63052. slide: (event, ui) => {
  63053. material.weightRGB = ui.value;
  63054. }
  63055. });
  63056. panel.find('#sldWeightIntensity').slider({
  63057. value: material.weightIntensity,
  63058. min: 0,
  63059. max: 1,
  63060. step: 0.01,
  63061. slide: (event, ui) => {
  63062. material.weightIntensity = ui.value;
  63063. }
  63064. });
  63065. panel.find('#sldWeightElevation').slider({
  63066. value: material.weightElevation,
  63067. min: 0,
  63068. max: 1,
  63069. step: 0.01,
  63070. slide: (event, ui) => {
  63071. material.weightElevation = ui.value;
  63072. }
  63073. });
  63074. panel.find('#sldWeightClassification').slider({
  63075. value: material.weightClassification,
  63076. min: 0,
  63077. max: 1,
  63078. step: 0.01,
  63079. slide: (event, ui) => {
  63080. material.weightClassification = ui.value;
  63081. }
  63082. });
  63083. panel.find('#sldWeightReturnNumber').slider({
  63084. value: material.weightReturnNumber,
  63085. min: 0,
  63086. max: 1,
  63087. step: 0.01,
  63088. slide: (event, ui) => {
  63089. material.weightReturnNumber = ui.value;
  63090. }
  63091. });
  63092. panel.find('#sldWeightSourceID').slider({
  63093. value: material.weightSourceID,
  63094. min: 0,
  63095. max: 1,
  63096. step: 0.01,
  63097. slide: (event, ui) => {
  63098. material.weightSourceID = ui.value;
  63099. }
  63100. });
  63101. panel.find("#materials\\.color\\.picker").spectrum({
  63102. flat: true,
  63103. showInput: true,
  63104. preferredFormat: 'rgb',
  63105. cancelText: '',
  63106. chooseText: 'Apply',
  63107. color: "#".concat(material.color.getHexString()),
  63108. move: color => {
  63109. var cRGB = color.toRgb();
  63110. var tc = new Color().setRGB(cRGB.r / 255, cRGB.g / 255, cRGB.b / 255);
  63111. material.color = tc;
  63112. },
  63113. change: color => {
  63114. var cRGB = color.toRgb();
  63115. var tc = new Color().setRGB(cRGB.r / 255, cRGB.g / 255, cRGB.b / 255);
  63116. material.color = tc;
  63117. }
  63118. });
  63119. this.addVolatileListener(material, "color_changed", () => {
  63120. panel.find("#materials\\.color\\.picker").spectrum('set', "#".concat(material.color.getHexString()));
  63121. });
  63122. var updateHeightRange = function updateHeightRange() {
  63123. var aPosition = pointcloud.getAttribute("position");
  63124. var bMin, bMax;
  63125. if (aPosition) {
  63126. // for new format 2.0 and loader that contain precomputed min/max of attributes
  63127. var min = aPosition.range[0][2];
  63128. var max = aPosition.range[1][2];
  63129. var width = max - min;
  63130. bMin = min - 0.2 * width;
  63131. bMax = max + 0.2 * width;
  63132. } else {
  63133. // for format up until exlusive 2.0
  63134. var box = [pointcloud.pcoGeometry.tightBoundingBox, pointcloud.getBoundingBoxWorld()].find(v => v !== undefined);
  63135. pointcloud.updateMatrixWorld(true);
  63136. box = Utils.computeTransformedBoundingBox(box, pointcloud.matrixWorld);
  63137. var bWidth = box.max.z - box.min.z;
  63138. bMin = box.min.z - 0.2 * bWidth;
  63139. bMax = box.max.z + 0.2 * bWidth;
  63140. }
  63141. var range = material.elevationRange;
  63142. panel.find('#lblHeightRange').html("".concat(range[0].toFixed(2), " to ").concat(range[1].toFixed(2)));
  63143. panel.find('#sldHeightRange').slider({
  63144. min: bMin,
  63145. max: bMax,
  63146. values: range
  63147. });
  63148. };
  63149. var updateExtraRange = function updateExtraRange() {
  63150. var attributeName = material.activeAttributeName;
  63151. var attribute = pointcloud.getAttribute(attributeName);
  63152. if (attribute == null) {
  63153. return;
  63154. }
  63155. var range = material.getRange(attributeName);
  63156. if (range == null) {
  63157. range = attribute.range;
  63158. }
  63159. // currently only supporting scalar ranges.
  63160. // rgba, normals, positions, etc have vector ranges, however
  63161. var isValidRange = typeof range[0] === "number" && typeof range[1] === "number";
  63162. if (!isValidRange) {
  63163. return;
  63164. }
  63165. if (range) {
  63166. var msg = "".concat(range[0].toFixed(2), " to ").concat(range[1].toFixed(2));
  63167. panel.find('#lblExtraRange').html(msg);
  63168. } else {
  63169. panel.find("could not deduce range");
  63170. }
  63171. };
  63172. var updateIntensityRange = function updateIntensityRange() {
  63173. var range = material.intensityRange;
  63174. panel.find('#lblIntensityRange').html("".concat(parseInt(range[0]), " to ").concat(parseInt(range[1])));
  63175. };
  63176. {
  63177. updateHeightRange();
  63178. panel.find("#sldHeightRange").slider('option', 'min');
  63179. panel.find("#sldHeightRange").slider('option', 'max');
  63180. }
  63181. {
  63182. var elGradientRepeat = panel.find("#gradient_repeat_option");
  63183. elGradientRepeat.selectgroup({
  63184. title: "Gradient"
  63185. });
  63186. elGradientRepeat.find("input").click(e => {
  63187. this.viewer.setElevationGradientRepeat(ElevationGradientRepeat[e.target.value]);
  63188. });
  63189. var current = Object.keys(ElevationGradientRepeat).filter(key => ElevationGradientRepeat[key] === this.viewer.elevationGradientRepeat);
  63190. elGradientRepeat.find("input[value=".concat(current, "]")).trigger("click");
  63191. }
  63192. var onIntensityChange = () => {
  63193. var gamma = material.intensityGamma;
  63194. var contrast = material.intensityContrast;
  63195. var brightness = material.intensityBrightness;
  63196. updateIntensityRange();
  63197. panel.find('#lblIntensityGamma').html(gamma.toFixed(2));
  63198. panel.find('#lblIntensityContrast').html(contrast.toFixed(2));
  63199. panel.find('#lblIntensityBrightness').html(brightness.toFixed(2));
  63200. panel.find('#sldIntensityGamma').slider({
  63201. value: gamma
  63202. });
  63203. panel.find('#sldIntensityContrast').slider({
  63204. value: contrast
  63205. });
  63206. panel.find('#sldIntensityBrightness').slider({
  63207. value: brightness
  63208. });
  63209. };
  63210. var onRGBChange = () => {
  63211. var gamma = material.rgbGamma;
  63212. var contrast = material.rgbContrast;
  63213. var brightness = material.rgbBrightness;
  63214. panel.find('#lblRGBGamma').html(gamma.toFixed(2));
  63215. panel.find('#lblRGBContrast').html(contrast.toFixed(2));
  63216. panel.find('#lblRGBBrightness').html(brightness.toFixed(2));
  63217. panel.find('#sldRGBGamma').slider({
  63218. value: gamma
  63219. });
  63220. panel.find('#sldRGBContrast').slider({
  63221. value: contrast
  63222. });
  63223. panel.find('#sldRGBBrightness').slider({
  63224. value: brightness
  63225. });
  63226. };
  63227. this.addVolatileListener(material, "material_property_changed", updateExtraRange);
  63228. this.addVolatileListener(material, "material_property_changed", updateHeightRange);
  63229. this.addVolatileListener(material, "material_property_changed", onIntensityChange);
  63230. this.addVolatileListener(material, "material_property_changed", onRGBChange);
  63231. updateExtraRange();
  63232. updateHeightRange();
  63233. onIntensityChange();
  63234. onRGBChange();
  63235. }
  63236. }
  63237. setMeasurement(object) {
  63238. var TYPE = {
  63239. DISTANCE: {
  63240. panel: DistancePanel
  63241. },
  63242. AREA: {
  63243. panel: AreaPanel
  63244. },
  63245. POINT: {
  63246. panel: PointPanel
  63247. },
  63248. ANGLE: {
  63249. panel: AnglePanel
  63250. },
  63251. HEIGHT: {
  63252. panel: HeightPanel
  63253. },
  63254. PROFILE: {
  63255. panel: ProfilePanel
  63256. },
  63257. VOLUME: {
  63258. panel: VolumePanel
  63259. },
  63260. CIRCLE: {
  63261. panel: CirclePanel
  63262. },
  63263. OTHER: {
  63264. panel: PointPanel
  63265. }
  63266. };
  63267. var getType = measurement => {
  63268. if (measurement instanceof Measure) {
  63269. if (measurement.showDistances && !measurement.showArea && !measurement.showAngles) {
  63270. return TYPE.DISTANCE;
  63271. } else if (measurement.showDistances && measurement.showArea && !measurement.showAngles) {
  63272. return TYPE.AREA;
  63273. } else if (measurement.maxMarkers === 1) {
  63274. return TYPE.POINT;
  63275. } else if (!measurement.showDistances && !measurement.showArea && measurement.showAngles) {
  63276. return TYPE.ANGLE;
  63277. } else if (measurement.showHeight) {
  63278. return TYPE.HEIGHT;
  63279. } else if (measurement.showCircle) {
  63280. return TYPE.CIRCLE;
  63281. } else {
  63282. return TYPE.OTHER;
  63283. }
  63284. } else if (measurement instanceof Profile) {
  63285. return TYPE.PROFILE;
  63286. } else if (measurement instanceof Volume) {
  63287. return TYPE.VOLUME;
  63288. }
  63289. };
  63290. //this.container.html("measurement");
  63291. var type = getType(object);
  63292. var Panel = type.panel;
  63293. var panel = new Panel(this.viewer, object, this);
  63294. this.container.append(panel.elContent);
  63295. }
  63296. setCamera(camera) {
  63297. var panel = new CameraPanel(this.viewer, this);
  63298. this.container.append(panel.elContent);
  63299. }
  63300. setAnnotation(annotation) {
  63301. var panel = new AnnotationPanel(this.viewer, this, annotation);
  63302. this.container.append(panel.elContent);
  63303. }
  63304. setCameraAnimation(animation) {
  63305. var panel = new CameraAnimationPanel(this.viewer, this, animation);
  63306. this.container.append(panel.elContent);
  63307. }
  63308. }
  63309. function addCommas(nStr) {
  63310. nStr += '';
  63311. var x = nStr.split('.');
  63312. var x1 = x[0];
  63313. var x2 = x.length > 1 ? '.' + x[1] : '';
  63314. var rgx = /(\d+)(\d{3})/;
  63315. while (rgx.test(x1)) {
  63316. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  63317. }
  63318. return x1 + x2;
  63319. }
  63320. ;
  63321. function format(value) {
  63322. return addCommas(value.toFixed(3));
  63323. }
  63324. ;
  63325. class HierarchicalSlider {
  63326. constructor() {
  63327. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  63328. this.element = document.createElement("div");
  63329. this.labels = [];
  63330. this.sliders = [];
  63331. this.range = params.range != null ? params.range : [0, 1];
  63332. this.slide = params.slide != null ? params.slide : null;
  63333. this.step = params.step != null ? params.step : 0.0001;
  63334. var levels = params.levels != null ? params.levels : 1;
  63335. for (var level = 0; level < levels; level++) {
  63336. this.addLevel();
  63337. }
  63338. }
  63339. setRange(range) {
  63340. this.range = [...range];
  63341. {
  63342. // root slider
  63343. var slider = this.sliders[0];
  63344. $(slider).slider({
  63345. min: range[0],
  63346. max: range[1]
  63347. });
  63348. }
  63349. for (var i = 1; i < this.sliders.length; i++) {
  63350. var parentSlider = this.sliders[i - 1];
  63351. var _slider = this.sliders[i];
  63352. var parentValues = $(parentSlider).slider("option", "values");
  63353. var childRange = [...parentValues];
  63354. $(_slider).slider({
  63355. min: childRange[0],
  63356. max: childRange[1]
  63357. });
  63358. }
  63359. this.updateLabels();
  63360. }
  63361. setValues(values) {
  63362. for (var slider of this.sliders) {
  63363. $(slider).slider({
  63364. values: [...values]
  63365. });
  63366. }
  63367. this.updateLabels();
  63368. }
  63369. addLevel() {
  63370. var elLevel = document.createElement("li");
  63371. var elRange = document.createTextNode("Range: ");
  63372. var label = document.createElement("span");
  63373. var slider = document.createElement("div");
  63374. var level = this.sliders.length;
  63375. var [min, max] = [0, 0];
  63376. if (this.sliders.length === 0) {
  63377. [min, max] = this.range;
  63378. } else {
  63379. var parentSlider = this.sliders[this.sliders.length - 1];
  63380. [min, max] = $(parentSlider).slider("option", "values");
  63381. }
  63382. $(slider).slider({
  63383. range: true,
  63384. min: min,
  63385. max: max,
  63386. step: this.step,
  63387. values: [min, max],
  63388. slide: (event, ui) => {
  63389. // set all descendants to same range
  63390. var levels = this.sliders.length;
  63391. for (var i = level + 1; i < levels; i++) {
  63392. var descendant = this.sliders[i];
  63393. $(descendant).slider({
  63394. range: true,
  63395. min: ui.values[0],
  63396. max: ui.values[1],
  63397. values: [...ui.values]
  63398. });
  63399. }
  63400. if (this.slide) {
  63401. var values = [...ui.values];
  63402. this.slide({
  63403. target: this,
  63404. range: this.range,
  63405. values: values
  63406. });
  63407. }
  63408. this.updateLabels();
  63409. }
  63410. });
  63411. elLevel.append(elRange, label, slider);
  63412. this.sliders.push(slider);
  63413. this.labels.push(label);
  63414. this.element.append(elLevel);
  63415. this.updateLabels();
  63416. }
  63417. removeLevel() {}
  63418. updateSliders() {}
  63419. updateLabels() {
  63420. var levels = this.sliders.length;
  63421. for (var i = 0; i < levels; i++) {
  63422. var slider = this.sliders[i];
  63423. var label = this.labels[i];
  63424. var [min, max] = $(slider).slider("option", "values");
  63425. var strMin = format(min);
  63426. var strMax = format(max);
  63427. var strLabel = "".concat(strMin, " to ").concat(strMax);
  63428. label.innerHTML = strLabel;
  63429. }
  63430. }
  63431. }
  63432. class OrientedImageControls extends EventDispatcher$1 {
  63433. constructor(viewer) {
  63434. super();
  63435. this.viewer = viewer;
  63436. this.renderer = viewer.renderer;
  63437. this.originalCam = viewer.scene.getActiveCamera();
  63438. this.shearCam = viewer.scene.getActiveCamera().clone();
  63439. this.shearCam.rotation.set(this.originalCam.rotation.toArray());
  63440. this.shearCam.updateProjectionMatrix();
  63441. this.shearCam.updateProjectionMatrix = () => {
  63442. return this.shearCam.projectionMatrix;
  63443. };
  63444. this.image = null;
  63445. this.fadeFactor = 20;
  63446. this.fovDelta = 0;
  63447. this.fovMin = 0.1;
  63448. this.fovMax = 120;
  63449. this.shear = [0, 0];
  63450. // const style = ``;
  63451. this.elUp = $("<input type=\"button\" value=\"\uD83E\uDC45\" style=\"position: absolute; top: 10px; left: calc(50%); z-index: 1000\" />");
  63452. this.elRight = $("<input type=\"button\" value=\"\uD83E\uDC46\" style=\"position: absolute; top: calc(50%); right: 10px; z-index: 1000\" />");
  63453. this.elDown = $("<input type=\"button\" value=\"\uD83E\uDC47\" style=\"position: absolute; bottom: 10px; left: calc(50%); z-index: 1000\" />");
  63454. this.elLeft = $("<input type=\"button\" value=\"\uD83E\uDC44\" style=\"position: absolute; top: calc(50%); left: 10px; z-index: 1000\" />");
  63455. this.elExit = $("<input type=\"button\" value=\"Back to 3D view\" style=\"position: absolute; bottom: 10px; right: 10px; z-index: 1000\" />");
  63456. this.elExit.click(() => {
  63457. this.release();
  63458. });
  63459. this.elUp.click(() => {
  63460. var fovY = viewer.getFOV();
  63461. var top = Math.tan(MathUtils.degToRad(fovY / 2));
  63462. this.shear[1] += 0.1 * top;
  63463. });
  63464. this.elRight.click(() => {
  63465. var fovY = viewer.getFOV();
  63466. var top = Math.tan(MathUtils.degToRad(fovY / 2));
  63467. this.shear[0] += 0.1 * top;
  63468. });
  63469. this.elDown.click(() => {
  63470. var fovY = viewer.getFOV();
  63471. var top = Math.tan(MathUtils.degToRad(fovY / 2));
  63472. this.shear[1] -= 0.1 * top;
  63473. });
  63474. this.elLeft.click(() => {
  63475. var fovY = viewer.getFOV();
  63476. var top = Math.tan(MathUtils.degToRad(fovY / 2));
  63477. this.shear[0] -= 0.1 * top;
  63478. });
  63479. this.scene = null;
  63480. this.sceneControls = new Scene();
  63481. var scroll = e => {
  63482. this.fovDelta += -e.delta * 1.0;
  63483. };
  63484. this.addEventListener('mousewheel', scroll);
  63485. //this.addEventListener("mousemove", onMove);
  63486. }
  63487. hasSomethingCaptured() {
  63488. return this.image !== null;
  63489. }
  63490. capture(image) {
  63491. if (this.hasSomethingCaptured()) {
  63492. return;
  63493. }
  63494. this.image = image;
  63495. this.originalFOV = this.viewer.getFOV();
  63496. this.originalControls = this.viewer.getControls();
  63497. this.viewer.setControls(this);
  63498. this.viewer.scene.overrideCamera = this.shearCam;
  63499. var elCanvas = this.viewer.renderer.domElement;
  63500. var elRoot = $(elCanvas.parentElement);
  63501. this.shear = [0, 0];
  63502. elRoot.append(this.elUp);
  63503. elRoot.append(this.elRight);
  63504. elRoot.append(this.elDown);
  63505. elRoot.append(this.elLeft);
  63506. elRoot.append(this.elExit);
  63507. }
  63508. release() {
  63509. this.image = null;
  63510. this.viewer.scene.overrideCamera = null;
  63511. this.elUp.detach();
  63512. this.elRight.detach();
  63513. this.elDown.detach();
  63514. this.elLeft.detach();
  63515. this.elExit.detach();
  63516. this.viewer.setFOV(this.originalFOV);
  63517. this.viewer.setControls(this.originalControls);
  63518. }
  63519. setScene(scene) {
  63520. this.scene = scene;
  63521. }
  63522. update(delta) {
  63523. // const view = this.scene.view;
  63524. // let prevTotal = this.shearCam.projectionMatrix.elements.reduce( (a, i) => a + i, 0);
  63525. //const progression = Math.min(1, this.fadeFactor * delta);
  63526. //const attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  63527. var progression = 1;
  63528. var attenuation = 0;
  63529. var oldFov = this.viewer.getFOV();
  63530. var fovProgression = progression * this.fovDelta;
  63531. var newFov = oldFov * (1 + fovProgression / 10);
  63532. newFov = Math.max(this.fovMin, newFov);
  63533. newFov = Math.min(this.fovMax, newFov);
  63534. var diff = newFov / oldFov;
  63535. var mouse = this.viewer.inputHandler.mouse;
  63536. var canvasSize = this.viewer.renderer.getSize(new Vector2());
  63537. var uv = [mouse.x / canvasSize.x, (canvasSize.y - mouse.y) / canvasSize.y];
  63538. var fovY = newFov;
  63539. var aspect = canvasSize.x / canvasSize.y;
  63540. var top = Math.tan(MathUtils.degToRad(fovY / 2));
  63541. var height = 2 * top;
  63542. var width = aspect * height;
  63543. var shearRangeX = [this.shear[0] - 0.5 * width, this.shear[0] + 0.5 * width];
  63544. var shearRangeY = [this.shear[1] - 0.5 * height, this.shear[1] + 0.5 * height];
  63545. var shx = (1 - uv[0]) * shearRangeX[0] + uv[0] * shearRangeX[1];
  63546. var shy = (1 - uv[1]) * shearRangeY[0] + uv[1] * shearRangeY[1];
  63547. var shu = 1 - diff;
  63548. var newShear = [(1 - shu) * this.shear[0] + shu * shx, (1 - shu) * this.shear[1] + shu * shy];
  63549. this.shear = newShear;
  63550. this.viewer.setFOV(newFov);
  63551. var {
  63552. originalCam,
  63553. shearCam
  63554. } = this;
  63555. originalCam.fov = newFov;
  63556. originalCam.updateMatrixWorld();
  63557. originalCam.updateProjectionMatrix();
  63558. shearCam.copy(originalCam);
  63559. shearCam.rotation.set(...originalCam.rotation.toArray());
  63560. shearCam.updateMatrixWorld();
  63561. shearCam.projectionMatrix.copy(originalCam.projectionMatrix);
  63562. var [sx, sy] = this.shear;
  63563. var mShear = new Matrix4().set(1, 0, sx, 0, 0, 1, sy, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  63564. var proj = shearCam.projectionMatrix;
  63565. proj.multiply(mShear);
  63566. shearCam.projectionMatrixInverse.copy(proj).invert();
  63567. var total = shearCam.projectionMatrix.elements.reduce((a, i) => a + i, 0);
  63568. this.fovDelta *= attenuation;
  63569. }
  63570. }
  63571. ;
  63572. // https://support.pix4d.com/hc/en-us/articles/205675256-How-are-yaw-pitch-roll-defined
  63573. // https://support.pix4d.com/hc/en-us/articles/202558969-How-are-omega-phi-kappa-defined
  63574. function createMaterial() {
  63575. var vertexShader = "\n\tuniform float uNear;\n\tvarying vec2 vUV;\n\tvarying vec4 vDebug;\n\t\n\tvoid main(){\n\t\tvDebug = vec4(0.0, 1.0, 0.0, 1.0);\n\t\tvec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n\t\t// make sure that this mesh is at least in front of the near plane\n\t\tmodelViewPosition.xyz += normalize(modelViewPosition.xyz) * uNear;\n\t\tgl_Position = projectionMatrix * modelViewPosition;\n\t\tvUV = uv;\n\t}\n\t";
  63576. var fragmentShader = "\n\tuniform sampler2D tColor;\n\tuniform float uOpacity;\n\tvarying vec2 vUV;\n\tvarying vec4 vDebug;\n\tvoid main(){\n\t\tvec4 color = texture2D(tColor, vUV);\n\t\tgl_FragColor = color;\n\t\tgl_FragColor.a = uOpacity;\n\t}\n\t";
  63577. var material = new ShaderMaterial({
  63578. uniforms: {
  63579. // time: { value: 1.0 },
  63580. // resolution: { value: new THREE.Vector2() }
  63581. tColor: {
  63582. value: new Texture()
  63583. },
  63584. uNear: {
  63585. value: 0.0
  63586. },
  63587. uOpacity: {
  63588. value: 1.0
  63589. }
  63590. },
  63591. vertexShader: vertexShader,
  63592. fragmentShader: fragmentShader,
  63593. side: DoubleSide
  63594. });
  63595. material.side = DoubleSide;
  63596. return material;
  63597. }
  63598. var planeGeometry$1 = new PlaneGeometry(1, 1);
  63599. var lineGeometry = new Geometry();
  63600. lineGeometry.vertices.push(new Vector3(-0.5, -0.5, 0), new Vector3(0.5, -0.5, 0), new Vector3(0.5, 0.5, 0), new Vector3(-0.5, 0.5, 0), new Vector3(-0.5, -0.5, 0));
  63601. class OrientedImage {
  63602. constructor(id) {
  63603. this.id = id;
  63604. this.fov = 1.0;
  63605. this.position = new Vector3();
  63606. this.rotation = new Vector3();
  63607. this.width = 0;
  63608. this.height = 0;
  63609. this.fov = 1.0;
  63610. var material = createMaterial();
  63611. var lineMaterial = new LineBasicMaterial({
  63612. color: 0x00ff00
  63613. });
  63614. this.mesh = new Mesh(planeGeometry$1, material);
  63615. this.line = new Line(lineGeometry, lineMaterial);
  63616. this.texture = null;
  63617. this.mesh.orientedImage = this;
  63618. }
  63619. set(position, rotation, dimension, fov) {
  63620. var radians = rotation.map(MathUtils.degToRad);
  63621. this.position.set(...position);
  63622. this.mesh.position.set(...position);
  63623. this.rotation.set(...radians);
  63624. this.mesh.rotation.set(...radians);
  63625. [this.width, this.height] = dimension;
  63626. this.mesh.scale.set(this.width / this.height, 1, 1);
  63627. this.fov = fov;
  63628. this.updateTransform();
  63629. }
  63630. updateTransform() {
  63631. var {
  63632. mesh,
  63633. line,
  63634. fov
  63635. } = this;
  63636. mesh.updateMatrixWorld();
  63637. var dir = mesh.getWorldDirection();
  63638. var alpha = MathUtils.degToRad(fov / 2);
  63639. var d = -0.5 / Math.tan(alpha);
  63640. var move = dir.clone().multiplyScalar(d);
  63641. mesh.position.add(move);
  63642. line.position.copy(mesh.position);
  63643. line.scale.copy(mesh.scale);
  63644. line.rotation.copy(mesh.rotation);
  63645. }
  63646. }
  63647. ;
  63648. class OrientedImages extends EventDispatcher$1 {
  63649. constructor() {
  63650. super();
  63651. this.node = null;
  63652. this.cameraParams = null;
  63653. this.imageParams = null;
  63654. this.images = null;
  63655. this._visible = true;
  63656. }
  63657. set visible(visible) {
  63658. if (this._visible === visible) {
  63659. return;
  63660. }
  63661. for (var image of this.images) {
  63662. image.mesh.visible = visible;
  63663. image.line.visible = visible;
  63664. }
  63665. this._visible = visible;
  63666. this.dispatchEvent({
  63667. type: "visibility_changed",
  63668. images: this
  63669. });
  63670. }
  63671. get visible() {
  63672. return this._visible;
  63673. }
  63674. }
  63675. ;
  63676. class OrientedImageLoader {
  63677. static async loadCameraParams(path) {
  63678. var res = await fetch(path);
  63679. var text = await res.text();
  63680. var parser = new DOMParser();
  63681. var doc = parser.parseFromString(text, "application/xml");
  63682. var width = parseInt(doc.getElementsByTagName("width")[0].textContent);
  63683. var height = parseInt(doc.getElementsByTagName("height")[0].textContent);
  63684. var f = parseFloat(doc.getElementsByTagName("f")[0].textContent);
  63685. var a = height / 2 / f;
  63686. var fov = 2 * MathUtils.radToDeg(Math.atan(a));
  63687. var params = {
  63688. path: path,
  63689. width: width,
  63690. height: height,
  63691. f: f,
  63692. fov: fov
  63693. };
  63694. return params;
  63695. }
  63696. static async loadImageParams(path) {
  63697. var response = await fetch(path);
  63698. if (!response.ok) {
  63699. console.error("failed to load ".concat(path));
  63700. return;
  63701. }
  63702. var content = await response.text();
  63703. var lines = content.split(/\r?\n/);
  63704. var imageParams = [];
  63705. for (var i = 1; i < lines.length; i++) {
  63706. var line = lines[i];
  63707. if (line.startsWith("#")) {
  63708. continue;
  63709. }
  63710. var tokens = line.split(/\s+/);
  63711. if (tokens.length < 6) {
  63712. continue;
  63713. }
  63714. var params = {
  63715. id: tokens[0],
  63716. x: Number.parseFloat(tokens[1]),
  63717. y: Number.parseFloat(tokens[2]),
  63718. z: Number.parseFloat(tokens[3]),
  63719. omega: Number.parseFloat(tokens[4]),
  63720. phi: Number.parseFloat(tokens[5]),
  63721. kappa: Number.parseFloat(tokens[6])
  63722. };
  63723. // const whitelist = ["47518.jpg"];
  63724. // if(whitelist.includes(params.id)){
  63725. // imageParams.push(params);
  63726. // }
  63727. imageParams.push(params);
  63728. }
  63729. // debug
  63730. //return [imageParams[50]];
  63731. return imageParams;
  63732. }
  63733. static async load(cameraParamsPath, imageParamsPath, viewer) {
  63734. var tStart = performance.now();
  63735. var [cameraParams, imageParams] = await Promise.all([OrientedImageLoader.loadCameraParams(cameraParamsPath), OrientedImageLoader.loadImageParams(imageParamsPath)]);
  63736. var orientedImageControls = new OrientedImageControls(viewer);
  63737. var raycaster = new Raycaster();
  63738. var tEnd = performance.now();
  63739. console.log(tEnd - tStart);
  63740. // const sp = new THREE.PlaneGeometry(1, 1);
  63741. // const lg = new THREE.Geometry();
  63742. // lg.vertices.push(
  63743. // new THREE.Vector3(-0.5, -0.5, 0),
  63744. // new THREE.Vector3( 0.5, -0.5, 0),
  63745. // new THREE.Vector3( 0.5, 0.5, 0),
  63746. // new THREE.Vector3(-0.5, 0.5, 0),
  63747. // new THREE.Vector3(-0.5, -0.5, 0),
  63748. // );
  63749. var {
  63750. width,
  63751. height
  63752. } = cameraParams;
  63753. var orientedImages = [];
  63754. var sceneNode = new Object3D();
  63755. sceneNode.name = "oriented_images";
  63756. for (var params of imageParams) {
  63757. // const material = createMaterial();
  63758. // const lm = new THREE.LineBasicMaterial( { color: 0x00ff00 } );
  63759. // const mesh = new THREE.Mesh(sp, material);
  63760. var {
  63761. x,
  63762. y,
  63763. z,
  63764. omega,
  63765. phi,
  63766. kappa
  63767. } = params;
  63768. // const [rx, ry, rz] = [omega, phi, kappa]
  63769. // .map(THREE.Math.degToRad);
  63770. // mesh.position.set(x, y, z);
  63771. // mesh.scale.set(width / height, 1, 1);
  63772. // mesh.rotation.set(rx, ry, rz);
  63773. // {
  63774. // mesh.updateMatrixWorld();
  63775. // const dir = mesh.getWorldDirection();
  63776. // const alpha = THREE.Math.degToRad(cameraParams.fov / 2);
  63777. // const d = -0.5 / Math.tan(alpha);
  63778. // const move = dir.clone().multiplyScalar(d);
  63779. // mesh.position.add(move);
  63780. // }
  63781. // sceneNode.add(mesh);
  63782. // const line = new THREE.Line(lg, lm);
  63783. // line.position.copy(mesh.position);
  63784. // line.scale.copy(mesh.scale);
  63785. // line.rotation.copy(mesh.rotation);
  63786. // sceneNode.add(line);
  63787. var orientedImage = new OrientedImage(params.id);
  63788. // orientedImage.setPosition(x, y, z);
  63789. // orientedImage.setRotation(omega, phi, kappa);
  63790. // orientedImage.setDimension(width, height);
  63791. var position = [x, y, z];
  63792. var rotation = [omega, phi, kappa];
  63793. var dimension = [width, height];
  63794. orientedImage.set(position, rotation, dimension, cameraParams.fov);
  63795. sceneNode.add(orientedImage.mesh);
  63796. sceneNode.add(orientedImage.line);
  63797. orientedImages.push(orientedImage);
  63798. }
  63799. var hoveredElement = null;
  63800. var clipVolume = null;
  63801. var onMouseMove = evt => {
  63802. var tStart = performance.now();
  63803. if (hoveredElement) {
  63804. hoveredElement.line.material.color.setRGB(0, 1, 0);
  63805. }
  63806. evt.preventDefault();
  63807. //var array = getMousePosition( container, evt.clientX, evt.clientY );
  63808. var rect = viewer.renderer.domElement.getBoundingClientRect();
  63809. var [x, y] = [evt.clientX, evt.clientY];
  63810. var array = [(x - rect.left) / rect.width, (y - rect.top) / rect.height];
  63811. var onClickPosition = new Vector2(...array);
  63812. //const intersects = getIntersects(onClickPosition, scene.children);
  63813. var camera = viewer.scene.getActiveCamera();
  63814. var mouse = new Vector3(+(onClickPosition.x * 2) - 1, -(onClickPosition.y * 2) + 1);
  63815. var objects = orientedImages.map(i => i.mesh);
  63816. raycaster.setFromCamera(mouse, camera);
  63817. var intersects = raycaster.intersectObjects(objects);
  63818. var selectionChanged = false;
  63819. if (intersects.length > 0) {
  63820. //console.log(intersects);
  63821. var intersection = intersects[0];
  63822. var _orientedImage = intersection.object.orientedImage;
  63823. _orientedImage.line.material.color.setRGB(1, 0, 0);
  63824. selectionChanged = hoveredElement !== _orientedImage;
  63825. hoveredElement = _orientedImage;
  63826. } else {
  63827. hoveredElement = null;
  63828. }
  63829. var shouldRemoveClipVolume = clipVolume !== null && hoveredElement === null;
  63830. var shouldAddClipVolume = clipVolume === null && hoveredElement !== null;
  63831. if (clipVolume !== null && (hoveredElement === null || selectionChanged)) {
  63832. // remove existing
  63833. viewer.scene.removePolygonClipVolume(clipVolume);
  63834. clipVolume = null;
  63835. }
  63836. if (shouldAddClipVolume || selectionChanged) {
  63837. var img = hoveredElement;
  63838. var fov = cameraParams.fov;
  63839. var aspect = cameraParams.width / cameraParams.height;
  63840. var near = 1.0;
  63841. var far = 1000 * 1000;
  63842. var _camera = new PerspectiveCamera(fov, aspect, near, far);
  63843. _camera.rotation.order = viewer.scene.getActiveCamera().rotation.order;
  63844. _camera.rotation.copy(img.mesh.rotation);
  63845. {
  63846. var mesh = img.mesh;
  63847. var dir = mesh.getWorldDirection();
  63848. var pos = mesh.position;
  63849. var alpha = MathUtils.degToRad(fov / 2);
  63850. var d = 0.5 / Math.tan(alpha);
  63851. var newCamPos = pos.clone().add(dir.clone().multiplyScalar(d));
  63852. var newCamDir = pos.clone().sub(newCamPos);
  63853. var newCamTarget = new Vector3().addVectors(newCamPos, newCamDir.clone().multiplyScalar(viewer.getMoveSpeed()));
  63854. _camera.position.copy(newCamPos);
  63855. }
  63856. var volume = new Potree.PolygonClipVolume(_camera);
  63857. var m0 = new Mesh();
  63858. var m1 = new Mesh();
  63859. var m2 = new Mesh();
  63860. var m3 = new Mesh();
  63861. m0.position.set(-1, -1, 0);
  63862. m1.position.set(1, -1, 0);
  63863. m2.position.set(1, 1, 0);
  63864. m3.position.set(-1, 1, 0);
  63865. volume.markers.push(m0, m1, m2, m3);
  63866. volume.initialized = true;
  63867. viewer.scene.addPolygonClipVolume(volume);
  63868. clipVolume = volume;
  63869. }
  63870. var tEnd = performance.now();
  63871. //console.log(tEnd - tStart);
  63872. };
  63873. var moveToImage = image => {
  63874. console.log("move to image " + image.id);
  63875. var mesh = image.mesh;
  63876. var newCamPos = image.position.clone();
  63877. var newCamTarget = mesh.position.clone();
  63878. viewer.scene.view.setView(newCamPos, newCamTarget, 500, () => {
  63879. orientedImageControls.capture(image);
  63880. });
  63881. if (image.texture === null) {
  63882. var target = image;
  63883. var tmpImagePath = "".concat(Potree.resourcePath, "/images/loading.jpg");
  63884. new TextureLoader().load(tmpImagePath, texture => {
  63885. if (target.texture === null) {
  63886. target.texture = texture;
  63887. target.mesh.material.uniforms.tColor.value = texture;
  63888. mesh.material.needsUpdate = true;
  63889. }
  63890. });
  63891. var imagePath = "".concat(imageParamsPath, "/../").concat(target.id);
  63892. new TextureLoader().load(imagePath, texture => {
  63893. target.texture = texture;
  63894. target.mesh.material.uniforms.tColor.value = texture;
  63895. mesh.material.needsUpdate = true;
  63896. });
  63897. }
  63898. };
  63899. var onMouseClick = evt => {
  63900. if (orientedImageControls.hasSomethingCaptured()) {
  63901. return;
  63902. }
  63903. if (hoveredElement) {
  63904. moveToImage(hoveredElement);
  63905. }
  63906. };
  63907. viewer.renderer.domElement.addEventListener('mousemove', onMouseMove, false);
  63908. viewer.renderer.domElement.addEventListener('mousedown', onMouseClick, false);
  63909. viewer.addEventListener("update", () => {
  63910. for (var image of orientedImages) {
  63911. var world = image.mesh.matrixWorld;
  63912. var {
  63913. width: _width,
  63914. height: _height
  63915. } = image;
  63916. var aspect = _width / _height;
  63917. var camera = viewer.scene.getActiveCamera();
  63918. var imgPos = image.mesh.getWorldPosition(new Vector3());
  63919. var camPos = camera.position;
  63920. var d = camPos.distanceTo(imgPos);
  63921. var minSize = 1; // in degrees of fov
  63922. var a = MathUtils.degToRad(minSize);
  63923. var r = d * Math.tan(a);
  63924. r = Math.max(r, 1);
  63925. image.mesh.scale.set(r * aspect, r, 1);
  63926. image.line.scale.set(r * aspect, r, 1);
  63927. image.mesh.material.uniforms.uNear.value = camera.near;
  63928. }
  63929. });
  63930. var images = new OrientedImages();
  63931. images.node = sceneNode;
  63932. images.cameraParamsPath = cameraParamsPath;
  63933. images.imageParamsPath = imageParamsPath;
  63934. images.cameraParams = cameraParams;
  63935. images.imageParams = imageParams;
  63936. images.images = orientedImages;
  63937. Potree.debug.moveToImage = moveToImage;
  63938. return images;
  63939. }
  63940. }
  63941. // This is a generated file. Do not edit.
  63942. var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
  63943. 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]/;
  63944. 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]/;
  63945. var unicode = {
  63946. Space_Separator: Space_Separator,
  63947. ID_Start: ID_Start,
  63948. ID_Continue: ID_Continue
  63949. };
  63950. var util = {
  63951. isSpaceSeparator(c) {
  63952. return typeof c === 'string' && unicode.Space_Separator.test(c);
  63953. },
  63954. isIdStartChar(c) {
  63955. return typeof c === 'string' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c === '$' || c === '_' || unicode.ID_Start.test(c));
  63956. },
  63957. isIdContinueChar(c) {
  63958. return typeof c === 'string' && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c === '$' || c === '_' || c === '\u200C' || c === '\u200D' || unicode.ID_Continue.test(c));
  63959. },
  63960. isDigit(c) {
  63961. return typeof c === 'string' && /[0-9]/.test(c);
  63962. },
  63963. isHexDigit(c) {
  63964. return typeof c === 'string' && /[0-9A-Fa-f]/.test(c);
  63965. }
  63966. };
  63967. var source;
  63968. var parseState;
  63969. var stack$1;
  63970. var pos;
  63971. var line;
  63972. var column;
  63973. var token;
  63974. var key;
  63975. var root;
  63976. var parse$4 = function parse(text, reviver) {
  63977. source = String(text);
  63978. parseState = 'start';
  63979. stack$1 = [];
  63980. pos = 0;
  63981. line = 1;
  63982. column = 0;
  63983. token = undefined;
  63984. key = undefined;
  63985. root = undefined;
  63986. do {
  63987. token = lex();
  63988. // This code is unreachable.
  63989. // if (!parseStates[parseState]) {
  63990. // throw invalidParseState()
  63991. // }
  63992. parseStates[parseState]();
  63993. } while (token.type !== 'eof');
  63994. if (typeof reviver === 'function') {
  63995. return internalize({
  63996. '': root
  63997. }, '', reviver);
  63998. }
  63999. return root;
  64000. };
  64001. function internalize(holder, name, reviver) {
  64002. var value = holder[name];
  64003. if (value != null && typeof value === 'object') {
  64004. for (var _key in value) {
  64005. var replacement = internalize(value, _key, reviver);
  64006. if (replacement === undefined) {
  64007. delete value[_key];
  64008. } else {
  64009. value[_key] = replacement;
  64010. }
  64011. }
  64012. }
  64013. return reviver.call(holder, name, value);
  64014. }
  64015. var lexState;
  64016. var buffer;
  64017. var doubleQuote;
  64018. var sign$1;
  64019. var c$2;
  64020. function lex() {
  64021. lexState = 'default';
  64022. buffer = '';
  64023. doubleQuote = false;
  64024. sign$1 = 1;
  64025. for (;;) {
  64026. c$2 = peek();
  64027. // This code is unreachable.
  64028. // if (!lexStates[lexState]) {
  64029. // throw invalidLexState(lexState)
  64030. // }
  64031. var _token = lexStates[lexState]();
  64032. if (_token) {
  64033. return _token;
  64034. }
  64035. }
  64036. }
  64037. function peek() {
  64038. if (source[pos]) {
  64039. return String.fromCodePoint(source.codePointAt(pos));
  64040. }
  64041. }
  64042. function read() {
  64043. var c = peek();
  64044. if (c === '\n') {
  64045. line++;
  64046. column = 0;
  64047. } else if (c) {
  64048. column += c.length;
  64049. } else {
  64050. column++;
  64051. }
  64052. if (c) {
  64053. pos += c.length;
  64054. }
  64055. return c;
  64056. }
  64057. var lexStates = {
  64058. default() {
  64059. switch (c$2) {
  64060. case '\t':
  64061. case '\v':
  64062. case '\f':
  64063. case ' ':
  64064. case '\u00A0':
  64065. case '\uFEFF':
  64066. case '\n':
  64067. case '\r':
  64068. case '\u2028':
  64069. case '\u2029':
  64070. read();
  64071. return;
  64072. case '/':
  64073. read();
  64074. lexState = 'comment';
  64075. return;
  64076. case undefined:
  64077. read();
  64078. return newToken('eof');
  64079. }
  64080. if (util.isSpaceSeparator(c$2)) {
  64081. read();
  64082. return;
  64083. }
  64084. // This code is unreachable.
  64085. // if (!lexStates[parseState]) {
  64086. // throw invalidLexState(parseState)
  64087. // }
  64088. return lexStates[parseState]();
  64089. },
  64090. comment() {
  64091. switch (c$2) {
  64092. case '*':
  64093. read();
  64094. lexState = 'multiLineComment';
  64095. return;
  64096. case '/':
  64097. read();
  64098. lexState = 'singleLineComment';
  64099. return;
  64100. }
  64101. throw invalidChar(read());
  64102. },
  64103. multiLineComment() {
  64104. switch (c$2) {
  64105. case '*':
  64106. read();
  64107. lexState = 'multiLineCommentAsterisk';
  64108. return;
  64109. case undefined:
  64110. throw invalidChar(read());
  64111. }
  64112. read();
  64113. },
  64114. multiLineCommentAsterisk() {
  64115. switch (c$2) {
  64116. case '*':
  64117. read();
  64118. return;
  64119. case '/':
  64120. read();
  64121. lexState = 'default';
  64122. return;
  64123. case undefined:
  64124. throw invalidChar(read());
  64125. }
  64126. read();
  64127. lexState = 'multiLineComment';
  64128. },
  64129. singleLineComment() {
  64130. switch (c$2) {
  64131. case '\n':
  64132. case '\r':
  64133. case '\u2028':
  64134. case '\u2029':
  64135. read();
  64136. lexState = 'default';
  64137. return;
  64138. case undefined:
  64139. read();
  64140. return newToken('eof');
  64141. }
  64142. read();
  64143. },
  64144. value() {
  64145. switch (c$2) {
  64146. case '{':
  64147. case '[':
  64148. return newToken('punctuator', read());
  64149. case 'n':
  64150. read();
  64151. literal('ull');
  64152. return newToken('null', null);
  64153. case 't':
  64154. read();
  64155. literal('rue');
  64156. return newToken('boolean', true);
  64157. case 'f':
  64158. read();
  64159. literal('alse');
  64160. return newToken('boolean', false);
  64161. case '-':
  64162. case '+':
  64163. if (read() === '-') {
  64164. sign$1 = -1;
  64165. }
  64166. lexState = 'sign';
  64167. return;
  64168. case '.':
  64169. buffer = read();
  64170. lexState = 'decimalPointLeading';
  64171. return;
  64172. case '0':
  64173. buffer = read();
  64174. lexState = 'zero';
  64175. return;
  64176. case '1':
  64177. case '2':
  64178. case '3':
  64179. case '4':
  64180. case '5':
  64181. case '6':
  64182. case '7':
  64183. case '8':
  64184. case '9':
  64185. buffer = read();
  64186. lexState = 'decimalInteger';
  64187. return;
  64188. case 'I':
  64189. read();
  64190. literal('nfinity');
  64191. return newToken('numeric', Infinity);
  64192. case 'N':
  64193. read();
  64194. literal('aN');
  64195. return newToken('numeric', NaN);
  64196. case '"':
  64197. case "'":
  64198. doubleQuote = read() === '"';
  64199. buffer = '';
  64200. lexState = 'string';
  64201. return;
  64202. }
  64203. throw invalidChar(read());
  64204. },
  64205. identifierNameStartEscape() {
  64206. if (c$2 !== 'u') {
  64207. throw invalidChar(read());
  64208. }
  64209. read();
  64210. var u = unicodeEscape();
  64211. switch (u) {
  64212. case '$':
  64213. case '_':
  64214. break;
  64215. default:
  64216. if (!util.isIdStartChar(u)) {
  64217. throw invalidIdentifier();
  64218. }
  64219. break;
  64220. }
  64221. buffer += u;
  64222. lexState = 'identifierName';
  64223. },
  64224. identifierName() {
  64225. switch (c$2) {
  64226. case '$':
  64227. case '_':
  64228. case '\u200C':
  64229. case '\u200D':
  64230. buffer += read();
  64231. return;
  64232. case '\\':
  64233. read();
  64234. lexState = 'identifierNameEscape';
  64235. return;
  64236. }
  64237. if (util.isIdContinueChar(c$2)) {
  64238. buffer += read();
  64239. return;
  64240. }
  64241. return newToken('identifier', buffer);
  64242. },
  64243. identifierNameEscape() {
  64244. if (c$2 !== 'u') {
  64245. throw invalidChar(read());
  64246. }
  64247. read();
  64248. var u = unicodeEscape();
  64249. switch (u) {
  64250. case '$':
  64251. case '_':
  64252. case '\u200C':
  64253. case '\u200D':
  64254. break;
  64255. default:
  64256. if (!util.isIdContinueChar(u)) {
  64257. throw invalidIdentifier();
  64258. }
  64259. break;
  64260. }
  64261. buffer += u;
  64262. lexState = 'identifierName';
  64263. },
  64264. sign() {
  64265. switch (c$2) {
  64266. case '.':
  64267. buffer = read();
  64268. lexState = 'decimalPointLeading';
  64269. return;
  64270. case '0':
  64271. buffer = read();
  64272. lexState = 'zero';
  64273. return;
  64274. case '1':
  64275. case '2':
  64276. case '3':
  64277. case '4':
  64278. case '5':
  64279. case '6':
  64280. case '7':
  64281. case '8':
  64282. case '9':
  64283. buffer = read();
  64284. lexState = 'decimalInteger';
  64285. return;
  64286. case 'I':
  64287. read();
  64288. literal('nfinity');
  64289. return newToken('numeric', sign$1 * Infinity);
  64290. case 'N':
  64291. read();
  64292. literal('aN');
  64293. return newToken('numeric', NaN);
  64294. }
  64295. throw invalidChar(read());
  64296. },
  64297. zero() {
  64298. switch (c$2) {
  64299. case '.':
  64300. buffer += read();
  64301. lexState = 'decimalPoint';
  64302. return;
  64303. case 'e':
  64304. case 'E':
  64305. buffer += read();
  64306. lexState = 'decimalExponent';
  64307. return;
  64308. case 'x':
  64309. case 'X':
  64310. buffer += read();
  64311. lexState = 'hexadecimal';
  64312. return;
  64313. }
  64314. return newToken('numeric', sign$1 * 0);
  64315. },
  64316. decimalInteger() {
  64317. switch (c$2) {
  64318. case '.':
  64319. buffer += read();
  64320. lexState = 'decimalPoint';
  64321. return;
  64322. case 'e':
  64323. case 'E':
  64324. buffer += read();
  64325. lexState = 'decimalExponent';
  64326. return;
  64327. }
  64328. if (util.isDigit(c$2)) {
  64329. buffer += read();
  64330. return;
  64331. }
  64332. return newToken('numeric', sign$1 * Number(buffer));
  64333. },
  64334. decimalPointLeading() {
  64335. if (util.isDigit(c$2)) {
  64336. buffer += read();
  64337. lexState = 'decimalFraction';
  64338. return;
  64339. }
  64340. throw invalidChar(read());
  64341. },
  64342. decimalPoint() {
  64343. switch (c$2) {
  64344. case 'e':
  64345. case 'E':
  64346. buffer += read();
  64347. lexState = 'decimalExponent';
  64348. return;
  64349. }
  64350. if (util.isDigit(c$2)) {
  64351. buffer += read();
  64352. lexState = 'decimalFraction';
  64353. return;
  64354. }
  64355. return newToken('numeric', sign$1 * Number(buffer));
  64356. },
  64357. decimalFraction() {
  64358. switch (c$2) {
  64359. case 'e':
  64360. case 'E':
  64361. buffer += read();
  64362. lexState = 'decimalExponent';
  64363. return;
  64364. }
  64365. if (util.isDigit(c$2)) {
  64366. buffer += read();
  64367. return;
  64368. }
  64369. return newToken('numeric', sign$1 * Number(buffer));
  64370. },
  64371. decimalExponent() {
  64372. switch (c$2) {
  64373. case '+':
  64374. case '-':
  64375. buffer += read();
  64376. lexState = 'decimalExponentSign';
  64377. return;
  64378. }
  64379. if (util.isDigit(c$2)) {
  64380. buffer += read();
  64381. lexState = 'decimalExponentInteger';
  64382. return;
  64383. }
  64384. throw invalidChar(read());
  64385. },
  64386. decimalExponentSign() {
  64387. if (util.isDigit(c$2)) {
  64388. buffer += read();
  64389. lexState = 'decimalExponentInteger';
  64390. return;
  64391. }
  64392. throw invalidChar(read());
  64393. },
  64394. decimalExponentInteger() {
  64395. if (util.isDigit(c$2)) {
  64396. buffer += read();
  64397. return;
  64398. }
  64399. return newToken('numeric', sign$1 * Number(buffer));
  64400. },
  64401. hexadecimal() {
  64402. if (util.isHexDigit(c$2)) {
  64403. buffer += read();
  64404. lexState = 'hexadecimalInteger';
  64405. return;
  64406. }
  64407. throw invalidChar(read());
  64408. },
  64409. hexadecimalInteger() {
  64410. if (util.isHexDigit(c$2)) {
  64411. buffer += read();
  64412. return;
  64413. }
  64414. return newToken('numeric', sign$1 * Number(buffer));
  64415. },
  64416. string() {
  64417. switch (c$2) {
  64418. case '\\':
  64419. read();
  64420. buffer += escape$1();
  64421. return;
  64422. case '"':
  64423. if (doubleQuote) {
  64424. read();
  64425. return newToken('string', buffer);
  64426. }
  64427. buffer += read();
  64428. return;
  64429. case "'":
  64430. if (!doubleQuote) {
  64431. read();
  64432. return newToken('string', buffer);
  64433. }
  64434. buffer += read();
  64435. return;
  64436. case '\n':
  64437. case '\r':
  64438. throw invalidChar(read());
  64439. case '\u2028':
  64440. case '\u2029':
  64441. separatorChar(c$2);
  64442. break;
  64443. case undefined:
  64444. throw invalidChar(read());
  64445. }
  64446. buffer += read();
  64447. },
  64448. start() {
  64449. switch (c$2) {
  64450. case '{':
  64451. case '[':
  64452. return newToken('punctuator', read());
  64453. // This code is unreachable since the default lexState handles eof.
  64454. // case undefined:
  64455. // return newToken('eof')
  64456. }
  64457. lexState = 'value';
  64458. },
  64459. beforePropertyName() {
  64460. switch (c$2) {
  64461. case '$':
  64462. case '_':
  64463. buffer = read();
  64464. lexState = 'identifierName';
  64465. return;
  64466. case '\\':
  64467. read();
  64468. lexState = 'identifierNameStartEscape';
  64469. return;
  64470. case '}':
  64471. return newToken('punctuator', read());
  64472. case '"':
  64473. case "'":
  64474. doubleQuote = read() === '"';
  64475. lexState = 'string';
  64476. return;
  64477. }
  64478. if (util.isIdStartChar(c$2)) {
  64479. buffer += read();
  64480. lexState = 'identifierName';
  64481. return;
  64482. }
  64483. throw invalidChar(read());
  64484. },
  64485. afterPropertyName() {
  64486. if (c$2 === ':') {
  64487. return newToken('punctuator', read());
  64488. }
  64489. throw invalidChar(read());
  64490. },
  64491. beforePropertyValue() {
  64492. lexState = 'value';
  64493. },
  64494. afterPropertyValue() {
  64495. switch (c$2) {
  64496. case ',':
  64497. case '}':
  64498. return newToken('punctuator', read());
  64499. }
  64500. throw invalidChar(read());
  64501. },
  64502. beforeArrayValue() {
  64503. if (c$2 === ']') {
  64504. return newToken('punctuator', read());
  64505. }
  64506. lexState = 'value';
  64507. },
  64508. afterArrayValue() {
  64509. switch (c$2) {
  64510. case ',':
  64511. case ']':
  64512. return newToken('punctuator', read());
  64513. }
  64514. throw invalidChar(read());
  64515. },
  64516. end() {
  64517. // This code is unreachable since it's handled by the default lexState.
  64518. // if (c === undefined) {
  64519. // read()
  64520. // return newToken('eof')
  64521. // }
  64522. throw invalidChar(read());
  64523. }
  64524. };
  64525. function newToken(type, value) {
  64526. return {
  64527. type,
  64528. value,
  64529. line,
  64530. column
  64531. };
  64532. }
  64533. function literal(s) {
  64534. for (var _c of s) {
  64535. var p = peek();
  64536. if (p !== _c) {
  64537. throw invalidChar(read());
  64538. }
  64539. read();
  64540. }
  64541. }
  64542. function escape$1() {
  64543. var c = peek();
  64544. switch (c) {
  64545. case 'b':
  64546. read();
  64547. return '\b';
  64548. case 'f':
  64549. read();
  64550. return '\f';
  64551. case 'n':
  64552. read();
  64553. return '\n';
  64554. case 'r':
  64555. read();
  64556. return '\r';
  64557. case 't':
  64558. read();
  64559. return '\t';
  64560. case 'v':
  64561. read();
  64562. return '\v';
  64563. case '0':
  64564. read();
  64565. if (util.isDigit(peek())) {
  64566. throw invalidChar(read());
  64567. }
  64568. return '\0';
  64569. case 'x':
  64570. read();
  64571. return hexEscape();
  64572. case 'u':
  64573. read();
  64574. return unicodeEscape();
  64575. case '\n':
  64576. case '\u2028':
  64577. case '\u2029':
  64578. read();
  64579. return '';
  64580. case '\r':
  64581. read();
  64582. if (peek() === '\n') {
  64583. read();
  64584. }
  64585. return '';
  64586. case '1':
  64587. case '2':
  64588. case '3':
  64589. case '4':
  64590. case '5':
  64591. case '6':
  64592. case '7':
  64593. case '8':
  64594. case '9':
  64595. throw invalidChar(read());
  64596. case undefined:
  64597. throw invalidChar(read());
  64598. }
  64599. return read();
  64600. }
  64601. function hexEscape() {
  64602. var buffer = '';
  64603. var c = peek();
  64604. if (!util.isHexDigit(c)) {
  64605. throw invalidChar(read());
  64606. }
  64607. buffer += read();
  64608. c = peek();
  64609. if (!util.isHexDigit(c)) {
  64610. throw invalidChar(read());
  64611. }
  64612. buffer += read();
  64613. return String.fromCodePoint(parseInt(buffer, 16));
  64614. }
  64615. function unicodeEscape() {
  64616. var buffer = '';
  64617. var count = 4;
  64618. while (count-- > 0) {
  64619. var _c2 = peek();
  64620. if (!util.isHexDigit(_c2)) {
  64621. throw invalidChar(read());
  64622. }
  64623. buffer += read();
  64624. }
  64625. return String.fromCodePoint(parseInt(buffer, 16));
  64626. }
  64627. var parseStates = {
  64628. start() {
  64629. if (token.type === 'eof') {
  64630. throw invalidEOF();
  64631. }
  64632. push();
  64633. },
  64634. beforePropertyName() {
  64635. switch (token.type) {
  64636. case 'identifier':
  64637. case 'string':
  64638. key = token.value;
  64639. parseState = 'afterPropertyName';
  64640. return;
  64641. case 'punctuator':
  64642. // This code is unreachable since it's handled by the lexState.
  64643. // if (token.value !== '}') {
  64644. // throw invalidToken()
  64645. // }
  64646. pop();
  64647. return;
  64648. case 'eof':
  64649. throw invalidEOF();
  64650. }
  64651. // This code is unreachable since it's handled by the lexState.
  64652. // throw invalidToken()
  64653. },
  64654. afterPropertyName() {
  64655. // This code is unreachable since it's handled by the lexState.
  64656. // if (token.type !== 'punctuator' || token.value !== ':') {
  64657. // throw invalidToken()
  64658. // }
  64659. if (token.type === 'eof') {
  64660. throw invalidEOF();
  64661. }
  64662. parseState = 'beforePropertyValue';
  64663. },
  64664. beforePropertyValue() {
  64665. if (token.type === 'eof') {
  64666. throw invalidEOF();
  64667. }
  64668. push();
  64669. },
  64670. beforeArrayValue() {
  64671. if (token.type === 'eof') {
  64672. throw invalidEOF();
  64673. }
  64674. if (token.type === 'punctuator' && token.value === ']') {
  64675. pop();
  64676. return;
  64677. }
  64678. push();
  64679. },
  64680. afterPropertyValue() {
  64681. // This code is unreachable since it's handled by the lexState.
  64682. // if (token.type !== 'punctuator') {
  64683. // throw invalidToken()
  64684. // }
  64685. if (token.type === 'eof') {
  64686. throw invalidEOF();
  64687. }
  64688. switch (token.value) {
  64689. case ',':
  64690. parseState = 'beforePropertyName';
  64691. return;
  64692. case '}':
  64693. pop();
  64694. }
  64695. // This code is unreachable since it's handled by the lexState.
  64696. // throw invalidToken()
  64697. },
  64698. afterArrayValue() {
  64699. // This code is unreachable since it's handled by the lexState.
  64700. // if (token.type !== 'punctuator') {
  64701. // throw invalidToken()
  64702. // }
  64703. if (token.type === 'eof') {
  64704. throw invalidEOF();
  64705. }
  64706. switch (token.value) {
  64707. case ',':
  64708. parseState = 'beforeArrayValue';
  64709. return;
  64710. case ']':
  64711. pop();
  64712. }
  64713. // This code is unreachable since it's handled by the lexState.
  64714. // throw invalidToken()
  64715. },
  64716. end() {
  64717. // This code is unreachable since it's handled by the lexState.
  64718. // if (token.type !== 'eof') {
  64719. // throw invalidToken()
  64720. // }
  64721. }
  64722. };
  64723. function push() {
  64724. var value;
  64725. switch (token.type) {
  64726. case 'punctuator':
  64727. switch (token.value) {
  64728. case '{':
  64729. value = {};
  64730. break;
  64731. case '[':
  64732. value = [];
  64733. break;
  64734. }
  64735. break;
  64736. case 'null':
  64737. case 'boolean':
  64738. case 'numeric':
  64739. case 'string':
  64740. value = token.value;
  64741. break;
  64742. // This code is unreachable.
  64743. // default:
  64744. // throw invalidToken()
  64745. }
  64746. if (root === undefined) {
  64747. root = value;
  64748. } else {
  64749. var parent = stack$1[stack$1.length - 1];
  64750. if (Array.isArray(parent)) {
  64751. parent.push(value);
  64752. } else {
  64753. parent[key] = value;
  64754. }
  64755. }
  64756. if (value !== null && typeof value === 'object') {
  64757. stack$1.push(value);
  64758. if (Array.isArray(value)) {
  64759. parseState = 'beforeArrayValue';
  64760. } else {
  64761. parseState = 'beforePropertyName';
  64762. }
  64763. } else {
  64764. var current = stack$1[stack$1.length - 1];
  64765. if (current == null) {
  64766. parseState = 'end';
  64767. } else if (Array.isArray(current)) {
  64768. parseState = 'afterArrayValue';
  64769. } else {
  64770. parseState = 'afterPropertyValue';
  64771. }
  64772. }
  64773. }
  64774. function pop() {
  64775. stack$1.pop();
  64776. var current = stack$1[stack$1.length - 1];
  64777. if (current == null) {
  64778. parseState = 'end';
  64779. } else if (Array.isArray(current)) {
  64780. parseState = 'afterArrayValue';
  64781. } else {
  64782. parseState = 'afterPropertyValue';
  64783. }
  64784. }
  64785. // This code is unreachable.
  64786. // function invalidParseState () {
  64787. // return new Error(`JSON5: invalid parse state '${parseState}'`)
  64788. // }
  64789. // This code is unreachable.
  64790. // function invalidLexState (state) {
  64791. // return new Error(`JSON5: invalid lex state '${state}'`)
  64792. // }
  64793. function invalidChar(c) {
  64794. if (c === undefined) {
  64795. return syntaxError("JSON5: invalid end of input at ".concat(line, ":").concat(column));
  64796. }
  64797. return syntaxError("JSON5: invalid character '".concat(formatChar(c), "' at ").concat(line, ":").concat(column));
  64798. }
  64799. function invalidEOF() {
  64800. return syntaxError("JSON5: invalid end of input at ".concat(line, ":").concat(column));
  64801. }
  64802. // This code is unreachable.
  64803. // function invalidToken () {
  64804. // if (token.type === 'eof') {
  64805. // return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
  64806. // }
  64807. // const c = String.fromCodePoint(token.value.codePointAt(0))
  64808. // return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
  64809. // }
  64810. function invalidIdentifier() {
  64811. column -= 5;
  64812. return syntaxError("JSON5: invalid identifier character at ".concat(line, ":").concat(column));
  64813. }
  64814. function separatorChar(c) {
  64815. console.warn("JSON5: '".concat(formatChar(c), "' in strings is not valid ECMAScript; consider escaping"));
  64816. }
  64817. function formatChar(c) {
  64818. var replacements = {
  64819. "'": "\\'",
  64820. '"': '\\"',
  64821. '\\': '\\\\',
  64822. '\b': '\\b',
  64823. '\f': '\\f',
  64824. '\n': '\\n',
  64825. '\r': '\\r',
  64826. '\t': '\\t',
  64827. '\v': '\\v',
  64828. '\0': '\\0',
  64829. '\u2028': '\\u2028',
  64830. '\u2029': '\\u2029'
  64831. };
  64832. if (replacements[c]) {
  64833. return replacements[c];
  64834. }
  64835. if (c < ' ') {
  64836. var hexString = c.charCodeAt(0).toString(16);
  64837. return '\\x' + ('00' + hexString).substring(hexString.length);
  64838. }
  64839. return c;
  64840. }
  64841. function syntaxError(message) {
  64842. var err = new SyntaxError(message);
  64843. err.lineNumber = line;
  64844. err.columnNumber = column;
  64845. return err;
  64846. }
  64847. var stringify = function stringify(value, replacer, space) {
  64848. var stack = [];
  64849. var indent = '';
  64850. var propertyList;
  64851. var replacerFunc;
  64852. var gap = '';
  64853. var quote;
  64854. if (replacer != null && typeof replacer === 'object' && !Array.isArray(replacer)) {
  64855. space = replacer.space;
  64856. quote = replacer.quote;
  64857. replacer = replacer.replacer;
  64858. }
  64859. if (typeof replacer === 'function') {
  64860. replacerFunc = replacer;
  64861. } else if (Array.isArray(replacer)) {
  64862. propertyList = [];
  64863. for (var v of replacer) {
  64864. var item = void 0;
  64865. if (typeof v === 'string') {
  64866. item = v;
  64867. } else if (typeof v === 'number' || v instanceof String || v instanceof Number) {
  64868. item = String(v);
  64869. }
  64870. if (item !== undefined && propertyList.indexOf(item) < 0) {
  64871. propertyList.push(item);
  64872. }
  64873. }
  64874. }
  64875. if (space instanceof Number) {
  64876. space = Number(space);
  64877. } else if (space instanceof String) {
  64878. space = String(space);
  64879. }
  64880. if (typeof space === 'number') {
  64881. if (space > 0) {
  64882. space = Math.min(10, Math.floor(space));
  64883. gap = ' '.substr(0, space);
  64884. }
  64885. } else if (typeof space === 'string') {
  64886. gap = space.substr(0, 10);
  64887. }
  64888. return serializeProperty('', {
  64889. '': value
  64890. });
  64891. function serializeProperty(key, holder) {
  64892. var value = holder[key];
  64893. if (value != null) {
  64894. if (typeof value.toJSON5 === 'function') {
  64895. value = value.toJSON5(key);
  64896. } else if (typeof value.toJSON === 'function') {
  64897. value = value.toJSON(key);
  64898. }
  64899. }
  64900. if (replacerFunc) {
  64901. value = replacerFunc.call(holder, key, value);
  64902. }
  64903. if (value instanceof Number) {
  64904. value = Number(value);
  64905. } else if (value instanceof String) {
  64906. value = String(value);
  64907. } else if (value instanceof Boolean) {
  64908. value = value.valueOf();
  64909. }
  64910. switch (value) {
  64911. case null:
  64912. return 'null';
  64913. case true:
  64914. return 'true';
  64915. case false:
  64916. return 'false';
  64917. }
  64918. if (typeof value === 'string') {
  64919. return quoteString(value, false);
  64920. }
  64921. if (typeof value === 'number') {
  64922. return String(value);
  64923. }
  64924. if (typeof value === 'object') {
  64925. return Array.isArray(value) ? serializeArray(value) : serializeObject(value);
  64926. }
  64927. return undefined;
  64928. }
  64929. function quoteString(value) {
  64930. var quotes = {
  64931. "'": 0.1,
  64932. '"': 0.2
  64933. };
  64934. var replacements = {
  64935. "'": "\\'",
  64936. '"': '\\"',
  64937. '\\': '\\\\',
  64938. '\b': '\\b',
  64939. '\f': '\\f',
  64940. '\n': '\\n',
  64941. '\r': '\\r',
  64942. '\t': '\\t',
  64943. '\v': '\\v',
  64944. '\0': '\\0',
  64945. '\u2028': '\\u2028',
  64946. '\u2029': '\\u2029'
  64947. };
  64948. var product = '';
  64949. for (var i = 0; i < value.length; i++) {
  64950. var _c3 = value[i];
  64951. switch (_c3) {
  64952. case "'":
  64953. case '"':
  64954. quotes[_c3]++;
  64955. product += _c3;
  64956. continue;
  64957. case '\0':
  64958. if (util.isDigit(value[i + 1])) {
  64959. product += '\\x00';
  64960. continue;
  64961. }
  64962. }
  64963. if (replacements[_c3]) {
  64964. product += replacements[_c3];
  64965. continue;
  64966. }
  64967. if (_c3 < ' ') {
  64968. var hexString = _c3.charCodeAt(0).toString(16);
  64969. product += '\\x' + ('00' + hexString).substring(hexString.length);
  64970. continue;
  64971. }
  64972. product += _c3;
  64973. }
  64974. var quoteChar = quote || Object.keys(quotes).reduce((a, b) => quotes[a] < quotes[b] ? a : b);
  64975. product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]);
  64976. return quoteChar + product + quoteChar;
  64977. }
  64978. function serializeObject(value) {
  64979. if (stack.indexOf(value) >= 0) {
  64980. throw TypeError('Converting circular structure to JSON5');
  64981. }
  64982. stack.push(value);
  64983. var stepback = indent;
  64984. indent = indent + gap;
  64985. var keys = propertyList || Object.keys(value);
  64986. var partial = [];
  64987. for (var _key2 of keys) {
  64988. var propertyString = serializeProperty(_key2, value);
  64989. if (propertyString !== undefined) {
  64990. var member = serializeKey(_key2) + ':';
  64991. if (gap !== '') {
  64992. member += ' ';
  64993. }
  64994. member += propertyString;
  64995. partial.push(member);
  64996. }
  64997. }
  64998. var final;
  64999. if (partial.length === 0) {
  65000. final = '{}';
  65001. } else {
  65002. var properties;
  65003. if (gap === '') {
  65004. properties = partial.join(',');
  65005. final = '{' + properties + '}';
  65006. } else {
  65007. var separator = ',\n' + indent;
  65008. properties = partial.join(separator);
  65009. final = '{\n' + indent + properties + ',\n' + stepback + '}';
  65010. }
  65011. }
  65012. stack.pop();
  65013. indent = stepback;
  65014. return final;
  65015. }
  65016. function serializeKey(key) {
  65017. if (key.length === 0) {
  65018. return quoteString(key, true);
  65019. }
  65020. var firstChar = String.fromCodePoint(key.codePointAt(0));
  65021. if (!util.isIdStartChar(firstChar)) {
  65022. return quoteString(key, true);
  65023. }
  65024. for (var i = firstChar.length; i < key.length; i++) {
  65025. if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
  65026. return quoteString(key, true);
  65027. }
  65028. }
  65029. return key;
  65030. }
  65031. function serializeArray(value) {
  65032. if (stack.indexOf(value) >= 0) {
  65033. throw TypeError('Converting circular structure to JSON5');
  65034. }
  65035. stack.push(value);
  65036. var stepback = indent;
  65037. indent = indent + gap;
  65038. var partial = [];
  65039. for (var i = 0; i < value.length; i++) {
  65040. var propertyString = serializeProperty(String(i), value);
  65041. partial.push(propertyString !== undefined ? propertyString : 'null');
  65042. }
  65043. var final;
  65044. if (partial.length === 0) {
  65045. final = '[]';
  65046. } else {
  65047. if (gap === '') {
  65048. var properties = partial.join(',');
  65049. final = '[' + properties + ']';
  65050. } else {
  65051. var separator = ',\n' + indent;
  65052. var _properties = partial.join(separator);
  65053. final = '[\n' + indent + _properties + ',\n' + stepback + ']';
  65054. }
  65055. }
  65056. stack.pop();
  65057. indent = stepback;
  65058. return final;
  65059. }
  65060. };
  65061. var JSON5$1 = {
  65062. parse: parse$4,
  65063. stringify
  65064. };
  65065. var lib = JSON5$1;
  65066. class Sidebar {
  65067. constructor(viewer) {
  65068. this.viewer = viewer;
  65069. this.measuringTool = viewer.measuringTool;
  65070. this.profileTool = viewer.profileTool;
  65071. this.volumeTool = viewer.volumeTool;
  65072. this.dom = $("#sidebar_root");
  65073. }
  65074. createToolIcon(icon, title, callback) {
  65075. var element = $("\n\t\t\t<img src=\"".concat(icon, "\"\n\t\t\t\tstyle=\"width: 32px; height: 32px\"\n\t\t\t\tclass=\"button-icon\"\n\t\t\t\tdata-i18n=\"").concat(title, "\" />\n\t\t"));
  65076. element.click(callback);
  65077. return element;
  65078. }
  65079. init() {
  65080. if (Potree.settings.editType == 'merge') {
  65081. this.initMergeBar();
  65082. this.initToolbar();
  65083. this.initScene();
  65084. this.initNavigation();
  65085. } else {
  65086. this.initAccordion();
  65087. this.initAppearance();
  65088. this.initToolbar();
  65089. this.initScene();
  65090. this.initNavigation();
  65091. this.initFilters();
  65092. //this.initClippingTool(); //因为修改了clipping,所以这项有bug不能使用
  65093. this.initSettings();
  65094. if (Potree.settings.editType != 'pano') {
  65095. this.initAlignment();
  65096. this.initClipModel();
  65097. this.initSiteModel();
  65098. this.initParitcle();
  65099. this.initClippingModel();
  65100. } else {
  65101. this.initPanosEdit();
  65102. }
  65103. }
  65104. $('#potree_version_number').html(Potree.version.major + "." + Potree.version.minor + Potree.version.suffix);
  65105. }
  65106. initAlignment() {
  65107. var Alignment = viewer.modules.Alignment;
  65108. var pannel = $('#alignment');
  65109. var buttons = pannel.find('[name="transform"] button');
  65110. var applyToPointcloud = (fun, value) => {
  65111. return function () {
  65112. var selected = $('#alignment li[name="selectPointCloud"] input:checked');
  65113. Array.from(selected).forEach(e => {
  65114. var pointcloud = viewer.scene.pointclouds.find(p => p.name == e.name);
  65115. fun(pointcloud, value);
  65116. });
  65117. };
  65118. };
  65119. //逆时针是正数
  65120. buttons.eq(0).on('click', applyToPointcloud(Alignment.rotate, 10));
  65121. //viewer.scene.pointclouds[0].rotation.z += THREE.Math.degToRad(10)
  65122. buttons.eq(1).on('click', applyToPointcloud(Alignment.rotate, 1));
  65123. buttons.eq(2).on('click', applyToPointcloud(Alignment.rotate, 0.1));
  65124. buttons.eq(3).on('click', applyToPointcloud(Alignment.rotate, -10));
  65125. buttons.eq(4).on('click', applyToPointcloud(Alignment.rotate, -1));
  65126. buttons.eq(5).on('click', applyToPointcloud(Alignment.rotate, -0.1));
  65127. buttons.eq(6).on('click', applyToPointcloud(Alignment.translate, new Vector3(-1, 0, 0)));
  65128. buttons.eq(7).on('click', applyToPointcloud(Alignment.translate, new Vector3(1, 0, 0)));
  65129. buttons.eq(8).on('click', applyToPointcloud(Alignment.translate, new Vector3(0, -1, 0)));
  65130. buttons.eq(9).on('click', applyToPointcloud(Alignment.translate, new Vector3(0, 1, 0)));
  65131. buttons.eq(10).on('click', applyToPointcloud(Alignment.translate, new Vector3(0, 0, -1)));
  65132. buttons.eq(11).on('click', applyToPointcloud(Alignment.translate, new Vector3(0, 0, 1)));
  65133. pannel.find('#startAlignment').on('click', () => {
  65134. Alignment.enter();
  65135. });
  65136. pannel.find('#exitAlignment').on('click', () => {
  65137. Alignment.save();
  65138. Alignment.leave();
  65139. });
  65140. pannel.find('#rotTool').on('click', () => {
  65141. Alignment.switchHandle('rotate');
  65142. });
  65143. pannel.find('#moveTool').on('click', () => {
  65144. Alignment.switchHandle('translate');
  65145. });
  65146. }
  65147. initMergeBar() {
  65148. //多元融合模块
  65149. var pannel = $('#mergeModel');
  65150. var buttons = pannel.find('button');
  65151. var MergeEditor = viewer.modules.MergeEditor;
  65152. var loading = false;
  65153. pannel.find('ul[name="model"] li button').on('click', e => {
  65154. if (loading) return console.log('还在加载', loading);
  65155. var $elem = $(e.target);
  65156. var parent = $elem.parent();
  65157. var name = parent.attr('name');
  65158. if ($elem.attr('name') == 'select') {
  65159. return Potree.selectModel(name);
  65160. }
  65161. if ($elem.text() == '添加') {
  65162. var startTime = Date.now();
  65163. Potree.addModel(name, () => {
  65164. loading = false;
  65165. //$elem.text('删除')
  65166. var now = Date.now();
  65167. console.log('加载完毕', name, '用时', (now - startTime) / 1000, 's');
  65168. });
  65169. loading = name;
  65170. } else {
  65171. Potree.removeModel(name);
  65172. $elem.text('添加');
  65173. }
  65174. });
  65175. pannel.find('li button[name="splitScreen"]').on('click', e => {
  65176. var $elem = $(e.target);
  65177. if ($elem.text() == '分屏') {
  65178. $elem.text('恢复');
  65179. MergeEditor.enterSplit();
  65180. } else {
  65181. $elem.text('分屏');
  65182. MergeEditor.leaveSplit();
  65183. }
  65184. });
  65185. var addingTag = false;
  65186. pannel.find('li button[name="tag"]').on('click', e => {
  65187. var $elem = $(e.target);
  65188. viewer.tagTool.startInsertion();
  65189. });
  65190. pannel.find('li button[name="path"]').on('click', e => {
  65191. var info = {
  65192. type: 'Path',
  65193. minMarkers: 2
  65194. };
  65195. viewer.measuringTool.startInsertion(info, () => {});
  65196. });
  65197. }
  65198. initClippingModel() {
  65199. //实时裁剪
  65200. /* 总共两种box : 可见和不可见(都是并集)
  65201. 当有可见box时,需要在任一可见box内才可见
  65202. 当有不可见box时,不在所有不可见box内才可见 */
  65203. var clipping = viewer.modules.clipping;
  65204. var pannel = $('#clipping');
  65205. var addBtn = pannel.find('[name="operation"] button[name="add"] ');
  65206. var switchBtn = pannel.find('[name="operation"] button[name="switchView"] ');
  65207. var enterBtn = pannel.find(' button[name="enter"] ');
  65208. var exitBtn = pannel.find(' button[name="exit"] ');
  65209. var list = pannel.find('[name="list"] ul ');
  65210. enterBtn.on('click', () => {
  65211. clipping.enter();
  65212. pannel.find('li[name=operation]').css('display', 'block');
  65213. pannel.find('li[name=list]').css('display', 'block');
  65214. });
  65215. exitBtn.on('click', () => {
  65216. clipping.leave();
  65217. pannel.find('li[name=operation]').css('display', 'none');
  65218. pannel.find('li[name=list]').css('display', 'none');
  65219. });
  65220. switchBtn.on('click', () => {
  65221. clipping.switchView(clipping.activeViewName == 'top' ? 'mainView' : 'top');
  65222. });
  65223. pannel.find('[name="operation"] button[name="translation"] ').on('click', () => {
  65224. clipping.setTranMode('translation');
  65225. });
  65226. pannel.find('[name="operation"] button[name="rotation"] ').on('click', () => {
  65227. clipping.setTranMode('rotation');
  65228. });
  65229. pannel.find('[name="operation"] button[name="scale"] ').on('click', () => {
  65230. clipping.setTranMode('scale');
  65231. });
  65232. addBtn.on('click', () => {
  65233. var volumeBox = this.volumeTool.startInsertion({
  65234. clip: true,
  65235. clipTask: Potree.ClipTask.SHOW_OUTSIDE
  65236. });
  65237. var li = $("<li><button name='changeTask'>不可见</button><button name='chose'>选择</button><button name='delete'>删除</button></li>");
  65238. list.append(li);
  65239. li.find('button[name=changeTask]').on('click', e => {
  65240. if (e.target.innerText == '不可见') {
  65241. volumeBox.clipTask = Potree.ClipTask.SHOW_INSIDE;
  65242. e.target.innerText = '可见';
  65243. } else {
  65244. volumeBox.clipTask = Potree.ClipTask.SHOW_OUTSIDE;
  65245. e.target.innerText = '不可见';
  65246. }
  65247. volumeBox.update();
  65248. });
  65249. li.find('button[name=chose]').on('click', e => {
  65250. viewer.transformObject(volumeBox); //viewer.inputHandler.toggleSelection(volumeBox)
  65251. });
  65252. li.find('button[name=delete]').on('click', e => {
  65253. li.remove();
  65254. viewer.scene.removeVolume(volumeBox);
  65255. });
  65256. });
  65257. pannel.find('button[name=save]').on('click', e => {
  65258. var data = clipping.saveClipData();
  65259. });
  65260. }
  65261. addAlignmentButton(pointcloud) {
  65262. var pannel = $('#alignment li[name="selectPointCloud"]>div');
  65263. var option = $(" <input name=\"".concat(pointcloud.name, "\" class=\"editCheckbox\" type=\"checkbox\" >\n \n <label for=\"showingLabels\">").concat(pointcloud.name, "</label>"));
  65264. pannel.append(option);
  65265. /* option.find("input").on('change',function(){
  65266. })
  65267. */
  65268. }
  65269. initClipModel() {
  65270. var Clip = viewer.modules.Clip;
  65271. var pannel = $('#clipModel');
  65272. var buttons = pannel.find('button');
  65273. buttons.eq(0).on('click', Clip.enter.bind(Clip));
  65274. buttons.eq(1).on('click', Clip.download.bind(Clip));
  65275. buttons.eq(2).on('click', Clip.leave.bind(Clip));
  65276. }
  65277. initSiteModel() {
  65278. var SiteModel = viewer.modules.SiteModel;
  65279. var pannel = $('#siteModel');
  65280. pannel.find('button[name="start"] ').on('click', SiteModel.enter.bind(SiteModel));
  65281. pannel.find('button[name="exit"] ').on('click', SiteModel.leave.bind(SiteModel));
  65282. pannel.find('button[name="building"] ').on('click', SiteModel.startInsertion.bind(SiteModel, 'building'));
  65283. pannel.find('button[name="floor"] ').on('click', () => {
  65284. SiteModel.addFloor(SiteModel.buildings[0], 'top');
  65285. });
  65286. pannel.find('button[name="room"] ').on('click', () => {
  65287. SiteModel.startInsertion('room', SiteModel.buildings[0].buildChildren[0]);
  65288. });
  65289. pannel.find('button[name="digHole"] ').on('click', () => {
  65290. SiteModel.selected && SiteModel.startInsertion('hole', SiteModel.selected);
  65291. });
  65292. pannel.find('button[name="selectBuilding"] ').on('click', () => {
  65293. SiteModel.selectEntity(SiteModel.buildings[0]);
  65294. });
  65295. pannel.find('button[name="selectFloor"] ').on('click', () => {
  65296. SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0]);
  65297. });
  65298. pannel.find('button[name="selectRoom"] ').on('click', () => {
  65299. SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]);
  65300. });
  65301. pannel.find('button[name="removeFirstBuilding"] ').on('click', () => {
  65302. SiteModel.removeEntity(SiteModel.buildings[0]);
  65303. });
  65304. pannel.find('button[name="removeFirstFloor"] ').on('click', () => {
  65305. SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0]);
  65306. });
  65307. pannel.find('button[name="removeFirstRoom"] ').on('click', () => {
  65308. SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]);
  65309. });
  65310. pannel.find('button[name="removeFirstHole"] ').on('click', () => {
  65311. SiteModel.selected.removeHole(SiteModel.selected.holes[0]);
  65312. });
  65313. pannel.find('button[name="removeFirstMarker"] ').on('click', () => {
  65314. //SiteModel.removeMarker(SiteModel.selected.markers[0])
  65315. SiteModel.selected.removeMarker(0);
  65316. });
  65317. }
  65318. initParitcle() {
  65319. var ParticleEditor = viewer.modules.ParticleEditor;
  65320. var pannel = $('#particle');
  65321. pannel.find('button[name="addFire"] ').on('click', () => {
  65322. ParticleEditor.startInsertion('fire+smoke');
  65323. });
  65324. pannel.find('button[name="addExplode"] ').on('click', () => {
  65325. ParticleEditor.startInsertion('explode');
  65326. });
  65327. }
  65328. initPanosEdit() {
  65329. var PanoEditor = viewer.modules.PanoEditor;
  65330. var Alignment = viewer.modules.Alignment;
  65331. var pannel = $('#panos');
  65332. pannel.find('button[name="save"] ').on('click', () => {
  65333. console.log('saveData', PanoEditor.exportSavingData());
  65334. });
  65335. pannel.find('button[name="translate"] ').on('click', () => {
  65336. Alignment.switchHandle('translate');
  65337. });
  65338. pannel.find('button[name="rotate"] ').on('click', () => {
  65339. Alignment.switchHandle('rotate');
  65340. });
  65341. pannel.find('button[name="topView"] ').on('click', () => {
  65342. PanoEditor.switchView('top');
  65343. });
  65344. pannel.find('button[name="sideView"] ').on('click', () => {
  65345. PanoEditor.switchView('right');
  65346. });
  65347. pannel.find('button[name="3DView"] ').on('click', () => {
  65348. PanoEditor.switchView('mainView');
  65349. });
  65350. pannel.find('button[name="addLink"] ').on('click', () => {
  65351. PanoEditor.setLinkOperateState('addLink', true);
  65352. });
  65353. pannel.find('button[name="removeLink"] ').on('click', () => {
  65354. PanoEditor.setLinkOperateState('removeLink', true);
  65355. });
  65356. pannel.find('button[name="getCloser"] ').on('click', () => {
  65357. PanoEditor.setZoomInState(true);
  65358. });
  65359. }
  65360. initToolbar() {
  65361. // ANGLE
  65362. var elToolbar = $('#tools');
  65363. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/angle.png', '[title]tt.angle_measurement', () => {
  65364. $('#menu_measurements').next().slideDown();
  65365. var measurement = this.measuringTool.startInsertion({
  65366. showDistances: false,
  65367. showAngles: true,
  65368. showArea: false,
  65369. closed: true,
  65370. maxMarkers: 3,
  65371. minMarkers: 3,
  65372. measureType: 'Angle'
  65373. });
  65374. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65375. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65376. $.jstree.reference(jsonNode.id).deselect_all();
  65377. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65378. }));
  65379. // POINT
  65380. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/point.svg', '[title]tt.point_measurement', () => {
  65381. $('#menu_measurements').next().slideDown();
  65382. var measurement = this.measuringTool.startInsertion({
  65383. showDistances: false,
  65384. showAngles: false,
  65385. showCoordinates: true,
  65386. showEdges: false,
  65387. showArea: false,
  65388. closed: true,
  65389. maxMarkers: 1,
  65390. minMarkers: 1,
  65391. measureType: 'Point'
  65392. });
  65393. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65394. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65395. $.jstree.reference(jsonNode.id).deselect_all();
  65396. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65397. }));
  65398. // DISTANCE
  65399. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/distance.svg', '[title]tt.distance_measurement', () => {
  65400. $('#menu_measurements').next().slideDown();
  65401. var measurement = this.measuringTool.startInsertion({
  65402. showDistances: true,
  65403. showArea: false,
  65404. closed: false,
  65405. minMarkers: 2,
  65406. maxMarkers: 2,
  65407. measureType: 'Distance'
  65408. });
  65409. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65410. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65411. $.jstree.reference(jsonNode.id).deselect_all();
  65412. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65413. }));
  65414. // DISTANCE2
  65415. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/distance.svg', '[title]MulDistance', () => {
  65416. $('#menu_measurements').next().slideDown();
  65417. var measurement = this.measuringTool.startInsertion({
  65418. showDistances: true,
  65419. showArea: false,
  65420. closed: false,
  65421. minMarkers: 2,
  65422. measureType: 'MulDistance'
  65423. });
  65424. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65425. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65426. $.jstree.reference(jsonNode.id).deselect_all();
  65427. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65428. }));
  65429. // DISTANCE2
  65430. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/distance.svg', '[title]MulDistance Ring', () => {
  65431. $('#menu_measurements').next().slideDown();
  65432. var measurement = this.measuringTool.startInsertion({
  65433. //showArea: false,
  65434. closed: true,
  65435. minMarkers: 3,
  65436. measureType: 'MulDistance Ring'
  65437. });
  65438. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65439. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65440. $.jstree.reference(jsonNode.id).deselect_all();
  65441. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65442. }));
  65443. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/distance.svg', '[title]Ver MulDistance', () => {
  65444. $('#menu_measurements').next().slideDown();
  65445. var measurement = this.measuringTool.startInsertion({
  65446. measureType: 'Ver MulDistance'
  65447. });
  65448. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65449. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65450. $.jstree.reference(jsonNode.id).deselect_all();
  65451. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65452. }));
  65453. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/distance.svg', '[title]Hor MulDistance', () => {
  65454. $('#menu_measurements').next().slideDown();
  65455. var measurement = this.measuringTool.startInsertion({
  65456. measureType: 'Hor MulDistance'
  65457. });
  65458. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65459. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65460. $.jstree.reference(jsonNode.id).deselect_all();
  65461. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65462. }));
  65463. // HEIGHT
  65464. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/height.svg', '[title]tt.height_measurement', () => {
  65465. $('#menu_measurements').next().slideDown();
  65466. var measurement = this.measuringTool.startInsertion({
  65467. showDistances: true,
  65468. //false,
  65469. showHeight: true,
  65470. showArea: false,
  65471. closed: false,
  65472. maxMarkers: 2,
  65473. minMarkers: 2,
  65474. //showGuideLine: true: true
  65475. measureType: 'Ver Distance'
  65476. });
  65477. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65478. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65479. $.jstree.reference(jsonNode.id).deselect_all();
  65480. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65481. }));
  65482. // CIRCLE
  65483. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/circle.svg', '[title]tt.circle_measurement', () => {
  65484. $('#menu_measurements').next().slideDown();
  65485. var measurement = this.measuringTool.startInsertion({
  65486. showDistances: false,
  65487. showHeight: false,
  65488. showArea: false,
  65489. showCircle: true,
  65490. showEdges: false,
  65491. closed: false,
  65492. maxMarkers: 3,
  65493. minMarkers: 3,
  65494. measureType: 'Circle'
  65495. });
  65496. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65497. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65498. $.jstree.reference(jsonNode.id).deselect_all();
  65499. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65500. }));
  65501. // AZIMUTH
  65502. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/azimuth.svg', 'Azimuth', () => {
  65503. $('#menu_measurements').next().slideDown();
  65504. var measurement = this.measuringTool.startInsertion({
  65505. showDistances: false,
  65506. showHeight: false,
  65507. showArea: false,
  65508. showCircle: false,
  65509. showEdges: false,
  65510. showAzimuth: true,
  65511. closed: false,
  65512. maxMarkers: 2,
  65513. minMarkers: 2,
  65514. measureType: 'Azimuth'
  65515. });
  65516. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65517. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65518. $.jstree.reference(jsonNode.id).deselect_all();
  65519. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65520. }));
  65521. // AREA
  65522. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]tt.area_measurement', () => {
  65523. $('#menu_measurements').next().slideDown();
  65524. var measurement = this.measuringTool.startInsertion({
  65525. showDistances: true,
  65526. showArea: true,
  65527. closed: true,
  65528. minMarkers: 3,
  65529. //showGuideLine: true: true,
  65530. measureType: 'Area'
  65531. });
  65532. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65533. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65534. $.jstree.reference(jsonNode.id).deselect_all();
  65535. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65536. }));
  65537. //Hor AREA
  65538. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]Hor Area', () => {
  65539. $('#menu_measurements').next().slideDown();
  65540. var measurement = this.measuringTool.startInsertion({
  65541. showDistances: true,
  65542. showArea: true,
  65543. closed: true,
  65544. minMarkers: 3,
  65545. measureType: 'Hor Area'
  65546. });
  65547. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65548. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65549. $.jstree.reference(jsonNode.id).deselect_all();
  65550. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65551. }));
  65552. // Ver Area
  65553. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]Ver Area', () => {
  65554. $('#menu_measurements').next().slideDown();
  65555. var measurement = this.measuringTool.startInsertion({
  65556. showDistances: true,
  65557. showArea: true,
  65558. closed: true,
  65559. minMarkers: 3,
  65560. measureType: 'Ver Area'
  65561. });
  65562. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65563. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65564. $.jstree.reference(jsonNode.id).deselect_all();
  65565. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65566. }));
  65567. // rect area freedom direction
  65568. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]area_freedom_rect', () => {
  65569. $('#menu_measurements').next().slideDown();
  65570. var measurement = this.measuringTool.startInsertion({
  65571. showDistances: true,
  65572. showArea: true,
  65573. closed: true,
  65574. minMarkers: 4,
  65575. maxMarkers: 4,
  65576. //showGuideLine: true: true,
  65577. isRect: true,
  65578. measureType: 'Rect Area'
  65579. });
  65580. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65581. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65582. $.jstree.reference(jsonNode.id).deselect_all();
  65583. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65584. }));
  65585. // rect area horizontal
  65586. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]area_horizontal_rect', () => {
  65587. $('#menu_measurements').next().slideDown();
  65588. var measurement = this.measuringTool.startInsertion({
  65589. showDistances: true,
  65590. showArea: true,
  65591. closed: true,
  65592. minMarkers: 4,
  65593. maxMarkers: 4,
  65594. //showGuideLine: true: true,
  65595. isRect: true,
  65596. faceDirection: "horizontal",
  65597. measureType: 'Hor Rect Area'
  65598. });
  65599. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65600. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65601. $.jstree.reference(jsonNode.id).deselect_all();
  65602. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65603. }));
  65604. // rect area vertical
  65605. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]area_vertical_rect', () => {
  65606. $('#menu_measurements').next().slideDown();
  65607. var measurement = this.measuringTool.startInsertion({
  65608. showDistances: true,
  65609. showArea: true,
  65610. closed: true,
  65611. minMarkers: 4,
  65612. maxMarkers: 4,
  65613. //showGuideLine: true: true,
  65614. isRect: true,
  65615. faceDirection: "vertical",
  65616. measureType: 'Ver Rect Area'
  65617. });
  65618. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65619. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65620. $.jstree.reference(jsonNode.id).deselect_all();
  65621. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65622. }));
  65623. // AREA
  65624. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/area.svg', '[title]prism', () => {
  65625. $('#menu_measurements').next().slideDown();
  65626. var measurement = this.measuringTool.startInsertion({
  65627. measureType: 'MulDistance Ring',
  65628. unit: 'metric'
  65629. });
  65630. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65631. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
  65632. $.jstree.reference(jsonNode.id).deselect_all();
  65633. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65634. }));
  65635. // VOLUME
  65636. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/volume.svg', '[title]tt.volume_measurement', () => {
  65637. var volume = this.volumeTool.startInsertion();
  65638. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65639. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid);
  65640. $.jstree.reference(jsonNode.id).deselect_all();
  65641. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65642. }));
  65643. // SPHERE VOLUME
  65644. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/sphere_distances.svg', '[title]tt.volume_measurement', () => {
  65645. var volume = this.volumeTool.startInsertion({
  65646. type: SphereVolume$2
  65647. });
  65648. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65649. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid);
  65650. $.jstree.reference(jsonNode.id).deselect_all();
  65651. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65652. }));
  65653. // PROFILE
  65654. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/profile.svg', '[title]tt.height_profile', () => {
  65655. $('#menu_measurements').next().slideDown();
  65656. ;
  65657. var profile = this.profileTool.startInsertion();
  65658. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  65659. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === profile.uuid);
  65660. $.jstree.reference(jsonNode.id).deselect_all();
  65661. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65662. }));
  65663. // ANNOTATION
  65664. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/annotation.svg', '[title]tt.annotation', () => {
  65665. $('#menu_measurements').next().slideDown();
  65666. ;
  65667. var annotation = this.viewer.annotationTool.startInsertion();
  65668. var annotationsRoot = $("#jstree_scene").jstree().get_json("annotations");
  65669. var jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid);
  65670. $.jstree.reference(jsonNode.id).deselect_all();
  65671. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  65672. }));
  65673. // REMOVE ALL
  65674. elToolbar.append(this.createToolIcon(Potree.resourcePath + '/icons/reset_tools.svg', '[title]tt.remove_all_measurement', () => {
  65675. this.viewer.scene.removeAllMeasurements();
  65676. }));
  65677. {
  65678. // SHOW / HIDE Measurements
  65679. var elShow = $("#measurement_options_show");
  65680. elShow.selectgroup({
  65681. title: "Show/Hide labels"
  65682. });
  65683. elShow.find("input").click(e => {
  65684. var show = e.target.value === "SHOW";
  65685. this.measuringTool.showLabels = show;
  65686. });
  65687. var currentShow = this.measuringTool.showLabels ? "SHOW" : "HIDE";
  65688. elShow.find("input[value=".concat(currentShow, "]")).trigger("click");
  65689. }
  65690. }
  65691. initScene() {
  65692. var elScene = $("#menu_scene");
  65693. var elObjects = elScene.next().find("#scene_objects");
  65694. var elProperties = elScene.next().find("#scene_object_properties");
  65695. {
  65696. var elExport = elScene.next().find("#scene_export");
  65697. var geoJSONIcon = "".concat(Potree.resourcePath, "/icons/file_geojson.svg");
  65698. var dxfIcon = "".concat(Potree.resourcePath, "/icons/file_dxf.svg");
  65699. var potreeIcon = "".concat(Potree.resourcePath, "/icons/file_potree.svg");
  65700. elExport.append("\n\t\t\t\tExport: <br>\n\t\t\t\t<a href=\"#\" download=\"measure.json\"><img name=\"geojson_export_button\" src=\"".concat(geoJSONIcon, "\" class=\"button-icon\" style=\"height: 24px\" /></a>\n\t\t\t\t<a href=\"#\" download=\"measure.dxf\"><img name=\"dxf_export_button\" src=\"").concat(dxfIcon, "\" class=\"button-icon\" style=\"height: 24px\" /></a>\n\t\t\t\t<a href=\"#\" download=\"potree.json5\"><img name=\"potree_export_button\" src=\"").concat(potreeIcon, "\" class=\"button-icon\" style=\"height: 24px\" /></a>\n\t\t\t"));
  65701. var elDownloadJSON = elExport.find("img[name=geojson_export_button]").parent();
  65702. elDownloadJSON.click(event => {
  65703. var scene = this.viewer.scene;
  65704. var measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes];
  65705. if (measurements.length > 0) {
  65706. var geoJson = GeoJSONExporter.toString(measurements);
  65707. var url = window.URL.createObjectURL(new Blob([geoJson], {
  65708. type: 'data:application/octet-stream'
  65709. }));
  65710. elDownloadJSON.attr('href', url);
  65711. } else {
  65712. this.viewer.postError("nothing to export");
  65713. event.preventDefault();
  65714. }
  65715. });
  65716. var elDownloadDXF = elExport.find("img[name=dxf_export_button]").parent();
  65717. elDownloadDXF.click(event => {
  65718. var scene = this.viewer.scene;
  65719. var measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes];
  65720. if (measurements.length > 0) {
  65721. var dxf = DXFExporter.toString(measurements);
  65722. var url = window.URL.createObjectURL(new Blob([dxf], {
  65723. type: 'data:application/octet-stream'
  65724. }));
  65725. elDownloadDXF.attr('href', url);
  65726. } else {
  65727. this.viewer.postError("no measurements to export");
  65728. event.preventDefault();
  65729. }
  65730. });
  65731. var elDownloadPotree = elExport.find("img[name=potree_export_button]").parent();
  65732. elDownloadPotree.click(event => {
  65733. var data = Potree.saveProject(this.viewer);
  65734. var dataString = lib.stringify(data, null, "\t");
  65735. var url = window.URL.createObjectURL(new Blob([dataString], {
  65736. type: 'data:application/octet-stream'
  65737. }));
  65738. elDownloadPotree.attr('href', url);
  65739. });
  65740. }
  65741. var propertiesPanel = new PropertiesPanel(elProperties, this.viewer);
  65742. propertiesPanel.setScene(this.viewer.scene);
  65743. localStorage.removeItem('jstree');
  65744. var tree = $("<div id=\"jstree_scene\"></div>");
  65745. elObjects.append(tree);
  65746. tree.jstree({
  65747. 'plugins': ["checkbox", "state"],
  65748. 'core': {
  65749. "dblclick_toggle": false,
  65750. "state": {
  65751. "checked": true
  65752. },
  65753. 'check_callback': true,
  65754. "expand_selected_onload": true
  65755. },
  65756. "checkbox": {
  65757. "keep_selected_style": true,
  65758. "three_state": false,
  65759. "whole_node": false,
  65760. "tie_selection": false
  65761. }
  65762. });
  65763. var createNode = (parent, text, icon, object) => {
  65764. var nodeID = tree.jstree('create_node', parent, {
  65765. "text": text,
  65766. "icon": icon,
  65767. "data": object
  65768. }, "last", false, false);
  65769. if (object.visible) {
  65770. tree.jstree('check_node', nodeID);
  65771. } else {
  65772. tree.jstree('uncheck_node', nodeID);
  65773. }
  65774. return nodeID;
  65775. };
  65776. var pcID = tree.jstree('create_node', "#", {
  65777. "text": "<b>Point Clouds</b>",
  65778. "id": "pointclouds"
  65779. }, "last", false, false);
  65780. var measurementID = tree.jstree('create_node', "#", {
  65781. "text": "<b>Measurements</b>",
  65782. "id": "measurements"
  65783. }, "last", false, false);
  65784. var annotationsID = tree.jstree('create_node', "#", {
  65785. "text": "<b>Annotations</b>",
  65786. "id": "annotations"
  65787. }, "last", false, false);
  65788. var otherID = tree.jstree('create_node', "#", {
  65789. "text": "<b>Other</b>",
  65790. "id": "other"
  65791. }, "last", false, false);
  65792. var vectorsID = tree.jstree('create_node', "#", {
  65793. "text": "<b>Vectors</b>",
  65794. "id": "vectors"
  65795. }, "last", false, false);
  65796. var imagesID = tree.jstree('create_node', "#", {
  65797. "text": "<b> Images</b>",
  65798. "id": "images"
  65799. }, "last", false, false);
  65800. tree.jstree("check_node", pcID);
  65801. tree.jstree("check_node", measurementID);
  65802. tree.jstree("check_node", annotationsID);
  65803. tree.jstree("check_node", otherID);
  65804. tree.jstree("check_node", vectorsID);
  65805. tree.jstree("check_node", imagesID);
  65806. tree.on('create_node.jstree', (e, data) => {
  65807. tree.jstree("open_all");
  65808. });
  65809. tree.on("select_node.jstree", (e, data) => {
  65810. var object = data.node.data;
  65811. propertiesPanel.set(object);
  65812. this.viewer.inputHandler.deselectAll();
  65813. if (object instanceof Volume$1) {
  65814. this.viewer.inputHandler.toggleSelection(object);
  65815. }
  65816. $(this.viewer.renderer.domElement).focus();
  65817. });
  65818. tree.on("deselect_node.jstree", (e, data) => {
  65819. propertiesPanel.set(null);
  65820. });
  65821. tree.on("delete_node.jstree", (e, data) => {
  65822. propertiesPanel.set(null);
  65823. });
  65824. tree.on('dblclick', '.jstree-anchor', e => {
  65825. var instance = $.jstree.reference(e.target);
  65826. var node = instance.get_node(e.target);
  65827. var object = node.data;
  65828. // ignore double click on checkbox
  65829. if (e.target.classList.contains("jstree-checkbox")) {
  65830. return;
  65831. }
  65832. if (object instanceof PointCloudTree) {
  65833. var box = this.viewer.getBoundingBox([object]);
  65834. var _node = new Object3D();
  65835. _node.boundingBox = box;
  65836. this.viewer.zoomTo(_node, 1, 500);
  65837. } else if (object instanceof Measure$1) {
  65838. var points = object.points.map(p => p.position);
  65839. var _box = new Box3().setFromPoints(points);
  65840. if (_box.getSize(new Vector3()).length() == 0) {
  65841. _box.min = _box.max.clone(); //禁止相同
  65842. _box.expandByVector(new Vector3(1, 1, 1));
  65843. }
  65844. var _node2 = new Object3D();
  65845. _node2.boundingBox = _box;
  65846. this.viewer.zoomTo(_node2, 2, 500);
  65847. } else if (object instanceof Profile) {
  65848. var _points = object.points;
  65849. var _box2 = new Box3().setFromPoints(_points);
  65850. if (_box2.getSize(new Vector3()).length() > 0) {
  65851. var _node3 = new Object3D();
  65852. _node3.boundingBox = _box2;
  65853. this.viewer.zoomTo(_node3, 1, 500);
  65854. }
  65855. } else if (object instanceof Volume$1) {
  65856. var _box3 = object.boundingBox.clone().applyMatrix4(object.matrixWorld);
  65857. if (_box3.getSize(new Vector3()).length() > 0) {
  65858. var _node4 = new Object3D();
  65859. _node4.boundingBox = _box3;
  65860. this.viewer.zoomTo(_node4, 1, 500);
  65861. }
  65862. } else if (object instanceof Annotation) {
  65863. object.moveHere(this.viewer.scene.getActiveCamera());
  65864. } else if (object instanceof PolygonClipVolume) {
  65865. var dir = object.camera.getWorldDirection(new Vector3());
  65866. var target;
  65867. if (object.camera instanceof OrthographicCamera) {
  65868. dir.multiplyScalar(object.camera.right);
  65869. target = new Vector3().addVectors(object.camera.position, dir);
  65870. this.viewer.setCameraMode(CameraMode.ORTHOGRAPHIC);
  65871. } else if (object.camera instanceof PerspectiveCamera) {
  65872. dir.multiplyScalar(this.viewer.scene.view.radius);
  65873. target = new Vector3().addVectors(object.camera.position, dir);
  65874. this.viewer.setCameraMode(CameraMode.PERSPECTIVE);
  65875. }
  65876. this.viewer.scene.view.position.copy(object.camera.position);
  65877. this.viewer.scene.view.lookAt(target);
  65878. } else if (object.type === "SpotLight") {
  65879. var distance = object.distance > 0 ? object.distance / 4 : 5 * 1000;
  65880. var position = object.position;
  65881. var _target = new Vector3().addVectors(position, object.getWorldDirection(new Vector3()).multiplyScalar(distance));
  65882. this.viewer.scene.view.position.copy(object.position);
  65883. this.viewer.scene.view.lookAt(_target);
  65884. } else if (object instanceof Object3D) {
  65885. var _box4 = new Box3().setFromObject(object);
  65886. if (_box4.getSize(new Vector3()).length() > 0) {
  65887. var _node5 = new Object3D();
  65888. _node5.boundingBox = _box4;
  65889. this.viewer.zoomTo(_node5, 1, 500);
  65890. }
  65891. } else if (object instanceof OrientedImage) {
  65892. // TODO zoom to images
  65893. // let box = new THREE.Box3().setFromObject(object);
  65894. // if(box.getSize(new THREE.Vector3()).length() > 0){
  65895. // let node = new THREE.Object3D();
  65896. // node.boundingBox = box;
  65897. // this.viewer.zoomTo(node, 1, 500);
  65898. // }
  65899. } else if (object instanceof Images360) {
  65900. // TODO
  65901. } else if (object instanceof Geopackage) {
  65902. // TODO
  65903. }
  65904. });
  65905. tree.on("uncheck_node.jstree", (e, data) => {
  65906. var object = data.node.data;
  65907. if (object) {
  65908. object.visible = false;
  65909. }
  65910. });
  65911. tree.on("check_node.jstree", (e, data) => {
  65912. var object = data.node.data;
  65913. if (object) {
  65914. object.visible = true;
  65915. }
  65916. });
  65917. var onPointCloudAdded = e => {
  65918. var pointcloud = e.pointcloud;
  65919. var cloudIcon = "".concat(Potree.resourcePath, "/icons/cloud.svg");
  65920. var node = createNode(pcID, pointcloud.name, cloudIcon, pointcloud);
  65921. pointcloud.addEventListener("visibility_changed", () => {
  65922. if (pointcloud.visible) {
  65923. tree.jstree('check_node', node);
  65924. } else {
  65925. tree.jstree('uncheck_node', node);
  65926. }
  65927. });
  65928. };
  65929. var onMeasurementAdded = e => {
  65930. var measurement = e.measurement;
  65931. var icon = Utils.getMeasurementIcon(measurement);
  65932. createNode(measurementID, measurement.name, icon, measurement);
  65933. };
  65934. var onVolumeAdded = e => {
  65935. var volume = e.volume;
  65936. var icon = Utils.getMeasurementIcon(volume);
  65937. var node = createNode(measurementID, volume.name, icon, volume);
  65938. volume.addEventListener("visibility_changed", () => {
  65939. if (volume.visible) {
  65940. tree.jstree('check_node', node);
  65941. } else {
  65942. tree.jstree('uncheck_node', node);
  65943. }
  65944. });
  65945. };
  65946. var onProfileAdded = e => {
  65947. var profile = e.profile;
  65948. var icon = Utils.getMeasurementIcon(profile);
  65949. createNode(measurementID, profile.name, icon, profile);
  65950. };
  65951. var onAnnotationAdded = e => {
  65952. var annotation = e.annotation;
  65953. var annotationIcon = "".concat(Potree.resourcePath, "/icons/annotation.svg");
  65954. var parentID = this.annotationMapping.get(annotation.parent);
  65955. var annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);
  65956. this.annotationMapping.set(annotation, annotationID);
  65957. annotation.addEventListener("annotation_changed", e => {
  65958. var annotationsRoot = $("#jstree_scene").jstree().get_json("annotations");
  65959. var jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid);
  65960. $.jstree.reference(jsonNode.id).rename_node(jsonNode.id, annotation.title);
  65961. });
  65962. };
  65963. var onCameraAnimationAdded = e => {
  65964. var animation = e.animation;
  65965. var animationIcon = "".concat(Potree.resourcePath, "/icons/camera_animation.svg");
  65966. createNode(otherID, "animation", animationIcon, animation);
  65967. };
  65968. var onOrientedImagesAdded = e => {
  65969. var images = e.images;
  65970. var imagesIcon = "".concat(Potree.resourcePath, "/icons/picture.svg");
  65971. var node = createNode(imagesID, "images", imagesIcon, images);
  65972. images.addEventListener("visibility_changed", () => {
  65973. if (images.visible) {
  65974. tree.jstree('check_node', node);
  65975. } else {
  65976. tree.jstree('uncheck_node', node);
  65977. }
  65978. });
  65979. };
  65980. var onImages360Added = e => {
  65981. var images = e.images;
  65982. var imagesIcon = "".concat(Potree.resourcePath, "/icons/picture.svg");
  65983. var node = createNode(imagesID, "360° images", imagesIcon, images);
  65984. images.addEventListener("visibility_changed", () => {
  65985. if (images.visible) {
  65986. tree.jstree('check_node', node);
  65987. } else {
  65988. tree.jstree('uncheck_node', node);
  65989. }
  65990. });
  65991. };
  65992. var onGeopackageAdded = e => {
  65993. var geopackage = e.geopackage;
  65994. var geopackageIcon = "".concat(Potree.resourcePath, "/icons/triangle.svg");
  65995. var tree = $("#jstree_scene");
  65996. var parentNode = "vectors";
  65997. for (var layer of geopackage.node.children) {
  65998. var name = layer.name;
  65999. var shpPointsID = tree.jstree('create_node', parentNode, {
  66000. "text": name,
  66001. "icon": geopackageIcon,
  66002. "object": layer,
  66003. "data": layer
  66004. }, "last", false, false);
  66005. tree.jstree(layer.visible ? "check_node" : "uncheck_node", shpPointsID);
  66006. }
  66007. };
  66008. this.viewer.scene.addEventListener("pointcloud_added", onPointCloudAdded);
  66009. this.viewer.scene.addEventListener("measurement_added", onMeasurementAdded);
  66010. this.viewer.scene.addEventListener("profile_added", onProfileAdded);
  66011. this.viewer.scene.addEventListener("volume_added", onVolumeAdded);
  66012. this.viewer.scene.addEventListener("camera_animation_added", onCameraAnimationAdded);
  66013. this.viewer.scene.addEventListener("oriented_images_added", onOrientedImagesAdded);
  66014. this.viewer.scene.addEventListener("360_images_added", onImages360Added);
  66015. this.viewer.scene.addEventListener("geopackage_added", onGeopackageAdded);
  66016. this.viewer.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);
  66017. this.viewer.scene.annotations.addEventListener("annotation_added", onAnnotationAdded);
  66018. var onMeasurementRemoved = e => {
  66019. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66020. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.measurement.uuid);
  66021. tree.jstree("delete_node", jsonNode.id);
  66022. };
  66023. var onVolumeRemoved = e => {
  66024. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66025. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);
  66026. tree.jstree("delete_node", jsonNode.id);
  66027. };
  66028. var onPolygonClipVolumeRemoved = e => {
  66029. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66030. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid);
  66031. tree.jstree("delete_node", jsonNode.id);
  66032. };
  66033. var onProfileRemoved = e => {
  66034. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66035. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.profile.uuid);
  66036. tree.jstree("delete_node", jsonNode.id);
  66037. };
  66038. this.viewer.scene.addEventListener("measurement_removed", onMeasurementRemoved);
  66039. this.viewer.scene.addEventListener("volume_removed", onVolumeRemoved);
  66040. this.viewer.scene.addEventListener("polygon_clip_volume_removed", onPolygonClipVolumeRemoved);
  66041. this.viewer.scene.addEventListener("profile_removed", onProfileRemoved);
  66042. {
  66043. var annotationIcon = "".concat(Potree.resourcePath, "/icons/annotation.svg");
  66044. this.annotationMapping = new Map();
  66045. this.annotationMapping.set(this.viewer.scene.annotations, annotationsID);
  66046. this.viewer.scene.annotations.traverseDescendants(annotation => {
  66047. var parentID = this.annotationMapping.get(annotation.parent);
  66048. var annotationID = createNode(parentID, annotation.title, annotationIcon, annotation);
  66049. this.annotationMapping.set(annotation, annotationID);
  66050. });
  66051. }
  66052. var scene = this.viewer.scene;
  66053. for (var pointcloud of scene.pointclouds) {
  66054. onPointCloudAdded({
  66055. pointcloud: pointcloud
  66056. });
  66057. }
  66058. for (var measurement of scene.measurements) {
  66059. onMeasurementAdded({
  66060. measurement: measurement
  66061. });
  66062. }
  66063. for (var volume of [...scene.volumes, ...scene.polygonClipVolumes]) {
  66064. onVolumeAdded({
  66065. volume: volume
  66066. });
  66067. }
  66068. for (var animation of scene.cameraAnimations) {
  66069. onCameraAnimationAdded({
  66070. animation: animation
  66071. });
  66072. }
  66073. for (var images of scene.orientedImages) {
  66074. onOrientedImagesAdded({
  66075. images: images
  66076. });
  66077. }
  66078. for (var _images of scene.images360) {
  66079. onImages360Added({
  66080. images: _images
  66081. });
  66082. }
  66083. for (var geopackage of scene.geopackages) {
  66084. onGeopackageAdded({
  66085. geopackage: geopackage
  66086. });
  66087. }
  66088. for (var profile of scene.profiles) {
  66089. onProfileAdded({
  66090. profile: profile
  66091. });
  66092. }
  66093. {
  66094. createNode(otherID, "Camera", null, new Camera());
  66095. }
  66096. this.viewer.addEventListener("scene_changed", e => {
  66097. propertiesPanel.setScene(e.scene);
  66098. e.oldScene.removeEventListener("pointcloud_added", onPointCloudAdded);
  66099. e.oldScene.removeEventListener("measurement_added", onMeasurementAdded);
  66100. e.oldScene.removeEventListener("profile_added", onProfileAdded);
  66101. e.oldScene.removeEventListener("volume_added", onVolumeAdded);
  66102. e.oldScene.removeEventListener("polygon_clip_volume_added", onVolumeAdded);
  66103. e.oldScene.removeEventListener("measurement_removed", onMeasurementRemoved);
  66104. e.scene.addEventListener("pointcloud_added", onPointCloudAdded);
  66105. e.scene.addEventListener("measurement_added", onMeasurementAdded);
  66106. e.scene.addEventListener("profile_added", onProfileAdded);
  66107. e.scene.addEventListener("volume_added", onVolumeAdded);
  66108. e.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded);
  66109. e.scene.addEventListener("measurement_removed", onMeasurementRemoved);
  66110. });
  66111. }
  66112. initClippingTool() {
  66113. this.viewer.addEventListener("cliptask_changed", event => {
  66114. console.log("TODO");
  66115. });
  66116. this.viewer.addEventListener("clipmethod_changed", event => {
  66117. console.log("TODO");
  66118. });
  66119. {
  66120. var elClipTask = $("#cliptask_options");
  66121. elClipTask.selectgroup({
  66122. title: "Clip Task"
  66123. });
  66124. elClipTask.find("input").click(e => {
  66125. this.viewer.setClipTask(ClipTask[e.target.value]);
  66126. });
  66127. var currentClipTask = Object.keys(ClipTask).filter(key => ClipTask[key] === this.viewer.clipTask);
  66128. elClipTask.find("input[value=".concat(currentClipTask, "]")).trigger("click");
  66129. }
  66130. {
  66131. var elClipMethod = $("#clipmethod_options");
  66132. elClipMethod.selectgroup({
  66133. title: "Clip Method"
  66134. });
  66135. elClipMethod.find("input").click(e => {
  66136. this.viewer.setClipMethod(ClipMethod[e.target.value]);
  66137. });
  66138. var currentClipMethod = Object.keys(ClipMethod).filter(key => ClipMethod[key] === this.viewer.clipMethod);
  66139. elClipMethod.find("input[value=".concat(currentClipMethod, "]")).trigger("click");
  66140. }
  66141. var clippingToolBar = $("#clipping_tools");
  66142. // CLIP VOLUME
  66143. clippingToolBar.append(this.createToolIcon(Potree.resourcePath + '/icons/clip_volume.svg', '[title]tt.clip_volume', () => {
  66144. var item = this.volumeTool.startInsertion({
  66145. clip: true
  66146. });
  66147. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66148. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  66149. $.jstree.reference(jsonNode.id).deselect_all();
  66150. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  66151. }));
  66152. // CLIP POLYGON
  66153. clippingToolBar.append(this.createToolIcon(Potree.resourcePath + "/icons/clip-polygon.svg", "[title]tt.clip_polygon", () => {
  66154. var item = this.viewer.clippingTool.startInsertion({
  66155. type: "polygon"
  66156. });
  66157. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66158. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  66159. $.jstree.reference(jsonNode.id).deselect_all();
  66160. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  66161. }));
  66162. {
  66163. // SCREEN BOX SELECT
  66164. var boxSelectTool = new ScreenBoxSelectTool(this.viewer);
  66165. clippingToolBar.append(this.createToolIcon(Potree.resourcePath + "/icons/clip-screen.svg", "[title]tt.screen_clip_box", () => {
  66166. if (!(this.viewer.scene.getActiveCamera() instanceof OrthographicCamera)) {
  66167. this.viewer.postMessage("Switch to Orthographic Camera Mode before using the Screen-Box-Select tool.", {
  66168. duration: 2000
  66169. });
  66170. return;
  66171. }
  66172. var item = boxSelectTool.startInsertion();
  66173. var measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
  66174. var jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid);
  66175. $.jstree.reference(jsonNode.id).deselect_all();
  66176. $.jstree.reference(jsonNode.id).select_node(jsonNode.id);
  66177. }));
  66178. }
  66179. {
  66180. // REMOVE CLIPPING TOOLS
  66181. clippingToolBar.append(this.createToolIcon(Potree.resourcePath + "/icons/remove.svg", "[title]tt.remove_all_clipping_volumes", () => {
  66182. this.viewer.scene.removeAllClipVolumes();
  66183. }));
  66184. }
  66185. }
  66186. initFilters() {
  66187. this.initClassificationList();
  66188. this.initReturnFilters();
  66189. this.initGPSTimeFilters();
  66190. this.initPointSourceIDFilters();
  66191. this.initTempFilters();
  66192. }
  66193. initTempFilters() {
  66194. //xzw add
  66195. var temperPanel = $('#temperature');
  66196. var rangeSlider = temperPanel.find('#sldTempRange');
  66197. rangeSlider.slider({
  66198. range: true,
  66199. min: 10,
  66200. max: 200,
  66201. step: 1,
  66202. values: [20, 50],
  66203. slide: (event, ui) => {
  66204. viewer.scene.pointclouds.forEach(e => e.material.setTempRange(ui.values[0], ui.values[1]));
  66205. viewer.images360.cube.material.setTempRange(ui.values[0], ui.values[1]);
  66206. viewer.dispatchEvent('content_changed');
  66207. temperPanel.find('#tempRange')[0].innerHTML = "".concat(ui.values[0], " to ").concat(ui.values[1]);
  66208. }
  66209. });
  66210. }
  66211. initReturnFilters() {
  66212. var elReturnFilterPanel = $('#return_filter_panel');
  66213. {
  66214. // RETURN NUMBER
  66215. var sldReturnNumber = elReturnFilterPanel.find('#sldReturnNumber');
  66216. var lblReturnNumber = elReturnFilterPanel.find('#lblReturnNumber');
  66217. sldReturnNumber.slider({
  66218. range: true,
  66219. min: 0,
  66220. max: 7,
  66221. step: 1,
  66222. values: [0, 7],
  66223. slide: (event, ui) => {
  66224. this.viewer.setFilterReturnNumberRange(ui.values[0], ui.values[1]);
  66225. }
  66226. });
  66227. var onReturnNumberChanged = event => {
  66228. var [from, to] = this.viewer.filterReturnNumberRange;
  66229. lblReturnNumber[0].innerHTML = "".concat(from, " to ").concat(to);
  66230. sldReturnNumber.slider({
  66231. values: [from, to]
  66232. });
  66233. };
  66234. this.viewer.addEventListener('filter_return_number_range_changed', onReturnNumberChanged);
  66235. onReturnNumberChanged();
  66236. }
  66237. {
  66238. // NUMBER OF RETURNS
  66239. var sldNumberOfReturns = elReturnFilterPanel.find('#sldNumberOfReturns');
  66240. var lblNumberOfReturns = elReturnFilterPanel.find('#lblNumberOfReturns');
  66241. sldNumberOfReturns.slider({
  66242. range: true,
  66243. min: 0,
  66244. max: 7,
  66245. step: 1,
  66246. values: [0, 7],
  66247. slide: (event, ui) => {
  66248. this.viewer.setFilterNumberOfReturnsRange(ui.values[0], ui.values[1]);
  66249. }
  66250. });
  66251. var onNumberOfReturnsChanged = event => {
  66252. var [from, to] = this.viewer.filterNumberOfReturnsRange;
  66253. lblNumberOfReturns[0].innerHTML = "".concat(from, " to ").concat(to);
  66254. sldNumberOfReturns.slider({
  66255. values: [from, to]
  66256. });
  66257. };
  66258. this.viewer.addEventListener('filter_number_of_returns_range_changed', onNumberOfReturnsChanged);
  66259. onNumberOfReturnsChanged();
  66260. }
  66261. }
  66262. initGPSTimeFilters() {
  66263. var elGPSTimeFilterPanel = $('#gpstime_filter_panel');
  66264. {
  66265. var slider = new HierarchicalSlider({
  66266. levels: 4,
  66267. slide: event => {
  66268. this.viewer.setFilterGPSTimeRange(...event.values);
  66269. }
  66270. });
  66271. var initialized = false;
  66272. var initialize = () => {
  66273. var elRangeContainer = $("#gpstime_multilevel_range_container");
  66274. elRangeContainer[0].prepend(slider.element);
  66275. var extent = this.viewer.getGpsTimeExtent();
  66276. slider.setRange(extent);
  66277. slider.setValues(extent);
  66278. initialized = true;
  66279. };
  66280. this.viewer.addEventListener("update", e => {
  66281. var extent = this.viewer.getGpsTimeExtent();
  66282. var gpsTimeAvailable = extent[0] !== Infinity;
  66283. if (!initialized && gpsTimeAvailable) {
  66284. initialize();
  66285. }
  66286. slider.setRange(extent); //高耗cpu
  66287. });
  66288. }
  66289. {
  66290. var txtGpsTime = elGPSTimeFilterPanel.find("#txtGpsTime");
  66291. var btnFindGpsTime = elGPSTimeFilterPanel.find("#btnFindGpsTime");
  66292. var targetTime = null;
  66293. txtGpsTime.on("input", e => {
  66294. var str = txtGpsTime.val();
  66295. if (!isNaN(str)) {
  66296. var value = parseFloat(str);
  66297. targetTime = value;
  66298. txtGpsTime.css("background-color", "");
  66299. } else {
  66300. targetTime = null;
  66301. txtGpsTime.css("background-color", "#ff9999");
  66302. }
  66303. });
  66304. btnFindGpsTime.click(() => {
  66305. if (targetTime !== null) {
  66306. viewer.moveToGpsTimeVicinity(targetTime);
  66307. }
  66308. });
  66309. }
  66310. }
  66311. initPointSourceIDFilters() {
  66312. var elPointSourceIDFilterPanel = $('#pointsourceid_filter_panel');
  66313. {
  66314. var slider = new HierarchicalSlider({
  66315. levels: 4,
  66316. range: [0, 65535],
  66317. precision: 1,
  66318. slide: event => {
  66319. var values = event.values;
  66320. this.viewer.setFilterPointSourceIDRange(values[0], values[1]);
  66321. }
  66322. });
  66323. var initialized = false;
  66324. var initialize = () => {
  66325. elPointSourceIDFilterPanel[0].prepend(slider.element);
  66326. initialized = true;
  66327. };
  66328. this.viewer.addEventListener("update", e => {
  66329. var extent = this.viewer.filterPointSourceIDRange;
  66330. if (!initialized) {
  66331. initialize();
  66332. slider.setValues(extent);
  66333. }
  66334. });
  66335. }
  66336. // let lblPointSourceID = elPointSourceIDFilterPanel.find("#lblPointSourceID");
  66337. // let elPointSourceID = elPointSourceIDFilterPanel.find("#spnPointSourceID");
  66338. // let slider = new ZoomableSlider();
  66339. // elPointSourceID[0].appendChild(slider.element);
  66340. // slider.update();
  66341. // slider.change( () => {
  66342. // let range = slider.chosenRange;
  66343. // this.viewer.setFilterPointSourceIDRange(range[0], range[1]);
  66344. // });
  66345. // let onPointSourceIDExtentChanged = (event) => {
  66346. // let range = this.viewer.filterPointSourceIDExtent;
  66347. // slider.setVisibleRange(range);
  66348. // };
  66349. // let onPointSourceIDChanged = (event) => {
  66350. // let range = this.viewer.filterPointSourceIDRange;
  66351. // let precision = 1;
  66352. // let from = `${Utils.addCommas(range[0].toFixed(precision))}`;
  66353. // let to = `${Utils.addCommas(range[1].toFixed(precision))}`;
  66354. // lblPointSourceID[0].innerHTML = `${from} to ${to}`;
  66355. // slider.setRange(range);
  66356. // };
  66357. // this.viewer.addEventListener('filter_point_source_id_range_changed', onPointSourceIDChanged);
  66358. // this.viewer.addEventListener('filter_point_source_id_extent_changed', onPointSourceIDExtentChanged);
  66359. }
  66360. initClassificationList() {
  66361. var elClassificationList = $('#classificationList');
  66362. var addClassificationItem = (code, name) => {
  66363. var classification = this.viewer.classifications[code];
  66364. var inputID = 'chkClassification_' + code;
  66365. var colorPickerID = 'colorPickerClassification_' + code;
  66366. var checked = classification.visible ? "checked" : "";
  66367. var element = $("\n\t\t\t\t<li>\n\t\t\t\t\t<label style=\"whitespace: nowrap; display: flex\">\n\t\t\t\t\t\t<input id=\"".concat(inputID, "\" type=\"checkbox\" ").concat(checked, "/>\n\t\t\t\t\t\t<span style=\"flex-grow: 1\">").concat(name, "</span>\n\t\t\t\t\t\t<input id=\"").concat(colorPickerID, "\" style=\"zoom: 0.5\" />\n\t\t\t\t\t</label>\n\t\t\t\t</li>\n\t\t\t"));
  66368. var elInput = element.find('input');
  66369. var elColorPicker = element.find("#".concat(colorPickerID));
  66370. elInput.click(event => {
  66371. this.viewer.setClassificationVisibility(code, event.target.checked);
  66372. });
  66373. var defaultColor = classification.color.map(c => c * 255).join(", ");
  66374. defaultColor = "rgb(".concat(defaultColor, ")");
  66375. elColorPicker.spectrum({
  66376. // flat: true,
  66377. color: defaultColor,
  66378. showInput: true,
  66379. preferredFormat: 'rgb',
  66380. cancelText: '',
  66381. chooseText: 'Apply',
  66382. move: color => {
  66383. var rgb = color.toRgb();
  66384. var c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1];
  66385. classification.color = c;
  66386. },
  66387. change: color => {
  66388. var rgb = color.toRgb();
  66389. var c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1];
  66390. classification.color = c;
  66391. }
  66392. });
  66393. elClassificationList.append(element);
  66394. };
  66395. var addToggleAllButton = () => {
  66396. // toggle all button
  66397. var element = $("\n\t\t\t\t<li>\n\t\t\t\t\t<label style=\"whitespace: nowrap\">\n\t\t\t\t\t\t<input id=\"toggleClassificationFilters\" type=\"checkbox\" checked/>\n\t\t\t\t\t\t<span>show/hide all</span>\n\t\t\t\t\t</label>\n\t\t\t\t</li>\n\t\t\t");
  66398. var elInput = element.find('input');
  66399. elInput.click(event => {
  66400. this.viewer.toggleAllClassificationsVisibility();
  66401. });
  66402. elClassificationList.append(element);
  66403. };
  66404. var addInvertButton = () => {
  66405. var element = $("\n\t\t\t\t<li>\n\t\t\t\t\t<input type=\"button\" value=\"invert\" />\n\t\t\t\t</li>\n\t\t\t");
  66406. var elInput = element.find('input');
  66407. elInput.click(() => {
  66408. var classifications = this.viewer.classifications;
  66409. for (var key of Object.keys(classifications)) {
  66410. var value = classifications[key];
  66411. this.viewer.setClassificationVisibility(key, !value.visible);
  66412. }
  66413. });
  66414. elClassificationList.append(element);
  66415. };
  66416. var populate = () => {
  66417. addToggleAllButton();
  66418. for (var classID in this.viewer.classifications) {
  66419. addClassificationItem(classID, this.viewer.classifications[classID].name);
  66420. }
  66421. addInvertButton();
  66422. };
  66423. populate();
  66424. this.viewer.addEventListener("classifications_changed", () => {
  66425. elClassificationList.empty();
  66426. populate();
  66427. });
  66428. this.viewer.addEventListener("classification_visibility_changed", () => {
  66429. {
  66430. // set checked state of classification buttons
  66431. for (var classID of Object.keys(this.viewer.classifications)) {
  66432. var classValue = this.viewer.classifications[classID];
  66433. var elItem = elClassificationList.find("#chkClassification_".concat(classID));
  66434. elItem.prop("checked", classValue.visible);
  66435. }
  66436. }
  66437. {
  66438. // set checked state of toggle button based on state of all other buttons
  66439. var numVisible = 0;
  66440. var numItems = 0;
  66441. for (var key of Object.keys(this.viewer.classifications)) {
  66442. if (this.viewer.classifications[key].visible) {
  66443. numVisible++;
  66444. }
  66445. numItems++;
  66446. }
  66447. var allVisible = numVisible === numItems;
  66448. var elToggle = elClassificationList.find("#toggleClassificationFilters");
  66449. elToggle.prop("checked", allVisible);
  66450. }
  66451. });
  66452. }
  66453. initAccordion() {
  66454. var _this = this;
  66455. $('.accordion > h3').each(function () {
  66456. var header = $(this);
  66457. var content = $(this).next();
  66458. //header.addClass('accordion-header ui-widget');
  66459. //content.addClass('accordion-content ui-widget');
  66460. content.hide();
  66461. header.click(() => {
  66462. content.slideToggle();
  66463. });
  66464. });
  66465. var languages = [["EN", "en"], ["FR", "fr"], ["DE", "de"], ["JP", "jp"], ["ES", "es"], ["SE", "se"], ["ZH", "zh"]];
  66466. var elLanguages = $('#potree_languages');
  66467. var _loop = function _loop() {
  66468. var [key, value] = languages[i];
  66469. var element = $("<a>".concat(key, "</a>"));
  66470. element.click(() => _this.viewer.setLanguage(value));
  66471. if (i === 0) {
  66472. element.css("margin-left", "30px");
  66473. }
  66474. elLanguages.append(element);
  66475. if (i < languages.length - 1) {
  66476. elLanguages.append($(document.createTextNode(' - ')));
  66477. }
  66478. };
  66479. for (var i = 0; i < languages.length; i++) {
  66480. _loop();
  66481. }
  66482. // to close all, call
  66483. // $(".accordion > div").hide()
  66484. // to open the, for example, tool menu, call:
  66485. // $("#menu_tools").next().show()
  66486. }
  66487. initAppearance() {
  66488. var sldPointBudget = this.dom.find('#sldPointBudget');
  66489. sldPointBudget.slider({
  66490. value: this.viewer.getPointBudget(),
  66491. min: 100 * 1000,
  66492. max: 10 * 1000 * 1000,
  66493. step: 1000,
  66494. slide: (event, ui) => {
  66495. this.viewer.setPointBudget(ui.value);
  66496. }
  66497. });
  66498. this.dom.find('#sldFOV').slider({
  66499. value: this.viewer.getFOV(),
  66500. min: 20,
  66501. max: 100,
  66502. step: 1,
  66503. slide: (event, ui) => {
  66504. this.viewer.setFOV(ui.value);
  66505. }
  66506. });
  66507. $('#sldEDLRadius').slider({
  66508. value: this.viewer.getEDLRadius(),
  66509. min: 1,
  66510. max: 4,
  66511. step: 0.01,
  66512. slide: (event, ui) => {
  66513. this.viewer.setEDLRadius(ui.value);
  66514. }
  66515. });
  66516. $('#sldEDLStrength').slider({
  66517. value: this.viewer.getEDLStrength(),
  66518. min: 0,
  66519. max: 5,
  66520. step: 0.01,
  66521. slide: (event, ui) => {
  66522. this.viewer.setEDLStrength(ui.value);
  66523. }
  66524. });
  66525. $('#sldEDLOpacity').slider({
  66526. value: this.viewer.getEDLOpacity(),
  66527. min: 0,
  66528. max: 1,
  66529. step: 0.01,
  66530. slide: (event, ui) => {
  66531. this.viewer.setEDLOpacity(ui.value);
  66532. }
  66533. });
  66534. this.viewer.addEventListener('point_budget_changed', event => {
  66535. $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget());
  66536. sldPointBudget.slider({
  66537. value: this.viewer.getPointBudget()
  66538. });
  66539. });
  66540. this.viewer.addEventListener('fov_changed', event => {
  66541. $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV());
  66542. $('#sldFOV').slider({
  66543. value: this.viewer.getFOV()
  66544. });
  66545. });
  66546. this.viewer.addEventListener('use_edl_changed', event => {
  66547. $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled();
  66548. });
  66549. this.viewer.addEventListener('edl_radius_changed', event => {
  66550. $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1);
  66551. $('#sldEDLRadius').slider({
  66552. value: this.viewer.getEDLRadius()
  66553. });
  66554. });
  66555. this.viewer.addEventListener('edl_strength_changed', event => {
  66556. $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1);
  66557. $('#sldEDLStrength').slider({
  66558. value: this.viewer.getEDLStrength()
  66559. });
  66560. });
  66561. this.viewer.addEventListener('background_changed', event => {
  66562. $("input[name=background][value='" + this.viewer.getBackground() + "']").prop('checked', true);
  66563. });
  66564. $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget());
  66565. $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV());
  66566. $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1);
  66567. $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1);
  66568. $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled();
  66569. {
  66570. var elBackground = $("#background_options");
  66571. elBackground.selectgroup();
  66572. elBackground.find("input").click(e => {
  66573. this.viewer.setBackground(e.target.value);
  66574. });
  66575. var currentBackground = this.viewer.getBackground();
  66576. try {
  66577. $("input[name=background_options][value=".concat(currentBackground, "]")).trigger("click");
  66578. } catch (e) {}
  66579. }
  66580. $('#chkEDLEnabled').click(() => {
  66581. this.viewer.setEDLEnabled($('#chkEDLEnabled').prop("checked"));
  66582. });
  66583. }
  66584. initNavigation() {
  66585. var elNavigation = $('#navigation');
  66586. var sldMoveSpeed = $('#sldMoveSpeed');
  66587. var lblMoveSpeed = $('#lblMoveSpeed');
  66588. elNavigation.append(this.createToolIcon(Potree.resourcePath + '/icons/earth_controls_1.png', '[title]tt.earth_control', () => {
  66589. this.viewer.setControls(this.viewer.earthControls);
  66590. }));
  66591. elNavigation.append(this.createToolIcon(Potree.resourcePath + '/icons/fps_controls.svg', '[title]tt.flight_control', () => {
  66592. this.viewer.setControls(this.viewer.fpControls);
  66593. this.viewer.fpControls.lockElevation = false;
  66594. }));
  66595. elNavigation.append(this.createToolIcon(Potree.resourcePath + '/icons/helicopter_controls.svg', '[title]tt.heli_control', () => {
  66596. this.viewer.setControls(this.viewer.fpControls);
  66597. this.viewer.fpControls.lockElevation = true;
  66598. }));
  66599. elNavigation.append(this.createToolIcon(Potree.resourcePath + '/icons/orbit_controls.svg', '[title]tt.orbit_control', () => {
  66600. this.viewer.setControls(this.viewer.orbitControls);
  66601. }));
  66602. elNavigation.append(this.createToolIcon(Potree.resourcePath + '/icons/focus.svg', '[title]tt.focus_control', () => {
  66603. this.viewer.fitToScreen();
  66604. }));
  66605. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/navigation_cube.svg", "[title]tt.navigation_cube_control", () => {
  66606. this.viewer.toggleNavigationCube();
  66607. }));
  66608. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/images/compas.svg", "[title]tt.compass", () => {
  66609. var visible = !this.viewer.compass.isVisible();
  66610. this.viewer.compass.setVisible(visible);
  66611. }));
  66612. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/camera_animation.svg", "[title]tt.camera_animation", () => {
  66613. var animation = CameraAnimation$1.defaultFromView(this.viewer);
  66614. viewer.scene.addCameraAnimation(animation);
  66615. }));
  66616. elNavigation.append("<br>");
  66617. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/left.svg", "[title]tt.left_view_control", () => {
  66618. this.viewer.setLeftView();
  66619. }));
  66620. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/right.svg", "[title]tt.right_view_control", () => {
  66621. this.viewer.setRightView();
  66622. }));
  66623. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/front.svg", "[title]tt.front_view_control", () => {
  66624. this.viewer.setFrontView();
  66625. }));
  66626. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/back.svg", "[title]tt.back_view_control", () => {
  66627. this.viewer.setBackView();
  66628. }));
  66629. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/top.svg", "[title]tt.top_view_control", () => {
  66630. this.viewer.setTopView();
  66631. }));
  66632. elNavigation.append(this.createToolIcon(Potree.resourcePath + "/icons/bottom.svg", "[title]tt.bottom_view_control", () => {
  66633. this.viewer.setBottomView();
  66634. }));
  66635. var elCameraProjection = $("\n\t\t\t<selectgroup id=\"camera_projection_options\">\n\t\t\t\t<option id=\"camera_projection_options_perspective\" value=\"PERSPECTIVE\">Perspective</option>\n\t\t\t\t<option id=\"camera_projection_options_orthigraphic\" value=\"ORTHOGRAPHIC\">Orthographic</option>\n\t\t\t</selectgroup>\n\t\t");
  66636. elNavigation.append(elCameraProjection);
  66637. elCameraProjection.selectgroup({
  66638. title: "Camera Projection"
  66639. });
  66640. elCameraProjection.find("input").click(e => {
  66641. this.viewer.setCameraMode(CameraMode[e.target.value]);
  66642. });
  66643. var cameraMode = Object.keys(CameraMode).filter(key => CameraMode[key] === this.viewer.scene.cameraMode);
  66644. elCameraProjection.find("input[value=".concat(cameraMode, "]")).trigger("click");
  66645. var speedRange = new Vector2(1, 10 * 1000);
  66646. var toLinearSpeed = value => {
  66647. return Math.pow(value, 4) * speedRange.y + speedRange.x;
  66648. };
  66649. var toExpSpeed = value => {
  66650. return Math.pow((value - speedRange.x) / speedRange.y, 1 / 4);
  66651. };
  66652. sldMoveSpeed.slider({
  66653. value: toExpSpeed(this.viewer.getMoveSpeed()),
  66654. min: 0,
  66655. max: 1,
  66656. step: 0.01,
  66657. slide: (event, ui) => {
  66658. this.viewer.setMoveSpeed(toLinearSpeed(ui.value));
  66659. }
  66660. });
  66661. this.viewer.addEventListener('move_speed_changed', event => {
  66662. lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1));
  66663. sldMoveSpeed.slider({
  66664. value: toExpSpeed(this.viewer.getMoveSpeed())
  66665. });
  66666. });
  66667. lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1));
  66668. }
  66669. initSettings() {
  66670. {
  66671. $('#sldMinNodeSize').slider({
  66672. value: this.viewer.getMinNodeSize(),
  66673. min: 0,
  66674. max: 1000,
  66675. step: 0.01,
  66676. slide: (event, ui) => {
  66677. this.viewer.setMinNodeSize(ui.value);
  66678. }
  66679. });
  66680. this.viewer.addEventListener('minnodesize_changed', event => {
  66681. $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize()));
  66682. $('#sldMinNodeSize').slider({
  66683. value: this.viewer.getMinNodeSize()
  66684. });
  66685. });
  66686. $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize()));
  66687. }
  66688. {
  66689. var elSplatQuality = $("#splat_quality_options");
  66690. elSplatQuality.selectgroup({
  66691. title: "Splat Quality"
  66692. });
  66693. elSplatQuality.find("input").click(e => {
  66694. if (e.target.value === "standard") {
  66695. this.viewer.useHQ = false;
  66696. } else if (e.target.value === "hq") {
  66697. this.viewer.useHQ = true;
  66698. }
  66699. });
  66700. var currentQuality = this.viewer.useHQ ? "hq" : "standard";
  66701. elSplatQuality.find("input[value=".concat(currentQuality, "]")).trigger("click");
  66702. }
  66703. $('#show_bounding_box').click(() => {
  66704. this.viewer.setShowBoundingBox($('#show_bounding_box').prop("checked"));
  66705. });
  66706. $('#set_freeze').click(() => {
  66707. this.viewer.setFreeze($('#set_freeze').prop("checked"));
  66708. });
  66709. }
  66710. }
  66711. class AnnotationTool extends EventDispatcher$1 {
  66712. constructor(viewer) {
  66713. super();
  66714. this.viewer = viewer;
  66715. this.renderer = viewer.renderer;
  66716. this.sg = new SphereGeometry(0.1);
  66717. this.sm = new MeshNormalMaterial();
  66718. this.s = new Mesh(this.sg, this.sm);
  66719. }
  66720. startInsertion() {
  66721. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  66722. var domElement = this.viewer.renderer.domElement;
  66723. var annotation = new Annotation({
  66724. position: [589748.270, 231444.540, 753.675],
  66725. title: "Annotation Title",
  66726. description: "Annotation Description"
  66727. });
  66728. this.dispatchEvent({
  66729. type: 'start_inserting_annotation',
  66730. annotation: annotation
  66731. });
  66732. var annotations = this.viewer.scene.annotations;
  66733. annotations.add(annotation);
  66734. var callbacks = {
  66735. cancel: null,
  66736. finish: null
  66737. };
  66738. var insertionCallback = e => {
  66739. if (e.button === MOUSE.LEFT) {
  66740. callbacks.finish();
  66741. } else if (e.button === MOUSE.RIGHT) {
  66742. callbacks.cancel();
  66743. }
  66744. };
  66745. callbacks.cancel = e => {
  66746. annotations.remove(annotation);
  66747. domElement.removeEventListener('mouseup', insertionCallback, true);
  66748. };
  66749. callbacks.finish = e => {
  66750. domElement.removeEventListener('mouseup', insertionCallback, true);
  66751. };
  66752. domElement.addEventListener('mouseup', insertionCallback, true);
  66753. var drag = e => {
  66754. var I = Utils.getMousePointCloudIntersection(e.drag.end, e.viewer.scene.getActiveCamera(), e.viewer, e.viewer.scene.pointclouds, {
  66755. pickClipped: true
  66756. });
  66757. if (I) {
  66758. this.s.position.copy(I.location);
  66759. annotation.position.copy(I.location);
  66760. }
  66761. };
  66762. var drop = e => {
  66763. viewer.scene.scene.remove(this.s);
  66764. this.s.removeEventListener("drag", drag);
  66765. this.s.removeEventListener("drop", drop);
  66766. };
  66767. this.s.addEventListener('drag', drag);
  66768. this.s.addEventListener('drop', drop);
  66769. this.viewer.scene.scene.add(this.s);
  66770. this.viewer.inputHandler.startDragging(this.s);
  66771. return annotation;
  66772. }
  66773. update() {
  66774. // let camera = this.viewer.scene.getActiveCamera();
  66775. // let domElement = this.renderer.domElement;
  66776. // let measurements = this.viewer.scene.measurements;
  66777. // const renderAreaSize = this.renderer.getSize(new THREE.Vector2());
  66778. // let clientWidth = renderAreaSize.width;
  66779. // let clientHeight = renderAreaSize.height;
  66780. }
  66781. render() {
  66782. //this.viewer.renderer.render(this.scene, this.viewer.scene.getActiveCamera());
  66783. }
  66784. }
  66785. ;
  66786. var planeGeometry$2 = new PlaneBufferGeometry(1, 1);
  66787. var height4dkk = 0.5; //4dkk的planeGeometry高度
  66788. var texLoader$a = new TextureLoader();
  66789. var videoPlayer$1 = Potree.browser.nonsupportH5Video ? new FlvVideoPlayerBase() : new H5VideoPlayerBase();
  66790. class Overlay extends Object3D {
  66791. constructor(data) {
  66792. super();
  66793. this.data = data;
  66794. this.external = external; //全景时不换材质
  66795. var plane = new Mesh(planeGeometry$2, new BasicMaterial({
  66796. color: '#00c8af',
  66797. opacity: 0.2,
  66798. transparent: !0,
  66799. polygonOffset: true,
  66800. //是否开启多边形偏移 //ie不开启时blank也不会闪烁
  66801. polygonOffsetFactor: -0.9,
  66802. //多边形偏移因子
  66803. polygonOffsetUnits: -4.0 //多边形偏移单位
  66804. }));
  66805. this.add(plane);
  66806. this.plane = plane;
  66807. this.setContent(data.media[0], data.url, data.isNew);
  66808. //this.setScale(data.width, data.height)
  66809. this.scale.set(data.width || 1, data.height || 1, 1); //需要把width转化一下吗,还是后端转化?
  66810. data.reverse && (this.scale.x *= -1);
  66811. this.addEventListener('dispose', this.dispose.bind(this));
  66812. var updatePlayInSight = () => {
  66813. Common.intervalTool.isWaiting('updatePlayInSight', () => {
  66814. Overlay.updatePlayInSight();
  66815. }, 500);
  66816. };
  66817. this.addEventListener('isVisible', updatePlayInSight);
  66818. this.addEventListener('transformChanged', updatePlayInSight);
  66819. Potree.Utils.setObjectLayers(this, 'dontIntersect');
  66820. }
  66821. setContent(type, src, autoSize) {
  66822. this.mediaType = type;
  66823. var loadDone = () => {
  66824. autoSize && this.autoSize();
  66825. this.plane.material.uniforms.color.value = new Color('#fff');
  66826. this.plane.material.opacity = 1;
  66827. };
  66828. if (type == 'photo') {
  66829. this.plane.material.map = texLoader$a.load(src, loadDone);
  66830. } else {
  66831. var video = videoPlayer$1.getVideo(src, this);
  66832. this.addEventListener('loadedmetadata', loadDone);
  66833. /* var video = $(`<video controls="controls" loop x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload" preload="meta" ></video>`)[0]
  66834. video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
  66835. video.src = src
  66836. video.onloadeddata = loadDone */
  66837. video.play();
  66838. this.plane.material.map = new VideoTexture(video);
  66839. Potree.Common.mobileAutoPlay(video, () => {
  66840. if (!this.disposed) {
  66841. video.play();
  66842. }
  66843. });
  66844. }
  66845. }
  66846. autoSize() {
  66847. //根据素材改变长宽
  66848. var size = this.getMediaSize();
  66849. if (size.x > 0 && size.y > 0) {
  66850. var area = this.plane.scale.x * this.plane.scale.y;
  66851. var r = Math.sqrt(area / (size.x * size.y));
  66852. this.scale.x = size.x * r;
  66853. this.scale.y = size.y * r;
  66854. }
  66855. this.dispatchEvent('scale_changed');
  66856. }
  66857. getMediaSize() {
  66858. var size = new Vector2();
  66859. var media = this.plane.material.map.image;
  66860. if (media) {
  66861. if (this.mediaType == 'photo') {
  66862. size.x = media.width;
  66863. size.y = media.height;
  66864. } else {
  66865. size.x = media.videoWidth;
  66866. size.y = media.videoHeight;
  66867. }
  66868. }
  66869. return size;
  66870. }
  66871. dispose() {
  66872. //geo和mat已经在mergeEditor里删了,这要删一下video啥的吗?
  66873. var index = viewer.scene.overlays.indexOf(this);
  66874. if (index == -1) return;
  66875. viewer.scene.overlays.splice(index, 1);
  66876. if (this.mediaType == 'video') {
  66877. var media = this.plane.material.map.image;
  66878. media === null || media === void 0 || media.pause();
  66879. this.disposed = true;
  66880. }
  66881. }
  66882. videoControl(state) {
  66883. var video = this.plane.material.map.image;
  66884. if (!video) return;
  66885. this.shouldPlay = state;
  66886. if (!state || state == 'stop') {
  66887. if (!video.paused) {
  66888. video.pause();
  66889. //console.log('videoControl paused ')
  66890. }
  66891. } else if (state) {
  66892. if (video.paused) {
  66893. //console.log('videoControl play ')
  66894. //video = this.loadVideo()
  66895. video.play();
  66896. }
  66897. }
  66898. }
  66899. static updatePlayInSight() {
  66900. var min = 0.15; //最小可播放尺寸(屏幕宽高都是2)
  66901. var camera = viewer.mainViewport.camera;
  66902. var camDir = viewer.mainViewport.view.direction;
  66903. var frustumMatrix = new Matrix4();
  66904. frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
  66905. var frustum = new Frustum();
  66906. frustum.setFromProjectionMatrix(frustumMatrix);
  66907. var insight = overlay => {
  66908. if (overlay.plane.material.side != 2) {
  66909. //side为0
  66910. var dir = overlay.plane.getWorldDirection(new Vector3());
  66911. if (dir.dot(camDir) > 0) {
  66912. //console.log('dir.dot(camDir)',dir.dot(camDir))
  66913. return false;
  66914. }
  66915. //可能看到背面。若能看到正面,视线方向和plane朝向必定为钝角
  66916. }
  66917. var bound = overlay.bound.clone();
  66918. var insight = frustum.intersectsBox(bound);
  66919. if (!insight) return false;
  66920. bound.applyMatrix4(frustumMatrix); //project on screen
  66921. var boundSize = bound.getSize(new Vector3());
  66922. if (boundSize.x < min && boundSize.y < min) {
  66923. //console.log('too small', boundSize)
  66924. return false;
  66925. }
  66926. return true;
  66927. };
  66928. viewer.scene.overlays.forEach(overlay => {
  66929. if (overlay.mediaType != 'video') return;
  66930. var shouldPlay = overlay.realVisible() && insight(overlay);
  66931. overlay.videoControl(shouldPlay);
  66932. });
  66933. }
  66934. }
  66935. class SplitScreen extends EventDispatcher {
  66936. constructor() {
  66937. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  66938. super();
  66939. }
  66940. /*
  66941. viewport.targetPlane // bound中心点处的plane,方向和view一致
  66942. viewport.shiftTarget // camera的位置project在targetPlane上的位置
  66943. 这两个参数的主要目的是为了getPosOutOfModel,以及rotateSideCamera时保持相对位置
  66944. */
  66945. splitStart(cameraProps) {
  66946. var _this = this;
  66947. var bound = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : viewer.bound.boundingBox;
  66948. var center = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : viewer.bound.center;
  66949. this.splited = true;
  66950. var viewports = [];
  66951. var subViewports = [viewer.mainViewport];
  66952. if (viewer.mapViewer) {
  66953. subViewports.push(viewer.mapViewer.viewports[0]);
  66954. }
  66955. var length = cameraProps.length;
  66956. var _loop = function _loop() {
  66957. var prop = cameraProps[i];
  66958. var viewport;
  66959. var v = subViewports.find(e => e.name == (prop.name2 || prop.name));
  66960. if (v) {
  66961. viewport = v;
  66962. viewport.left = prop.left;
  66963. viewport.bottom = prop.bottom;
  66964. viewport.width = prop.width;
  66965. viewport.height = prop.height;
  66966. }
  66967. if (!viewport) {
  66968. var view = new ExtendView();
  66969. if (prop.limitBound) view.limitBound = prop.limitBound;
  66970. prop.direction && (view.direction = prop.direction);
  66971. viewport = new Viewport(view, _this.getOrthoCamera(), prop);
  66972. if (prop.viewContainsPoints) viewport.viewContainsPoints = prop.viewContainsPoints;
  66973. //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
  66974. }
  66975. if (viewport.camera.type == 'OrthographicCamera') {
  66976. viewport.targetPlane = new Plane();
  66977. viewport.shiftTarget = new Vector3(); //project在targetPlane上的位置
  66978. }
  66979. viewport.fitMargin = prop.margin;
  66980. viewports.push(viewport);
  66981. };
  66982. for (var i = 0; i < length; i++) {
  66983. _loop();
  66984. }
  66985. viewer.viewports = viewports;
  66986. viewer.updateScreenSize({
  66987. forceUpdateSize: true
  66988. });
  66989. viewports.forEach(viewport => {
  66990. if (viewport.name == 'MainView') return;
  66991. this.viewportFitBound(viewport, bound, center, 0, viewport.fitMargin);
  66992. });
  66993. return viewports;
  66994. }
  66995. unSplit() {
  66996. this.splited = false;
  66997. this.unfocusViewport();
  66998. viewer.inputHandler.hoverViewport = null; //清空
  66999. viewer.viewports = [viewer.mainViewport];
  67000. viewer.mainViewport.width = 1;
  67001. viewer.mainViewport.height = 1;
  67002. viewer.mainViewport.left = 0;
  67003. viewer.mainViewport.bottom = 0;
  67004. viewer.updateScreenSize({
  67005. forceUpdateSize: true
  67006. });
  67007. }
  67008. viewportFitBound(viewport, bound, center) {
  67009. var duration = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  67010. var margin = arguments.length > 4 ? arguments[4] : undefined;
  67011. var view = viewport.view;
  67012. var info = {
  67013. bound
  67014. };
  67015. var {
  67016. boundSize,
  67017. boundCenter
  67018. } = this.getViewBound(viewport, bound);
  67019. //this.setShiftTarget(viewport, boundCenter)
  67020. viewport.targetPlane.setFromNormalAndCoplanarPoint(view.direction.clone(), boundCenter);
  67021. viewport.targetPlane.projectPoint(center, viewport.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外 this.shiftTarget是得到的
  67022. info.endPosition = this.getPosOutOfModel(viewport, boundSize);
  67023. //if(viewport.name == 'mapViewport')info.endPosition.z = Math.max(Potree.config.map.cameraHeight, info.endPosition.z)
  67024. info.margin = margin || {
  67025. x: 30,
  67026. y: 30
  67027. };
  67028. view.moveOrthoCamera(viewport, info, duration);
  67029. }
  67030. getViewBound(viewport, boundingBox) {
  67031. if (boundingBox) {
  67032. boundSize = boundingBox.getSize(new Vector3());
  67033. center = boundingBox.getCenter(new Vector3());
  67034. } else {
  67035. var {
  67036. boundSize,
  67037. center,
  67038. boundingBox
  67039. } = viewer.bound;
  67040. }
  67041. var containsPoints = [];
  67042. this.focusCenter && containsPoints.push(this.focusCenter);
  67043. viewport.viewContainsPoints && containsPoints.push(...viewport.viewContainsPoints);
  67044. if (containsPoints.length) {
  67045. //视野范围内必须要包含的点,直接算入模型区域。这时候得到的boundCenter和模型中心不重合
  67046. boundingBox = boundingBox.clone();
  67047. containsPoints.forEach(point => {
  67048. boundingBox.expandByPoint(point);
  67049. });
  67050. boundSize = boundingBox.getSize(new Vector3());
  67051. center = boundingBox.getCenter(new Vector3());
  67052. }
  67053. return {
  67054. boundSize,
  67055. boundCenter: center
  67056. };
  67057. }
  67058. getPosOutOfModel(viewport, boundSize) {
  67059. //let {boundSize, center} = viewer.bound
  67060. boundSize = boundSize || this.getViewBound(viewport).boundSize;
  67061. var expand = 10;
  67062. var radius = boundSize.length() * 2;
  67063. var position = viewport.shiftTarget.clone().sub(viewport.view.direction.clone().multiplyScalar(radius + expand));
  67064. return position;
  67065. }
  67066. updateCameraOutOfModel() {
  67067. //因为移动模型导致模型超出相机外,所以更新位置
  67068. viewer.viewports.forEach((viewport, i) => {
  67069. if (viewport.camera.isOrthographicCamera) {
  67070. //or if(viewport.targetPlane)
  67071. var {
  67072. boundSize,
  67073. boundCenter
  67074. } = this.getViewBound(viewport);
  67075. /* viewport.targetPlane.setFromNormalAndCoplanarPoint( viewport.view.direction.clone(), boundCenter)
  67076. viewport.targetPlane.projectPoint(viewport.view.position, viewport.shiftTarget) //target转换到过模型中心的平面,以保证镜头一定在模型外 this.shiftTarget是得到的
  67077. */
  67078. this.setShiftTarget(viewport, boundCenter);
  67079. var endPosition = this.getPosOutOfModel(viewport, boundSize);
  67080. //if(viewport.name == 'mapViewport')endPosition.z = Math.max(Potree.config.map.cameraHeight, endPosition.z)
  67081. viewport.view.position.copy(endPosition);
  67082. }
  67083. });
  67084. }
  67085. setShiftTarget(viewport, center) {
  67086. if (!viewport.targetPlane) {
  67087. viewport.targetPlane = new Plane();
  67088. viewport.shiftTarget = new Vector3(); //project在targetPlane上的位置
  67089. }
  67090. viewport.targetPlane.setFromNormalAndCoplanarPoint(viewport.view.direction, center);
  67091. viewport.targetPlane.projectPoint(viewport.view.position, viewport.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外
  67092. }
  67093. rotateSideCamera(viewport, angle) {
  67094. //侧视图或俯视图绕模型中心水平旋转
  67095. //let {boundSize, center} = viewer.bound
  67096. var {
  67097. boundSize,
  67098. boundCenter
  67099. } = this.getViewBound(viewport);
  67100. var center = this.focusCenter || boundCenter; //旋转中心,一般是所有模型的中心,除非想指定中心点
  67101. this.setShiftTarget(viewport, center);
  67102. //找到平移向量
  67103. var vec = new Vector3().subVectors(center, viewport.shiftTarget); //相对于中心的偏移值,旋转后偏移值也旋转
  67104. //旋转
  67105. var rotMatrix = new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), angle);
  67106. viewport.view.direction = viewport.view.direction.applyMatrix4(rotMatrix);
  67107. vec.applyMatrix4(rotMatrix);
  67108. viewport.shiftTarget.subVectors(center, vec); //新的
  67109. viewport.view.position = this.getPosOutOfModel(viewport, boundSize);
  67110. }
  67111. getOrthoCamera() {
  67112. var camera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  67113. camera.up.set(0, 0, 1);
  67114. return camera;
  67115. }
  67116. focusOnViewport(name) {
  67117. //全屏
  67118. viewer.viewports.forEach((viewport, i) => {
  67119. if (viewport.name == name) {
  67120. this.focusInfo = {
  67121. name,
  67122. left: viewport.left,
  67123. bottom: viewport.bottom,
  67124. height: viewport.height,
  67125. width: viewport.width
  67126. };
  67127. viewport.left = 0;
  67128. viewport.bottom = 0;
  67129. viewport.height = 1;
  67130. viewport.width = 1;
  67131. } else {
  67132. viewport.active = false;
  67133. }
  67134. });
  67135. viewer.updateScreenSize({
  67136. forceUpdateSize: true
  67137. });
  67138. }
  67139. unfocusViewport() {
  67140. if (!this.focusInfo) return;
  67141. viewer.viewports.forEach((viewport, i) => {
  67142. if (this.focusInfo.name == viewport.name) {
  67143. //全屏的恢复
  67144. viewport.left = this.focusInfo.left;
  67145. viewport.bottom = this.focusInfo.bottom;
  67146. viewport.height = this.focusInfo.height;
  67147. viewport.width = this.focusInfo.width;
  67148. }
  67149. viewport.active = true;
  67150. });
  67151. viewer.updateScreenSize({
  67152. forceUpdateSize: true
  67153. });
  67154. this.focusInfo = null;
  67155. }
  67156. }
  67157. var FEET_TO_INCHES_FACTOR = 12;
  67158. var EIGHTHS_SYMBOLS = ["", "⅛", "¼", "⅜", "½", "⅝", "¾", "⅞"]; //eighths 八分之……
  67159. class UnitOfMeasurement {
  67160. //转化单位工具
  67161. constructor(t, e, n, i) {
  67162. this.name = t, this.symbol = e, this.base = n, this.factor = i;
  67163. }
  67164. toBase(t) {
  67165. //换算到base
  67166. return t * this.factor;
  67167. }
  67168. fromBase(t) {
  67169. //换算到当前
  67170. return t / this.factor;
  67171. }
  67172. }
  67173. /* var o = function t(e) {
  67174. this.gettext = e,
  67175. t.METRIC = this.gettext("metric", void 0, "measurement system"),
  67176. t.IMPERIAL = this.gettext("imperial", void 0, "measurement system")
  67177. };
  67178. e.UoMSystem = o;
  67179. let UoMSystem = {
  67180. } */
  67181. /* var MeasurementDomain = {
  67182. DISTANCE : "DISTANCE",
  67183. t.AREA = "AREA",
  67184. t.VOLUME = "VOLUME",
  67185. t.DATA = "DATA",
  67186. t
  67187. }
  67188. */
  67189. var UnitsOfMeasurement = {
  67190. MILLIMETER: ["Millimeter", "mm"],
  67191. CENTIMETER: ["Centimeter", "cm"],
  67192. METER: ["Meter", "m"],
  67193. KILOMETER: ["Kilometer", "km"],
  67194. INCH: ["Inch", "in"],
  67195. FOOT: ["Foot", "ft"],
  67196. MILE: ["Mile", "mi"],
  67197. SQUAREMETER: ["SquareMeter", "m²"],
  67198. SQUAREFOOT: ["SquareFoot", "ft²"],
  67199. CUBICMETER: ["CubicMeter", "m³"],
  67200. CUBICFOOT: ["CubicFoot", "ft³"],
  67201. BYTE: ["Byte", "B"],
  67202. KILOBYTE: ["Kilobyte", "kB"],
  67203. MEGABYTE: ["Megabyte", "MB"],
  67204. GIGABYTE: ["Gigabyte", "GB"],
  67205. TERABYTE: ["Terabyte", "TB"],
  67206. PETABYTE: ["Petabyte", "PB"],
  67207. init: function init() {
  67208. var e,
  67209. n,
  67210. i,
  67211. a,
  67212. s,
  67213. c,
  67214. l,
  67215. u,
  67216. d,
  67217. p,
  67218. h,
  67219. f = new UnitOfMeasurement(UnitsOfMeasurement.METER[0], UnitsOfMeasurement.METER[1], void 0, 1),
  67220. g = new UnitOfMeasurement(UnitsOfMeasurement.SQUAREMETER[0], UnitsOfMeasurement.SQUAREMETER[1], void 0, 1),
  67221. m = new UnitOfMeasurement(UnitsOfMeasurement.CUBICMETER[0], UnitsOfMeasurement.CUBICMETER[1], void 0, 1),
  67222. v = new UnitOfMeasurement(UnitsOfMeasurement.BYTE[0], UnitsOfMeasurement.BYTE[1], void 0, 1);
  67223. UnitsOfMeasurement.DISTANCE = ((e = {})['metric'] = ((n = {})[UnitsOfMeasurement.MILLIMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MILLIMETER[0], UnitsOfMeasurement.MILLIMETER[1], f, .001), n[UnitsOfMeasurement.CENTIMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.CENTIMETER[0], UnitsOfMeasurement.CENTIMETER[1], f, .01), n[UnitsOfMeasurement.METER[0]] = f, n[UnitsOfMeasurement.KILOMETER[0]] = new UnitOfMeasurement(UnitsOfMeasurement.KILOMETER[0], UnitsOfMeasurement.KILOMETER[1], f, 1e3), n), e['imperial'] = ((i = {})[UnitsOfMeasurement.INCH[0]] = new UnitOfMeasurement(UnitsOfMeasurement.INCH[0], UnitsOfMeasurement.INCH[1], f, .0254), i[UnitsOfMeasurement.FOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.FOOT[0], UnitsOfMeasurement.FOOT[1], f, .3048), i[UnitsOfMeasurement.MILE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MILE[0], UnitsOfMeasurement.MILE[1], f, 1609.344), i), e);
  67224. UnitsOfMeasurement.AREA = ((a = {})['metric'] = ((s = {})[UnitsOfMeasurement.SQUAREMETER[0]] = g, s), a['imperial'] = ((c = {})[UnitsOfMeasurement.SQUAREFOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.SQUAREFOOT[0], UnitsOfMeasurement.SQUAREFOOT[1], g, .092903), c), a);
  67225. UnitsOfMeasurement.VOLUME = ((l = {})['metric'] = ((u = {})[UnitsOfMeasurement.CUBICMETER[0]] = m, u), l['imperial'] = ((d = {})[UnitsOfMeasurement.CUBICFOOT[0]] = new UnitOfMeasurement(UnitsOfMeasurement.CUBICFOOT[0], UnitsOfMeasurement.CUBICFOOT[1], m, .0283168), d), l);
  67226. //数据大小
  67227. var y = ((p = {})[UnitsOfMeasurement.BYTE[0]] = v, p[UnitsOfMeasurement.KILOBYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.KILOBYTE[0], UnitsOfMeasurement.KILOBYTE[1], v, 1e3), p[UnitsOfMeasurement.MEGABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.MEGABYTE[0], UnitsOfMeasurement.MEGABYTE[1], v, 1e6), p[UnitsOfMeasurement.GIGABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.GIGABYTE[0], UnitsOfMeasurement.GIGABYTE[1], v, 1e9), p[UnitsOfMeasurement.TERABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.TERABYTE[0], UnitsOfMeasurement.TERABYTE[1], v, 1e12), p[UnitsOfMeasurement.PETABYTE[0]] = new UnitOfMeasurement(UnitsOfMeasurement.PETABYTE[0], UnitsOfMeasurement.PETABYTE[1], v, 1e15), p);
  67228. UnitsOfMeasurement.DATA = ((h = {})['metric'] = y, h['imperial'] = y, h);
  67229. },
  67230. getUnitsOfMeasurementByDomain: function getUnitsOfMeasurementByDomain(e) {
  67231. return this[e.toUpperCase()];
  67232. /* switch (e.toUpperCase()) {
  67233. case a.DISTANCE:
  67234. return t.DISTANCE;
  67235. case a.AREA:
  67236. return t.AREA;
  67237. case a.VOLUME:
  67238. return t.VOLUME;
  67239. case a.DATA:
  67240. return t.DATA;
  67241. default:
  67242. console.error(e + " measurement domain is not supported.")
  67243. } */
  67244. },
  67245. getUnitsOfMeasurementByDomainAndSystem: function getUnitsOfMeasurementByDomainAndSystem(domain, system) {
  67246. var r = this.getUnitsOfMeasurementByDomain(domain);
  67247. if (r.hasOwnProperty(system.toLowerCase())) return r[system.toLowerCase()];
  67248. console.error(n + " measurement system is not supported.");
  67249. },
  67250. getDefaultUnitByDomainAndSystem: function getDefaultUnitByDomainAndSystem(e, n) {
  67251. switch (e.toUpperCase()) {
  67252. case 'DISTANCE':
  67253. switch (n.toLowerCase()) {
  67254. case 'metric':
  67255. return this.DISTANCE['metric'][this.METER[0]];
  67256. case 'imperial':
  67257. return this.DISTANCE['imperial'][this.FOOT[0]];
  67258. default:
  67259. console.error(n + " measurement system is not supported.");
  67260. }
  67261. case 'AREA':
  67262. switch (n.toLowerCase()) {
  67263. case 'metric':
  67264. return this.AREA['metric'][this.SQUAREMETER[0]];
  67265. case 'imperial':
  67266. return this.AREA['imperial'][this.SQUAREFOOT[0]];
  67267. default:
  67268. console.error(n + " measurement system is not supported.");
  67269. }
  67270. case 'VOLUME':
  67271. switch (n.toLowerCase()) {
  67272. case 'metric':
  67273. return this.VOLUME['metric'][this.CUBICMETER[0]];
  67274. case 'imperial':
  67275. return this.VOLUME['imperial'][this.CUBICFOOT[0]];
  67276. default:
  67277. console.error(n + " measurement system is not supported.");
  67278. }
  67279. case 'DATA':
  67280. switch (n.toLowerCase()) {
  67281. case 'metric':
  67282. return this.DATA['metric'][this.BYTE[0]];
  67283. case 'imperial':
  67284. return this.DATA['imperial'][this.BYTE[0]];
  67285. default:
  67286. console.error(n + " measurement system is not supported.");
  67287. }
  67288. default:
  67289. console.error(e + " measurement domain is not supported.");
  67290. }
  67291. }
  67292. };
  67293. class UnitService {
  67294. constructor( /* e, n, i */
  67295. ) {
  67296. //this.LanguageService = e,
  67297. //this.localStorageService = n,
  67298. //this.gettext = i,
  67299. //this.unitChanged = new r.Signal,
  67300. this.LOCAL_STORAGE_KEY = "iv_unit_key"; //?
  67301. UnitsOfMeasurement.init();
  67302. this.unitSystems = ['metric', 'imperial']; //[o.UoMSystem.METRIC, o.UoMSystem.IMPERIAL],
  67303. this.defaultSystem = 'metric'; //'imperial'
  67304. //var a = this.LanguageService.getBrowserLocaleString().toLowerCase();
  67305. //this.defaultSystem = t.isLocaleImperial(a) ? o.UoMSystem.IMPERIAL : o.UoMSystem.METRIC,
  67306. //this.initUnit()
  67307. }
  67308. /* initUnit() {
  67309. var t = this.localStorageService.get(this.LOCAL_STORAGE_KEY);
  67310. if (t)
  67311. for (var e = 0, n = this.unitSystems; e < n.length; e++) {
  67312. var i = n[e];
  67313. if (i === t)
  67314. return void this.setUnit(i, !0)
  67315. }
  67316. this.setUnit(this.defaultSystem, !1)
  67317. }
  67318. setUnit(t, e) {
  67319. this.currentSystem !== t && (this.currentSystem = t,
  67320. this.unitChanged.emit()),
  67321. e && this.localStorageService.set(this.LOCAL_STORAGE_KEY, t)
  67322. } */
  67323. /*isLocaleImperial(e) {
  67324. return t.IMPERIAL_LOCALES.indexOf(e.toLowerCase()) >= 0
  67325. }
  67326. ,
  67327. t.IMPERIAL_LOCALES = ["en_us"],
  67328. t.ɵfac(e) {
  67329. return new (e || t)(c.ɵɵinject(l.LanguageService),
  67330. c.ɵɵinject("localStorageService"),c.ɵɵinject("gettext"))
  67331. }
  67332. ,
  67333. t.ɵprov = c.ɵɵdefineInjectable({
  67334. token: t,
  67335. factory: t.ɵfac,
  67336. providedIn: "root"
  67337. }), */
  67338. }
  67339. class UoMService {
  67340. constructor( /* UnitService */
  67341. ) {
  67342. this.UnitService = new UnitService(); /* UnitService */
  67343. }
  67344. scopedConvert(t, n) {
  67345. var precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
  67346. var r = arguments.length > 3 ? arguments[3] : undefined;
  67347. var minFactor = arguments.length > 4 ? arguments[4] : undefined;
  67348. return this.convert(t, n, precision, r, minFactor);
  67349. }
  67350. convert(number, domain) {
  67351. var precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
  67352. var system = arguments.length > 3 ? arguments[3] : undefined;
  67353. var ifEighths = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : !1;
  67354. var o /* minFactor, ifRestrict */ = arguments.length > 5 ? arguments[5] : undefined;
  67355. var {
  67356. minFactor,
  67357. restrictUnit
  67358. } = o[system];
  67359. //if (!number) return "";
  67360. var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, minFactor, restrictUnit);
  67361. return this.getFormattedMeasurementString(s[0], s[1], precision, ifEighths);
  67362. }
  67363. convertBack(number, domain) {
  67364. var precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
  67365. var fromSystem = arguments.length > 3 ? arguments[3] : undefined;
  67366. var minFactor = arguments.length > 4 ? arguments[4] : undefined;
  67367. //从英制转到'metric'
  67368. if (!number) return "";
  67369. var d = UnitsOfMeasurement.getDefaultUnitByDomainAndSystem(domain, 'metric');
  67370. var s = this.getMostRelevantMeasurement2(domain, fromSystem, number, minFactor);
  67371. return this.getFormattedMeasurementString(s[0], d, precision);
  67372. /* 栗子:
  67373. viewer.unitConvert.convertBack(1, 'area', 5, 'imperial')
  67374. '0.09290 m²'
  67375. viewer.unitConvert.convertBack(1, 'Distance', 2, 'imperial')
  67376. '0.03 m'
  67377. */
  67378. }
  67379. getFormattedMeasurementString(number, unit, precision, ifEighths) {
  67380. var result;
  67381. if (ifEighths && unit.name === UnitsOfMeasurement.FOOT[0]) {
  67382. result = this.formatImperialDistance(number * FEET_TO_INCHES_FACTOR);
  67383. } else if (ifEighths && unit.name === UnitsOfMeasurement.INCH[0]) {
  67384. result = this.formatImperialDistance(number);
  67385. } else {
  67386. result = number.toLocaleString(void 0, {
  67387. minimumFractionDigits: precision,
  67388. maximumFractionDigits: precision
  67389. }) + " " + unit.symbol;
  67390. }
  67391. return result;
  67392. }
  67393. formatImperialDistance(e) {
  67394. var n = Math.round(8 * e),
  67395. i = Math.floor(n / 8),
  67396. r = Math.floor(i / FEET_TO_INCHES_FACTOR),
  67397. o = i - r * FEET_TO_INCHES_FACTOR,
  67398. a = EIGHTHS_SYMBOLS[Math.abs(n % 8)],
  67399. s = 0 === o && "" !== a ? "" : o;
  67400. "" !== s && "" !== a && (a = " " + a);
  67401. return 0 !== r ? r + "' " + s + a + '"' : "" + s + a + '"';
  67402. }
  67403. getMostRelevantMeasurement(domain, system, number) {
  67404. var minFactor = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  67405. var restrictUnit = arguments.length > 4 ? arguments[4] : undefined;
  67406. /* var a = r.values(UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system))
  67407. , s = r.filter(a, function(t) {
  67408. return t.factor >= i
  67409. })
  67410. , c = r.reduce(s, function(t, e) {
  67411. return e.fromBase(number) < t.fromBase(number) && e.fromBase(number) >= 1 ? e : t
  67412. }); */
  67413. var a = [];
  67414. var u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system);
  67415. for (var i in u) {
  67416. a.push(u[i]);
  67417. }
  67418. var s = a;
  67419. if (s.length > 1) {
  67420. if (restrictUnit) {
  67421. //是否只用这一单位,如只用mm。如果不是,就会寻找最大的接近的单位,如设置最小为mmminFactor=0.001),则1.2米时是'1.2m'、0.2米时是'20cm'、0.002米时是'2mm'
  67422. s = a.filter(m => m.name == restrictUnit);
  67423. } else {
  67424. s = a.filter(m => m.factor >= minFactor);
  67425. }
  67426. }
  67427. var c = s.reduce(function (prev, currentValue) {
  67428. //reduce最终值是最后一次return的值 ( 没看懂这句话作用)
  67429. return currentValue.fromBase(number) < prev.fromBase(number) && currentValue.fromBase(number) >= 1 ? currentValue : prev;
  67430. });
  67431. return c ? [c.fromBase(number), c] : void 0;
  67432. }
  67433. getMostRelevantMeasurement2(domain, system, number) {
  67434. var minFactor = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  67435. //add
  67436. var a = [];
  67437. var u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system);
  67438. for (var i in u) {
  67439. a.push(u[i]);
  67440. }
  67441. var s = a.filter(m => m.factor >= minFactor);
  67442. var c = s.reduce(function (prev, currentValue) {
  67443. //reduce最终值是最后一次return的值 ( 没看懂这句话作用)
  67444. return currentValue.toBase(number) < prev.toBase(number) && currentValue.toBase(number) >= 1 ? currentValue : prev;
  67445. });
  67446. return c ? [c.toBase(number), c] : void 0;
  67447. }
  67448. /* ɵfac(e){
  67449. return new (e || t)(c.ɵɵinject(l.UnitService))
  67450. }
  67451. ɵprov = c.ɵɵdefineInjectable({
  67452. token: t,
  67453. factory: t.ɵfac,
  67454. providedIn: "root"
  67455. }) */
  67456. }
  67457. var texLoader$b = new TextureLoader();
  67458. var color$1 = new Color(config$1.clip.color);
  67459. var markerMats$1;
  67460. var markerSizeInfo$1 = {
  67461. width2d: 40
  67462. };
  67463. var pickOrders = {
  67464. marker: 1,
  67465. area: 0
  67466. };
  67467. class mapClipBox extends ctrlPolygon {
  67468. constructor(center, scale) {
  67469. center = center.clone().setZ(0); //所有Z都为0
  67470. var prop = {
  67471. points: getPoints(center, scale, 0),
  67472. closed: true,
  67473. atPlane: true,
  67474. isRect: true,
  67475. dimension: '2d'
  67476. };
  67477. super('mapClipBox', prop);
  67478. this.angle = 0;
  67479. this.createRotateBar();
  67480. this.edgeMarkers = [];
  67481. //addMarkers:
  67482. this.initData(prop);
  67483. {
  67484. //areaPlane event 能拖动
  67485. this.areaPlane.addEventListener('mouseover', () => {
  67486. viewer.dispatchEvent({
  67487. type: "CursorChange",
  67488. action: "add",
  67489. name: "mapClipMove"
  67490. });
  67491. });
  67492. this.areaPlane.addEventListener('mouseleave', () => {
  67493. viewer.dispatchEvent({
  67494. type: "CursorChange",
  67495. action: "remove",
  67496. name: "mapClipMove"
  67497. });
  67498. });
  67499. var lastPos;
  67500. var drag = e => {
  67501. var intersect = e.intersect.orthoIntersect;
  67502. if (lastPos) {
  67503. var moveVec = new Vector3().subVectors(intersect, lastPos).setZ(0);
  67504. this.center.add(moveVec);
  67505. this.updatePoints();
  67506. this.dispatchEvent({
  67507. type: 'repos'
  67508. });
  67509. }
  67510. lastPos = intersect.clone();
  67511. };
  67512. var drop = e => {
  67513. lastPos = null;
  67514. };
  67515. this.areaPlane.addEventListener('drag', drag);
  67516. this.areaPlane.addEventListener('drop', drop);
  67517. }
  67518. /* this.addEventListener('dragChange',()=>{
  67519. this.updateTwoMidMarker(index+1)
  67520. }) */
  67521. Potree.Utils.setObjectLayers(this, 'mapObjects');
  67522. }
  67523. getScale() {
  67524. return new Vector3(this.points[0].distanceTo(this.points[1]), this.points[1].distanceTo(this.points[2]), 1);
  67525. }
  67526. addMarker() {
  67527. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  67528. var marker = new Sprite$2({
  67529. mat: this.getMarkerMaterial('default'),
  67530. pickOrder: pickOrders.marker,
  67531. sizeInfo: markerSizeInfo$1,
  67532. dontFixOrient: true,
  67533. viewports: viewer.mapViewer.viewports,
  67534. name: "mapClipBox_marker"
  67535. });
  67536. marker.renderOrder = 3;
  67537. //marker.markerSelectStates = {}
  67538. var edge = LineDraw.createLine([new Vector3(), new Vector3()], {
  67539. color: color$1
  67540. });
  67541. var edgeMarker = new Sprite$2({
  67542. mat: this.getMarkerMaterial('default'),
  67543. pickOrder: pickOrders.marker,
  67544. sizeInfo: markerSizeInfo$1,
  67545. dontFixOrient: true,
  67546. viewports: viewer.mapViewer.viewports,
  67547. name: "mapClipBox_edgePoint"
  67548. });
  67549. var mouseover = e => {
  67550. this.setMarkerSelected(e.object, true, 'single');
  67551. viewer.dispatchEvent({
  67552. type: "CursorChange",
  67553. action: "add",
  67554. name: "markerMove"
  67555. });
  67556. };
  67557. var mouseleave = e => {
  67558. this.setMarkerSelected(e.object, false, 'single');
  67559. viewer.dispatchEvent({
  67560. type: "CursorChange",
  67561. action: "remove",
  67562. name: "markerMove"
  67563. });
  67564. };
  67565. edgeMarker.addEventListener('mouseover', mouseover);
  67566. edgeMarker.addEventListener('mouseleave', mouseleave);
  67567. var dragInfo = {
  67568. lastPos: null
  67569. };
  67570. edgeMarker.addEventListener('drag', this.dragEdge.bind(this, dragInfo));
  67571. edgeMarker.addEventListener('drop', this.dropEdge.bind(this, dragInfo));
  67572. this.edgeMarkers.push(edgeMarker);
  67573. this.add(edgeMarker);
  67574. marker.dispatchEvent('addHoverEvent');
  67575. super.addMarker({
  67576. point: o.point,
  67577. marker: marker,
  67578. edge
  67579. });
  67580. }
  67581. dragEdge(dragInfo, e) {
  67582. //拖拽一个边(或一个边类型的marker),带动它的两个端点。 可以转化为拖拽marker往法线方向
  67583. var I, atMap;
  67584. atMap = e.dragViewport.name == 'mapViewport';
  67585. I = e.intersect.orthoIntersect;
  67586. if (I && dragInfo.lastPos) {
  67587. var i = this.edgeMarkers.indexOf(e.drag.object);
  67588. if (i !== -1) {
  67589. var lineNormal = math.getNormal2d({
  67590. p1: this.points[i],
  67591. p2: this.points[(i + 1) % 4]
  67592. });
  67593. var moveVec = new Vector3().subVectors(I, dragInfo.lastPos).setZ(0); //移动的向量
  67594. var dragVec = moveVec.projectOnVector(lineNormal).setZ(0); //在法线上移动的向量
  67595. var newPos = new Vector3().addVectors(this.points[i], dragVec); //marker应到的位置
  67596. this.dragChange(newPos, i, atMap); //转化为这个marker的拖拽
  67597. }
  67598. }
  67599. dragInfo.lastPos = I.clone();
  67600. }
  67601. dropEdge(dragInfo, e) {
  67602. dragInfo.lastPos = null;
  67603. this.setMarkerSelected(e.drag.object, false, 'single'); //拖拽时似乎没有触发mouseout
  67604. }
  67605. createAreaPlane() {
  67606. var planeMat = new MeshBasicMaterial({
  67607. color: color$1,
  67608. //"#00eeff",
  67609. side: DoubleSide,
  67610. opacity: 0.3,
  67611. transparent: true,
  67612. depthTest: false
  67613. });
  67614. return super.createAreaPlane(planeMat);
  67615. }
  67616. getMarkerMaterial(type) {
  67617. if (!markerMats$1) {
  67618. markerMats$1 = {
  67619. default: new MeshBasicMaterial({
  67620. transparent: !0,
  67621. color: color$1,
  67622. opacity: 0.8,
  67623. map: texLoader$b.load(Potree.resourcePath + '/textures/whiteCircle.png')
  67624. }),
  67625. select: new MeshBasicMaterial({
  67626. transparent: !0,
  67627. color: color$1,
  67628. opacity: 1,
  67629. map: texLoader$b.load(Potree.resourcePath + '/textures/whiteCircle.png')
  67630. })
  67631. };
  67632. mapClipBox.markerMats = markerMats$1;
  67633. }
  67634. return markerMats$1[type];
  67635. }
  67636. setMarkerSelected(marker, state, hoverObject) {
  67637. //console.warn(marker.id , state, hoverObject)
  67638. if (state == 'hover') {
  67639. marker.material = this.getMarkerMaterial('select');
  67640. } else {
  67641. marker.material = this.getMarkerMaterial('default');
  67642. }
  67643. /* marker.markerSelectStates[hoverObject] = state
  67644. let absoluteState = false
  67645. for(var i in marker.markerSelectStates){
  67646. if(marker.markerSelectStates[i]){
  67647. absoluteState = true; break;
  67648. }
  67649. }
  67650. if(absoluteState){
  67651. marker.material = this.getMarkerMaterial('select')
  67652. }else{
  67653. marker.material = this.getMarkerMaterial('default')
  67654. }
  67655. marker.selected = absoluteState */
  67656. viewer.mapViewer.dispatchEvent('content_changed');
  67657. }
  67658. createRotateBar() {
  67659. //中心点在线的一端,整体初始在box上方
  67660. var lineLen = 1.5,
  67661. circleWidth = 2,
  67662. barOpacity = 0.7;
  67663. var object = new Object3D();
  67664. var bar = new Sprite$2({
  67665. mat: new MeshBasicMaterial({
  67666. side: DoubleSide,
  67667. opacity: barOpacity,
  67668. transparent: true,
  67669. depthTest: false,
  67670. map: texLoader$b.load(Potree.resourcePath + '/textures/rotation_circle.png')
  67671. }),
  67672. root: object,
  67673. sizeInfo: markerSizeInfo$1,
  67674. dontFixOrient: true,
  67675. viewports: viewer.mapViewer.viewports,
  67676. name: "mapClipRotateBar"
  67677. });
  67678. bar.position.set(0, lineLen + circleWidth / 2, 0);
  67679. bar.scale.set(circleWidth, circleWidth, circleWidth);
  67680. bar.addEventListener('mouseover', () => {
  67681. bar.material.opacity = 1;
  67682. viewer.dispatchEvent({
  67683. type: "CursorChange",
  67684. action: "add",
  67685. name: "mapClipRotate"
  67686. });
  67687. viewer.mapViewer.dispatchEvent('content_changed');
  67688. });
  67689. var leave = () => {
  67690. bar.material.opacity = barOpacity;
  67691. viewer.dispatchEvent({
  67692. type: "CursorChange",
  67693. action: "remove",
  67694. name: "mapClipRotate"
  67695. });
  67696. viewer.mapViewer.dispatchEvent('content_changed');
  67697. };
  67698. bar.addEventListener('mouseleave', leave);
  67699. this.addEventListener('dispose', leave);
  67700. var lastPos;
  67701. bar.addEventListener('drag', e => {
  67702. var intersect = e.intersect.orthoIntersect;
  67703. if (lastPos) {
  67704. var vec1 = new Vector3().subVectors(lastPos, this.center).setZ(0);
  67705. var vec2 = new Vector3().subVectors(intersect, this.center).setZ(0);
  67706. var angle = math.getAngle(vec1, vec2, 'z');
  67707. this.angle += angle;
  67708. this.rotateBar.rotation.z = this.angle;
  67709. this.updatePoints();
  67710. this.dispatchEvent({
  67711. type: 'rotate',
  67712. angle: this.angle
  67713. });
  67714. }
  67715. lastPos = intersect.clone();
  67716. });
  67717. bar.addEventListener('drop', () => {
  67718. lastPos = null;
  67719. viewer.dispatchEvent({
  67720. type: "CursorChange",
  67721. action: "remove",
  67722. name: "mapClipRotate"
  67723. });
  67724. });
  67725. var line = LineDraw.createLine([new Vector3(), new Vector3(0, lineLen, 0)], {
  67726. color: color$1
  67727. });
  67728. object.add(bar);
  67729. object.add(line);
  67730. this.add(object);
  67731. this.rotateBar = object;
  67732. this.rotateBar.bar = bar;
  67733. }
  67734. updatePoints(scale) {
  67735. this.points = getPoints(this.center, scale || this.getScale(), this.angle);
  67736. this.getPoint2dInfo(this.points);
  67737. this.update({
  67738. ifUpdateMarkers: true
  67739. });
  67740. }
  67741. update() {
  67742. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  67743. super.update(options);
  67744. {
  67745. //update rotateBar
  67746. var center = new Vector3().addVectors(this.points[0], this.points[1]).multiplyScalar(0.5);
  67747. this.rotateBar.position.copy(center);
  67748. this.rotateBar.bar.waitUpdate(); //更新sprite matrix
  67749. }
  67750. {
  67751. for (var i = 0; i < 4; i++) {
  67752. var current = this.points[i];
  67753. var next = this.points[(i + 1) % 4];
  67754. var mid = new Vector3().addVectors(current, next).multiplyScalar(0.5);
  67755. this.updateMarker(this.edgeMarkers[i], mid);
  67756. }
  67757. }
  67758. }
  67759. dispose() {
  67760. super.dispose();
  67761. this.dispatchEvent('dispose');
  67762. this.rotateBar.bar.dispose();
  67763. }
  67764. }
  67765. function getPoints(center, scale) {
  67766. var angle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  67767. var points = [new Vector3(-scale.x / 2, +scale.y / 2, 0), new Vector3(+scale.x / 2, +scale.y / 2, 0), new Vector3(+scale.x / 2, -scale.y / 2, 0), new Vector3(-scale.x / 2, -scale.y / 2, 0)];
  67768. var rotMatrix = new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), angle); //再旋转
  67769. points.forEach(e => {
  67770. e.applyMatrix4(rotMatrix);
  67771. e.add(center);
  67772. });
  67773. return points;
  67774. }
  67775. var defaultBoxWidth = 16; //navvis: 10
  67776. //navvis position: si {x: 0, y: 0, z: 0}
  67777. var cameraProps = [{
  67778. name: 'top',
  67779. axis: ["x", "y"],
  67780. direction: new Vector3(0, 0, -1),
  67781. //镜头朝向
  67782. openCount: 0
  67783. }, {
  67784. name: 'front',
  67785. axis: ["x", "z"],
  67786. direction: new Vector3(0, 1, 0),
  67787. openCount: 0
  67788. }, {
  67789. name: 'mainView',
  67790. openCount: 0
  67791. }];
  67792. var Clip = {
  67793. bus: new EventDispatcher(),
  67794. selectedDatasets: [],
  67795. changeCallback(force) {
  67796. if (this.activeViewName != 'mainView') {
  67797. this.splitScreenTool.updateCameraOutOfModel(); //更新相机位置
  67798. }
  67799. if (Potree.settings.isOfficial && this.showMap) {
  67800. var fun = () => {
  67801. var pointclouds = this.getIntersectPointcloud();
  67802. if (Common$1.getDifferenceSet(pointclouds, this.selectedDatasets).length) {
  67803. this.selectedDatasets = pointclouds;
  67804. //console.error('clipSelectedDatasets',selectedDatasets)
  67805. this.bus.dispatchEvent({
  67806. type: 'updateSelectedDatasets',
  67807. selectedDatasets: pointclouds.map(e => e.dataset_id)
  67808. });
  67809. }
  67810. };
  67811. if (force) fun();else Common$1.intervalTool.isWaiting('clipSelectedDatasets', fun, 300);
  67812. }
  67813. },
  67814. enter: function enter() {
  67815. this.initViews();
  67816. this.previousView = {
  67817. position: viewer.images360.position,
  67818. target: viewer.scene.view.getPivot(),
  67819. displayMode: Potree.settings.displayMode,
  67820. //---
  67821. ifShowMarker: Potree.settings.ifShowMarker
  67822. };
  67823. var pointcloud = this.getPointcloud();
  67824. var bound = pointcloud.bound; //只选取其中一个数据集的bound,而非整体,是因为担心两个数据集中间有空隙,于是刚好落在没有点云的地方。
  67825. var boundSize = bound.getSize(new Vector3());
  67826. var target = this.getTarget(bound.getCenter(new Vector3())); //navvis的位置xy是用相机位置 this.ViewService.mainView.getCamera().position 我觉得也可以用第一个漫游点的,或者最接近bound中心的漫游点
  67827. var scale = new Vector3(defaultBoxWidth, defaultBoxWidth, boundSize.z); //z和navvis一样
  67828. var eyeDir = viewer.scene.view.direction.clone().setZ(0 /* -boundSize.z/3 */).multiplyScalar(-defaultBoxWidth); //为了使所在楼层不变,不修改z
  67829. //let eyeDir = scale.clone().setZ(boundSize.z/3).multiplyScalar(1.3)
  67830. var position = new Vector3().addVectors(target, eyeDir);
  67831. Potree.settings.displayMode = 'showPointCloud';
  67832. viewer.setView({
  67833. position,
  67834. target,
  67835. duration: 300,
  67836. callback: function callback() {}
  67837. });
  67838. //viewer.setControls(viewer.orbitControls);
  67839. viewer.setLimitFar(false);
  67840. //viewer.setClipState(false) //暂时关闭旧的clipping
  67841. /* new AxisViewer(viewer.mainViewport, viewer.renderArea,{domStyle:{
  67842. bottom: '2px',right: '20px', width:'80px',height:'80px'}
  67843. }) */
  67844. {
  67845. this.box = new BoxVolume$1({
  67846. clip: true
  67847. });
  67848. this.box.clipTask = ClipTask['SHOW_INSIDE_Big' /* "SHOW_INSIDE" */];
  67849. this.box.showBox = false;
  67850. this.box.name = "ClipBox";
  67851. this.box.position.copy(target);
  67852. this.box.scale.copy(scale);
  67853. viewer.controls.setTarget(this.box.position); //绕其旋转
  67854. this.splitScreenTool.focusCenter = this.box.position;
  67855. //带动mapBox
  67856. this.box.addEventListener('position_changed', e => {
  67857. if (this.showMap) {
  67858. this.mapBox.center.setX(this.box.position.x);
  67859. this.mapBox.center.setY(this.box.position.y);
  67860. this.mapBox.updatePoints();
  67861. }
  67862. this.changeCallback();
  67863. });
  67864. this.box.addEventListener('scale_changed', e => {
  67865. if (this.showMap) {
  67866. var scale = this.box.scale;
  67867. this.mapBox.updatePoints(scale);
  67868. }
  67869. this.changeCallback();
  67870. });
  67871. this.box.addEventListener('orientation_changed', e => {
  67872. if (this.showMap) {
  67873. this.mapBox.angle = this.box.rotation.z;
  67874. this.mapBox.rotateBar.rotation.z = this.mapBox.angle;
  67875. this.mapBox.updatePoints();
  67876. }
  67877. this.changeCallback();
  67878. });
  67879. viewer.scene.addVolume(this.box);
  67880. }
  67881. if (this.showMap) {
  67882. //map
  67883. var boxRotateBack = () => {
  67884. //不知道是不是这么写。 因为可能z的旋转不一定都在z
  67885. this.box.rotation.x = 0;
  67886. this.box.rotation.y = 0;
  67887. };
  67888. this.mapBox = new mapClipBox(target, scale);
  67889. viewer.mapViewer.scene.add(this.mapBox);
  67890. //带动box
  67891. this.mapBox.addEventListener('repos', e => {
  67892. this.box.position.setX(this.mapBox.center.x);
  67893. this.box.position.setY(this.mapBox.center.y);
  67894. boxRotateBack();
  67895. this.changeCallback();
  67896. });
  67897. this.mapBox.addEventListener('dragChange', e => {
  67898. var scale = this.mapBox.getScale();
  67899. this.box.scale.setX(scale.x);
  67900. this.box.scale.setY(scale.y);
  67901. this.box.position.setX(this.mapBox.center.x);
  67902. this.box.position.setY(this.mapBox.center.y);
  67903. boxRotateBack();
  67904. this.changeCallback();
  67905. });
  67906. this.mapBox.addEventListener('rotate', e => {
  67907. this.box.rotation.z = this.mapBox.angle;
  67908. boxRotateBack();
  67909. this.changeCallback();
  67910. });
  67911. }
  67912. this.switchView('mainView');
  67913. {
  67914. //viewer.setClipTask(ClipTask["SHOW_INSIDE"])
  67915. }
  67916. Potree.settings.unableNavigate = true;
  67917. Potree.settings.ifShowMarker = false;
  67918. Potree.Utils.updateVisible(viewer.scene.overlayScene /* viewer.measuringTool.scene */, 'clipModel', false);
  67919. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'clipModel', false)//隐藏地图游标
  67920. viewer.inputHandler.toggleSelection(this.box);
  67921. viewer.inputHandler.fixSelection = true;
  67922. viewer.transformationTool.setModeEnable(['scale', 'translation', 'rotation']);
  67923. viewer.transformationTool.frame.material.color.set(Potree.config.clip.color); //navvis 15899953
  67924. viewer.setPointStandardMat(true);
  67925. if (this.showMap) {
  67926. var mapVisi = false;
  67927. this.events = {
  67928. flyToPos: e => {
  67929. var dis = 2;
  67930. var target = e.position;
  67931. target = this.box.position;
  67932. position = e.position;
  67933. //为了方便缩放操作,直接使用box中心作为target
  67934. var duration = e.duration == void 0 ? 1000 : e.duration;
  67935. viewer.scene.view.setView({
  67936. position,
  67937. duration,
  67938. target
  67939. });
  67940. },
  67941. mapVisiChange(e) {
  67942. mapVisi = e.visible;
  67943. var delay = 100; //因resize了camera需要时间更新projectionMatrix
  67944. setTimeout(() => {
  67945. var boundingBox = Clip.box.boundingBox.clone().applyMatrix4(Clip.box.matrixWorld);
  67946. if (mapVisi) {
  67947. //切换地图
  67948. if (viewer.fpVisiDatasets.length == 0) {
  67949. //不会显示任何一个floorplan图,就要就近移动到一个可见数据集里
  67950. var clouds = viewer.scene.pointclouds.filter(e => e.visible);
  67951. if (clouds.length == 0) clouds = viewer.scene.pointclouds;
  67952. var scores = clouds.map((e, i) => {
  67953. return [-viewer.scene.view.position.distanceToSquared(e.bound2), i];
  67954. });
  67955. scores = scores.sort((a, b) => a[0] - b[0]);
  67956. var neareast = clouds[scores[0][1]];
  67957. viewer.flyToDataset({
  67958. pointcloud: neareast,
  67959. duration: 0
  67960. });
  67961. }
  67962. if (Clip.switchMapCount == 0 || !Potree.Utils.getPos2d(viewer.scene.view.position, viewer.mapViewer.viewports[0], viewer.mapViewer.renderArea).inSight || !Potree.Utils.isInsideFrustum(boundingBox, viewer.mapViewer.camera)) {
  67963. //要使box框和游标都在屏幕内。因为游标是3d的当前位置,很可能是准备去框住的位置
  67964. var _bound = boundingBox.clone();
  67965. _bound.expandByPoint(viewer.scene.view.position);
  67966. var size = _bound.getSize(new Vector3());
  67967. var center = _bound.getCenter(new Vector3());
  67968. var margin = viewer.mainViewport.resolution.clone().multiplyScalar(0.3);
  67969. viewer.mapViewer.moveTo(center, size, 100, margin);
  67970. }
  67971. Clip.switchMapCount++;
  67972. //关于究竟是focus box还是dataset有点纠结,又或是两个的union。box和数据集可能离得很远,且无法确定当前想选择的数据集,且数据集可能无floorplan, 即使有可能也不展示……
  67973. } else {
  67974. //切换3d
  67975. if (!Potree.Utils.isInsideFrustum(boundingBox, viewer.scene.getActiveCamera())) {
  67976. //屏幕上没有box的话
  67977. viewer.focusOnObject({
  67978. boundingBox
  67979. }, 'boundingBox', 100);
  67980. }
  67981. }
  67982. }, delay);
  67983. }
  67984. };
  67985. this.switchMapCount = 0;
  67986. this.bus.addEventListener('flyToPos', this.events.flyToPos);
  67987. viewer.mapViewer.addEventListener('forceVisible', this.events.mapVisiChange);
  67988. }
  67989. this.editing = true;
  67990. setTimeout(() => {
  67991. this.changeCallback(true);
  67992. }, 1);
  67993. },
  67994. leave: function leave() {
  67995. viewer.inputHandler.fixSelection = false;
  67996. viewer.scene.removeVolume(this.box);
  67997. this.showMap && this.mapBox.dispose();
  67998. //viewer.setControls(viewer.fpControls);
  67999. this.switchView('mainView');
  68000. Potree.settings.unableNavigate = false;
  68001. Potree.settings.ifShowMarker = this.previousView.ifShowMarker;
  68002. Potree.Utils.updateVisible(viewer.scene.overlayScene /* viewer.measuringTool.scene */, 'clipModel', true);
  68003. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'clipModel', true)
  68004. viewer.setView(this.previousView);
  68005. viewer.setLimitFar(true);
  68006. viewer.setPointStandardMat(false);
  68007. //viewer.setClipState(true)
  68008. viewer.controls.setTarget(null);
  68009. this.splitScreenTool.focusCenter = null;
  68010. //viewer.mainViewport.axis.dispose()
  68011. cameraProps.forEach(e => e.openCount = 0);
  68012. if (this.showMap) {
  68013. this.bus.removeEventListener('flyToPos', this.events.flyToPos);
  68014. viewer.mapViewer.removeEventListener('forceVisible', this.events.mapVisiChange);
  68015. this.events = null;
  68016. }
  68017. this.editing = false;
  68018. },
  68019. initViews() {
  68020. if (this.views) {
  68021. this.views.top.pitch = -Math.PI;
  68022. this.views.top.yaw = 0;
  68023. this.views.front.pitch = 0;
  68024. this.views.front.yaw = 0; //--还原for bugID 44757
  68025. return;
  68026. }
  68027. this.views = {};
  68028. this.cameras = {};
  68029. this.orthoCamera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  68030. this.orthoCamera.up.set(0, 0, 1);
  68031. this.splitScreenTool = new SplitScreen();
  68032. this.targetPlane = viewer.mainViewport.targetPlane = new Plane();
  68033. this.shiftTarget = viewer.mainViewport.shiftTarget = new Vector3(); //project在targetPlane上的位置
  68034. for (var i = 0; i < 2; i++) {
  68035. var prop = cameraProps[i];
  68036. var view = new ExtendView();
  68037. this.views[prop.name] = view;
  68038. this.cameras[prop.name] = this.orthoCamera;
  68039. view.name = prop.name;
  68040. view.direction = prop.direction;
  68041. }
  68042. this.views.mainView = viewer.mainViewport.view;
  68043. this.cameras.mainView = viewer.mainViewport.camera;
  68044. },
  68045. switchView(name) {
  68046. //替换view和camera到mainViewport
  68047. if (this.activeViewName == name) return;
  68048. var view = this.views[name];
  68049. var camera = this.cameras[name];
  68050. var prop = cameraProps.find(e => e.name == name);
  68051. var {
  68052. boundSize,
  68053. center,
  68054. boundingBox
  68055. } = viewer.bound;
  68056. this.lastViewName = this.activeViewName;
  68057. this.activeViewName = name;
  68058. var lastView = this.views[this.lastViewName];
  68059. var lastCamera = this.cameras[this.lastViewName];
  68060. viewer.mainViewport.view = view;
  68061. viewer.mainViewport.camera = camera;
  68062. if (lastCamera) lastView.zoom = lastCamera.zoom;
  68063. view.zoom && (camera.zoom = view.zoom);
  68064. viewer.updateScreenSize({
  68065. forceUpdateSize: true
  68066. }); //更新camera aspect left等
  68067. view.applyToCamera(camera);
  68068. var ifFocus;
  68069. var boxBound = Clip.box.boundingBox.clone().applyMatrix4(Clip.box.matrixWorld);
  68070. if (!Potree.Utils.isInsideFrustum(boxBound, camera)) {
  68071. //屏幕上没有box的话
  68072. ifFocus = true;
  68073. }
  68074. if (name == 'mainView') {
  68075. if (lastView) {//2d->3d
  68076. }
  68077. if (prop.openCount == 0) ifFocus = false;
  68078. //viewer.fpControls.lockKey = false
  68079. } else {
  68080. this.targetPlane.setFromNormalAndCoplanarPoint(view.direction.clone(), center);
  68081. this.targetPlane.projectPoint(view.position, this.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外
  68082. //view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport))
  68083. //if(view.zoom)camera.zoom = view.zoom//恢复上次的zoom
  68084. if (prop.openCount == 0) {
  68085. //至多执行一次
  68086. ifFocus = true;
  68087. }
  68088. if (this.lastViewName == 'mainView') {//3d->2d
  68089. } else {}
  68090. ifFocus || this.splitScreenTool.updateCameraOutOfModel(); //更新相机位置
  68091. //if(name == 'top') viewer.mainViewport.alignment = {rotate:true,translate:true};
  68092. if (name == 'front') {
  68093. //viewer.mainViewport.alignment = {translate:true, rotateSide:true, translateVec:new THREE.Vector3(0,0,1)}; //只能上下移动
  68094. viewer.mainViewport.rotateSide = true;
  68095. } else {
  68096. viewer.mainViewport.rotateSide = false;
  68097. }
  68098. //viewer.fpControls.lockKey = true
  68099. }
  68100. ifFocus && this.focusOnObject(this.box);
  68101. //首次到front最好能自动对准box的长边的角度上
  68102. prop.openCount++;
  68103. },
  68104. focusOnObject(box) {
  68105. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  68106. if (this.activeViewName == 'mainView') {
  68107. viewer.focusOnObject({
  68108. boundingBox: box.boundingBox.clone().applyMatrix4(box.matrixWorld)
  68109. }, 'boundingBox', duration);
  68110. } else {
  68111. this.orthoMoveFit(box.position, {
  68112. bound: box.boundingBox.clone().applyMatrix4(box.matrixWorld)
  68113. }, duration);
  68114. }
  68115. },
  68116. transform(type, axis, value) {
  68117. //使用按键微调
  68118. this.box[type][axis] += value;
  68119. },
  68120. setModeEnable(type, enable) {
  68121. var modes = [];
  68122. ['scale', 'translation', 'rotation'].forEach(e => {
  68123. if (e == type) {
  68124. enable && modes.push(e);
  68125. } else {
  68126. viewer.transformationTool.modesEnabled[e] && modes.push(e);
  68127. }
  68128. });
  68129. viewer.transformationTool.setModeEnable(modes);
  68130. viewer.dispatchEvent('content_changed');
  68131. },
  68132. rotateSideCamera(angle) {
  68133. //侧视图绕模型中心水平旋转到的角度 angle: -180 ~ 180
  68134. var diff = MathUtils.degToRad(angle) - viewer.mainViewport.view.yaw;
  68135. this.splitScreenTool.rotateSideCamera(viewer.mainViewport, diff);
  68136. },
  68137. orthoMoveFit(pos, info, duration) {
  68138. var margin = {
  68139. x: viewer.mainViewport.resolution.x * 0.4,
  68140. y: viewer.mainViewport.resolution.y * 0.4
  68141. };
  68142. this.splitScreenTool.viewportFitBound(viewer.mainViewport, info.bound, pos, duration, margin);
  68143. },
  68144. getPointcloud: function getPointcloud() {
  68145. //找一个离当前最近的点云,且最好有漫游点
  68146. var pointclouds = viewer.scene.pointclouds.filter(e => e.panos.length > 0);
  68147. if (pointclouds.length == 0) pointclouds = viewer.scene.pointclouds;
  68148. var result = Common$1.sortByScore(pointclouds, [], [e => {
  68149. var center = e.bound.getCenter(new Vector3());
  68150. var size = e.bound.getSize(new Vector3()).length() / 2;
  68151. var posToCenter = viewer.images360.position.distanceTo(center);
  68152. return size / posToCenter;
  68153. }]);
  68154. return result[0].item;
  68155. },
  68156. getTarget: function getTarget(boundCenter) {
  68157. //box位置。要找一个有点云的地方。方案1相机位置, 方案2接近相机的漫游点, 方案3接近中心的漫游点。选择方案2,因最大概率有点云
  68158. var target = new Vector3();
  68159. var cameraPos = viewer.images360.position;
  68160. var pano = Common$1.find(viewer.images360.panos, [], [Images360.sortFunctions.floorDisSquaredToPoint(cameraPos)]);
  68161. if (pano) {
  68162. target.copy(pano.position);
  68163. target.setZ(boundCenter.z);
  68164. } else {
  68165. target.copy(boundCenter);
  68166. }
  68167. return target;
  68168. },
  68169. /* switchMap:function(state){
  68170. }, */
  68171. download: function download() {
  68172. if (this.getIntersectPointcloud().length == 0) {
  68173. return null;
  68174. }
  68175. var visiPointclouds = viewer.scene.pointclouds.filter(e => Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  68176. visiPointclouds.sort((a, b) => {
  68177. return a.dataset_id - b.dataset_id;
  68178. }); //缓存需要固定排序好比较
  68179. var data = {
  68180. transformation_matrix: visiPointclouds.map(cloud => {
  68181. var data = {
  68182. id: cloud.dataset_id,
  68183. matrix: this.getTransformationMatrix(cloud).elements,
  68184. //剪裁大框
  68185. visiMatrixes: cloud.material.clipBoxes_in.map(e => this.getTransformationMatrix(cloud, e.inverse).elements),
  68186. //若干个可见型小框(虽然现在用不到了,因为普通界面不展示这些剪裁区域)
  68187. unVisiMatrixes: cloud.material.clipBoxes_out.map(e => this.getTransformationMatrix(cloud, e.inverse).elements),
  68188. //若干个不可见型小框
  68189. modelMatrix: new Matrix4().copy(cloud.transformMatrix).transpose().elements
  68190. };
  68191. return data;
  68192. }),
  68193. aabb: "b-0.5 -0.5 -0.5 0.5 0.5 0.5" //剪裁空间( 所有点在乘上这个矩阵后, 还能落在 1 * 1 * 1的box内的点就是所裁剪的
  68194. };
  68195. return data;
  68196. },
  68197. downloadNoCrop() {
  68198. //不剪裁 下载整个点云
  68199. var visiPointclouds = viewer.scene.pointclouds.filter(e => Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  68200. visiPointclouds.sort((a, b) => {
  68201. return a.dataset_id - b.dataset_id;
  68202. }); //缓存需要固定排序好比较
  68203. var data = {
  68204. transformation_matrix: visiPointclouds.map(cloud => {
  68205. var data = {
  68206. id: cloud.dataset_id,
  68207. matrix: new Matrix4().elements,
  68208. //固定值
  68209. modelMatrix: new Matrix4().copy(cloud.transformMatrix).transpose().elements
  68210. };
  68211. return data;
  68212. }),
  68213. aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //固定剪裁空间
  68214. };
  68215. console.log(data);
  68216. return data;
  68217. },
  68218. getTransformationMatrix: function getTransformationMatrix(pointcloud, invMatrix) {
  68219. //剪裁矩阵
  68220. var invMatrix = invMatrix || this.box.matrixWorld.clone().invert();
  68221. return new Matrix4().multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose();
  68222. },
  68223. getIntersectPointcloud() {
  68224. var intersect = pointcloud => {
  68225. if (pointcloud.intersectBox(this.box.matrixWorld)) return true;
  68226. };
  68227. return viewer.scene.pointclouds.filter(e => intersect(e));
  68228. },
  68229. getRulerBound() {
  68230. //坐标尺边界 米
  68231. var camera = viewer.mainViewport.camera;
  68232. if (!camera.isOrthographicCamera) return;
  68233. var w = camera.right / camera.zoom; //half
  68234. var h = camera.top / camera.zoom;
  68235. var points = [];
  68236. var boundAtCamera = new Box3();
  68237. Clip.box.children[0].geometry.vertices.forEach(e => {
  68238. //模仿getPosWithFullBound
  68239. var p = e.clone().applyMatrix4(Clip.box.matrixWorld);
  68240. points.push(p);
  68241. var p1 = p.clone().applyMatrix4(camera.matrixWorldInverse);
  68242. boundAtCamera.expandByPoint(p1);
  68243. });
  68244. //需要找出clipbox的bound的左上角,它在标尺中是原点
  68245. var ClipBoxLeftTop = new Vector2(boundAtCamera.min.x, boundAtCamera.max.y); //相对于相机的位置
  68246. var camPos = new Vector2(-ClipBoxLeftTop.x, ClipBoxLeftTop.y); //由于ClipBoxLeftTop要变换到原点,所以相机位置就成了ClipBoxLeftTop的相反数, 但因是从上到下所以y再乘-1
  68247. var bound_ = {
  68248. left: camPos.x - w,
  68249. right: camPos.x + w,
  68250. bottom: camPos.y + h,
  68251. //注意从上到下增大
  68252. top: camPos.y - h
  68253. };
  68254. //console.log(bound)
  68255. //标尺里又改为左下角原点了
  68256. return bound_;
  68257. },
  68258. screenshot: async (ifShowRuler, rulerToolFactory /*unitText = '像素 : 米' */) => {
  68259. //测绘图下载。顶视图|侧视图
  68260. if (!rulerToolFactory) {
  68261. ifShowRuler = false;
  68262. }
  68263. var getRulerUnit = num => {
  68264. var unitSystem = 'metric';
  68265. var str = viewer.unitConvert.convert(num, 'distance', 0, unitSystem, true, {
  68266. 'imperial': {
  68267. minFactor: 0.01
  68268. },
  68269. 'metric': {
  68270. minFactor: 0.001
  68271. }
  68272. });
  68273. return str.trim();
  68274. };
  68275. return new Promise((resolve, reject) => {
  68276. if (Clip.screenshoting) return reject();
  68277. var rulerBound = {}; //因为margin 扩大bound
  68278. var meterPerPixel;
  68279. var visiPointclouds = viewer.scene.pointclouds.filter(e => Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  68280. var camera = viewer.mainViewport.camera;
  68281. //if(Clip.activeViewName == 'mainView')return reject()
  68282. var maxWidth = 8192,
  68283. minWidth = Potree.browser.urlHasValue('clipMinWidth', true) || 1024; //图片尺寸最大最小值。
  68284. //Potree.settings.pointDensity = 'ultraHigh'
  68285. viewer.inputHandler.deselectAll();
  68286. Clip.box.visible = false;
  68287. Clip.screenshoting = true;
  68288. var material = new ExtendPointCloudMaterial();
  68289. material.pointSizeType = Potree.PointSizeType.FIXED; //Potree.PointSizeType
  68290. material.size = Potree.browser.urlHasValue('clipPointSize', true) || 1;
  68291. material.uniforms.minSize.value = 0.1;
  68292. material.activeAttributeName = 'rgba';
  68293. //material.classification = pointcloud.material.classification;
  68294. material.clipBoxBig_in = visiPointclouds[0].material.clipBoxBig_in;
  68295. material.shaderNeedsUpdate = true;
  68296. material.bigClipInBox = visiPointclouds[0].material.bigClipInBox;
  68297. var materials = visiPointclouds.map(e => {
  68298. var mat = e.material;
  68299. e.material = material;
  68300. return mat;
  68301. });
  68302. //根据boundingBox尺寸来定图片尺寸
  68303. var boundingBox = Clip.box.boundingBox.clone().applyMatrix4(Clip.box.matrixWorld);
  68304. var points = [];
  68305. var bound = new Box3();
  68306. Clip.box.children[0].geometry.vertices.forEach(e => {
  68307. //模仿getPosWithFullBound
  68308. var p = e.clone().applyMatrix4(Clip.box.matrixWorld);
  68309. points.push(p);
  68310. var p1 = p.clone().applyMatrix4(camera.matrixWorldInverse);
  68311. bound.expandByPoint(p1);
  68312. });
  68313. var boundSize = bound.getSize(new Vector3());
  68314. var minZoom = Potree.browser.urlHasValue('clipZoom', true) || 80; //1px = 1个点 = 1cm , 如果一个点都是1cm的话
  68315. //zoom不宜过大或过小,过小点云重叠、画面模糊;过大点云有间隙,纹理就看不清
  68316. //中间部分75-80为佳,文字100,边缘50. 最好支持调节 . 且当下载尺寸变大往往点云也多,可能冲破pointbudget限制
  68317. //let text = `1 : ${(1 / camera.zoom).toFixed(4)}(像素 : 米)`
  68318. var w = boundSize.x * minZoom;
  68319. var h = boundSize.y * minZoom;
  68320. var max = Math.max(w, h);
  68321. var s = 1;
  68322. if (max > maxWidth) {
  68323. s = maxWidth / max;
  68324. } else if (max < minWidth) {
  68325. s = minWidth / max;
  68326. }
  68327. w *= s, h *= s;
  68328. s != 1 && console.log('宽度缩放倍数', s);
  68329. //虽然size>1就是浪费像素,但是太小了视觉效果有点差……可能因为fov不真实。 点云大就像是老式电视机虽然显示像素量少但感觉不出画面模糊,且边缘锐利。
  68330. w = Math.round(w);
  68331. h = Math.round(h);
  68332. var focusObjectInfo = [{
  68333. boundingBox,
  68334. points
  68335. }, 'boundingBox', 0, {
  68336. dontChangeCamDir: true,
  68337. dontMoveMap: true,
  68338. boundScale: 1,
  68339. minBound: 0.1
  68340. }];
  68341. //分块渲染截图,最后拼合图片。需要使每一块的点数不超过pointBudget, 且尺寸不超过4096(会崩溃),过小的话一般不会超过pointBudget,除非是深度较大后排点云多。
  68342. var r = MathUtils.clamp(Math.sqrt(3.5e7 / boundSize.z) * s, 1024, 4096); //每多少米分一块。 推理 wc*hc = w / r * h / r = zoom * w * s * zoom * h * s / r^2 = xyz / V(常数,每多少立方米会超出pointBudget,就是括号里的数字,给大概值)
  68343. //let r = THREE.Math.clamp(1024 / boundSize.z, 256, 4096);
  68344. var wc = w / r; //横向块数
  68345. var hc = h / r; //纵向块数
  68346. var splitRenderInfo = (wc > 1 || hc > 1) && {
  68347. wc: Math.ceil(wc),
  68348. hc: Math.ceil(hc)
  68349. }; //因为结果需要化为整数所以可能不太理想, 分割数过多。 另外如果面积小但是因z过长而超出pointBudget没关系,因后排点云无需绘制
  68350. console.log({
  68351. wc,
  68352. hc,
  68353. w,
  68354. h
  68355. });
  68356. var beforeScreenshot = () => {
  68357. //if(ifShowRuler){
  68358. var ruler = Clip.getRulerBound();
  68359. Object.assign(rulerBound, ruler);
  68360. //因为focusOnObject时有最小边界,所以当box很小时截图区域不止box
  68361. var cameraBoundSizeX = ruler.right - ruler.left;
  68362. meterPerPixel = cameraBoundSizeX / w;
  68363. var zoom = viewer.mainViewport.camera.zoom;
  68364. material.size *= Math.min(zoom / minZoom, 10); //限制一下,避免测试时界面点云很小,截图点云很大
  68365. //}
  68366. };
  68367. var {
  68368. getImagePromise,
  68369. finishPromise
  68370. } = viewer.startScreenshot({
  68371. type: 'default',
  68372. bgOpacity: 0,
  68373. focusObjectInfo,
  68374. maxTimeForPointLoad: 3e5,
  68375. pointDensity: 'screenshot2',
  68376. splitRenderInfo,
  68377. beforeScreenshot
  68378. }, w, h, 1);
  68379. finishPromise.done(_ref => {
  68380. var {
  68381. dataUrl
  68382. } = _ref;
  68383. viewer.inputHandler.toggleSelection(Clip.box);
  68384. Clip.box.visible = true;
  68385. var img = new Image();
  68386. img.src = dataUrl;
  68387. img.onload = async () => {
  68388. //加上标尺比例水印
  68389. //固定文字大小和边距像素 //如果有一边过小,可能超出画面外,暂时不管这种可能
  68390. var fontsize = math.linearClamp(w, [100, 700, 8000], [12, 20, 30]);
  68391. /* const marginSelf = {//img外的margin(标尺内)
  68392. left : ifShowRuler ? 76 : 40,
  68393. right : ifShowRuler ? 30 : 40,
  68394. bottom : (70 + fontsize*2) ,
  68395. top : ifShowRuler ? 60 : 40,
  68396. } */
  68397. var marginSelf = {
  68398. //img外的margin(标尺内)
  68399. left: 76,
  68400. right: 40,
  68401. bottom: 70 + fontsize * 2,
  68402. top: 60
  68403. }; //因要求无论有无标尺比例尺都一样,所以marginSelf必须一样
  68404. //文字的边距
  68405. var bottomRatioToImg = -Math.min(fontsize * 2.5, ifShowRuler ? marginSelf.bottom : marginSelf.bottom * 0.8) / h; //- (marginSelf.bottom - fontsize)/ h //在img之下. text底部到img底部的距离
  68406. var rulerMargin = 20; //标尺外的margin px
  68407. var labelInfo = {
  68408. bottomRatioToImg,
  68409. horizonCenter: true,
  68410. //leftRatioToImg,
  68411. textColor: ifShowRuler ? {
  68412. r: 0,
  68413. g: 0,
  68414. b: 0,
  68415. a: 1
  68416. } : {
  68417. r: 221,
  68418. g: 221,
  68419. b: 221,
  68420. a: 1
  68421. },
  68422. textBorderColor: {
  68423. r: 30,
  68424. g: 30,
  68425. b: 30,
  68426. a: 1
  68427. },
  68428. textBorderThick: ifShowRuler ? 0 : 1,
  68429. fontsize,
  68430. fontWeight: ifShowRuler ? 'normal' : 'Bold',
  68431. outputCanvas: true,
  68432. bgColor: ifShowRuler ? {
  68433. r: 255,
  68434. g: 255,
  68435. b: 255,
  68436. a: 255
  68437. } : null
  68438. };
  68439. labelInfo.bgMargin = {
  68440. //img外需要多少margin
  68441. left: marginSelf.left + rulerMargin,
  68442. //rulerMargin是在标尺外的margin
  68443. bottom: marginSelf.bottom + rulerMargin,
  68444. right: marginSelf.right + rulerMargin,
  68445. top: marginSelf.top + rulerMargin
  68446. };
  68447. //console.log('topRatioToImg',topRatioToImg,'leftRatioToImg',leftRatioToImg,'fontsize', labelInfo.fontsize)
  68448. var rulerImg, drawRuler, labelGot, rulerGot, canvas, unitText, resultSrc, unitLen;
  68449. if (rulerToolFactory) {
  68450. rulerBound.left -= marginSelf.left * meterPerPixel; //标尺范围内的宽度(米)
  68451. rulerBound.right += marginSelf.right * meterPerPixel;
  68452. rulerBound.top -= marginSelf.top * meterPerPixel;
  68453. rulerBound.bottom += marginSelf.bottom * meterPerPixel;
  68454. var width = img.width + marginSelf.left + marginSelf.right; //标尺范围内的像素宽度
  68455. var height = img.height + marginSelf.top + marginSelf.bottom;
  68456. var xNumTicks = Math.round(width / 100); ///THREE.Math.clamp(Math.round(canvas.width / 100), 1, 30) //大格子数量(但结果不会和这个一模一样)
  68457. var yNumTicks = Math.round(height / 100); //THREE.Math.clamp(Math.round(canvas.height / 100), 1, 30),//yNumTicks.value,
  68458. var result = await rulerToolFactory(
  68459. //绘制标尺
  68460. [rulerBound.left, rulerBound.right],
  68461. //xRang.value,
  68462. [rulerBound.top, rulerBound.bottom],
  68463. //yRang.value,
  68464. xNumTicks, yNumTicks, width, height, '#000000');
  68465. if (ifShowRuler) {
  68466. rulerImg = new Image();
  68467. rulerImg.src = result.url;
  68468. //Common.downloadFile(result.url, 'ruler.png')
  68469. drawRuler = () => {
  68470. if (!labelGot || !rulerGot) return;
  68471. resultSrc = Potree.Common.imgAddLabel(canvas, rulerImg, {
  68472. topRatioToImg: rulerMargin / canvas.height,
  68473. leftRatioToImg: rulerMargin / canvas.width
  68474. });
  68475. resolve(resultSrc);
  68476. };
  68477. rulerImg.onload = () => {
  68478. rulerGot = true;
  68479. drawRuler();
  68480. };
  68481. }
  68482. console.log('xUnit', result.xUnit, 'yUnit', result.yUnit);
  68483. unitLen = result.xUnit; //为了得到这个,不管需不需要绘制标尺都要rulerToolFactory
  68484. } else {
  68485. //本地没有
  68486. unitLen = boundSize.x / 10; //假定一个
  68487. }
  68488. unitText = '1:' + getRulerUnit(unitLen);
  68489. canvas = await Potree.Utils.imgAddText(img, unitText, labelInfo);
  68490. {
  68491. //绘制比例尺参照横线
  68492. var ctx = canvas.getContext('2d');
  68493. // 开始新的路径
  68494. ctx.beginPath();
  68495. // 移动到起点
  68496. var lenX = Math.round(unitLen / meterPerPixel),
  68497. lenY = 7,
  68498. x = Math.round(img.width / 2 + labelInfo.bgMargin.left - lenX / 2),
  68499. y = Math.round(canvas.height - rulerMargin - 58);
  68500. //left ver line
  68501. ctx.moveTo(x, y);
  68502. ctx.lineTo(x, y + lenY);
  68503. //right ver line
  68504. ctx.moveTo(x + lenX, y);
  68505. ctx.lineTo(x + lenX, y + lenY);
  68506. //horizon line
  68507. ctx.moveTo(x, y + lenY / 2);
  68508. ctx.lineTo(x + lenX, y + lenY / 2);
  68509. // 设置线条样式(可选)
  68510. ctx.strokeStyle = ifShowRuler ? '#000' : '#ddd';
  68511. ctx.lineWidth = 1; // 线条宽度
  68512. // 绘制线段
  68513. ctx.stroke();
  68514. }
  68515. labelGot = true;
  68516. //Common.downloadFile(finalDataUrl, 'screenshot11.png')
  68517. visiPointclouds.forEach((e, i) => e.material = materials[i]);
  68518. Clip.screenshoting = false;
  68519. viewer.viewports = [viewer.mainViewport];
  68520. if (ifShowRuler) {
  68521. drawRuler();
  68522. } else {
  68523. resultSrc = canvas.toDataURL('image/png');
  68524. resolve(resultSrc);
  68525. }
  68526. };
  68527. });
  68528. });
  68529. /*
  68530. 隐患:无法获知最大可加载的点的数量,也未知需要加载的点的数量。需要掌控好分块数量,避免因pointBudget限制造成周围的点稀疏。
  68531. 加载点云时间过久
  68532. */
  68533. return finishPromise;
  68534. }
  68535. };
  68536. /*
  68537. 裁剪点云时,2D界面显示全部平面图,按楼层切换显示。
  68538. 所有点云下载后点云所带的本地坐标都是场景显示的local坐标,这样才能看起来一样。
  68539. 且为了使之和坐标页面对应,坐标页面的本地坐标也是local,而非mesh_local.
  68540. //保存box
  68541. viewer.modules.Clip.box.matrix
  68542. //恢复box
  68543. let a = new THREE.Matrix4().fromArray([
  68544. 14.189120116830964,
  68545. 0,
  68546. 0,
  68547. 0,
  68548. 0,
  68549. 9.924790069368392,
  68550. 0,
  68551. 0,
  68552. 0,
  68553. 0,
  68554. 0.8751009568437951,
  68555. 0,
  68556. -7.433819981633984,
  68557. 1.528696446650445,
  68558. 2.9412375879215977,
  68559. 1
  68560. ])
  68561. a.decompose(viewer.modules.Clip.box.position,viewer.modules.Clip.box.quaternion,viewer.modules.Clip.box.scale)
  68562. viewer.modules.Clip.rotateSideCamera(-93)
  68563. */
  68564. var viewportProps = [{
  68565. left: 0.5,
  68566. bottom: 0.5,
  68567. width: 0.5,
  68568. height: 0.5,
  68569. name: 'MainView',
  68570. //view: viewer.scene.view,
  68571. active: true
  68572. }, {
  68573. left: 0,
  68574. bottom: 0.5,
  68575. width: 0.5,
  68576. height: 0.5,
  68577. name: 'top',
  68578. name2: 'mapViewport',
  68579. axis: ["x", "y"],
  68580. direction: new Vector3(0, 0, -1),
  68581. //镜头朝向
  68582. //axisSign:[1,1],
  68583. active: true
  68584. //相机位置在z轴正向
  68585. }, {
  68586. left: 0.5,
  68587. bottom: 0,
  68588. width: 0.5,
  68589. height: 0.5,
  68590. name: 'right',
  68591. axis: ["y", "z"],
  68592. direction: new Vector3(1, 0, 0),
  68593. //axisSign:[1,1],
  68594. active: true
  68595. //相机位置在x轴负向 右下角屏
  68596. }, {
  68597. left: 0,
  68598. bottom: 0,
  68599. width: 0.5,
  68600. height: 0.5,
  68601. name: 'back',
  68602. axis: ["x", "z"],
  68603. direction: new Vector3(0, -1, 0),
  68604. //axisSign:[-1,1], // 从镜头方向看 x向左 所以取负
  68605. active: true
  68606. //相机位置在y轴正向 左下角屏
  68607. }];
  68608. var SplitScreen4Views = new SplitScreen();
  68609. SplitScreen4Views.split = function () {
  68610. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  68611. var defaultCamera = viewer.scene.getActiveCamera();
  68612. var {
  68613. boundSize,
  68614. center
  68615. } = viewer.bound;
  68616. viewer.setLimitFar(false);
  68617. viewer.mapViewer.attachToMainViewer(true, 'split4Screens', 'dontSet');
  68618. viewer.renderer.clear(); //clear back的viewport左边的1px宽的部分,因setScissor的bug
  68619. var viewports = this.splitStart(viewportProps);
  68620. //覆盖在map上、点云等其他物体之下的一层背景
  68621. var mapViewport = viewer.mapViewer.viewports[0];
  68622. mapViewport.noPointcloud = false;
  68623. //隐藏地图游标
  68624. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'split4Screens', false)
  68625. /* viewer.images360.panos.forEach(pano=>{
  68626. Potree.Utils.updateVisible(pano.mapMarker, 'split4Screens', false) //希望这时候mapMarker已经建好了吧
  68627. }) */
  68628. /* viewer.images360.panos.forEach(pano=>{
  68629. pano.addLabel2()
  68630. Potree.Utils.updateVisible(pano.label2, 'notDisplay', true)
  68631. pano.dispatchEvent({type:'changeMarkerTex',name:'ring'})
  68632. }) */
  68633. //材质
  68634. this.statesBefore = {
  68635. pointDensity: Potree.settings.pointDensity,
  68636. displayMode: Potree.settings.displayMode,
  68637. position: viewer.images360.position,
  68638. target: viewer.scene.view.getPivot(),
  68639. currentPano: viewer.images360.currentPano
  68640. //---
  68641. //ifShowMarker : Potree.settings.ifShowMarker,
  68642. };
  68643. viewer.setPointStandardMat(true, null, true); //切换到标准模式(主要为了mainViewport) 点云使用标准大小
  68644. var matBefore = {
  68645. opacity: new Map()
  68646. };
  68647. var newOpacityMap = new Map();
  68648. viewer.scene.pointclouds.forEach(e => {
  68649. matBefore.opacity.set(e, e.temp.pointOpacity);
  68650. matBefore.colorType = e.material.activeAttributeName;
  68651. /* {
  68652. var map = new Map()
  68653. newOpacityMap.set(e, map )
  68654. var size = e.bound.getSize()
  68655. viewports.forEach(viewport=>{//根据bound设置opacity,越小的要靠越近,需要大的opacity。但似乎影响太大了
  68656. if(viewport.name == 'MainView')return;
  68657. var prop = viewportProps.find(v => viewport.name == v.name2||viewport.name == v.name)
  68658. let axis = prop.axis
  68659. var width = size[axis[0]]
  68660. var height = size[axis[1]]
  68661. var area = width * height
  68662. map.set(viewport, 5000/area);
  68663. })
  68664. } */
  68665. });
  68666. var beforeRender = function beforeRender() {
  68667. viewer.dealBeforeRender = true; //使不全部渲染
  68668. viewer.scene.pointclouds.forEach(e => {
  68669. if (this.name == "MainView") {
  68670. e.material.activeAttributeName = matBefore.colorType; // 'rgba'
  68671. e.material.useFilterByNormal = false;
  68672. //e.material.pointSizeType = Potree.config.material.pointSizeType
  68673. e.changePointOpacity(matBefore.opacity.get(e)); //1 //恢复下 e.temp.pointOpacity 其实就是1
  68674. Potree.settings.pointDensity = 'fourViewportsMain'; /* 'fourViewports' */ //本来想比另外三屏高一点质量,结果发现会闪烁,因为点云加载需要时间 (navvis仿版也是一样,以后看看能否优化)
  68675. } else {
  68676. e.material.activeAttributeName = "color";
  68677. e.material.useFilterByNormal = true;
  68678. //e.material.pointSizeType = 'ADAPTIVE'
  68679. Potree.settings.pointDensity = 'fourViewports'; //强制降低点云质量
  68680. //侧面重叠概率更大,所以透明度调小
  68681. e.changePointOpacity(this.name == "mapViewport" ? 0.5 : 0.1 /* newOpacityMap.get(e).get(viewport), true */); //多数据集有的数据集很小,放大后显示特别淡
  68682. //console.log(e.name, viewport.name, e.temp.pointOpacity, e.material.opacity)
  68683. }
  68684. viewer.images360.panos.forEach(pano => {
  68685. if (this.name == 'mapViewport') {
  68686. Potree.Utils.updateVisible(pano.marker, 'showOnMap', true, 1, 'add');
  68687. } else {
  68688. Potree.Utils.updateVisible(pano.marker, 'showOnMap', false, 1, 'cancel');
  68689. }
  68690. });
  68691. });
  68692. viewer.dealBeforeRender = false;
  68693. };
  68694. viewports.forEach(viewport => {
  68695. viewport.beforeRender = beforeRender;
  68696. new AxisViewer(viewport, viewer.renderArea, {
  68697. domStyle: {
  68698. top: '22px',
  68699. //viewport.name == 'mapViewport' ? '2px' : '-25px',
  68700. right: viewport.name == 'mapViewport' ? '30px' : '2px',
  68701. width: '80px',
  68702. height: '80px'
  68703. }
  68704. });
  68705. });
  68706. this.enableMap(false);
  68707. this.enableFloorplan(false);
  68708. viewer.mapViewer.setViewLimit('null'); //多数据集距离远时可以任意远,所以不限制了。但是这样就会看到地图边界了怎么办?超出后让地图隐藏?
  68709. //viewer.dispatchEvent({'type': 'beginSplitView' })
  68710. //viewer.updateScreenSize({forceUpdateSize:true})
  68711. //this.viewportFitBound(mapViewport, boundSize, center)
  68712. //Potree.settings.ifShowMarker = false
  68713. Potree.settings.displayMode = 'showPointCloud';
  68714. };
  68715. SplitScreen4Views.recover = function () {
  68716. viewer.viewports.forEach(e => {
  68717. e.axis.dispose();
  68718. });
  68719. this.unSplit();
  68720. viewer.mapViewer.viewports[0].beforeRender = null;
  68721. /* const {width, height} = viewer.renderer.getSize(new THREE.Vector2());
  68722. viewer.renderer.setViewport(0,0,width,height)
  68723. viewer.renderer.setScissorTest( false ); */
  68724. viewer.setView({
  68725. position: this.statesBefore.position,
  68726. target: this.statesBefore.target,
  68727. currentPano: this.statesBefore.currentPano,
  68728. duration: 300,
  68729. callback: function callback() {}
  68730. });
  68731. viewer.mainViewport.beforeRender = null;
  68732. viewer.setLimitFar(true);
  68733. var mapViewport = viewer.mapViewer.viewports[0];
  68734. viewer.mapViewer.attachToMainViewer(false);
  68735. //Potree.Utils.updateVisible(viewer.mapViewer.cursor, 'split4Screens', true)
  68736. /* viewer.images360.panos.forEach(pano=>{
  68737. Potree.Utils.updateVisible(pano.mapMarker, 'split4Screens', true)
  68738. }) */
  68739. /* viewer.images360.panos.forEach(pano=>{
  68740. Potree.Utils.updateVisible(pano.label2, 'notDisplay', false )
  68741. pano.dispatchEvent({type:'changeMarkerTex',name:'default'})
  68742. }) */
  68743. mapViewport.noPointcloud = true;
  68744. {
  68745. this.enableMap(Potree.settings.mapEnable);
  68746. this.enableFloorplan(Potree.settings.floorplanEnable);
  68747. if (this.floorplanListener) {
  68748. viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded', this.floorplanListener);
  68749. this.floorplanListener = null;
  68750. }
  68751. }
  68752. Potree.settings.pointDensity = this.statesBefore.pointDensity;
  68753. if (!Potree.settings.isOfficial) {
  68754. Potree.settings.displayMode = this.statesBefore.displayMode;
  68755. }
  68756. viewer.scene.pointclouds.forEach(e => {
  68757. e.material.useFilterByNormal = false;
  68758. //e.material.pointSizeType = Potree.config.material.pointSizeType
  68759. });
  68760. viewer.setPointStandardMat(false);
  68761. viewer.mapViewer.setViewLimit('standard');
  68762. viewer.images360.panos.forEach(pano => {
  68763. Potree.Utils.updateVisible(pano.marker, 'showOnMap', false, 1, 'cancel');
  68764. });
  68765. //Potree.settings.ifShowMarker = this.statesBefore.ifShowMarker
  68766. //viewer.dispatchEvent({'type': 'finishSplitView' })
  68767. //viewer.updateScreenSize({forceUpdateSize:true})
  68768. };
  68769. SplitScreen4Views.updateMapViewerBG = function () {
  68770. var mapViewport = viewer.mapViewer.viewports[0];
  68771. if (this.splited && (this.floorplanEnabled || this.mapEnabled)) {
  68772. mapViewport.background = 'overlayColor';
  68773. mapViewport.backgroundColor = new Color(0, 0, 0);
  68774. mapViewport.backgroundOpacity = 0.5;
  68775. } else {
  68776. mapViewport.background = null;
  68777. mapViewport.backgroundColor = null;
  68778. mapViewport.backgroundOpacity = null;
  68779. }
  68780. viewer.mapViewer.mapChanged = true;
  68781. viewer.mapViewer.needUpdate = true;
  68782. };
  68783. SplitScreen4Views.setFloorplanDisplay = function (e) {
  68784. var show = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  68785. e.floorplan.setEnable(show);
  68786. };
  68787. SplitScreen4Views.enableMap = function (enable) {
  68788. var map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'map');
  68789. map.setEnable(!!enable);
  68790. //viewer.mapViewer.mapGradientBG = viewer.background == 'gradient' && !enable
  68791. this.mapEnabled = enable;
  68792. this.updateMapViewerBG();
  68793. },
  68794. //直接覆盖原设置
  68795. SplitScreen4Views.enableFloorplan = function (enable) {
  68796. //是否让自定义的平面图显示
  68797. var floorplans = viewer.mapViewer.mapLayer.maps.filter(e => e.name.includes('floorplan'));
  68798. if (this.floorplanListener) {
  68799. viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded', this.floorplanListener);
  68800. }
  68801. this.floorplanListener = e => {
  68802. this.setFloorplanDisplay(e, enable);
  68803. };
  68804. viewer.mapViewer.mapLayer.addEventListener('floorplanLoaded', this.floorplanListener); //万一之后才加载
  68805. if (!enable) {
  68806. //隐藏平面图
  68807. floorplans.forEach(floorplan => this.setFloorplanDisplay({
  68808. floorplan
  68809. }, false));
  68810. } else {
  68811. floorplans.forEach(floorplan => this.setFloorplanDisplay({
  68812. floorplan
  68813. }, true));
  68814. }
  68815. if (enable && floorplans.length == 0) Potree.loadMapEntity('all', true);
  68816. this.floorplanEnabled = enable;
  68817. this.updateMapViewerBG();
  68818. },
  68819. /* viewportFitBound:function(viewport, boundSize, center){ //使一个viewport聚焦在某个范围
  68820. var prop = viewportProps.find(v => viewport.name == v.name2||viewport.name == v.name)
  68821. let axis = prop.axis
  68822. let expand = 10;
  68823. let position = center.clone()
  68824. var moveAtAxis = ['x','y','z'].find(e=>!(axis.includes(e)))
  68825. if(viewport.name == 'mapViewport'){
  68826. let ori = viewport.view.position[moveAtAxis]
  68827. position[moveAtAxis] = ori //不改变这个值,尤其是mapViewer中的z
  68828. }else{
  68829. position[moveAtAxis] += boundSize[moveAtAxis]/2+expand//移动到bounding边缘外
  68830. }
  68831. viewport.view.position.copy(position)
  68832. var width = Math.max(boundSize[axis[0]], boundSize[axis[1]] * viewport.camera.aspect)//视口宽度(米)
  68833. var margin = 50 //px
  68834. viewport.camera.zoom = (viewport.resolution.x - margin) / width
  68835. viewport.camera.updateProjectionMatrix()
  68836. },
  68837. */
  68838. SplitScreen4Views.focusOnPointCloud = function (pointcloud) {
  68839. //三个屏都聚焦在这个点云
  68840. var boundSize = pointcloud.bound.getSize(new Vector3());
  68841. var center = pointcloud.bound.getCenter(new Vector3());
  68842. var target = pointcloud.panosBound && pointcloud.panosBound.center; //看向pano集中的地方,也就是真正有点云的地方。(因为需要展示所有点云,所以没办法用这个做为center)
  68843. this.focusOnObject(pointcloud.bound, center, target);
  68844. viewer.flyToDataset({
  68845. pointcloud,
  68846. dontMoveMap: true,
  68847. duration: 0
  68848. });
  68849. };
  68850. SplitScreen4Views.focusOnObject = function (bound, center, target) {
  68851. var duration = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  68852. viewer.viewports.forEach(e => {
  68853. if (e.name == 'MainView') {
  68854. /* let len = boundSize.length()
  68855. let distance = THREE.Math.clamp(e.view.position.distanceTo(center), len * 0.01, len*0.3 ) //距离限制
  68856. //viewer.focusOnObject({position:center}, 'point', duration, {distance, direction: e.view.direction,dontMoveMap:true} )//平移镜头
  68857. //为了方便定位,直接飞到中心位置:
  68858. e.view.setView({
  68859. position:center, duration, target
  68860. }) */
  68861. } else {
  68862. this.viewportFitBound(e, bound, center);
  68863. }
  68864. });
  68865. };
  68866. var lastUseCamera;
  68867. var TransformControls = function TransformControls(camera, domElement, options) {
  68868. if (domElement === undefined) {
  68869. console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.');
  68870. domElement = document;
  68871. }
  68872. Object3D.call(this);
  68873. Potree.Utils.updateVisible(this, 'attach', false);
  68874. this.domElement = domElement;
  68875. var _gizmo = new TransformControlsGizmo(options);
  68876. this.add(_gizmo);
  68877. this._gizmo = _gizmo;
  68878. var _plane = new TransformControlsPlane(options);
  68879. this.add(_plane);
  68880. /* this.linesAssistance = new TransformControlsLines(options); //水平 垂直 辅助
  68881. this.add( this.linesAssistance ); */
  68882. var scope = this;
  68883. //this.player = options.player;//xzw add
  68884. this.options = options; //xzw add
  68885. // Define properties with getters/setter
  68886. // Setting the defined property will automatically trigger change event
  68887. // Defined properties are passed down to gizmo and plane
  68888. defineProperty("camera", camera);
  68889. defineProperty("object", undefined);
  68890. defineProperty("enabled", true);
  68891. defineProperty("axis", null);
  68892. defineProperty("mode", "translate");
  68893. defineProperty("translationSnap", null);
  68894. defineProperty("rotationSnap", null);
  68895. defineProperty("scaleSnap", null);
  68896. defineProperty("space", "world");
  68897. defineProperty("size", 1);
  68898. defineProperty("dragging", false);
  68899. defineProperty("showX", true);
  68900. defineProperty("showY", true);
  68901. defineProperty("showZ", true);
  68902. var changeEvent = {
  68903. type: "change"
  68904. };
  68905. var mouseDownEvent = {
  68906. type: "mouseDown"
  68907. };
  68908. var mouseUpEvent = {
  68909. type: "mouseUp",
  68910. mode: scope.mode
  68911. };
  68912. var objectChangeEvent = {
  68913. type: "objectChange"
  68914. };
  68915. // Reusable utility variables
  68916. var ray = new Raycaster();
  68917. var _tempVector = new Vector3();
  68918. var _tempVector2 = new Vector3();
  68919. var _tempQuaternion = new Quaternion();
  68920. var _unit = {
  68921. X: new Vector3(1, 0, 0),
  68922. Y: new Vector3(0, 1, 0),
  68923. Z: new Vector3(0, 0, 1)
  68924. };
  68925. var pointStart = new Vector3();
  68926. var pointEnd = new Vector3();
  68927. var offset = new Vector3();
  68928. var rotationAxis = new Vector3();
  68929. var startNorm = new Vector3();
  68930. var endNorm = new Vector3();
  68931. var rotationAngle = 0;
  68932. var cameraPosition = new Vector3();
  68933. var cameraQuaternion = new Quaternion();
  68934. var cameraScale = new Vector3();
  68935. var parentPosition = new Vector3();
  68936. var parentQuaternion = new Quaternion();
  68937. var parentQuaternionInv = new Quaternion();
  68938. var parentScale = new Vector3();
  68939. var worldPositionStart = new Vector3();
  68940. var worldQuaternionStart = new Quaternion();
  68941. var worldScaleStart = new Vector3();
  68942. var worldPosition = new Vector3();
  68943. var worldQuaternion = new Quaternion();
  68944. var worldQuaternionInv = new Quaternion();
  68945. var worldScale = new Vector3();
  68946. var eye = new Vector3(); //整体共用
  68947. var positionStart = new Vector3();
  68948. var quaternionStart = new Quaternion();
  68949. var scaleStart = new Vector3();
  68950. // TODO: remove properties unused in plane and gizmo
  68951. defineProperty("worldPosition", worldPosition);
  68952. defineProperty("worldPositionStart", worldPositionStart);
  68953. defineProperty("worldQuaternion", worldQuaternion);
  68954. defineProperty("worldQuaternionStart", worldQuaternionStart);
  68955. defineProperty("cameraPosition", cameraPosition);
  68956. defineProperty("cameraQuaternion", cameraQuaternion);
  68957. defineProperty("pointStart", pointStart);
  68958. defineProperty("pointEnd", pointEnd);
  68959. defineProperty("rotationAxis", rotationAxis);
  68960. defineProperty("rotationAngle", rotationAngle);
  68961. defineProperty("eye", eye);
  68962. {
  68963. domElement.addEventListener("mousedown", onPointerDown, false);
  68964. domElement.addEventListener("touchstart", onPointerDown, false);
  68965. domElement.addEventListener("mousemove", onPointerHover, false);
  68966. domElement.addEventListener("touchmove", onPointerHover, false);
  68967. domElement.addEventListener("touchmove", onPointerMove, false);
  68968. document.addEventListener("mouseup", onPointerUp, false);
  68969. domElement.addEventListener("touchend", onPointerUp, false);
  68970. domElement.addEventListener("touchcancel", onPointerUp, false);
  68971. domElement.addEventListener("touchleave", onPointerUp, false);
  68972. var drag = e => {
  68973. if (this.dragging && e.buttons == Potree.defines.Buttons.LEFT) {
  68974. this.pointerMove();
  68975. return {
  68976. stopContinue: true
  68977. };
  68978. }
  68979. };
  68980. this.addEventListener('dragging', drag, {
  68981. importance: 10
  68982. });
  68983. viewer.addEventListener('global_drag', drag, {
  68984. importance: 10
  68985. });
  68986. }
  68987. this.setRotateMethod = function (number) {
  68988. //add 注意为2时 旋转期间不能改变位置 space可能不能为local ._gizmo.hideAxis = { rotate:[这里必须包含'e' ] }
  68989. this.rotateMethod = number;
  68990. };
  68991. this.dispose = function () {
  68992. domElement.removeEventListener("mousedown", onPointerDown);
  68993. domElement.removeEventListener("touchstart", onPointerDown);
  68994. domElement.removeEventListener("mousemove", onPointerHover);
  68995. domElement.removeEventListener("mousemove", onPointerMove);
  68996. domElement.removeEventListener("touchmove", onPointerHover);
  68997. domElement.removeEventListener("touchmove", onPointerMove);
  68998. document.removeEventListener("mouseup", onPointerUp);
  68999. domElement.removeEventListener("touchend", onPointerUp);
  69000. domElement.removeEventListener("touchcancel", onPointerUp);
  69001. domElement.removeEventListener("touchleave", onPointerUp);
  69002. this.traverse(function (child) {
  69003. if (child.geometry) child.geometry.dispose();
  69004. if (child.material) child.material.dispose();
  69005. });
  69006. };
  69007. // Set current object
  69008. this.attach = function (object, clickPos) {
  69009. this.object = object;
  69010. Potree.Utils.updateVisible(this, 'attach', true);
  69011. //Config.keyCon = false;//add
  69012. //this.linesAssistance.setVisible(true)
  69013. this.clickPos = clickPos !== null && clickPos !== void 0 && clickPos.isVector3 ? clickPos : null;
  69014. viewer.dispatchEvent('content_changed');
  69015. return this;
  69016. };
  69017. // Detatch from object
  69018. this.detach = function () {
  69019. console.warn('detach');
  69020. this.object = undefined;
  69021. this.axis = null;
  69022. //Config.keyCon = true;//add
  69023. Potree.Utils.updateVisible(this, 'attach', false);
  69024. //this.linesAssistance.setVisible(false)
  69025. viewer.dispatchEvent('content_changed');
  69026. return this;
  69027. };
  69028. //this.space = 'local'
  69029. /* this.hideAxis = function ( mode, axis=[] ) {//xzw add 设置不可见的axis
  69030. var handles = [];
  69031. handles = handles.concat( this._gizmo.picker[ mode ].children );
  69032. handles = handles.concat( this._gizmo.gizmo[ mode ].children );
  69033. handles = handles.concat( this._gizmo.helper[ mode ].children );
  69034. handles.forEach(e=>e.visible = false)
  69035. axis.forEach(name=>{
  69036. handles.filter(handle =>!handle.name.includes(name))
  69037. })
  69038. handles.forEach(e=>e.visible = true)
  69039. }; */
  69040. // Defined getter, setter and store for a property
  69041. function defineProperty(propName, defaultValue) {
  69042. //三个共用参数
  69043. var propValue = defaultValue;
  69044. Object.defineProperty(scope, propName, {
  69045. get: function get() {
  69046. return propValue !== undefined ? propValue : defaultValue;
  69047. },
  69048. set: function set(value) {
  69049. if (propValue !== value) {
  69050. propValue = value;
  69051. _plane[propName] = value;
  69052. _gizmo[propName] = value;
  69053. scope.dispatchEvent({
  69054. type: propName + "-changed",
  69055. value: value
  69056. });
  69057. scope.dispatchEvent(changeEvent);
  69058. }
  69059. }
  69060. });
  69061. scope[propName] = defaultValue;
  69062. _plane[propName] = defaultValue;
  69063. _gizmo[propName] = defaultValue;
  69064. }
  69065. // updateMatrixWorld updates key transformation variables
  69066. this.updateEye = function (camera) {
  69067. if (camera.type == "OrthographicCamera") {
  69068. //xzw add
  69069. eye.set(0, 0, -1).applyQuaternion(camera.quaternion); // this.view.direction
  69070. } else {
  69071. eye.copy(cameraPosition).sub(worldPosition).normalize();
  69072. }
  69073. };
  69074. this.updateMatrixWorld = function () {
  69075. var _arguments$, _Potree$currentRender;
  69076. //TransformControls
  69077. if (!this.visible) return; //add
  69078. var camera = (_arguments$ = arguments[1]) !== null && _arguments$ !== void 0 && _arguments$.isCamera ? arguments[1] : ((_Potree$currentRender = Potree.currentRender) === null || _Potree$currentRender === void 0 ? void 0 : _Potree$currentRender.camera) || this.camera;
  69079. lastUseCamera = camera; //add 使用父级使用的camera
  69080. if (this.object !== undefined) {
  69081. this.object.updateMatrixWorld();
  69082. this.object.parent.matrixWorld.decompose(parentPosition, parentQuaternion, parentScale);
  69083. this.object.matrixWorld.decompose(worldPosition, worldQuaternion, worldScale);
  69084. if (Potree.settings.mergeTransCtlOnClick && this.mode == 'translate' && this.clickPos) {
  69085. //允许位移控件出现在点击的位置
  69086. var pos = this.clickPos.clone().applyMatrix4(this.object.matrixWorld);
  69087. worldPosition.copy(pos);
  69088. } else if (this.object.boundingBox) {
  69089. var boundingBox = this.object.boundingBox.clone().applyMatrix4(this.object.matrixWorld);
  69090. boundingBox.getCenter(worldPosition); //bound中心
  69091. if (this.pivotOnBottom) {
  69092. worldPosition.setZ(boundingBox.min.z); //中心点居于模型bound底部,因固定离地高度,旋转时旋转中心在地面上就不会变位置
  69093. }
  69094. }
  69095. parentQuaternionInv.copy(parentQuaternion).invert();
  69096. worldQuaternionInv.copy(worldQuaternion).invert();
  69097. }
  69098. camera.updateMatrixWorld();
  69099. camera.matrixWorld.decompose(cameraPosition, cameraQuaternion, cameraScale);
  69100. this.updateEye(camera);
  69101. Object3D.prototype.updateMatrixWorld.call(this);
  69102. };
  69103. this.pointerHover = function () {
  69104. var _viewer$inputHandler$;
  69105. var pointer = viewer.inputHandler.pointer;
  69106. if (this.object === undefined) return;
  69107. var camera = (_viewer$inputHandler$ = viewer.inputHandler.hoverViewport) === null || _viewer$inputHandler$ === void 0 ? void 0 : _viewer$inputHandler$.camera;
  69108. //if(this.dragging === true /* || ( pointer.button !== undefined && pointer.button !== 0 ) */) return;
  69109. if (!this.dragging) {
  69110. var oldAxis = this.axis;
  69111. //ray.setFromCamera( pointer, this.camera ); //这句会在floorplan模式get不到intersect
  69112. var {
  69113. origin,
  69114. direction
  69115. } = viewer.inputHandler.getMouseDirection();
  69116. ray.set(origin, direction);
  69117. Potree.Utils.setCameraLayers(ray,
  69118. //设置能识别到的layers
  69119. ['sceneObjects', 'mapObjects', /* 'measure', */'transformationTool', 'model'], viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers);
  69120. camera && camera != lastUseCamera && this.updateMatrixWorld(null, camera); //add 多viewport时重新根据hover的camera更新下
  69121. var intersect = ray.intersectObjects(_gizmo.picker[this.mode].children.filter(e => e.visible), true)[0] || false;
  69122. if (intersect) {
  69123. this.axis = intersect.object.name;
  69124. } else {
  69125. this.axis = null;
  69126. }
  69127. //console.log('hover', !!intersect)
  69128. if (oldAxis != this.axis) {
  69129. this.dispatchEvent({
  69130. type: 'axisHoveredChange',
  69131. axis: this.axis,
  69132. mode: this.mode
  69133. });
  69134. viewer.dispatchEvent('content_changed');
  69135. }
  69136. } else {
  69137. //this.pointerMove()
  69138. }
  69139. };
  69140. this.pointerDown = function /* pointer */
  69141. () {
  69142. var pointer = viewer.inputHandler.pointer;
  69143. if (this.object === undefined || this.dragging === true /* || ( pointer.button !== undefined && pointer.button !== 0 ) */) return;
  69144. if ( /* ( pointer.button === 0 || pointer.button === undefined ) && */this.axis !== null) {
  69145. //ray.setFromCamera( pointer, camera ); //这句会在floorplan模式get不到intersect
  69146. var {
  69147. origin,
  69148. direction
  69149. } = viewer.inputHandler.getMouseDirection();
  69150. ray.set(origin, direction);
  69151. Potree.Utils.setCameraLayers(ray,
  69152. //设置能识别到的layers
  69153. ['sceneObjects', 'mapObjects', /* 'measure', */'transformationTool', 'model'], viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers);
  69154. var planeIntersect = ray.intersectObjects([_plane], true)[0] || false;
  69155. if (planeIntersect) {
  69156. var space = this.space;
  69157. if (this.mode === 'scale') {
  69158. space = 'local';
  69159. } else if (this.axis === 'E' || this.axis === 'XYZE' || this.axis === 'XYZ') {
  69160. space = 'world';
  69161. }
  69162. if (space === 'local' && this.mode === 'rotate') {
  69163. var snap = this.rotationSnap;
  69164. if (this.axis === 'X' && snap) this.object.rotation.x = Math.round(this.object.rotation.x / snap) * snap;
  69165. if (this.axis === 'Y' && snap) this.object.rotation.y = Math.round(this.object.rotation.y / snap) * snap;
  69166. if (this.axis === 'Z' && snap) this.object.rotation.z = Math.round(this.object.rotation.z / snap) * snap;
  69167. }
  69168. this.object.updateMatrixWorld();
  69169. this.object.parent.updateMatrixWorld();
  69170. positionStart.copy(this.object.position);
  69171. quaternionStart.copy(this.object.quaternion);
  69172. scaleStart.copy(this.object.scale);
  69173. this.object.matrixWorld.decompose(worldPositionStart, worldQuaternionStart, worldScaleStart);
  69174. //add: 使坐标轴在boundingBox中心
  69175. this.object.boundingBox && this.object.boundingBox.getCenter(worldPositionStart).applyMatrix4(this.object.matrixWorld);
  69176. pointStart.copy(planeIntersect.point).sub(worldPositionStart);
  69177. /* if(this.player.cameraControls.activeControl){
  69178. //this.player.cameraControls.activeControl.locked = true; //add
  69179. this.player.cameraControls.activeControl.enabled = false; //add
  69180. } */
  69181. }
  69182. this.dragging = true;
  69183. //console.log('this.dragging = true;')
  69184. mouseDownEvent.mode = this.mode;
  69185. this.dispatchEvent(mouseDownEvent);
  69186. }
  69187. };
  69188. this.pointerMove = function /* pointer */
  69189. () {
  69190. var _viewer$inputHandler$2;
  69191. //console.log('pointerMove')
  69192. var pointer = viewer.inputHandler.pointer;
  69193. var axis = this.axis;
  69194. var mode = this.mode;
  69195. var object = this.object;
  69196. var space = this.space;
  69197. var camera = (_viewer$inputHandler$2 = viewer.inputHandler.hoverViewport) === null || _viewer$inputHandler$2 === void 0 ? void 0 : _viewer$inputHandler$2.camera;
  69198. if (mode === 'scale') {
  69199. space = 'local';
  69200. } else if (axis === 'E' || axis === 'XYZE' || axis === 'XYZ') {
  69201. space = 'world';
  69202. }
  69203. if (object === undefined || axis === null || this.dragging === false || pointer.button !== undefined && pointer.button !== 0) return;
  69204. //ray.setFromCamera( pointer, camera ); //这句会在floorplan模式get不到intersect
  69205. var {
  69206. origin,
  69207. direction
  69208. } = viewer.inputHandler.getMouseDirection();
  69209. ray.set(origin, direction);
  69210. Potree.Utils.setCameraLayers(ray,
  69211. //设置能识别到的layers
  69212. ['sceneObjects', 'mapObjects', /* 'measure', */'transformationTool', 'model'], viewer.inputHandler.hoverViewport && viewer.inputHandler.hoverViewport.extraEnableLayers);
  69213. camera && camera != lastUseCamera && this.updateMatrixWorld(null, camera); //add 多viewport时重新根据hover的camera更新下
  69214. var planeIntersect = ray.intersectObjects([_plane], true)[0] || false;
  69215. if (planeIntersect === false) return;
  69216. pointEnd.copy(planeIntersect.point).sub(worldPositionStart);
  69217. if (mode === 'translate') {
  69218. // Apply translate
  69219. offset.copy(pointEnd).sub(pointStart);
  69220. if (space === 'local' && axis !== 'XYZ') {
  69221. offset.applyQuaternion(worldQuaternionInv);
  69222. }
  69223. if (axis.indexOf('X') === -1) offset.x = 0;
  69224. if (axis.indexOf('Y') === -1) offset.y = 0;
  69225. if (axis.indexOf('Z') === -1) offset.z = 0;
  69226. if (space === 'local' && axis !== 'XYZ') {
  69227. //xzw 加,否则会反向-----three官网也有问题----2025.4又改了一下(之前改完没测试吗=,=),经测试没问题---
  69228. //object.scale.x < 0 && (offset.x *= -1)
  69229. object.scale.y < 0 && (offset.x *= -1, offset.y *= -1);
  69230. object.scale.z < 0 && (offset.x *= -1, offset.z *= -1);
  69231. offset.applyQuaternion(quaternionStart).divide(parentScale);
  69232. } else {
  69233. offset.applyQuaternion(parentQuaternionInv).divide(parentScale);
  69234. }
  69235. object.position.copy(offset).add(positionStart);
  69236. // Apply translation snap
  69237. if (this.translationSnap) {
  69238. if (space === 'local') {
  69239. object.position.applyQuaternion(_tempQuaternion.copy(quaternionStart).invert());
  69240. if (axis.search('X') !== -1) {
  69241. object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
  69242. }
  69243. if (axis.search('Y') !== -1) {
  69244. object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
  69245. }
  69246. if (axis.search('Z') !== -1) {
  69247. object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
  69248. }
  69249. object.position.applyQuaternion(quaternionStart);
  69250. }
  69251. if (space === 'world') {
  69252. if (object.parent) {
  69253. object.position.add(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
  69254. }
  69255. if (axis.search('X') !== -1) {
  69256. object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
  69257. }
  69258. if (axis.search('Y') !== -1) {
  69259. object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
  69260. }
  69261. if (axis.search('Z') !== -1) {
  69262. object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
  69263. }
  69264. if (object.parent) {
  69265. object.position.sub(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
  69266. }
  69267. }
  69268. }
  69269. //add:
  69270. object.dispatchEvent({
  69271. type: "position_changed",
  69272. byControl: true
  69273. });
  69274. } else if (mode === 'scale') {
  69275. if (axis.search('XYZ') !== -1) {
  69276. var d = pointEnd.length() / pointStart.length();
  69277. if (pointEnd.dot(pointStart) < 0) d *= -1;
  69278. if (options.NoScaleZ) {
  69279. //xzw add
  69280. _tempVector2.set(d, d, 1);
  69281. } else {
  69282. _tempVector2.set(d, d, d);
  69283. }
  69284. } else if (axis.search('XY') !== -1) {
  69285. //add 等比例for plane
  69286. var d = pointEnd.length() / pointStart.length();
  69287. if (pointEnd.dot(pointStart) < 0) d *= -1;
  69288. _tempVector2.set(d, d, 1);
  69289. } else {
  69290. _tempVector.copy(pointStart);
  69291. _tempVector2.copy(pointEnd);
  69292. _tempVector.applyQuaternion(worldQuaternionInv);
  69293. _tempVector2.applyQuaternion(worldQuaternionInv);
  69294. _tempVector2.divide(_tempVector);
  69295. if (axis.search('X') === -1) {
  69296. _tempVector2.x = 1;
  69297. }
  69298. if (axis.search('Y') === -1) {
  69299. _tempVector2.y = 1;
  69300. }
  69301. if (axis.search('Z') === -1) {
  69302. _tempVector2.z = 1;
  69303. }
  69304. }
  69305. // Apply scale
  69306. object.scale.copy(scaleStart).multiply(_tempVector2);
  69307. if (this.scaleSnap) {
  69308. if (axis.search('X') !== -1) {
  69309. object.scale.x = Math.round(object.scale.x / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
  69310. }
  69311. if (axis.search('Y') !== -1) {
  69312. object.scale.y = Math.round(object.scale.y / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
  69313. }
  69314. if (axis.search('Z') !== -1) {
  69315. object.scale.z = Math.round(object.scale.z / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
  69316. }
  69317. }
  69318. //add:
  69319. this.options.minScale && object.scale.max(this.options.minScale);
  69320. object.dispatchEvent({
  69321. type: "scale_changed",
  69322. byControl: true
  69323. });
  69324. } else if (mode === 'rotate') {
  69325. if (this.rotateMethod == 2) {
  69326. //新版参照transfromTool的写法,更跟手,但是有bug,在同时移动位置时或e轴上有问题
  69327. if (axis === 'E') {
  69328. //绕着视线转
  69329. rotationAxis.copy(eye); //旋转轴
  69330. rotationAngle = pointEnd.angleTo(pointStart);
  69331. startNorm.copy(pointStart).normalize();
  69332. endNorm.copy(pointEnd).normalize();
  69333. rotationAngle *= endNorm.cross(startNorm).dot(eye) < 0 ? 1 : -1; //角度
  69334. } else {
  69335. if (axis === 'XYZE') {
  69336. //像滚球一样拨动,鼠标滑动方向为拨动方向,在plane面上滚动
  69337. offset.copy(pointEnd).sub(pointStart);
  69338. rotationAxis.copy(offset).cross(eye).normalize();
  69339. } else {
  69340. rotationAxis.copy(_unit[axis]);
  69341. }
  69342. var center = new Vector3(); //坐标轴位置
  69343. /* if(this.object.boundingBox){
  69344. center.copy(worldPosition) //center设置为boundingbox的中心。但center一直更改会导致虽然在按某个时针旋转,但v2相对v1可能会时不时逆向,导致闪烁。所以固定住center,虽然这样计算的角度和绕模型中心的感觉偏颇
  69345. }else{ */
  69346. center.copy(worldPositionStart);
  69347. //}
  69348. var rotationAxis_ = space === 'local' ? rotationAxis.clone().applyQuaternion(worldQuaternion) : rotationAxis;
  69349. var plane = new Plane().setFromNormalAndCoplanarPoint(rotationAxis_, center); //旋转过程中rotationAxis不会变化,但center可能会
  69350. var {
  69351. origin: _origin,
  69352. direction: _direction
  69353. } = viewer.inputHandler.getMouseDirection();
  69354. ray.set(_origin, _direction);
  69355. var I = ray.ray.intersectPlane(plane, new Vector3());
  69356. if (I) {
  69357. var v2 = I.clone().sub(center); //.normalize();
  69358. if (!this.rotateStart) {
  69359. this.rotateStart = {
  69360. v1: v2
  69361. };
  69362. return;
  69363. }
  69364. var v1 = this.rotateStart.v1;
  69365. rotationAngle = math.getAngle(v1, v2, rotationAxis_);
  69366. //console.log('rot', rotationAngle, /* center.toArray(), */ v1, v2)
  69367. if (Number.isNaN(rotationAngle)) {
  69368. return;
  69369. }
  69370. this.rotateStart.v1 = v2;
  69371. } else {
  69372. rotationAngle = 0;
  69373. //console.log('!I', rotationAngle)
  69374. }
  69375. }
  69376. } else {
  69377. //pointStart 是起始intersect - object中心的向量
  69378. //pointEnd 是当前intersect - object中心的向量
  69379. offset.copy(pointEnd).sub(pointStart);
  69380. var ROTATION_SPEED = 2 / worldPosition.distanceTo(_tempVector.setFromMatrixPosition(this.camera.matrixWorld));
  69381. if (axis === 'E') {
  69382. //绕着视线转
  69383. rotationAxis.copy(eye); //旋转轴
  69384. rotationAngle = pointEnd.angleTo(pointStart);
  69385. startNorm.copy(pointStart).normalize();
  69386. endNorm.copy(pointEnd).normalize();
  69387. rotationAngle *= endNorm.cross(startNorm).dot(eye) < 0 ? 1 : -1; //角度
  69388. } else if (axis === 'XYZE') {
  69389. //像滚球一样拨动,鼠标滑动方向为拨动方向,在plane面上滚动
  69390. rotationAxis.copy(offset).cross(eye).normalize();
  69391. rotationAngle = offset.dot(_tempVector.copy(rotationAxis).cross(this.eye)) * ROTATION_SPEED;
  69392. } else if (axis === 'X' || axis === 'Y' || axis === 'Z') {
  69393. rotationAxis.copy(_unit[axis]);
  69394. _tempVector.copy(_unit[axis]);
  69395. if (space === 'local') {
  69396. _tempVector.applyQuaternion(worldQuaternion);
  69397. }
  69398. rotationAngle = offset.dot(_tempVector.cross(eye).normalize()) * ROTATION_SPEED;
  69399. }
  69400. // Apply rotation snap
  69401. if (this.rotationSnap) rotationAngle = Math.round(rotationAngle / this.rotationSnap) * this.rotationSnap;
  69402. this.rotationAngle = rotationAngle;
  69403. }
  69404. // Apply rotate
  69405. if (space === 'local' && axis !== 'E' && axis !== 'XYZE') {
  69406. object.scale[axis.toLowerCase()] < 0 && (rotationAngle *= -1); //xzw 加,否则会反向
  69407. object.quaternion.copy(quaternionStart);
  69408. object.quaternion.multiply(_tempQuaternion.setFromAxisAngle(rotationAxis, rotationAngle)).normalize();
  69409. } else {
  69410. rotationAxis.applyQuaternion(parentQuaternionInv);
  69411. object.quaternion.copy(_tempQuaternion.setFromAxisAngle(rotationAxis, rotationAngle));
  69412. object.quaternion.multiply(quaternionStart).normalize();
  69413. }
  69414. if (this.rotateMethod == 2 && axis != 'E') {
  69415. quaternionStart.copy(object.quaternion);
  69416. }
  69417. //add:
  69418. object.dispatchEvent({
  69419. type: "rotation_changed",
  69420. byControl: true
  69421. });
  69422. }
  69423. this.dispatchEvent(changeEvent);
  69424. this.dispatchEvent(objectChangeEvent);
  69425. viewer.dispatchEvent('content_changed');
  69426. };
  69427. this.pointerUp = function (pointer) {
  69428. //if ( pointer.button !== undefined && pointer.button !== 0 ) return;
  69429. if (this.dragging && this.axis !== null) {
  69430. mouseUpEvent.mode = this.mode;
  69431. this.dispatchEvent(mouseUpEvent);
  69432. /* if(this.player.cameraControls.activeControl){
  69433. //this.player.cameraControls.activeControl.locked = false; //add
  69434. this.player.cameraControls.activeControl.pointerDragOn = false //add
  69435. this.player.cameraControls.activeControl.enabled = true
  69436. } */
  69437. this.rotateStart = null; //add
  69438. }
  69439. this.dragging = false;
  69440. //if ( pointer.button === undefined ) this.axis = null;
  69441. /* if(this.player.cameraControls.activeControl){
  69442. //this.player.cameraControls.activeControl.locked = false; //add
  69443. this.player.cameraControls.activeControl.pointerDragOn = false //add
  69444. this.player.cameraControls.activeControl.enabled = true
  69445. } */
  69446. };
  69447. // normalize mouse / touch pointer and remap {x,y} to view space.
  69448. function getPointer(event) {
  69449. if (!event) {
  69450. console.log('hhahhhahah');
  69451. return;
  69452. }
  69453. if (document.pointerLockElement) {
  69454. return {
  69455. x: 0,
  69456. y: 0,
  69457. button: event.button
  69458. };
  69459. } else {
  69460. var pointer = event.changedTouches ? event.changedTouches[0] : event;
  69461. var rect = domElement.getBoundingClientRect();
  69462. return {
  69463. x: (pointer.clientX - rect.left) / rect.width * 2 - 1,
  69464. y: -(pointer.clientY - rect.top) / rect.height * 2 + 1,
  69465. button: event.button
  69466. };
  69467. }
  69468. }
  69469. // mouse / touch event handlers
  69470. function onPointerHover(event) {
  69471. if (!scope.enabled) return;
  69472. //scope.pointerHover( getPointer( event ) );
  69473. scope.pointerHover();
  69474. }
  69475. function onPointerDown(event) {
  69476. if (!scope.enabled) return;
  69477. //document.addEventListener( "mousemove", onPointerMove, false );
  69478. /* scope.pointerHover( getPointer( event ) );
  69479. scope.pointerDown( getPointer( event ) ); */
  69480. scope.pointerHover();
  69481. scope.pointerDown();
  69482. }
  69483. this.onPointerDown = onPointerDown;
  69484. function onPointerMove(event) {
  69485. if (!scope.enabled || !this.dragging) return; //xzw change
  69486. //scope.pointerMove( getPointer( event ) );
  69487. scope.pointerMove();
  69488. }
  69489. this.onPointerMove = onPointerMove;
  69490. function onPointerUp(event) {
  69491. if (!scope.enabled) return;
  69492. //document.removeEventListener( "mousemove", onPointerMove, false );
  69493. //scope.pointerUp( getPointer( event ) );
  69494. scope.pointerUp();
  69495. }
  69496. this.onPointerUp = onPointerUp;
  69497. // TODO: deprecate
  69498. this.getMode = function () {
  69499. return scope.mode;
  69500. };
  69501. this.setMode = function (mode) {
  69502. scope.mode = mode;
  69503. };
  69504. this.setTranslationSnap = function (translationSnap) {
  69505. scope.translationSnap = translationSnap;
  69506. };
  69507. this.setRotationSnap = function (rotationSnap) {
  69508. scope.rotationSnap = rotationSnap;
  69509. };
  69510. this.setScaleSnap = function (scaleSnap) {
  69511. scope.scaleSnap = scaleSnap;
  69512. };
  69513. this.setSize = function (size) {
  69514. scope.size = size;
  69515. };
  69516. this.setSpace = function (space) {
  69517. scope.space = space;
  69518. };
  69519. this.setCamera = function (camera) {
  69520. //add
  69521. scope.camera = camera;
  69522. };
  69523. this.update = function () {
  69524. console.warn('THREE.TransformControls: update function has no more functionality and therefore has been deprecated.');
  69525. };
  69526. };
  69527. var TransformControlsGizmo = function TransformControlsGizmo(options) {
  69528. 'use strict';
  69529. Object3D.call(this);
  69530. this.type = 'TransformControlsGizmo';
  69531. // shared materials
  69532. this.hideAxis = {}, this.showAxis = {};
  69533. var gizmoMaterial = new MeshBasicMaterial({
  69534. depthTest: false,
  69535. depthWrite: false,
  69536. transparent: true,
  69537. side: DoubleSide,
  69538. fog: false
  69539. });
  69540. var gizmoLineMaterial = new LineBasicMaterial({
  69541. depthTest: false,
  69542. depthWrite: false,
  69543. transparent: true,
  69544. fog: false
  69545. });
  69546. // Make unique material for each axis/color
  69547. var matInvisible = gizmoMaterial.clone();
  69548. matInvisible.opacity = 0.15;
  69549. var matHelper = gizmoMaterial.clone();
  69550. matHelper.opacity = 0.1;
  69551. var matRed = gizmoMaterial.clone();
  69552. matRed.color.set(0xff0000);
  69553. var matGreen = gizmoMaterial.clone();
  69554. matGreen.color.set(0x00ff00);
  69555. var matBlue = gizmoMaterial.clone();
  69556. matBlue.color.set(0x0000ff);
  69557. var matWhiteTransparent = gizmoMaterial.clone();
  69558. matWhiteTransparent.opacity = 0.35;
  69559. matWhiteTransparent.color.set(0x00d0fd); //xzw add
  69560. var matYellowTransparent = matWhiteTransparent.clone();
  69561. matYellowTransparent.color.set(0xffff00);
  69562. var matCyanTransparent = matWhiteTransparent.clone();
  69563. matCyanTransparent.color.set(0x00ffff);
  69564. var matMagentaTransparent = matWhiteTransparent.clone();
  69565. matMagentaTransparent.color.set(0xff00ff);
  69566. var matYellow = gizmoMaterial.clone();
  69567. matYellow.color.set(0xffff00);
  69568. var matLineRed = gizmoLineMaterial.clone();
  69569. matLineRed.color.set(0xff0000);
  69570. var matLineGreen = gizmoLineMaterial.clone();
  69571. matLineGreen.color.set(0x00ff00);
  69572. var matLineBlue = gizmoLineMaterial.clone();
  69573. matLineBlue.color.set(0x0000ff);
  69574. var matLineCyan = gizmoLineMaterial.clone();
  69575. matLineCyan.color.set(0x00ffff);
  69576. var matLineMagenta = gizmoLineMaterial.clone();
  69577. matLineMagenta.color.set(0xff00ff);
  69578. var matLineYellow = gizmoLineMaterial.clone();
  69579. matLineYellow.color.set(0xffff00);
  69580. var matLineGray = gizmoLineMaterial.clone();
  69581. matLineGray.color.set(0x999999);
  69582. var matLineYellowTransparent = matLineYellow.clone();
  69583. matLineYellowTransparent.opacity = 0.25;
  69584. // reusable geometry
  69585. var arrowGeometry = new CylinderBufferGeometry(0, 0.05, 0.2, 12, 1, false);
  69586. var scaleHandleGeometry = new BoxBufferGeometry(0.125, 0.125, 0.125);
  69587. var lineGeometry = new BufferGeometry();
  69588. //lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
  69589. lineGeometry.setAttribute("position", new BufferAttribute(new Float32Array([0, 0, 0, 1, 0, 0]), 3));
  69590. var CircleGeometry = function CircleGeometry(radius, arc) {
  69591. var geometry = new BufferGeometry();
  69592. var vertices = [];
  69593. for (var i = 0; i <= 64 * arc; ++i) {
  69594. vertices.push(0, Math.cos(i / 32 * Math.PI) * radius, Math.sin(i / 32 * Math.PI) * radius);
  69595. }
  69596. //geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
  69597. geometry.setAttribute("position", new BufferAttribute(new Float32Array(vertices), 3));
  69598. return geometry;
  69599. };
  69600. // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position
  69601. var TranslateHelperGeometry = function TranslateHelperGeometry() {
  69602. var geometry = new BufferGeometry();
  69603. //geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) );
  69604. geometry.setAttribute("position", new BufferAttribute(new Float32Array([0, 0, 0, 1, 1, 1]), 3));
  69605. return geometry;
  69606. };
  69607. // Gizmo definitions - custom hierarchy definitions for setupGizmo() function
  69608. var gizmoTranslate = {
  69609. X: [[new Mesh(arrowGeometry, matRed), [1, 0, 0], [0, 0, -Math.PI / 2], null, 'fwd'],
  69610. //[ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ],
  69611. [new Line(lineGeometry, matLineRed)]],
  69612. Y: [[new Mesh(arrowGeometry, matGreen), [0, 1, 0], null, null, 'fwd'],
  69613. //[ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ],
  69614. [new Line(lineGeometry, matLineGreen), null, [0, 0, Math.PI / 2]]],
  69615. Z: [[new Mesh(arrowGeometry, matBlue), [0, 0, 1], [Math.PI / 2, 0, 0], null, 'fwd'],
  69616. //[ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ - Math.PI / 2, 0, 0 ], null, 'bwd' ],
  69617. [new Line(lineGeometry, matLineBlue), null, [0, -Math.PI / 2, 0]]],
  69618. /* XYZ: [
  69619. [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ], [ 0, 0, 0 ]]
  69620. ], */
  69621. XY: [[new Mesh(new PlaneBufferGeometry(0.295, 0.295), matYellowTransparent.clone()), [0.15, 0.15, 0]], [new Line(lineGeometry, matLineYellow), [0.18, 0.3, 0], null, [0.125, 1, 1]], [new Line(lineGeometry, matLineYellow), [0.3, 0.18, 0], [0, 0, Math.PI / 2], [0.125, 1, 1]]],
  69622. YZ: [[new Mesh(new PlaneBufferGeometry(0.295, 0.295), matCyanTransparent.clone()), [0, 0.15, 0.15], [0, Math.PI / 2, 0]], [new Line(lineGeometry, matLineCyan), [0, 0.18, 0.3], [0, 0, Math.PI / 2], [0.125, 1, 1]], [new Line(lineGeometry, matLineCyan), [0, 0.3, 0.18], [0, -Math.PI / 2, 0], [0.125, 1, 1]]],
  69623. XZ: [[new Mesh(new PlaneBufferGeometry(0.295, 0.295), matMagentaTransparent.clone()), [0.15, 0, 0.15], [-Math.PI / 2, 0, 0]], [new Line(lineGeometry, matLineMagenta), [0.18, 0, 0.3], null, [0.125, 1, 1]], [new Line(lineGeometry, matLineMagenta), [0.3, 0, 0.18], [0, -Math.PI / 2, 0], [0.125, 1, 1]]]
  69624. };
  69625. var pickerTranslate = {
  69626. X: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), matInvisible), [0.6, 0, 0], [0, 0, -Math.PI / 2]]],
  69627. Y: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), matInvisible), [0, 0.6, 0]]],
  69628. Z: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 1, 4, 1, false), matInvisible), [0, 0, 0.6], [Math.PI / 2, 0, 0]]],
  69629. /* XYZ: [
  69630. [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.2, 0 ), matInvisible ) ]
  69631. ], */
  69632. XY: [[new Mesh(new PlaneBufferGeometry(0.4, 0.4), matInvisible), [0.2, 0.2, 0]]],
  69633. YZ: [[new Mesh(new PlaneBufferGeometry(0.4, 0.4), matInvisible), [0, 0.2, 0.2], [0, Math.PI / 2, 0]]],
  69634. XZ: [[new Mesh(new PlaneBufferGeometry(0.4, 0.4), matInvisible), [0.2, 0, 0.2], [-Math.PI / 2, 0, 0]]]
  69635. };
  69636. var helperTranslate = {
  69637. START: [[new Mesh(new OctahedronBufferGeometry(0.01, 2), matHelper), null, null, null, 'helper']],
  69638. END: [[new Mesh(new OctahedronBufferGeometry(0.01, 2), matHelper), null, null, null, 'helper']],
  69639. DELTA: [[new Line(TranslateHelperGeometry(), matHelper), null, null, null, 'helper']],
  69640. X: [[new Line(lineGeometry, matHelper.clone()), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']],
  69641. Y: [[new Line(lineGeometry, matHelper.clone()), [0, -1e3, 0], [0, 0, Math.PI / 2], [1e6, 1, 1], 'helper']],
  69642. Z: [[new Line(lineGeometry, matHelper.clone()), [0, 0, -1e3], [0, -Math.PI / 2, 0], [1e6, 1, 1], 'helper']]
  69643. };
  69644. var arc = options.rotFullCircle ? 1 : 0.5; //add
  69645. var gizmoRotate = {
  69646. X: [[new Line(CircleGeometry(1, arc), matLineRed)], [new Mesh(new OctahedronBufferGeometry(0.04, 0), matRed), [0, 0, 0.99], null, [1, 3, 1]]],
  69647. Y: [[new Line(CircleGeometry(1, arc), matLineGreen), null, [0, 0, -Math.PI / 2]], [new Mesh(new OctahedronBufferGeometry(0.04, 0), matGreen), [0, 0, 0.99], null, [3, 1, 1]]],
  69648. Z: [[new Line(CircleGeometry(1, arc), matLineBlue), null, [0, Math.PI / 2, 0]], [new Mesh(new OctahedronBufferGeometry(0.04, 0), matBlue), [0.99, 0, 0], null, [1, 3, 1]]],
  69649. E: [[new Line(CircleGeometry(1.25, 1), matLineYellowTransparent), null, [0, Math.PI / 2, 0]], [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]], [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]], [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]], [new Mesh(new CylinderBufferGeometry(0.03, 0, 0.15, 4, 1, false), matLineYellowTransparent), [0, 1.17, 0], [0, 0, 0], [1, 1, 0.001]]],
  69650. XYZE: [[new Line(CircleGeometry(1, 1), matLineGray), null, [0, Math.PI / 2, 0]]]
  69651. };
  69652. var helperRotate = {
  69653. AXIS: [[new Line(lineGeometry, matHelper.clone()), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']]
  69654. };
  69655. var pickerRotate = {
  69656. X: [
  69657. //xzw 由原先全弧度改为一半弧度(Math.PI),否则在背面也会hover到
  69658. [new Mesh(new TorusBufferGeometry(1, 0.06, 4, 24, options.rotFullCircle ? Math.PI * 2 : Math.PI), matInvisible), [0, 0, 0], [0, -Math.PI / 2, -Math.PI / 2]]],
  69659. Y: [[new Mesh(new TorusBufferGeometry(1, 0.06, 4, 24, options.rotFullCircle ? Math.PI * 2 : Math.PI), matInvisible), [0, 0, 0], [Math.PI / 2, 0, 0]]],
  69660. Z: [[new Mesh(new TorusBufferGeometry(1, 0.06, 4, 24, options.rotFullCircle ? Math.PI * 2 : Math.PI), matInvisible), [0, 0, 0], [0, 0, -Math.PI / 2]]],
  69661. E: [[new Mesh(new TorusBufferGeometry(1.25, 0.06, 2, 24), matInvisible)]],
  69662. XYZE: [[new Mesh(new SphereBufferGeometry(0.7, 10, 8), matInvisible)]]
  69663. };
  69664. var gizmoScale = {
  69665. X: [[new Mesh(scaleHandleGeometry, matRed), [0.8, 0, 0], [0, 0, -Math.PI / 2]], [new Line(lineGeometry, matLineRed), null, null, [0.8, 1, 1]]],
  69666. Y: [[new Mesh(scaleHandleGeometry, matGreen), [0, 0.8, 0]], [new Line(lineGeometry, matLineGreen), null, [0, 0, Math.PI / 2], [0.8, 1, 1]]],
  69667. Z: [[new Mesh(scaleHandleGeometry, matBlue), [0, 0, 0.8], [Math.PI / 2, 0, 0]], [new Line(lineGeometry, matLineBlue), null, [0, -Math.PI / 2, 0], [0.8, 1, 1]]],
  69668. XY: [[new Mesh(scaleHandleGeometry, matYellowTransparent), [0.85, 0.85, 0], null, [2, 2, 0.2]], [new Line(lineGeometry, matLineYellow), [0.855, 0.98, 0], null, [0.125, 1, 1]], [new Line(lineGeometry, matLineYellow), [0.98, 0.855, 0], [0, 0, Math.PI / 2], [0.125, 1, 1]]],
  69669. /* YZ: [
  69670. [ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ]],
  69671. [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]],
  69672. [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  69673. ],
  69674. XZ: [
  69675. [ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ]],
  69676. [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ]],
  69677. [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]
  69678. ],
  69679. XYZX: [
  69680. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 1.1, 0, 0 ]],
  69681. ],*/
  69682. XYZY: [[new Mesh(new BoxBufferGeometry(0.125, 0.125, 0.125), matWhiteTransparent.clone()), [0, 1.1, 0]]] /* ,
  69683. XYZZ: [
  69684. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 0, 1.1 ]],
  69685. ] */
  69686. };
  69687. var pickerScale = {
  69688. X: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 0.8, 4, 1, false), matInvisible), [0.5, 0, 0], [0, 0, -Math.PI / 2]]],
  69689. Y: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 0.8, 4, 1, false), matInvisible), [0, 0.5, 0]]],
  69690. Z: [[new Mesh(new CylinderBufferGeometry(0.2, 0, 0.8, 4, 1, false), matInvisible), [0, 0, 0.5], [Math.PI / 2, 0, 0]]],
  69691. XY: [[new Mesh(scaleHandleGeometry, matInvisible), [0.85, 0.85, 0], null, [3, 3, 0.2]]],
  69692. /*YZ: [
  69693. [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ]],
  69694. ],
  69695. XZ: [
  69696. [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ]],
  69697. ],
  69698. XYZX: [
  69699. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ]],
  69700. ],*/
  69701. XYZY: [[new Mesh(new BoxBufferGeometry(0.2, 0.2, 0.2), matInvisible), [0, 1.1, 0]]] /* ,
  69702. XYZZ: [
  69703. [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ]],
  69704. ] */
  69705. };
  69706. var helperScale = {
  69707. X: [[new Line(lineGeometry, matHelper.clone()), [-1e3, 0, 0], null, [1e6, 1, 1], 'helper']],
  69708. Y: [[new Line(lineGeometry, matHelper.clone()), [0, -1e3, 0], [0, 0, Math.PI / 2], [1e6, 1, 1], 'helper']],
  69709. Z: [[new Line(lineGeometry, matHelper.clone()), [0, 0, -1e3], [0, -Math.PI / 2, 0], [1e6, 1, 1], 'helper']]
  69710. };
  69711. // Creates an THREE.Object3D with gizmos described in custom hierarchy definition.
  69712. var setupGizmo = function setupGizmo(gizmoMap) {
  69713. var gizmo = new Object3D();
  69714. for (var name in gizmoMap) {
  69715. for (var i = gizmoMap[name].length; i--;) {
  69716. var object = gizmoMap[name][i][0].clone();
  69717. var position = gizmoMap[name][i][1];
  69718. var rotation = gizmoMap[name][i][2];
  69719. var scale = gizmoMap[name][i][3];
  69720. var tag = gizmoMap[name][i][4];
  69721. // name and tag properties are essential for picking and updating logic.
  69722. object.name = name;
  69723. object.tag = tag;
  69724. if (position) {
  69725. object.position.set(position[0], position[1], position[2]);
  69726. }
  69727. if (rotation) {
  69728. object.rotation.set(rotation[0], rotation[1], rotation[2]);
  69729. }
  69730. if (scale) {
  69731. object.scale.set(scale[0], scale[1], scale[2]);
  69732. }
  69733. object.updateMatrix();
  69734. var tempGeometry = object.geometry.clone();
  69735. tempGeometry.applyMatrix4(object.matrix);
  69736. object.geometry = tempGeometry;
  69737. object.renderOrder = Infinity;
  69738. object.position.set(0, 0, 0);
  69739. object.rotation.set(0, 0, 0);
  69740. object.scale.set(1, 1, 1);
  69741. gizmo.add(object);
  69742. }
  69743. }
  69744. return gizmo;
  69745. };
  69746. // Reusable utility variables
  69747. var tempVector = new Vector3(0, 0, 0);
  69748. var tempEuler = new Euler();
  69749. var alignVector = new Vector3(0, 1, 0);
  69750. var zeroVector = new Vector3(0, 0, 0);
  69751. var lookAtMatrix = new Matrix4();
  69752. var tempQuaternion = new Quaternion();
  69753. var tempQuaternion2 = new Quaternion();
  69754. var identityQuaternion = new Quaternion();
  69755. var unitX = new Vector3(1, 0, 0);
  69756. var unitY = new Vector3(0, 1, 0);
  69757. var unitZ = new Vector3(0, 0, 1);
  69758. // Gizmo creation
  69759. this.gizmo = {};
  69760. this.picker = {};
  69761. this.helper = {};
  69762. this.add(this.gizmo["translate"] = setupGizmo(gizmoTranslate));
  69763. this.add(this.gizmo["rotate"] = setupGizmo(gizmoRotate));
  69764. this.add(this.gizmo["scale"] = setupGizmo(gizmoScale));
  69765. this.add(this.picker["translate"] = setupGizmo(pickerTranslate));
  69766. this.add(this.picker["rotate"] = setupGizmo(pickerRotate));
  69767. this.add(this.picker["scale"] = setupGizmo(pickerScale));
  69768. this.add(this.helper["translate"] = setupGizmo(helperTranslate));
  69769. this.add(this.helper["rotate"] = setupGizmo(helperRotate));
  69770. this.add(this.helper["scale"] = setupGizmo(helperScale));
  69771. // Pickers should be hidden always
  69772. this.picker["translate"].visible = false;
  69773. this.picker["rotate"].visible = false;
  69774. this.picker["scale"].visible = false;
  69775. // updateMatrixWorld will update transformations and appearance of individual handles
  69776. this.updateMatrixWorld = function () {
  69777. var _Potree$currentRender2;
  69778. //TransformControlsGizmo
  69779. if (!this.parent.visible) return; //add
  69780. var space = this.space;
  69781. var camera = lastUseCamera || ((_Potree$currentRender2 = Potree.currentRender) === null || _Potree$currentRender2 === void 0 ? void 0 : _Potree$currentRender2.camera) || this.camera;
  69782. if (this.mode === 'scale') space = 'local'; // scale always oriented to local rotation
  69783. var quaternion = space === "local" ? this.worldQuaternion : identityQuaternion;
  69784. // Show only gizmos for current transform mode
  69785. this.gizmo["translate"].visible = this.mode === "translate";
  69786. this.gizmo["rotate"].visible = this.mode === "rotate";
  69787. this.gizmo["scale"].visible = this.mode === "scale";
  69788. this.helper["translate"].visible = this.mode === "translate";
  69789. this.helper["rotate"].visible = this.mode === "rotate";
  69790. this.helper["scale"].visible = this.mode === "scale";
  69791. var handles = [];
  69792. handles = handles.concat(this.picker[this.mode].children);
  69793. handles = handles.concat(this.gizmo[this.mode].children);
  69794. handles = handles.concat(this.helper[this.mode].children);
  69795. Potree.Utils.updateVisible(this.gizmo["rotate"].children.find(e => e.name == 'XYZE'), 'decorateCircle', options.showRotXYZE, 1, this.showRotXYZE ? 'add' : 'cancel'); //xzw add 没有环的话不好看。但不要picker
  69796. for (var i = 0; i < handles.length; i++) {
  69797. var _this$hideAxis$this$m, _this$showAxis$this$m;
  69798. var handle = handles[i];
  69799. //add
  69800. if ((_this$hideAxis$this$m = this.hideAxis[this.mode]) !== null && _this$hideAxis$this$m !== void 0 && _this$hideAxis$this$m.some(e => handle.name.includes(e.toUpperCase())) && !((_this$showAxis$this$m = this.showAxis[this.mode]) !== null && _this$showAxis$this$m !== void 0 && _this$showAxis$this$m.some(e => handle.name == e.toUpperCase()))) {
  69801. Potree.Utils.updateVisible(handle, 'hidden', false);
  69802. if (!handle.visible) continue; //XYZE还是要作为装饰显示
  69803. }
  69804. var visible = true;
  69805. // hide aligned to camera
  69806. handle.rotation.set(0, 0, 0);
  69807. handle.position.copy(this.worldPosition);
  69808. if (camera.type == "OrthographicCamera") {
  69809. var eyeDistance = 800 / camera.zoom;
  69810. } else {
  69811. var eyeDistance = this.worldPosition.distanceTo(this.cameraPosition);
  69812. }
  69813. handle.scale.set(1, 1, 1).multiplyScalar(eyeDistance * this.size / 7);
  69814. // TODO: simplify helpers and consider decoupling from gizmo
  69815. if (handle.tag === 'helper') {
  69816. visible = false;
  69817. if (handle.name === 'AXIS') {
  69818. handle.position.copy(this.worldPositionStart);
  69819. visible = !!this.axis;
  69820. if (this.axis === 'X') {
  69821. tempQuaternion.setFromEuler(tempEuler.set(0, 0, 0));
  69822. handle.quaternion.copy(quaternion).multiply(tempQuaternion);
  69823. if (Math.abs(alignVector.copy(unitX).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
  69824. visible = false;
  69825. }
  69826. }
  69827. if (this.axis === 'Y') {
  69828. tempQuaternion.setFromEuler(tempEuler.set(0, 0, Math.PI / 2));
  69829. handle.quaternion.copy(quaternion).multiply(tempQuaternion);
  69830. if (Math.abs(alignVector.copy(unitY).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
  69831. visible = false;
  69832. }
  69833. }
  69834. if (this.axis === 'Z') {
  69835. tempQuaternion.setFromEuler(tempEuler.set(0, Math.PI / 2, 0));
  69836. handle.quaternion.copy(quaternion).multiply(tempQuaternion);
  69837. if (Math.abs(alignVector.copy(unitZ).applyQuaternion(quaternion).dot(this.eye)) > 0.9) {
  69838. visible = false;
  69839. }
  69840. }
  69841. if (this.axis === 'XYZE') {
  69842. tempQuaternion.setFromEuler(tempEuler.set(0, Math.PI / 2, 0));
  69843. alignVector.copy(this.rotationAxis);
  69844. handle.quaternion.setFromRotationMatrix(lookAtMatrix.lookAt(zeroVector, alignVector, unitY));
  69845. handle.quaternion.multiply(tempQuaternion);
  69846. visible = this.dragging;
  69847. }
  69848. if (this.axis === 'E') {
  69849. visible = false;
  69850. }
  69851. } else if (handle.name === 'START') {
  69852. handle.position.copy(this.worldPositionStart);
  69853. visible = this.dragging;
  69854. } else if (handle.name === 'END') {
  69855. handle.position.copy(this.worldPosition);
  69856. visible = this.dragging;
  69857. } else if (handle.name === 'DELTA') {
  69858. handle.position.copy(this.worldPositionStart);
  69859. handle.quaternion.copy(this.worldQuaternionStart);
  69860. tempVector.set(1e-10, 1e-10, 1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1);
  69861. tempVector.applyQuaternion(this.worldQuaternionStart.clone().invert());
  69862. handle.scale.copy(tempVector);
  69863. visible = this.dragging;
  69864. } else {
  69865. handle.quaternion.copy(quaternion);
  69866. if (this.dragging) {
  69867. handle.position.copy(this.worldPositionStart);
  69868. } else {
  69869. handle.position.copy(this.worldPosition);
  69870. }
  69871. if (this.axis) {
  69872. visible = this.axis.search(handle.name) !== -1;
  69873. }
  69874. }
  69875. // If updating helper, skip rest of the loop
  69876. Potree.Utils.updateVisible(handle, 'hidden', !!visible);
  69877. continue;
  69878. }
  69879. // Align handles to current local or world rotation
  69880. handle.quaternion.copy(quaternion);
  69881. if (this.mode === 'translate' || this.mode === 'scale') {
  69882. // Hide translate and scale axis facing the camera
  69883. var AXIS_HIDE_TRESHOLD = 0.99;
  69884. var PLANE_HIDE_TRESHOLD = 0.2;
  69885. var AXIS_FLIP_TRESHOLD = 0.0;
  69886. if (options.dontHideWhenFaceCamera) {//xzw add
  69887. //正对镜头时不隐藏箭头
  69888. } else {
  69889. if (handle.name === 'X' || handle.name === 'XYZX') {
  69890. if (Math.abs(alignVector.copy(unitX).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
  69891. handle.scale.set(1e-10, 1e-10, 1e-10);
  69892. visible = false;
  69893. }
  69894. }
  69895. if (handle.name === 'Y' || handle.name === 'XYZY') {
  69896. if (Math.abs(alignVector.copy(unitY).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
  69897. handle.scale.set(1e-10, 1e-10, 1e-10);
  69898. visible = false;
  69899. }
  69900. }
  69901. if (handle.name === 'Z' || handle.name === 'XYZZ') {
  69902. if (Math.abs(alignVector.copy(unitZ).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_TRESHOLD) {
  69903. handle.scale.set(1e-10, 1e-10, 1e-10);
  69904. visible = false;
  69905. }
  69906. }
  69907. if (handle.name === 'XY') {
  69908. if (Math.abs(alignVector.copy(unitZ).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
  69909. handle.scale.set(1e-10, 1e-10, 1e-10);
  69910. visible = false;
  69911. }
  69912. }
  69913. if (handle.name === 'YZ') {
  69914. if (Math.abs(alignVector.copy(unitX).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
  69915. handle.scale.set(1e-10, 1e-10, 1e-10);
  69916. visible = false;
  69917. }
  69918. }
  69919. if (handle.name === 'XZ') {
  69920. if (Math.abs(alignVector.copy(unitY).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_TRESHOLD) {
  69921. handle.scale.set(1e-10, 1e-10, 1e-10);
  69922. visible = false;
  69923. }
  69924. }
  69925. }
  69926. // Flip translate and scale axis ocluded behind another axis
  69927. //xzw 改 去掉反向箭头
  69928. if (handle.name.search('X') !== -1) {
  69929. if (alignVector.copy(unitX).applyQuaternion(quaternion).dot(this.eye) < AXIS_FLIP_TRESHOLD) {
  69930. /* if ( handle.tag === 'fwd' ) {
  69931. handle.visible = false;
  69932. } else {
  69933. handle.scale.x *= - 1;
  69934. }
  69935. } else if ( handle.tag === 'bwd' ) {
  69936. handle.visible = false;*/
  69937. handle.scale.x *= -1;
  69938. }
  69939. }
  69940. if (handle.name.search('Y') !== -1) {
  69941. if (alignVector.copy(unitY).applyQuaternion(quaternion).dot(this.eye) < AXIS_FLIP_TRESHOLD) {
  69942. /* if ( handle.tag === 'fwd' ) {
  69943. handle.visible = false;
  69944. } else {
  69945. handle.scale.y *= - 1;
  69946. }
  69947. } else if ( handle.tag === 'bwd' ) {
  69948. handle.visible = false;
  69949. */
  69950. handle.scale.y *= -1;
  69951. }
  69952. }
  69953. if (handle.name.search('Z') !== -1) {
  69954. if (alignVector.copy(unitZ).applyQuaternion(quaternion).dot(this.eye) < AXIS_FLIP_TRESHOLD) {
  69955. /* if ( handle.tag === 'fwd' ) {
  69956. handle.visible = false;
  69957. } else {
  69958. handle.scale.z *= - 1;
  69959. }
  69960. } else if ( handle.tag === 'bwd' ) {
  69961. handle.visible = false; */
  69962. handle.scale.z *= -1;
  69963. }
  69964. }
  69965. } else if (this.mode === 'rotate') {
  69966. // Align handles to current local or world rotation
  69967. tempQuaternion2.copy(quaternion);
  69968. alignVector.copy(this.eye).applyQuaternion(tempQuaternion.copy(quaternion).invert());
  69969. if (handle.name.search("E") !== -1) {
  69970. handle.quaternion.setFromRotationMatrix(lookAtMatrix.lookAt(this.eye, zeroVector, unitY));
  69971. }
  69972. if (handle.name === 'X') {
  69973. tempQuaternion.setFromAxisAngle(unitX, Math.atan2(-alignVector.y, alignVector.z));
  69974. tempQuaternion.multiplyQuaternions(tempQuaternion2, tempQuaternion);
  69975. handle.quaternion.copy(tempQuaternion);
  69976. }
  69977. if (handle.name === 'Y') {
  69978. tempQuaternion.setFromAxisAngle(unitY, Math.atan2(alignVector.x, alignVector.z));
  69979. tempQuaternion.multiplyQuaternions(tempQuaternion2, tempQuaternion);
  69980. handle.quaternion.copy(tempQuaternion);
  69981. }
  69982. if (handle.name === 'Z') {
  69983. tempQuaternion.setFromAxisAngle(unitZ, Math.atan2(alignVector.y, alignVector.x));
  69984. tempQuaternion.multiplyQuaternions(tempQuaternion2, tempQuaternion);
  69985. handle.quaternion.copy(tempQuaternion);
  69986. }
  69987. }
  69988. // Hide disabled axes
  69989. visible = visible && (handle.name.indexOf("X") === -1 || this.showX);
  69990. visible = visible && (handle.name.indexOf("Y") === -1 || this.showY);
  69991. visible = visible && (handle.name.indexOf("Z") === -1 || this.showZ);
  69992. visible = visible && (handle.name.indexOf("E") === -1 || this.showX && this.showY && this.showZ);
  69993. Potree.Utils.updateVisible(handle, 'hidden', !!visible);
  69994. // highlight selected axis
  69995. handle.material._opacity = handle.material._opacity || handle.material.opacity;
  69996. handle.material._color = handle.material._color || handle.material.color.clone();
  69997. handle.material.color.copy(handle.material._color);
  69998. handle.material.opacity = handle.material._opacity;
  69999. if (!this.enabled) {
  70000. handle.material.opacity *= 0.5;
  70001. handle.material.color.lerp(new Color(1, 1, 1), 0.5);
  70002. } else if (this.axis) {
  70003. if (handle.name === this.axis) {
  70004. handle.material.opacity = 1.0;
  70005. handle.material.color.lerp(new Color(1, 1, 1), 0.5);
  70006. } else if (this.axis.split('').some(function (a) {
  70007. return handle.name === a;
  70008. })) {
  70009. handle.material.opacity = 1.0;
  70010. handle.material.color.lerp(new Color(1, 1, 1), 0.5);
  70011. } else {
  70012. handle.material.opacity *= 0.25;
  70013. handle.material.color.lerp(new Color(1, 1, 1), 0.5);
  70014. }
  70015. }
  70016. }
  70017. Object3D.prototype.updateMatrixWorld.call(this);
  70018. };
  70019. };
  70020. /* var TransformControlsLines = function (options) {
  70021. THREE.Object3D.call( this)
  70022. let label1 = new Label2D({ innerHTML:`<div>与相机水平距离</div>` , domElement:$("#otherLabels")[0] ,autoUpdate:true })
  70023. let label2 = new Label2D({ innerHTML:`<div>与相机高度差</div>` , domElement:$("#otherLabels")[0] ,autoUpdate:true })
  70024. let css = {'opacity': 0.7, 'color': '#07fceb', transform:'translate(-50%, -50%)'}
  70025. label1.elem.css(css);
  70026. label2.elem.css(css)
  70027. //for(let i=0;i<2;i++){
  70028. // let line = LineDraw.createLine([new THREE.THREE.Vector3, new THREE.THREE.Vector3],{color:'#07fceb', opacity:0.7 })
  70029. // this.add(line)
  70030. //}
  70031. this.updateTransform = function(object){
  70032. object = object || this.parent.object;
  70033. let A = player.position.clone(); //当前相机位置
  70034. let B = object.position //物体位置
  70035. let C = B.clone().setY(A.y); //物体在相机的高度的位置
  70036. let D = A.clone().setY(B.y); //相机在物体的高度的位置
  70037. //LineDraw.moveLine(this.children[0], [B, C]) // 垂直线
  70038. //LineDraw.moveLine(this.children[1], [D, B]) // 水平线
  70039. let dis1 = toPrecision(D.distanceTo(B),1)
  70040. let dis2 = C.y - B.y
  70041. label1.elem.text('与相机水平距离: '+dis1+'米')
  70042. label2.elem.text('在相机之'+ (dis2>0?'下' : '上') +' :'+ toPrecision(dis2 , 1) +'米')
  70043. label1.setPos(new THREE.THREE.Vector3().addVectors(D,B).multiplyScalar(0.5))
  70044. label2.setPos(new THREE.THREE.Vector3().addVectors(B,C).multiplyScalar(0.5))
  70045. }
  70046. this.setVisible = (v,reason)=>{
  70047. label1.setVisible(v, reason || 'unvisi')
  70048. label2.setVisible(v, reason || 'unvisi')
  70049. this.visible = label1.visible
  70050. if(this.visible){
  70051. this.updateTransform()
  70052. }
  70053. }
  70054. this.setVisible(false)
  70055. player.on("mode.changing",(currentMode, mode, pano, duration)=>{
  70056. if(mode != 'panorama'){
  70057. this.setVisible(false, 'isPanorama')
  70058. }else{
  70059. this.setVisible(true, 'isPanorama')
  70060. }
  70061. })
  70062. player.on("flying.started",( )=>{
  70063. this.setVisible(false, 'flying')
  70064. })
  70065. player.on("flying.ended",( )=>{
  70066. this.setVisible(true, 'flying')
  70067. })
  70068. }
  70069. */
  70070. var TransformControlsPlane = function TransformControlsPlane(options) {
  70071. 'use strict';
  70072. Mesh.call(this, new PlaneBufferGeometry(100000, 100000, 2, 2), new MeshBasicMaterial({
  70073. color: "#ff0000",
  70074. visible: false,
  70075. wireframe: false,
  70076. side: DoubleSide,
  70077. transparent: true,
  70078. opacity: 0.2
  70079. }));
  70080. this.type = 'TransformControlsPlane';
  70081. var unitX = new Vector3(1, 0, 0);
  70082. var unitY = new Vector3(0, 1, 0);
  70083. var unitZ = new Vector3(0, 0, 1);
  70084. var tempVector = new Vector3();
  70085. var dirVector = new Vector3();
  70086. var alignVector = new Vector3();
  70087. var tempMatrix = new Matrix4();
  70088. var identityQuaternion = new Quaternion();
  70089. this.updateMatrixWorld = function () {
  70090. //TransformControlsPlane
  70091. if (!this.visible) return; //add
  70092. var space = this.space;
  70093. this.position.copy(this.worldPosition);
  70094. if (this.mode === 'scale') space = 'local'; // scale always oriented to local rotation
  70095. unitX.set(1, 0, 0).applyQuaternion(space === "local" ? this.worldQuaternion : identityQuaternion);
  70096. unitY.set(0, 1, 0).applyQuaternion(space === "local" ? this.worldQuaternion : identityQuaternion);
  70097. unitZ.set(0, 0, 1).applyQuaternion(space === "local" ? this.worldQuaternion : identityQuaternion);
  70098. // Align the plane for current transform mode, axis and space.
  70099. alignVector.copy(unitY);
  70100. switch (this.mode) {
  70101. case 'translate':
  70102. case 'scale':
  70103. switch (this.axis) {
  70104. case 'X':
  70105. alignVector.copy(this.eye).cross(unitX);
  70106. dirVector.copy(unitX).cross(alignVector);
  70107. break;
  70108. case 'Y':
  70109. alignVector.copy(this.eye).cross(unitY);
  70110. dirVector.copy(unitY).cross(alignVector);
  70111. break;
  70112. case 'Z':
  70113. alignVector.copy(this.eye).cross(unitZ);
  70114. dirVector.copy(unitZ).cross(alignVector);
  70115. break;
  70116. case 'XY':
  70117. dirVector.copy(unitZ);
  70118. break;
  70119. case 'YZ':
  70120. dirVector.copy(unitX);
  70121. break;
  70122. case 'XZ':
  70123. alignVector.copy(unitZ);
  70124. dirVector.copy(unitY);
  70125. break;
  70126. case 'XYZ':
  70127. case 'E':
  70128. default:
  70129. //xzw add for scale xyzz
  70130. dirVector.set(0, 0, 0);
  70131. break;
  70132. }
  70133. break;
  70134. case 'rotate':
  70135. default:
  70136. // special case for rotate
  70137. dirVector.set(0, 0, 0);
  70138. }
  70139. if (dirVector.length() === 0) {
  70140. //使物体在视线中平移
  70141. // If in rotate mode, make the plane parallel to camera
  70142. this.quaternion.copy(this.cameraQuaternion);
  70143. } else {
  70144. //方向滑动所在面
  70145. tempMatrix.lookAt(tempVector.set(0, 0, 0), dirVector, alignVector);
  70146. this.quaternion.setFromRotationMatrix(tempMatrix);
  70147. }
  70148. Object3D.prototype.updateMatrixWorld.call(this);
  70149. };
  70150. };
  70151. TransformControls.prototype = Object.assign(Object.create(Object3D.prototype), {
  70152. constructor: TransformControls,
  70153. isTransformControls: true
  70154. });
  70155. TransformControlsGizmo.prototype = Object.assign(Object.create(Object3D.prototype), {
  70156. constructor: TransformControlsGizmo,
  70157. isTransformControlsGizmo: true
  70158. });
  70159. TransformControlsPlane.prototype = Object.assign(Object.create(Mesh.prototype), {
  70160. constructor: TransformControlsPlane,
  70161. isTransformControlsPlane: true
  70162. });
  70163. /*
  70164. 备注:
  70165. //这里虽然 使坐标轴在boundingBox中心
  70166. boundingBox && this.object.boundingBox.getCenter(worldPosition).applyMatrix4(this.object.matrixWorld);
  70167. 但是旋转中心并不是这个坐标轴显示的位置,需要再执行 MergeEditor.maintainBoundXY()才能维持在这个中心
  70168. */
  70169. var Alignment = {
  70170. SplitScreen: SplitScreen4Views,
  70171. handleState: null,
  70172. //操作状态 'translate'|'rotate'
  70173. bus: new EventDispatcher(),
  70174. selectedClouds: [],
  70175. /* prepareRecord : true,
  70176. writeToHistory(pointclouds){
  70177. if(!this.prepareRecord)return;
  70178. this.prepareRecord = false
  70179. let content = this.getTemp(pointclouds)
  70180. this.history.writeIn(content)
  70181. },
  70182. undo(){//撤销一步
  70183. let last = this.history.pop();
  70184. last && last.forEach(item=>{
  70185. this.applyTemp(item)
  70186. })
  70187. }, */
  70188. applyTemp(item) {
  70189. var pointcloud = viewer.scene.pointclouds.find(p => p.dataset_id + p.name == item.sid);
  70190. pointcloud.orientationUser = item.orientationUser;
  70191. pointcloud.translateUser = item.translateUser;
  70192. this.setMatrix(pointcloud);
  70193. },
  70194. getTemp(pointclouds) {
  70195. //记录最近一次保存后的状态,便于恢复
  70196. pointclouds = pointclouds || viewer.scene.pointclouds;
  70197. return pointclouds.map(e => {
  70198. return {
  70199. sid: e.dataset_id + e.name,
  70200. orientationUser: typeof e.orientationUser == 'number' ? e.orientationUser : e.orientationUser.clone(),
  70201. translateUser: e.translateUser.clone()
  70202. };
  70203. });
  70204. },
  70205. getDatasetQuaternion(pointcloud) {
  70206. var quaternion;
  70207. if (typeof pointcloud.orientationUser == 'number') {
  70208. quaternion = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), pointcloud.orientationUser);
  70209. } else {
  70210. quaternion = pointcloud.orientationUser;
  70211. }
  70212. return quaternion;
  70213. },
  70214. getDatasetOrient(pointcloud) {
  70215. var orientation;
  70216. if (typeof pointcloud.orientationUser == 'number') {
  70217. orientation = pointcloud.orientationUser;
  70218. } else {
  70219. orientation = math.getYawPitchByQua(pointcloud.orientationUser);
  70220. }
  70221. return orientation;
  70222. },
  70223. init: function init() {
  70224. var transfromInfo, sideRotHovered;
  70225. this.history = new History({
  70226. applyData: data => {
  70227. data.forEach(item => {
  70228. Alignment.applyTemp(item);
  70229. });
  70230. return true;
  70231. },
  70232. getData: pointclouds => {
  70233. return Alignment.getTemp(pointclouds);
  70234. }
  70235. });
  70236. {
  70237. //侧视图旋转
  70238. this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea, {
  70239. //dontHideWhenFaceCamera: true,
  70240. rotFullCircle: true
  70241. });
  70242. this.transformControls.name = 'Alignment-transformControls';
  70243. this.transformControls.setSize(0.5);
  70244. viewer.scene.scene.add(this.transformControls);
  70245. this.transformControls.setMode('rotate');
  70246. this.transformControls.setRotateMethod(2);
  70247. this.transformControls._gizmo.hideAxis = {
  70248. rotate: ['x', 'z', 'y']
  70249. };
  70250. this.fakeMarkerForTran = new Mesh(new BoxBufferGeometry(0.3, 0.3, 0.3), new MeshBasicMaterial({
  70251. color: "#F00",
  70252. opacity: 0.9,
  70253. transparent: true,
  70254. visible: false
  70255. })); //一个看不见的mesh,只是为了让transformControls移动点云
  70256. this.fakeMarkerForTran.name = 'fakeMarkerForTran';
  70257. viewer.scene.scene.add(this.fakeMarkerForTran);
  70258. var afterMoveCtl = type => {
  70259. if (Alignment.afterMoveCtl) {
  70260. Alignment.afterMoveCtl(type);
  70261. } else {
  70262. if (type == 'position') {
  70263. var moveVec = new Vector3().subVectors(this.fakeMarkerForTran.position, this.fakeMarkerForTran.oldState.position);
  70264. Alignment.translate(this.selectedClouds[0], moveVec);
  70265. } else {
  70266. var center = this.selectedClouds[0].translateUser;
  70267. var diffQua = new Quaternion().multiplyQuaternions(this.fakeMarkerForTran.quaternion, this.fakeMarkerForTran.oldState.quaternion.clone().invert());
  70268. CursorDeal.add('rotatePointcloud');
  70269. //Alignment.rotateAround(center, this.selectedClouds, diffQua)
  70270. Alignment.rotate(this.selectedClouds[0], null, diffQua);
  70271. }
  70272. }
  70273. this.fakeMarkerForTran.oldState = {
  70274. position: this.fakeMarkerForTran.position.clone(),
  70275. quaternion: this.fakeMarkerForTran.quaternion.clone()
  70276. };
  70277. Alignment.history.beforeChange(this.selectedClouds);
  70278. };
  70279. this.fakeMarkerForTran.addEventListener('position_changed', afterMoveCtl.bind(this, 'position'));
  70280. this.fakeMarkerForTran.addEventListener("rotation_changed", afterMoveCtl.bind(this, 'rotation'));
  70281. this.transformControls.addEventListener('mouseUp', () => {
  70282. Alignment.history.afterChange(this.selectedClouds);
  70283. });
  70284. this.transformControls.addEventListener('axisHoveredChange', e => {
  70285. if (e.axis && e.mode == 'rotate') {
  70286. CursorDeal.add('rotatePointcloud'), sideRotHovered = true;
  70287. } else {
  70288. CursorDeal.remove('rotatePointcloud');
  70289. sideRotHovered = false;
  70290. }
  70291. });
  70292. this.history.addEventListener('undo', () => {
  70293. this.updateFakeMarker();
  70294. });
  70295. }
  70296. viewer.fpControls.addEventListener("transformPointcloud", e => {
  70297. if (e.pointclouds[0].dataset_id == Potree.settings.originDatasetId && Potree.settings.editType != 'pano') {
  70298. //禁止手动移动初始数据集
  70299. return this.bus.dispatchEvent('forbitMoveOriginDataset');
  70300. }
  70301. this.history.beforeChange(e.pointclouds);
  70302. //this.writeToHistory( e.pointclouds )
  70303. if (!transfromInfo) {
  70304. transfromInfo = {
  70305. pointclouds: e.pointclouds
  70306. };
  70307. }
  70308. if (this.handleState == 'translate') {
  70309. e.pointclouds.forEach(cloud => Alignment.translate(cloud, e.moveVec));
  70310. //this.updateFakeMarker()
  70311. } else if (this.handleState == 'rotate') {
  70312. //if(Potree.settings.editType == 'pano'){
  70313. //旋转中心是intersectStart的版本
  70314. /* let center = e.intersectStart //旋转中心是mousedown的位置
  70315. if(e.intersect.equals(center))return
  70316. if(!transfromInfo){
  70317. transfromInfo = {
  70318. orientationUser : e.pointclouds[0].orientationUser,
  70319. //vecStart : e.moveVec, // 首次移动向量 只有八个方向,精度太小,所以延迟
  70320. pointclouds: e.pointclouds
  70321. }
  70322. this.bus.dispatchEvent({type:'rotateStart', startPoint:center})
  70323. return
  70324. }else if(!transfromInfo.vecStart){
  70325. let vec = new THREE.Vector3().subVectors(e.intersect, center).setZ(0)
  70326. if(vec.length() * e.camera.zoom > 30){ //在屏幕上距离初始点有一定距离后开始算
  70327. //console.log('moveVec',vec)
  70328. transfromInfo.vecStart = vec
  70329. } */
  70330. var center = Potree.settings.editType == 'pano' ? e.pointclouds[0].translateUser : e.pointclouds[0].bound.getCenter(new Vector3()); //点云编辑:旋转中心是第一个点云的位置 ; 数据集校准:饶当前数据集bound中心,因有的上传的数据集偏离原点很远
  70331. if (e.intersect.equals(center)) return;
  70332. if (!transfromInfo.vecStart) {
  70333. //transfromInfo.orientationUser = e.pointclouds[0].orientationUser
  70334. transfromInfo.vecStart = new Vector3().subVectors(e.intersectStart, center).setZ(0);
  70335. transfromInfo.lastQua = new Quaternion();
  70336. } else {
  70337. var vec = new Vector3().subVectors(e.intersect, center).setZ(0);
  70338. var angle = math.getAngle(transfromInfo.vecStart, vec, 'z');
  70339. //let diffAngle = transfromInfo.orientationUser + angle - transfromInfo.pointclouds[0].orientationUser
  70340. var diffQuaFromStart = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), angle);
  70341. var diffQua = new Quaternion().multiplyQuaternions(diffQuaFromStart, transfromInfo.lastQua.clone().invert());
  70342. transfromInfo.lastQua.copy(diffQuaFromStart);
  70343. transfromInfo.pointclouds.forEach(cloud => {
  70344. /* let centerNoTranfrom = Potree.Utils.datasetPosTransform({ toDataset: true, pointcloud:cloud, position: center }) //中心点在数据集中的位置
  70345. Alignment.rotate(cloud, null, diffAngle)
  70346. let centerNow = Potree.Utils.datasetPosTransform({ fromDataset: true, pointcloud:cloud, position: centerNoTranfrom }) //中心点的现在位置
  70347. let shift = new THREE.Vector3().subVectors( center, centerNow); //偏移量
  70348. Alignment.translate(cloud,shift) //使center还保留在原位
  70349. //let centerNow1 = Potree.Utils.datasetPosTransform({ fromDataset: true, pointcloud:transfromInfo.pointcloud, position: centerNoTranfrom }) //中心点的现在位置
  70350. */
  70351. Alignment.rotateAround(center, cloud, diffQua);
  70352. });
  70353. }
  70354. //this.bus.dispatchEvent({type:'rotate', endPoint: e.intersect})
  70355. /* }else{ //旧版数据集校准只转z轴
  70356. let center = e.pointclouds[0].translateUser //移动到的位置就是中心
  70357. if(e.intersect.equals(center))return
  70358. if(!transfromInfo.vecStart){
  70359. transfromInfo.orientationUser = e.pointclouds[0].orientationUser
  70360. transfromInfo.vecStart = new THREE.Vector3().subVectors(e.intersectStart, center).setZ(0)
  70361. }else{
  70362. let vec = new THREE.Vector3().subVectors(e.intersect, center).setZ(0)
  70363. let angle = math.getAngle(transfromInfo.vecStart,vec,'z')
  70364. let diffAngle = transfromInfo.orientationUser + angle - transfromInfo.pointclouds[0].orientationUser
  70365. Alignment.rotate(transfromInfo.pointclouds[0], null, diffAngle)
  70366. }
  70367. } */
  70368. }
  70369. });
  70370. viewer.fpControls.addEventListener("end", e => {
  70371. transfromInfo && this.history.afterChange(transfromInfo.pointclouds);
  70372. transfromInfo = null;
  70373. });
  70374. // cursor:
  70375. var updateCursor = e => {
  70376. if (e.drag || !this.editing) return; //仅在鼠标不按下时更新:
  70377. var handleState = Alignment.handleState;
  70378. if (e.hoverViewport.alignment && handleState && e.hoverViewport.alignment[handleState]) {
  70379. if (handleState == 'translate') {
  70380. if (e.intersect && e.intersect.location) {
  70381. CursorDeal.add('movePointcloud');
  70382. } else {
  70383. CursorDeal.remove('movePointcloud');
  70384. }
  70385. } else if (handleState == 'rotate') {
  70386. if (e.intersect && e.intersect.location) {
  70387. CursorDeal.add('rotatePointcloud');
  70388. } else {
  70389. CursorDeal.remove('rotatePointcloud');
  70390. }
  70391. }
  70392. } else {
  70393. //清空:
  70394. CursorDeal.remove('movePointcloud');
  70395. if (!sideRotHovered) CursorDeal.remove('rotatePointcloud');
  70396. }
  70397. };
  70398. viewer.addEventListener('global_mousemove', updateCursor);
  70399. viewer.addEventListener('global_drop', updateCursor); //拖拽结束
  70400. viewer.addEventListener('updateModelBound', e => {
  70401. if (this.editing) {
  70402. this.SplitScreen.updateCameraOutOfModel();
  70403. }
  70404. });
  70405. },
  70406. setMatrix: function setMatrix(pointcloud) {
  70407. var vec1 = pointcloud.position; //position为数据集内部的偏移,在navvis中对应的是dataset.pointCloudSceneNode的children[0].position
  70408. var vec2 = pointcloud.translateUser;
  70409. var pos1Matrix = new Matrix4().setPosition(vec1); //先移动到点云本身应该在的初始位置(在4dkk里和其他应用中都是在这个位置的,也能和漫游点对应上)
  70410. var rotMatrix = typeof pointcloud.orientationUser == 'number' ?
  70411. //再旋转
  70412. new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), pointcloud.orientationUser) : new Matrix4().makeRotationFromQuaternion(pointcloud.orientationUser);
  70413. var pos2Matrix = new Matrix4().setPosition(vec2); //最后是平移
  70414. var matrix = new Matrix4().multiplyMatrices(pos2Matrix, rotMatrix);
  70415. pointcloud.transformMatrix = matrix.clone(); //为该数据集的变化矩阵。 对应navvis的m2w_
  70416. pointcloud.transformInvMatrix.copy(pointcloud.transformMatrix).invert();
  70417. pointcloud.rotateMatrix = rotMatrix;
  70418. pointcloud.rotateInvMatrix.copy(rotMatrix).invert();
  70419. pointcloud.panos.forEach(e => e.transformByPointcloud());
  70420. matrix = new Matrix4().multiplyMatrices(matrix, pos1Matrix);
  70421. //matrix.premultiply(viewer.scene.scene.matrix);////////////////////////add
  70422. pointcloud.matrix = matrix;
  70423. //pointcloud.matrixWorldNeedsUpdate = true //更新matrixWorld (非计算,直接赋值)
  70424. pointcloud.updateMatrixWorld(true);
  70425. if (this.editing) {
  70426. Alignment.changeCallBack && Alignment.changeCallBack();
  70427. }
  70428. if (pointcloud.spriteNodeRoot) {
  70429. pointcloud.spriteNodeRoot.matrixWorld.copy(pointcloud.matrixWorld); //.multiplyMatrices(pointcloud.matrixWorld, pointcloud.matrixWorld);
  70430. }
  70431. viewer.boundNeedUpdate = true;
  70432. //pointcloud.updateBound()
  70433. pointcloud.getPanosBound();
  70434. viewer.dispatchEvent('content_changed');
  70435. },
  70436. rotateAround(center, pointcloud, angle, axis) {
  70437. //绕center点水平转动
  70438. var vec1 = new Vector3().subVectors(pointcloud.translateUser, center);
  70439. var rotMatrix = typeof angle == 'number' ? new Matrix4().makeRotationAxis(new Vector3(0, 0, 1), angle) : new Matrix4().makeRotationFromQuaternion(angle);
  70440. var vec2 = vec1.clone().applyMatrix4(rotMatrix); //将到旋转中心的偏差也转动
  70441. var vec3 = new Vector3().subVectors(vec2, vec1); //这个就是多出来的一步translateUser
  70442. this.rotate(pointcloud, null, angle);
  70443. this.translate(pointcloud, vec3);
  70444. //绕点转动就是比普通转动多一步移动到相对center的某个位置。 1 初始点云移动到自己的position; 2 移动一个vec1 3绕原点旋转 4再移动一个原本的translateUser。 绘制出来后发现移动量就是第二步vec旋转后的偏移
  70445. },
  70446. rotate: function rotate(pointcloud, deg, angle, axis) {
  70447. //绕各自中心水平转动(各自的position) 假设点云位移position后0,0,0就是它的中心了(根据navvis观察这样做是绕同一个点旋转的)
  70448. var qua;
  70449. if (deg || typeof angle == 'number') {
  70450. angle = angle != void 0 ? angle : MathUtils.degToRad(deg); //正逆负顺
  70451. } else if (angle instanceof Array) {
  70452. //when init
  70453. qua = new Quaternion().fromArray(angle);
  70454. } else {
  70455. qua = angle;
  70456. }
  70457. if (typeof pointcloud.orientationUser == 'number') {
  70458. //pointcloud.orientationUser += angle
  70459. pointcloud.orientationUser = this.getDatasetQuaternion(pointcloud);
  70460. }
  70461. if (!qua) {
  70462. qua = new Quaternion().setFromAxisAngle(axis || new Vector3(0, 0, 1), angle);
  70463. }
  70464. pointcloud.orientationUser.premultiply(qua);
  70465. //新版全部使用qua
  70466. Alignment.setMatrix(pointcloud);
  70467. },
  70468. translate: function translate(pointcloud, vec) {
  70469. pointcloud.translateUser.add(vec);
  70470. Alignment.setMatrix(pointcloud);
  70471. },
  70472. enter: function enter() {
  70473. //this.saveTemp()
  70474. this.originData = this.getTemp();
  70475. this.SplitScreen.split({
  70476. alignment: true
  70477. });
  70478. /* viewer.images360.panos.forEach(pano=>{
  70479. Potree.Utils.updateVisible(pano.mapMarker, 'split4Screens', false)
  70480. }) */
  70481. viewer.viewports.find(e => e.name == 'mapViewport').alignment = {
  70482. rotate: true,
  70483. translate: true
  70484. };
  70485. viewer.viewports.find(e => e.name == 'right').alignment = {
  70486. translate: true,
  70487. translateVec: new Vector3(0, 0, 1)
  70488. }; //只能上下移动
  70489. viewer.viewports.find(e => e.name == 'back').alignment = {
  70490. translate: true,
  70491. translateVec: new Vector3(0, 0, 1)
  70492. }; //只能上下移动
  70493. viewer.viewports.forEach(e => {
  70494. if (e.name == 'right' || e.name == 'back') {
  70495. e.layersAdd('sideVisi');
  70496. /* if(e.name == 'right') e.layersAdd('layer1')
  70497. else if(e.name == 'back') e.layersAdd('layer2') */
  70498. }
  70499. });
  70500. Potree.Utils.setObjectLayers(this.transformControls, 'sideVisi');
  70501. /* Potree.Utils.setObjectLayers(this.transformControls, 'layer1' )
  70502. Potree.Utils.setObjectLayers(this.transformControls, 'layer2' ) */
  70503. {
  70504. /* viewer.viewports.forEach(e=>{
  70505. let oldFun = e.beforeRender
  70506. e.beforeRender = function(){
  70507. oldFun.bind(this)()
  70508. if(e.name == 'right'){
  70509. Alignment.transformControls._gizmo.hideAxis = {rotate:['e','z','y'] }
  70510. }else if(e.name == 'back'){
  70511. Alignment.transformControls._gizmo.hideAxis = {rotate:['e','z','x'] }
  70512. }
  70513. }
  70514. }) */
  70515. /* viewer.viewports.find(e=>e.name == 'right').beforeRender = function(){
  70516. oldFun.bind(this)()
  70517. if(this.name == right)
  70518. }
  70519. viewer.viewports.find(e=>e.name == 'back').beforeRender = (e)=>{
  70520. old2()
  70521. this.transformControls._gizmo.hideAxis = {rotate:['e','z','x'] }
  70522. } */
  70523. }
  70524. this.editing = true;
  70525. viewer.updateFpVisiDatasets();
  70526. },
  70527. leave: function leave() {
  70528. this.switchHandle(null);
  70529. /* this.originData.forEach(e=>{//恢复
  70530. var pointcloud = viewer.scene.pointclouds.find(p=>p.dataset_id == e.id)
  70531. this.translate(pointcloud, new THREE.Vector3().subVectors(e.translateUser , pointcloud.translateUser))
  70532. this.rotate(pointcloud, null, e.orientationUser - pointcloud.orientationUser)
  70533. }) */
  70534. this.originData.forEach(e => {
  70535. //恢复
  70536. this.applyTemp(e);
  70537. });
  70538. this.SplitScreen.recover();
  70539. /* viewer.images360.panos.forEach(pano=>{
  70540. Potree.Utils.updateVisible(pano.mapMarker, 'split4Screens', true)
  70541. }) */
  70542. this.editing = false;
  70543. this.history.clear();
  70544. viewer.updateFpVisiDatasets();
  70545. CursorDeal.remove('movePointcloud');
  70546. CursorDeal.remove('rotatePointcloud');
  70547. },
  70548. switchHandle: function switchHandle(state) {
  70549. console.log('switchHandle', state);
  70550. this.handleState = state;
  70551. //清空:
  70552. CursorDeal.remove('movePointcloud');
  70553. CursorDeal.remove('rotatePointcloud');
  70554. this.bus.dispatchEvent({
  70555. type: 'switchHandle',
  70556. state
  70557. });
  70558. this.updateCtlDisplay();
  70559. },
  70560. updateCtlDisplay() {
  70561. //仅数据集校准执行
  70562. if (!this.editing) return;
  70563. var selected = this.handleState == 'rotate' && this.selectedClouds.length > 0;
  70564. if (selected) {
  70565. this.updateFakeMarker();
  70566. } else {
  70567. this.transformControls.detach();
  70568. }
  70569. },
  70570. updateFakeMarker() {
  70571. this.transformControls.attach(this.fakeMarkerForTran);
  70572. var position = this.selectedClouds[0].translateUser;
  70573. var quaternion = this.getDatasetQuaternion(this.selectedClouds[0]);
  70574. this.fakeMarkerForTran.position.copy(position);
  70575. this.fakeMarkerForTran.quaternion.copy(quaternion);
  70576. this.fakeMarkerForTran.oldState = {
  70577. position: position.clone(),
  70578. quaternion: quaternion.clone()
  70579. };
  70580. },
  70581. save: function save() {
  70582. //保存所有数据集的位置和旋转
  70583. var callback = () => {
  70584. //保存成功后
  70585. this.originData = this.getTemp(); //this.saveTemp();
  70586. //需要修改 测量线的position。漫游点已经实时修改了
  70587. viewer.scene.measurements.forEach(e => e.transformByPointcloud());
  70588. viewer.images360.updateCube(viewer.bound);
  70589. };
  70590. var initialPointcloud = viewer.scene.pointclouds.find(e => e.dataset_id == Potree.settings.originDatasetId);
  70591. var data = viewer.scene.pointclouds.map(e => {
  70592. var pos = viewer.transform.lonlatToLocal.inverse(e.translateUser.clone());
  70593. var data = {
  70594. id: e.dataset_id,
  70595. quaternion: this.getDatasetQuaternion(e).toArray(),
  70596. orientation: this.getDatasetOrient(e).yaw,
  70597. location: [pos.x, pos.y, pos.z + initialPointcloud.datasetData.location[2]]
  70598. //transformMatrix: e.transformMatrix.elements,
  70599. };
  70600. return data;
  70601. });
  70602. //data = JSON.stringify(data)
  70603. //test: 退出后保留结果
  70604. if (!Potree.settings.isOfficial) {
  70605. callback();
  70606. }
  70607. return {
  70608. data,
  70609. callback
  70610. };
  70611. }
  70612. };
  70613. var texLoader$c = new TextureLoader();
  70614. var markerMats$2;
  70615. var markerSizeInfo$2 = {
  70616. width2d: 35
  70617. };
  70618. var color$2 = new Color('#FFF');
  70619. var faceMats;
  70620. var getFaceMat = name => {
  70621. if (!faceMats) {
  70622. //navvis材质可以搜gridTexture
  70623. var gridTex = texLoader$c.load(Potree.resourcePath + '/textures/gridmap.png');
  70624. gridTex.wrapS = gridTex.wrapT = RepeatWrapping;
  70625. //gridTex.repeat.set(0.5,0.5)//放大一些
  70626. faceMats = {
  70627. dataset: new MeshStandardMaterial({
  70628. color: 812922,
  70629. side: DoubleSide,
  70630. opacity: 0.2,
  70631. transparent: true,
  70632. depthTest: false,
  70633. wireframe: true
  70634. }),
  70635. building: new MeshStandardMaterial({
  70636. color: 812922,
  70637. metalness: 0.2,
  70638. roughness: 0.8,
  70639. side: DoubleSide,
  70640. opacity: 0.1,
  70641. transparent: true,
  70642. depthTest: true
  70643. }),
  70644. buildingSelect: new MeshStandardMaterial({
  70645. color: 36582,
  70646. metalness: 0,
  70647. roughness: 1,
  70648. side: DoubleSide,
  70649. opacity: 0.1,
  70650. transparent: true,
  70651. depthTest: true
  70652. }),
  70653. floor: new MeshStandardMaterial({
  70654. color: 11708469,
  70655. metalness: 0.1,
  70656. roughness: 1,
  70657. side: DoubleSide,
  70658. //BackSide,
  70659. opacity: 0.05,
  70660. transparent: true,
  70661. depthTest: true
  70662. }),
  70663. floorSelect: new DepthBasicMaterial({
  70664. map: gridTex,
  70665. color: 16707151,
  70666. side: DoubleSide,
  70667. //BackSide,
  70668. opacity: 1,
  70669. transparent: true,
  70670. useDepth: true,
  70671. clipDistance: 1,
  70672. occlusionDistance: 1,
  70673. /* occlusionDistance:变为backColor距离, clipDistance:opacity到达0或者1-maxClipFactor时的距离 */
  70674. maxClipFactor: 0.9,
  70675. backColor: '#efe' //backColor:"#669988" ,
  70676. }),
  70677. room: new MeshStandardMaterial({
  70678. color: "#ff44ee",
  70679. metalness: 0,
  70680. roughness: 1,
  70681. side: DoubleSide,
  70682. //BackSide,
  70683. opacity: 0.08,
  70684. transparent: true,
  70685. depthTest: false
  70686. }),
  70687. roomSelect: new DepthBasicMaterial({
  70688. map: gridTex,
  70689. color: "#ff44ee",
  70690. side: DoubleSide,
  70691. //BackSide,
  70692. opacity: 1,
  70693. transparent: true,
  70694. useDepth: true,
  70695. clipDistance: 1,
  70696. occlusionDistance: 0.5,
  70697. /* occlusionDistance:变为backColor距离, clipDistance:opacity到达0或者1-maxClipFactor时的距离 */
  70698. maxClipFactor: 0.8,
  70699. backColor: '#ff88dd' //"#cc99c2" ,
  70700. })
  70701. };
  70702. }
  70703. return faceMats[name];
  70704. };
  70705. class BuildingBox extends ctrlPolygon {
  70706. //建筑实体,包括building, floor, room
  70707. constructor(prop) {
  70708. prop.dimension = '3d';
  70709. //prop.name = Potree.config.siteModel.names[prop.buildType] +
  70710. super('siteModel_' + prop.buildType, prop);
  70711. this.midMarkers = [];
  70712. this.buildChildren = []; //子实体
  70713. this.holes = []; //在这创建的hole
  70714. this.parentHoles = []; //floor从building那得到的当层holes
  70715. this.mats = {}; //材质
  70716. this.panos = this.panos || [];
  70717. this.center; //中心点
  70718. if (this.buildType == 'floor') {
  70719. this.points = prop.points = this.buildParent.points; //完全等于建筑的点
  70720. this.buildParent.holes.forEach(hole => {
  70721. //从building获取holes
  70722. var floorHole = new BuildingBox({
  70723. buildType: 'hole',
  70724. buildParent: this,
  70725. originHole: hole,
  70726. //整栋大楼在当层的hole
  70727. ifDraw: this.ifDraw || Potree.settings.drawEntityData
  70728. });
  70729. this.parentHoles.push(floorHole);
  70730. this.add(floorHole);
  70731. floorHole.points = hole.points; //完全等于建筑的点
  70732. });
  70733. }
  70734. if (this.buildType == 'room' || this.buildType == 'hole') {
  70735. this.restrictArea = this.buildParent; //不能超出的区域
  70736. }
  70737. if (this.buildParent) this.dontDragFloorHeight = this.buildParent.dontDragFloorHeight;
  70738. if (this.buildType != 'hole') {
  70739. this.box = this.createBox(); //无论是否edit都绘制的原因:为了将在外的点移到在内,需要用mesh来获取intersect
  70740. this.add(this.box);
  70741. this.box.visible = !!this.ifDraw;
  70742. }
  70743. if (this.ifDraw) {
  70744. //只存储空间模型信息,不绘制
  70745. {
  70746. this.createPrismLines(color$2);
  70747. this.lineMesh.visible = false;
  70748. Potree.Utils.setObjectLayers(this.lineMesh, 'bothMapAndScene');
  70749. }
  70750. this.addEventListener('dragChange', e => {
  70751. //修改中点
  70752. this.updateTwoMidMarker(e.index);
  70753. });
  70754. }
  70755. this.initData(prop);
  70756. }
  70757. initData(prop) {
  70758. if (prop.ifDraw) {
  70759. super.initData(prop);
  70760. } else {
  70761. if (prop.points) {
  70762. this.points = prop.points;
  70763. }
  70764. }
  70765. }
  70766. intersectPointcloudVolume(pointcloud) {
  70767. //和pointcloud的重叠体积
  70768. return this.intersectPointcloudArea(pointcloud) * this.coverPointcloudHeight(pointcloud);
  70769. }
  70770. coverPointcloudHeight(pointcloud, getPercent) {
  70771. var bound2 = pointcloud.bound;
  70772. var {
  70773. zMin,
  70774. zMax
  70775. } = this.getRealZ();
  70776. var min = Math.min(zMin, bound2.min.z);
  70777. var max = Math.max(zMax, bound2.max.z);
  70778. var height1 = zMax - zMin;
  70779. var height2 = bound2.max.z - bound2.min.z;
  70780. var coverHeight = height1 + height2 - (max - min); //重叠高度 <=0是没重叠
  70781. if (getPercent) {
  70782. return coverHeight / height1;
  70783. }
  70784. return coverHeight;
  70785. }
  70786. intersectPointcloudArea(pointcloud, getPercent) {
  70787. //和pointcloud的重叠面积
  70788. var bound = this.getBound();
  70789. var bound2 = pointcloud.bound;
  70790. if (!bound.intersectsBox(bound2)) return 0;
  70791. var boxPoints = pointcloud.getUnrotBoundPoint(); //获取tightBound的四个点。 如果是有旋转角度的点云,这个和pointcloud.bound的四个点是不一致的,覆盖面积小于pointcloud.bound
  70792. var areaWhole = 0;
  70793. var area1 = this.getArea();
  70794. var area2 = Math.abs(math.getArea(boxPoints));
  70795. {
  70796. //计算points与点云总面积 (但是把hole也加入了面积)(并集,重叠部分只算一次)
  70797. var rings = math.getPolygonsMixedRings([this.points, boxPoints]);
  70798. rings.forEach(e => {
  70799. areaWhole += e.area;
  70800. });
  70801. }
  70802. var coverHoleArea = 0; //holes与数据集重叠的部分
  70803. var holes = this.holes.concat(this.parentHoles);
  70804. var holesArea = 0; //所有holes面积相加
  70805. var areaHoleWithPointcloud = 0; //hole和点云的面积并集
  70806. if (holes.length > 0) {
  70807. //还要再扣除holes与数据集重叠的部分。其中holes为mix轮廓
  70808. var outHoles = []; //没有重合的holes的外轮廓
  70809. /* if(holes.length>=2){//合并holes。如果能在绘制时直接合并holes就好啦,这步就转移到那去,但是要删除hole好麻烦
  70810. let holes_ = holes.map(e=>e.points)
  70811. outHoles = math.getPolygonsMixedRings(holes_, true )
  70812. outHoles.forEach(e=>{
  70813. holesArea+=e.area
  70814. })
  70815. outHoles = outHoles.map(e=>e.points)
  70816. }else{
  70817. outHoles = holes.map(e=>e.points)
  70818. outHoles.forEach(e=> holesArea += Math.abs(math.getArea(e)))
  70819. } */
  70820. holesArea = this.getHolesArea();
  70821. //holes与数据集重叠的部分
  70822. {
  70823. var polygons = outHoles.concat([boxPoints]);
  70824. var _rings = math.getPolygonsMixedRings(polygons);
  70825. _rings.forEach(e => {
  70826. areaHoleWithPointcloud += e.area;
  70827. });
  70828. coverHoleArea = holesArea + area2 - areaHoleWithPointcloud; //hole和点云的交集
  70829. }
  70830. }
  70831. var coverArea = area1 + area2 - areaWhole - coverHoleArea; //重叠面积
  70832. if (getPercent) {
  70833. return {
  70834. toEntity: coverArea / this.getArea(true),
  70835. //占entity
  70836. toPointcloud: coverArea / area2 //占点云
  70837. };
  70838. }
  70839. return coverArea;
  70840. }
  70841. addHole() {
  70842. var points = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  70843. var prop = {
  70844. buildType: 'hole',
  70845. zMin: this.zMin,
  70846. zMax: this.zMax,
  70847. points,
  70848. buildParent: this,
  70849. ifDraw: this.ifDraw || Potree.settings.drawEntityData
  70850. };
  70851. //hole的zMin zMax跟随buildParent
  70852. var hole = new BuildingBox(prop);
  70853. this.holes.push(hole);
  70854. if (this.buildType == 'building') {
  70855. //为每一层添加对应的hole
  70856. this.buildChildren.forEach(floor => {
  70857. var floorHole = new BuildingBox({
  70858. buildType: 'hole',
  70859. zMin: this.zMin,
  70860. zMax: this.zMax,
  70861. buildParent: floor,
  70862. originHole: hole,
  70863. //整栋大楼在当层的hole
  70864. ifDraw: this.ifDraw || Potree.settings.drawEntityData
  70865. });
  70866. floor.parentHoles.push(floorHole);
  70867. floor.add(floorHole);
  70868. floorHole.points = hole.points; //完全等于建筑的点
  70869. });
  70870. }
  70871. this.add(hole); //直接加在这,不加meshGroup了
  70872. this.update(); //update box mesh
  70873. return hole;
  70874. //hole不创建box,只有它的buildParent需要更新box。 但有线条和marker. hole不在buildChildren里,但有buildParent
  70875. }
  70876. removeHole(hole) {
  70877. // 这个hole不会是parentHoles里的。
  70878. hole.dispose();
  70879. if (this.buildType == 'building') {
  70880. //若是整栋大楼的hole,在每层去除它的对应hole
  70881. this.buildChildren.forEach(floor => {
  70882. var holeAtFloor = floor.parentHoles.find(e => e.originHole == this);
  70883. var index = floor.parentHoles.indexOf(holeAtFloor);
  70884. index > -1 && floor.parentHoles.splice(index, 1);
  70885. holeAtFloor.dispose();
  70886. });
  70887. }
  70888. var index = this.holes.indexOf(hole);
  70889. if (index > -1) {
  70890. this.holes.splice(index, 1);
  70891. }
  70892. this.remove(hole);
  70893. this.update();
  70894. }
  70895. createBox() {
  70896. var geometry = new Geometry();
  70897. this.mats.boxDefault = getFaceMat(this.buildType);
  70898. this.mats.boxSelected = getFaceMat(this.buildType + 'Select');
  70899. var mesh = new Mesh(geometry, this.mats.boxDefault);
  70900. mesh.name = 'buildingBox';
  70901. if (this.buildType == 'floor') {
  70902. Potree.Utils.setObjectLayers(mesh, 'mapUnvisi'); //楼层默认在地图不显示,为了不会叠加透明度
  70903. //mesh.renderOrder = 1
  70904. } else {
  70905. /* if(this.buildType == 'room'){
  70906. mesh.renderOrder = 2
  70907. } */
  70908. Potree.Utils.setObjectLayers(mesh, 'bothMapAndScene');
  70909. }
  70910. //mesh.frustumCulled = false;
  70911. return mesh;
  70912. }
  70913. addMarker() {
  70914. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  70915. if (this.buildType == 'floor') return; //楼层不需要marker
  70916. var marker = new Sprite$2({
  70917. mat: this.getMarkerMaterial('default'),
  70918. renderOrder: 3,
  70919. sizeInfo: markerSizeInfo$2,
  70920. dontFixOrient: true,
  70921. name: "building_marker"
  70922. });
  70923. Potree.Utils.setObjectLayers(marker, 'onlyMapVisi');
  70924. o.marker = marker;
  70925. super.addMarker(o);
  70926. if (!this.selected) Potree.Utils.updateVisible(marker, 'select', false);
  70927. var addClickEvent = e => {
  70928. var click = e => {
  70929. this.dispatchEvent({
  70930. type: 'clickMarker',
  70931. marker
  70932. }); //由entity发送给sitemodel统一处理
  70933. };
  70934. marker.addEventListener('click', click);
  70935. marker.addEventListener('clickSelect', e => {
  70936. this.setMarkerSelected(marker, e.state ? 'select' : 'unselect');
  70937. });
  70938. marker.removeEventListener('addHoverEvent', addClickEvent);
  70939. };
  70940. marker.addEventListener('addHoverEvent', addClickEvent); //当非isNew时才添加事件
  70941. if (!this.isNew) {
  70942. marker.dispatchEvent('addHoverEvent');
  70943. }
  70944. return marker;
  70945. }
  70946. removeMarker(index) {
  70947. super.removeMarker(index);
  70948. if (!this.isNew) {
  70949. //重新添加midMarkers
  70950. this.midMarkers.forEach(e => this.remove(e));
  70951. this.midMarkers = [];
  70952. this.addMidMarkers();
  70953. }
  70954. this.update();
  70955. if (this.points.length == 2 && this.box) {
  70956. //清除原先length>=3时候的
  70957. this.box.geometry = new Geometry();
  70958. }
  70959. }
  70960. addMidMarker(index, point) {
  70961. if (this.buildType == 'floor') return; //楼层不需要marker
  70962. var marker = new Sprite$2({
  70963. mat: this.getMarkerMaterial('midPrepare'),
  70964. sizeInfo: markerSizeInfo$2,
  70965. dontFixOrient: true,
  70966. name: "building_midMarker"
  70967. });
  70968. this.midMarkers = [...this.midMarkers.slice(0, index), marker, ...this.midMarkers.slice(index, this.midMarkers.length)];
  70969. marker.renderOrder = 3;
  70970. Potree.Utils.setObjectLayers(marker, 'onlyMapVisi');
  70971. {
  70972. // Event Listeners
  70973. var mouseover = e => {
  70974. this.setMarkerSelected(e.object, 'hover', 'single');
  70975. viewer.dispatchEvent({
  70976. type: "CursorChange",
  70977. action: "add",
  70978. name: "markerMove"
  70979. });
  70980. };
  70981. var mouseleave = e => {
  70982. this.setMarkerSelected(e.object, 'unhover', 'single');
  70983. viewer.dispatchEvent({
  70984. type: "CursorChange",
  70985. action: "remove",
  70986. name: "markerMove"
  70987. });
  70988. };
  70989. var drag = e => {
  70990. this.dispatchEvent('startDragging');
  70991. var index = this.midMarkers.indexOf(marker);
  70992. var newMarker = this.addMarker({
  70993. index: index + 1,
  70994. point: marker.position.clone()
  70995. });
  70996. this.addMidMarker(index + 1, new Vector3());
  70997. this.updateTwoMidMarker(index + 1);
  70998. this.setMarkerSelected(marker, 'unhover');
  70999. viewer.inputHandler.startDragging(newMarker, {/* dragViewport:viewer.mapViewer.viewports[0], */}); //notPressMouse代表不是通过按下鼠标来拖拽. dragViewport指定了只能在地图上拖拽
  71000. };
  71001. marker.addEventListener('drag', drag);
  71002. marker.addEventListener('mouseover', mouseover);
  71003. marker.addEventListener('mouseleave', mouseleave);
  71004. }
  71005. this.add(marker);
  71006. this.updateMarker(marker, point);
  71007. if (!this.selected) Potree.Utils.updateVisible(marker, 'select', false);
  71008. return marker;
  71009. }
  71010. addMidMarkers() {
  71011. //第一次画好所有marker后,一次性为线段增加中点marker
  71012. var length = this.points.length;
  71013. this.points.forEach((point, index) => {
  71014. var nextPoint = this.points[(index + 1) % length];
  71015. var midPoint = new Vector3().addVectors(point, nextPoint).multiplyScalar(0.5);
  71016. this.addMidMarker(index, midPoint);
  71017. });
  71018. }
  71019. updateTwoMidMarker(index) {
  71020. //更新第index个marker两边的midMarker
  71021. if (!this.midMarkers.length) return;
  71022. var length = this.points.length;
  71023. var last = this.points[(index - 1 + length) % length]; //它之前的marker位置
  71024. var next = this.points[(index + 1) % length]; //它之后的marker位置
  71025. var current = this.points[index]; //当前位置
  71026. var lastMid = new Vector3().addVectors(last, current).multiplyScalar(0.5); //上一个中点
  71027. var nextMid = new Vector3().addVectors(next, current).multiplyScalar(0.5); //下一个中点
  71028. var lastMidMarker = this.midMarkers[(index - 1 + length) % length];
  71029. var nextMidMarker = this.midMarkers[index];
  71030. this.updateMarker(lastMidMarker, lastMid);
  71031. this.updateMarker(nextMidMarker, nextMid);
  71032. }
  71033. dispose() {
  71034. //销毁geo、remove from parent
  71035. super.dispose();
  71036. this.box && this.box.geometry.dispose();
  71037. this.lineMesh && this.lineMesh.geometry.dispose();
  71038. this.holes.forEach(e => e.dispose());
  71039. this.parentHoles.forEach(e => e.dispose());
  71040. //this.buildChildren.forEach(e=>e.dispose())
  71041. this.dispatchEvent('dispose');
  71042. }
  71043. updateBox() {
  71044. if (!this.box) return;
  71045. this.box.geometry.dispose();
  71046. var shrink = this.buildType == 'room' ? 0.11 : this.buildType == 'floor' ? 0.082 : 0.2; //防止mesh重叠冲突(给一个不寻常的数字) 但离远了还是会有点闪烁
  71047. if (this.points.length >= 3) {
  71048. var holes = this.holes.concat(this.parentHoles);
  71049. var holesPoints = holes.filter(e => e.points.length > 2).map(e => e.points);
  71050. this.box.geometry = MeshDraw.getExtrudeGeo(this.points, holesPoints, {
  71051. depth: this.zMax - this.zMin - shrink,
  71052. UVGenerator: new MetricUVGenerator()
  71053. });
  71054. if (this.buildType == 'building') {
  71055. this.box.position.z = this.zMin - shrink / 2;
  71056. } else {
  71057. this.box.position.z = this.zMin + shrink / 2;
  71058. }
  71059. }
  71060. }
  71061. update() {
  71062. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  71063. super.update(this.buildType != 'floor' && options.ifUpdateMarkers);
  71064. var length = this.points.length;
  71065. {
  71066. //确保一下一样
  71067. if (this.originHole) {
  71068. this.points = this.originHole.points; //完全等于building的hole
  71069. }
  71070. if (this.buildType == 'hole') {
  71071. this.zMin = this.buildParent.zMin;
  71072. this.zMax = this.buildParent.zMax;
  71073. }
  71074. }
  71075. if (!options.dontUpdateBox) {
  71076. var boxOwner;
  71077. if (this.buildType == 'hole') {
  71078. if (this.buildParent.buildType == 'building') {
  71079. //若是整栋大楼的hole,在每层都要更新下它的对应hole
  71080. this.buildParent.buildChildren.forEach(floor => {
  71081. var holeAtFloor = floor.parentHoles.find(e => e.originHole == this);
  71082. holeAtFloor && holeAtFloor.update(); //刚开始创建时还没创建对应的 holeAtFloor会为null
  71083. });
  71084. }
  71085. boxOwner = this.buildParent;
  71086. } else {
  71087. boxOwner = this;
  71088. }
  71089. boxOwner.updateBox();
  71090. }
  71091. this.updatePrismLines(); //update lines
  71092. if (!options.dontUpdateChildren) {
  71093. if (this.buildType == 'building') {
  71094. this.buildChildren.forEach(floor => {
  71095. floor.points = this.points;
  71096. floor.update();
  71097. });
  71098. }
  71099. {
  71100. var holes = this.holes.concat(this.parentHoles);
  71101. holes.forEach(hole => {
  71102. hole.update({
  71103. dontUpdateBox: true
  71104. }); //父级更新了box,hole就不需要更新box了
  71105. });
  71106. }
  71107. }
  71108. }
  71109. getHolesArea() {
  71110. var holes = this.holes.concat(this.parentHoles);
  71111. var outHoles,
  71112. holesArea = 0;
  71113. if (holes.length >= 2) {
  71114. //合并holes。如果能在绘制时直接合并holes就好啦,这步就转移到那去,但是要删除hole好麻烦
  71115. var holes_ = holes.map(e => e.points);
  71116. outHoles = math.getPolygonsMixedRings(holes_, true);
  71117. outHoles.forEach(e => {
  71118. holesArea += e.area;
  71119. });
  71120. outHoles = outHoles.map(e => e.points);
  71121. } else {
  71122. outHoles = holes.map(e => e.points);
  71123. outHoles.forEach(e => holesArea += Math.abs(math.getArea(e)));
  71124. }
  71125. return holesArea;
  71126. }
  71127. getArea(ifRidOfHoles) {
  71128. //面积
  71129. //不排除hole
  71130. return Math.abs(math.getArea(this.points)) - (ifRidOfHoles ? this.getHolesArea() : 0);
  71131. }
  71132. getVolume(ifRidOfHoles) {
  71133. //体积
  71134. var {
  71135. zMin,
  71136. zMax
  71137. } = this.getRealZ();
  71138. var height = zMax - zMin;
  71139. if (isNaN(height)) height = 0;
  71140. return this.getArea(ifRidOfHoles) * height;
  71141. }
  71142. getRealZ() {
  71143. //求真实高度时用到的
  71144. var zMin, zMax;
  71145. if (this.buildType == 'building') {
  71146. //因为building只有一个地基平面 所以自身的zMin == 自身的zMax 所以要算
  71147. var top = this.buildChildren[this.buildChildren.length - 1];
  71148. var btm = this.buildChildren[0];
  71149. zMin = btm ? btm.zMin : 0; //建好的建筑不加楼的话是0。
  71150. zMax = top ? top.zMax : 0;
  71151. } else if (this.buildType == 'hole') {
  71152. return this.buildParent.getRealZ();
  71153. } else {
  71154. zMin = this.zMin, zMax = this.zMax;
  71155. }
  71156. return {
  71157. zMin,
  71158. zMax
  71159. };
  71160. }
  71161. //架站式多楼层SG-t-ihjV2cDVFlE 有初始的z, 但是总高度范围小于数据集。 不允许修改高度。
  71162. /* getDrawZ(){ //画线和box时用到的z
  71163. let zMin , zMax
  71164. if(this.buildType == 'hole'){
  71165. if(this.buildParent.buildType == 'building' && atFloor){
  71166. zMin = atFloor.zMin, zMax = atFloor.zMax
  71167. }else{
  71168. zMin = this.buildParent.zMin, zMax = this.buildParent.zMax
  71169. }
  71170. }else{
  71171. zMin = this.zMin, zMax = this.zMax
  71172. }
  71173. return {zMin, zMax}
  71174. } */
  71175. getBound() {
  71176. var bound = new Box3();
  71177. var {
  71178. zMin,
  71179. zMax
  71180. } = this.getRealZ();
  71181. var points = this.buildType == 'floor' ? this.buildParent.points : this.points;
  71182. points.forEach(p => {
  71183. bound.expandByPoint(p.clone().setZ(zMin));
  71184. bound.expandByPoint(p.clone().setZ(zMax));
  71185. });
  71186. return bound;
  71187. }
  71188. getMarkerMaterial(type) {
  71189. if (!markerMats$2) {
  71190. markerMats$2 = {
  71191. default: new MeshBasicMaterial({
  71192. transparent: !0,
  71193. color: color$2,
  71194. opacity: 0.8,
  71195. map: texLoader$c.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  71196. depthTest: false
  71197. }),
  71198. midPrepare: new MeshBasicMaterial({
  71199. //线中心的半透明点
  71200. transparent: !0,
  71201. color: color$2,
  71202. opacity: 0.4,
  71203. map: texLoader$c.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  71204. depthTest: false
  71205. }),
  71206. hover: new MeshBasicMaterial({
  71207. transparent: !0,
  71208. color: color$2,
  71209. opacity: 1,
  71210. map: texLoader$c.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  71211. depthTest: false
  71212. }),
  71213. select: new MeshBasicMaterial({
  71214. transparent: !0,
  71215. color: new Color('#00C8AF'),
  71216. opacity: 1,
  71217. map: texLoader$c.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  71218. depthTest: false
  71219. })
  71220. };
  71221. }
  71222. return markerMats$2[type];
  71223. }
  71224. setMarkerSelected(marker, state, hoverObject) {
  71225. //console.warn(marker.id , state, hoverObject)
  71226. if (state == 'select') {
  71227. marker.selected = true;
  71228. marker.material = this.getMarkerMaterial('select');
  71229. } else if (state == 'unselect') {
  71230. marker.selected = false;
  71231. marker.material = this.getMarkerMaterial('default');
  71232. } else {
  71233. if (marker.selected) return; //选中时不允许修改为除了'unselect'以外的状态
  71234. if (state == 'hover') {
  71235. marker.material = this.getMarkerMaterial('hover');
  71236. } else if (state == 'unhover') {
  71237. if (marker.name.includes('mid')) {
  71238. marker.material = this.getMarkerMaterial('midPrepare');
  71239. } else {
  71240. marker.material = this.getMarkerMaterial('default');
  71241. }
  71242. }
  71243. }
  71244. }
  71245. select() {
  71246. //最多再显示一层子级的线,如building不会显示room中的hole的线
  71247. //box是一直显示的,但会切换材质
  71248. /*
  71249. 选中 box 线
  71250. building 自己(底盘)选中 自己, floor不带hole
  71251. floor 自己选中 自己, room不带hole
  71252. room 自己选中 自己
  71253. */ //注:自己的就代表定包括hole,如果有parentHoles的也(building上的hole的对应)
  71254. //console.log('select '+this.name, this.selected)
  71255. if (this.selected) return;
  71256. if (this.box) {
  71257. this.box.material = this.mats.boxSelected;
  71258. }
  71259. if (this.buildType == 'building' || this.buildType == 'floor') {
  71260. this.buildChildren.forEach(e => {
  71261. e.lineMesh.visible = true;
  71262. });
  71263. if (this.buildType == 'floor') {
  71264. Potree.Utils.setObjectLayers(this.box, 'bothMapAndScene');
  71265. Potree.Utils.setObjectLayers(this.buildParent.box, 'mapUnvisi'); //当选中floor或room时,building在地图不可见
  71266. }
  71267. } else if (this.buildType == 'room') {
  71268. Potree.Utils.setObjectLayers(this.buildParent.box, 'bothMapAndScene');
  71269. Potree.Utils.setObjectLayers(this.buildParent.buildParent.box, 'mapUnvisi');
  71270. }
  71271. this.lineMesh.visible = true;
  71272. this.markers && this.markers.forEach(e => Potree.Utils.updateVisible(e, 'select', true));
  71273. this.midMarkers && this.midMarkers.forEach(e => Potree.Utils.updateVisible(e, 'select', true));
  71274. var holes = this.holes.concat(this.parentHoles);
  71275. holes.forEach(e => e.select());
  71276. this.selected = true;
  71277. this.dispatchEvent({
  71278. type: 'select'
  71279. });
  71280. }
  71281. unselect() {
  71282. if (!this.selected) return;
  71283. //console.log('unselect '+this.name )
  71284. if (this.box) {
  71285. this.box.material = this.mats.boxDefault;
  71286. }
  71287. if (this.buildType == 'building' || this.buildType == 'floor') {
  71288. this.buildChildren.forEach(e => {
  71289. //(这里要保证选中前要先取消选中,否则如选中房间后取消了楼层,房间线就隐藏了)
  71290. e.lineMesh.visible = false;
  71291. });
  71292. if (this.buildType == 'floor') {
  71293. Potree.Utils.setObjectLayers(this.box, 'mapUnvisi');
  71294. Potree.Utils.setObjectLayers(this.buildParent.box, 'bothMapAndScene');
  71295. }
  71296. } else if (this.buildType == 'room') {
  71297. Potree.Utils.setObjectLayers(this.buildParent.box, 'mapUnvisi');
  71298. Potree.Utils.setObjectLayers(this.buildParent.buildParent.box, 'bothMapAndScene');
  71299. }
  71300. this.lineMesh.visible = false;
  71301. this.markers && this.markers.forEach(e => Potree.Utils.updateVisible(e, 'select', false));
  71302. this.midMarkers && this.midMarkers.forEach(e => Potree.Utils.updateVisible(e, 'select', false));
  71303. var holes = this.holes.concat(this.parentHoles);
  71304. holes.forEach(e => e.unselect());
  71305. this.selected = false;
  71306. this.dispatchEvent({
  71307. type: 'unselect'
  71308. });
  71309. }
  71310. ifContainsPoint(position) {
  71311. //看它所定义的空间是否包含某个坐标(要排除hole)
  71312. var {
  71313. zMin,
  71314. zMax
  71315. } = this.getRealZ();
  71316. if (position.z < zMin || position.z > zMax) return;
  71317. var holes = this.holes.concat(this.parentHoles);
  71318. var holesPoints = holes.filter(e => e != this && e.points.length > 2).map(e => e.points);
  71319. var inShape = math.isPointInArea(this.points, holesPoints, position);
  71320. return !!inShape;
  71321. }
  71322. }
  71323. class MetricUVGenerator {
  71324. constructor() {
  71325. this.a = new Vector3(), this.b = new Vector3(), this.c = new Vector3(), this.d = new Vector3();
  71326. }
  71327. generateTopUV(t, e, n, r, o) {
  71328. return [new Vector2(e[3 * n], e[3 * n + 1]), new Vector2(e[3 * r], e[3 * r + 1]), new Vector2(e[3 * o], e[3 * o + 1])];
  71329. }
  71330. generateSideWallUV(t, e, n, r, o, a) {
  71331. var s = e;
  71332. this.a.set(s[3 * n], s[3 * n + 1], s[3 * n + 2]), this.b.set(s[3 * r], s[3 * r + 1], s[3 * r + 2]), this.c.set(s[3 * o], s[3 * o + 1], s[3 * o + 2]), this.d.set(s[3 * a], s[3 * a + 1], s[3 * a + 2]);
  71333. var c = this.a.x !== this.b.x,
  71334. l = c ? this.b : this.d,
  71335. u = this.a.distanceTo(l),
  71336. d = l.distanceTo(this.c);
  71337. return [new Vector2(this.a.x, 0), c ? new Vector2(this.a.x + u, 0) : new Vector2(this.a.x, d), new Vector2(this.a.x + u, d), c ? new Vector2(this.a.x, d) : new Vector2(this.a.x + u, 0)];
  71338. }
  71339. }
  71340. var minFloorHeight = 0.5;
  71341. var ifDrawDatasetBound = true; //显示一下数据集的tightBound线框
  71342. var minMarkers = 3;
  71343. var Limit = {
  71344. zMin: -config$1.map.cameraHeight,
  71345. zMax: config$1.map.cameraHeight
  71346. }; //不能超过camera的高度,为了对称所以也限制了最低
  71347. var SiteModel = {
  71348. bus: new EventDispatcher(),
  71349. entities: [],
  71350. //所有实体
  71351. buildings: [],
  71352. //所有建筑父集
  71353. meshGroup: new Object3D(),
  71354. inEntity: null,
  71355. lastPos: new Vector3(Infinity, Infinity, Infinity),
  71356. init: function init() {
  71357. viewer.scene.scene.add(this.meshGroup);
  71358. this.meshGroup.name = 'siteModel';
  71359. this.SplitScreen = SplitScreen4Views;
  71360. /* if(Potree.settings.editType == 'pano'){
  71361. return
  71362. } */
  71363. if (Potree.settings.editType != 'pano') {
  71364. this.createHeightPull();
  71365. this.history = new History({
  71366. applyData: data => {
  71367. if (data.entity.parent && data.entity.selected) {
  71368. data = Potree.Common.CloneObject(data); //避免使用后更改数据又被使用
  71369. data.entity.reDraw();
  71370. data.entity.initData(data);
  71371. data.isNew || data.entity.addMidMarkers();
  71372. data.entity.isNew = data.isNew;
  71373. data.entity.dispatchEvent('changeByHistory');
  71374. return true;
  71375. }
  71376. },
  71377. getData: entity => {
  71378. //if(entity.isNew)return
  71379. return {
  71380. entity,
  71381. points: entity.points.map(e => e.clone()),
  71382. ifDraw: true,
  71383. isNew: entity.isNew
  71384. };
  71385. }
  71386. });
  71387. {
  71388. var pressDelete = e => {
  71389. if (e.keyCode == KeyCodes.BACKSPACE || e.keyCode == KeyCodes.DELETE) {
  71390. if (this.selectedMarker) {
  71391. var entity = this.selectedMarker.parent;
  71392. var index = entity.markers.indexOf(this.selectedMarker);
  71393. entity.removeMarker(index);
  71394. if (entity.points.length < 2) {
  71395. //删到只剩一个点时重新画(如果是hole的点,直接删除hole吧?)
  71396. this.startInsertion('resume', entity);
  71397. }
  71398. }
  71399. }
  71400. };
  71401. viewer.inputHandler.addEventListener('keydown', pressDelete);
  71402. }
  71403. {
  71404. var updated = false;
  71405. this.bus.addEventListener('updated', () => {
  71406. Common$1.intervalTool.isWaiting('siteModelUpdated', () => {
  71407. this.changedCallback();
  71408. }, 500);
  71409. });
  71410. }
  71411. }
  71412. if (Potree.settings.isTest && ifDrawDatasetBound) {
  71413. viewer.addEventListener('allLoaded', () => {
  71414. viewer.scene.pointclouds.forEach(pointcloud => {
  71415. var boxPoints = pointcloud.getUnrotBoundPoint();
  71416. var boundingBox = new BuildingBox({
  71417. name: '数据集tightBound_' + pointcloud.dataset_id,
  71418. points: boxPoints,
  71419. buildType: 'dataset',
  71420. zMax: pointcloud.bound.max.z,
  71421. zMin: pointcloud.bound.min.z,
  71422. ifDraw: true
  71423. });
  71424. this.meshGroup.add(boundingBox);
  71425. //boundingBox.markers.forEach(e=>e.visible = false)
  71426. });
  71427. });
  71428. }
  71429. if (Potree.settings.isOfficial) {
  71430. viewer.addEventListener('camera_changed', e => {
  71431. if (e.changeInfo && e.changeInfo.positionChanged) {
  71432. this.updateEntityAt();
  71433. }
  71434. });
  71435. }
  71436. },
  71437. changedCallback() {
  71438. this.findPanos();
  71439. this.findEntityForDataset();
  71440. this.updateEntityAt(true); //更新所在建筑,更新marker显示
  71441. //console.log('changedCallback')
  71442. },
  71443. updateEntityAt(force) {
  71444. var {
  71445. measure
  71446. } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  71447. //if(!this.entities.length || this.editing) return //编辑时也要根据位置显示不同楼层的漫游点与cad
  71448. var fun = () => {
  71449. //延时update,防止卡顿
  71450. var currPos = viewer.mainViewport.view.position;
  71451. if (this.pauseUpdateEntity) return; // console.error('pauseUpdateEntity')
  71452. //if(force || !currPos.equals(this.lastPos) ){
  71453. //console.log('currPos ', currPos.toArray())
  71454. this.lastPos.copy(currPos);
  71455. var entity;
  71456. if (measure) {
  71457. //因为测量线的点可能在多个房间,所以干脆直接找在哪个楼层
  71458. var list = [];
  71459. measure.points.forEach(e => {
  71460. var entity = this.pointInWhichEntity(e, 'floor'); //每个点都找到其所在楼层
  71461. var item = list.find(e => e.entity == entity);
  71462. if (item) {
  71463. item.count++;
  71464. } else {
  71465. list.push({
  71466. entity,
  71467. count: 1
  71468. });
  71469. }
  71470. });
  71471. list.sort((a, b) => {
  71472. return b.count - a.count;
  71473. }); //找出出现次数最多的楼层
  71474. if (list[0]) {
  71475. entity = list[0].entity;
  71476. }
  71477. } else {
  71478. var searchPos = Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : currPos;
  71479. entity = this.pointInWhichEntity(searchPos, 'room');
  71480. }
  71481. if (force || this.inEntity != entity) {
  71482. var oldEntity = this.inEntity;
  71483. this.inEntity = entity;
  71484. //console.log('buildingChange', entity)
  71485. this.bus.dispatchEvent({
  71486. type: 'buildingChange',
  71487. entity
  71488. });
  71489. //this.updatePanosVisible(oldEntity, this.inEntity)
  71490. var lastFloor = this.currentFloor; //oldEntity ? oldEntity.buildType == 'floor' ? oldEntity : oldEntity.buildType == 'room' ? oldEntity.buildParent : null : null; //基本只会是floor或room
  71491. var currentFloor = entity ? entity.buildType == 'floor' ? entity : entity.buildType == 'room' ? entity.buildParent : null : null; //基本只会是floor或room
  71492. if (force || currentFloor != lastFloor) {
  71493. //console.log('改变了floor',lastFloor,currentFloor)
  71494. this.currentFloor = currentFloor;
  71495. this.bus.dispatchEvent({
  71496. type: 'FloorChange',
  71497. currentFloor
  71498. });
  71499. }
  71500. }
  71501. force = false;
  71502. //}
  71503. };
  71504. if (force) fun();else Common$1.intervalTool.isWaiting('sitemodelCameraInterval', fun, 500);
  71505. },
  71506. enter: function enter() {
  71507. Potree.Log('sitemodel enter');
  71508. this.clear(); //确保全部清空
  71509. this.editing = true;
  71510. //this.updatePanosVisible(null, null, true)//show all
  71511. viewer.updateFpVisiDatasets();
  71512. var mapViewport = viewer.mapViewer.viewports[0];
  71513. this.SplitScreen.split({
  71514. siteModel: true
  71515. });
  71516. viewer.viewports.forEach(e => {
  71517. if (e.name != 'mapViewport') {
  71518. e.layersAdd('mapUnvisi');
  71519. }
  71520. if (e.name == 'right' || e.name == 'back') {
  71521. e.layersAdd('sideVisi');
  71522. }
  71523. });
  71524. viewer.images360.panos.forEach(pano => {
  71525. Potree.Utils.setObjectLayers(pano.marker, 'mapUnvisi');
  71526. //Potree.Utils.setObjectLayers(pano.label2, 'bothMapAndScene')
  71527. });
  71528. mapViewport.layersAdd('onlyMapVisi'); //只有mapViewport能看到marker
  71529. },
  71530. leave: function leave() {
  71531. Potree.Log('sitemodel leave');
  71532. var mapViewport = viewer.mapViewer.viewports[0];
  71533. this.SplitScreen.recover();
  71534. viewer.viewports.forEach(e => {
  71535. if (e.name != 'mapViewport') {
  71536. e.layersRemove('mapUnvisi');
  71537. }
  71538. if (e.name == 'right' || e.name == 'back') {
  71539. e.layersRemove('sideVisi');
  71540. }
  71541. });
  71542. viewer.images360.panos.forEach(pano => {
  71543. Potree.Utils.setObjectLayers(pano.marker, 'sceneObjects');
  71544. //Potree.Utils.setObjectLayers(pano.label2, 'bothMapAndScene')
  71545. });
  71546. mapViewport.layersRemove('onlyMapVisi');
  71547. this.clear();
  71548. this.editing = false;
  71549. this.updateEntityAt(true);
  71550. viewer.updateFpVisiDatasets();
  71551. },
  71552. addFloor: function addFloor(parent, dirType, sid, name) {
  71553. //dirType:'top'|'bottom'在上方建还是下方。如果建筑中没有楼层,默认在基底建一个
  71554. var buildType = 'floor';
  71555. var zMin, zMax;
  71556. if (parent.buildChildren.length == 0) {
  71557. zMin = parent.zMin;
  71558. zMax = zMin + Potree.config.siteModel.floorHeightDefault;
  71559. } else {
  71560. if (dirType == 'bottom') {
  71561. //var btm = Common.find(parent.buildChildren,null,[e=>e.zMin])
  71562. var btm = parent.buildChildren[0];
  71563. zMax = btm.zMin;
  71564. zMin = zMax - Potree.config.siteModel.floorHeightDefault;
  71565. } else {
  71566. //var top = Common.find(parent.buildChildren,null,[e=>e.zMax])
  71567. var top = parent.buildChildren[parent.buildChildren.length - 1];
  71568. zMin = top.zMax;
  71569. zMax = zMin + Potree.config.siteModel.floorHeightDefault;
  71570. }
  71571. }
  71572. var prop = {
  71573. buildType,
  71574. //name : Potree.config.siteModel.names[buildType],
  71575. zMin,
  71576. zMax,
  71577. buildParent: parent,
  71578. sid,
  71579. name,
  71580. ifDraw: true
  71581. };
  71582. var floor = new BuildingBox(prop);
  71583. /* parent.buildChildren.push(floor)
  71584. this.meshGroup.add(floor);
  71585. this.entities.push(floor) */
  71586. floor.update();
  71587. this.addEntity(floor, parent);
  71588. //this.selectEntity(floor)
  71589. if (this.selected == parent) {
  71590. //重新选择下,为了显示新楼层线框
  71591. parent.unselect();
  71592. parent.select();
  71593. }
  71594. this.bus.dispatchEvent('updated');
  71595. return floor;
  71596. },
  71597. startInsertion: function startInsertion(buildType, parent, sid, name, callback, cancelFun) {
  71598. var _this = this;
  71599. var zMin, zMax, entity, resume;
  71600. var mapViewport = viewer.mapViewer.viewports[0];
  71601. if (buildType == 'resume') {
  71602. //继续画(使用最后一个点或者新加的点)
  71603. resume = true;
  71604. entity = parent;
  71605. buildType = parent.buildType;
  71606. //删除原先所有的点,因为它们已经添加了事件,会很麻烦:
  71607. entity.reDraw(0);
  71608. entity.isNew = true; //当作新的来画
  71609. }
  71610. if (!resume) {
  71611. if (buildType == 'hole' || buildType == 'room') {
  71612. zMin = parent.zMin;
  71613. zMax = parent.zMax;
  71614. } else if (buildType == 'building') {
  71615. parent = null;
  71616. zMin = viewer.bound.boundingBox.min.z;
  71617. zMax = viewer.bound.boundingBox.min.z;
  71618. }
  71619. if (buildType == 'hole') {
  71620. entity = parent.addHole();
  71621. entity.isNew = true;
  71622. this.selectEntity(parent);
  71623. entity.select();
  71624. console.log('挖洞 ', entity.uuid);
  71625. } else {
  71626. var prop = {
  71627. buildType,
  71628. //name : Potree.config.siteModel.names[buildType],//'building',
  71629. zMin,
  71630. zMax,
  71631. buildParent: parent,
  71632. sid,
  71633. name,
  71634. ifDraw: true
  71635. };
  71636. entity = new BuildingBox(prop);
  71637. entity.isNew = true;
  71638. this.selectEntity(entity);
  71639. }
  71640. this.addEntity(entity, parent);
  71641. }
  71642. var timer;
  71643. var endDragFun = e => {
  71644. if (e.button == MOUSE.LEFT) {
  71645. this.history.beforeChange(entity);
  71646. var marker = entity.addMarker({
  71647. point: entity.points[entity.points.length - 1].clone()
  71648. });
  71649. this.history.afterChange(entity);
  71650. //entity.editStateChange(true) //重新激活reticule状态
  71651. entity.continueDrag(marker, e);
  71652. } else if (e.button === MOUSE.RIGHT) {
  71653. if (e.pressDistance < Potree.config.clickMaxDragDis) end(e); //非拖拽的话
  71654. else entity.continueDrag(null, e /* .drag.object */);
  71655. }
  71656. };
  71657. var finish = () => {
  71658. //结束绘画
  71659. viewer.removeEventListener('cancel_insertions', Exit);
  71660. entity.removeEventListener('unselect', Exit);
  71661. clearTimeout(timer);
  71662. entity.editStateChange(false);
  71663. //pressExit && viewer.inputHandler.removeEventListener('keydown', pressExit);
  71664. callback && callback(entity);
  71665. viewer.dispatchEvent('endBuildEntity');
  71666. };
  71667. var end = function end() {
  71668. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  71669. //尝试结束
  71670. /* 退出的三种形式:
  71671. 1 普通:如果大于三个marker,结束且保留;否则重新画。()
  71672. 2 删除:直接结束且删除。(remove)
  71673. 3 结束:如果大于三个marker,结束且保留;否则结束且删除。 (finish)
  71674. 4 保留:无论几个marker,都保留着,结束。(remain)
  71675. */
  71676. if (e.remove) {
  71677. finish();
  71678. return _this.removeEntity(entity);
  71679. }
  71680. if (!e.remain && !e.finish && !e.remove && entity.markers.length <= minMarkers) {
  71681. //右键 当个数不够时取消
  71682. //重新开始画
  71683. entity.reDraw(1);
  71684. Potree.Utils.updateVisible(entity.markers[0], 'unMove', false);
  71685. var f = () => {
  71686. Potree.Utils.updateVisible(entity.markers[0], 'unMove', true);
  71687. entity.removeEventListener('dragChange', f);
  71688. };
  71689. entity.addEventListener('dragChange', f);
  71690. //console.log('waitcontinue')
  71691. entity.continueDrag(entity.markers[0], e);
  71692. return;
  71693. }
  71694. finish();
  71695. if (e.remain || !e.remove && entity.markers.length > 3) {
  71696. //保留
  71697. entity.removeMarker(entity.points.length - 1);
  71698. entity.markers.forEach(marker => {
  71699. marker.dispatchEvent('addHoverEvent');
  71700. });
  71701. if (buildType == 'room') {
  71702. _this.fitPullBox();
  71703. }
  71704. entity.isNew = false;
  71705. entity.addMidMarkers();
  71706. var boundingBox = entity.getBound();
  71707. var center = boundingBox.getCenter(new Vector3());
  71708. viewer.controls.setTarget(center, 2);
  71709. } else {
  71710. _this.removeEntity(entity); //直接删除没画好的,比较简单。这样就不用担心旧的continueDrag仍旧触发了
  71711. }
  71712. return entity;
  71713. };
  71714. var Exit = e => {
  71715. //强制结束
  71716. entity.removeEventListener('unselect', Exit);
  71717. if (viewer.inputHandler.drag) {
  71718. //还未触发drop的话
  71719. viewer.inputHandler.drag.object.dispatchEvent({
  71720. type: 'drop',
  71721. drag: viewer.inputHandler.drag,
  71722. viewer: viewer,
  71723. pressDistance: 0,
  71724. button: MOUSE.RIGHT
  71725. });
  71726. viewer.inputHandler.drag.object.isDragging = false;
  71727. } else {
  71728. end({
  71729. remain: true
  71730. });
  71731. }
  71732. viewer.inputHandler.drag = null;
  71733. };
  71734. viewer.dispatchEvent('cancel_insertions'); //取消之前的
  71735. viewer.addEventListener('cancel_insertions', Exit);
  71736. setTimeout(() => {
  71737. entity.isNew && entity.addEventListener('unselect', Exit);
  71738. }, 1); //因为刚创建会unselect一下所以延迟
  71739. var marker = entity.addMarker({
  71740. point: new Vector3(0, 0, 0)
  71741. });
  71742. Potree.Utils.updateVisible(marker, 'unMove', false); //这时候的位置是假的(0,0,0)所以先不可见
  71743. var f = () => {
  71744. Potree.Utils.updateVisible(marker, 'unMove', true);
  71745. entity.removeEventListener('dragChange', f);
  71746. };
  71747. entity.addEventListener('dragChange', f);
  71748. marker.isDragging = true;
  71749. viewer.inputHandler.startDragging(marker, {
  71750. dragViewport: mapViewport,
  71751. endDragFun,
  71752. notPressMouse: true
  71753. }); //notPressMouse代表不是通过按下鼠标来拖拽. dragViewport指定了只能在地图上拖拽
  71754. viewer.dispatchEvent('startBuildEntity');
  71755. var changeByHistory = e => {
  71756. if (!entity.isNew) return;
  71757. var marker = entity.markers[entity.points.length - 1];
  71758. viewer.inputHandler.startDragging(marker, {
  71759. dragViewport: mapViewport,
  71760. endDragFun,
  71761. notPressMouse: true
  71762. });
  71763. var I = viewer.inputHandler.intersect && (viewer.inputHandler.intersect.orthoIntersect || viewer.inputHandler.intersect.location);
  71764. if (I) {
  71765. entity.dragChange(I.clone(), entity.points.length - 1); //使最后一个点在鼠标处
  71766. }
  71767. };
  71768. entity.addEventListener('changeByHistory', changeByHistory);
  71769. return entity;
  71770. },
  71771. getPreDealData(points, zMin, zMax, initial, buildType, parent) {
  71772. /* if( buildType == 'building' ){
  71773. zMax = zMin //强制变得一样,作为基底。如果有必要,保存时再算真实的zMax。目前zMin没有保存所以数据是错的,会直接根据floor计算
  71774. } */
  71775. var bound = viewer.bound.boundingBox;
  71776. if (buildType == 'building' && initial) {
  71777. //初始数据错的,要自己建(只有一个building和floor) 原posIsLonlat
  71778. console.log('空间模型未编辑过, 初始化了一个');
  71779. points = [new Vector3(bound.min.x, bound.min.y, 0), new Vector3(bound.max.x, bound.min.y, 0), new Vector3(bound.max.x, bound.max.y, 0), new Vector3(bound.min.x, bound.max.y, 0)];
  71780. zMin = bound.min.z;
  71781. zMax = bound.max.z;
  71782. /* points = points.map(e=>{
  71783. return viewer.transform.lonlatToLocal.forward(e)
  71784. }) */
  71785. } else {
  71786. //相对于初始数据集的模型内坐标
  71787. points = points.map(e => this.transform(e, 'fromDataset'));
  71788. if (buildType == 'floor' && initial) {
  71789. zMin = bound.min.z;
  71790. zMax = bound.max.z;
  71791. }
  71792. }
  71793. return {
  71794. points,
  71795. zMax,
  71796. zMin
  71797. };
  71798. },
  71799. resetFromData: function resetFromData(entity) {
  71800. var _this2 = this;
  71801. var points = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  71802. var holes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  71803. var zMin = arguments.length > 3 ? arguments[3] : undefined;
  71804. var zMax = arguments.length > 4 ? arguments[4] : undefined;
  71805. return function (points, zMin, zMax) {
  71806. var {
  71807. points,
  71808. zMax,
  71809. zMin
  71810. } = _this2.getPreDealData(points, zMin, zMax, _this2.autoBuild, entity.buildType, entity.buildParent);
  71811. if (entity.buildType != 'floor') entity.points = points;
  71812. if (entity.buildType == 'room') {
  71813. entity.zMin = zMin;
  71814. entity.zMax = zMax;
  71815. } else if (entity.buildType == 'floor') {
  71816. //改楼高
  71817. var height = zMax - zMin;
  71818. var zMax2 = entity.zMin + height;
  71819. SiteModel.changeZ(entity, 'zMax', zMax2);
  71820. }
  71821. {
  71822. //删除旧的holes重新添加
  71823. var holesOld = entity.holes;
  71824. holesOld.forEach(e => {
  71825. entity.removeHole(e);
  71826. });
  71827. holes.forEach(points => {
  71828. var ps = points.map(e => _this2.transform(e, 'fromDataset'));
  71829. var hole = entity.addHole(ps);
  71830. hole.addMidMarkers();
  71831. });
  71832. }
  71833. entity.update();
  71834. return entity;
  71835. }(points, zMin, zMax);
  71836. },
  71837. createFromData: function createFromData(buildType, parent, sid, name) {
  71838. var _this3 = this;
  71839. var points = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
  71840. var holes = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : [];
  71841. var zMin = arguments.length > 6 ? arguments[6] : undefined;
  71842. var zMax = arguments.length > 7 ? arguments[7] : undefined;
  71843. var initial = arguments.length > 8 ? arguments[8] : undefined;
  71844. var panos_ = arguments.length > 9 ? arguments[9] : undefined;
  71845. var flagPano = arguments.length > 10 ? arguments[10] : undefined;
  71846. return function (points, zMin, zMax) {
  71847. if (buildType != 'building' && buildType != 'floor' && buildType != 'room') return;
  71848. var {
  71849. points,
  71850. zMax,
  71851. zMin
  71852. } = _this3.getPreDealData(points, zMin, zMax, initial, buildType, parent);
  71853. var panos = [];
  71854. {
  71855. if (panos_) {
  71856. panos_.forEach(sid => {
  71857. var pano = viewer.images360.getPano(sid, 'sid');
  71858. if (pano) panos.push(pano);
  71859. });
  71860. }
  71861. flagPano = flagPano != void 0 ? viewer.images360.getPano(flagPano, 'sid') : null; //最中心的pano 或者 最靠近该实体的pano(当panos为空时)
  71862. if (!_this3.editing && buildType == 'floor' && !flagPano) {
  71863. //没有的话可能是自动添加的floor,直接用parent的吧
  71864. panos = parent.panos;
  71865. flagPano = parent.flagPano;
  71866. }
  71867. }
  71868. var prop = {
  71869. buildType,
  71870. points,
  71871. name,
  71872. sid,
  71873. zMin,
  71874. zMax,
  71875. buildParent: parent,
  71876. ifDraw: _this3.editing || Potree.settings.drawEntityData,
  71877. panos,
  71878. flagPano,
  71879. autoBuild: initial
  71880. };
  71881. var entity = new BuildingBox(prop);
  71882. SiteModel.addEntity(entity, parent);
  71883. if (_this3.editing) {
  71884. if (buildType == 'building' || buildType == 'room') {
  71885. entity.addMidMarkers();
  71886. }
  71887. }
  71888. holes.forEach(points => {
  71889. var ps = points.map(e => _this3.transform(e, 'fromDataset'));
  71890. var hole = entity.addHole(ps);
  71891. _this3.editing && hole.addMidMarkers();
  71892. });
  71893. /* if(buildType == 'floor'){
  71894. this.updateBuildingZ(parent)
  71895. } */
  71896. return entity;
  71897. }(points, zMin, zMax);
  71898. },
  71899. transform: function transform(pos, type) {
  71900. if (Potree.settings.editType == 'pano') {
  71901. // 模型不经转换
  71902. return new Vector3().copy(pos).setZ(0);
  71903. }
  71904. if (type == 'toDataset') {
  71905. var point = Potree.Utils.datasetPosTransform({
  71906. toDataset: true,
  71907. position: pos.clone(),
  71908. datasetId: Potree.settings.originDatasetId
  71909. });
  71910. return new Vector2().copy(point);
  71911. } else {
  71912. var position = new Vector3().copy(pos).setZ(0);
  71913. return Potree.Utils.datasetPosTransform({
  71914. fromDataset: true,
  71915. position,
  71916. datasetId: Potree.settings.originDatasetId
  71917. });
  71918. }
  71919. },
  71920. addEntity: function addEntity(entity, parent) {
  71921. if (entity.buildType != 'hole') {
  71922. this.meshGroup.add(entity);
  71923. this.entities.push(entity);
  71924. if (entity.buildType == 'building') {
  71925. this.buildings.push(entity);
  71926. } else {
  71927. parent.buildChildren.push(entity);
  71928. }
  71929. }
  71930. if (entity.buildType == 'room') {
  71931. entity.addEventListener('marker_dropped', () => {
  71932. this.fitPullBox();
  71933. });
  71934. } else if (entity.buildType == 'floor') {
  71935. this.updateBuildingZ(parent);
  71936. parent.dispatchEvent({
  71937. type: 'addFloor'
  71938. });
  71939. }
  71940. {
  71941. //仅能存在一个marker被选中。选中的点可以被删除
  71942. entity.addEventListener('clickMarker', e => {
  71943. if (this.selectedMarker == e.marker) {
  71944. this.selectedMarker.dispatchEvent({
  71945. type: 'clickSelect',
  71946. state: false
  71947. });
  71948. this.selectedMarker = null;
  71949. } else {
  71950. if (this.selectedMarker) {
  71951. this.selectedMarker.dispatchEvent({
  71952. type: 'clickSelect',
  71953. state: false
  71954. });
  71955. }
  71956. this.selectedMarker = e.marker;
  71957. this.selectedMarker.dispatchEvent({
  71958. type: 'clickSelect',
  71959. state: true
  71960. });
  71961. }
  71962. });
  71963. entity.addEventListener('removeMarker', e => {
  71964. if (this.selectedMarker == e.marker) {
  71965. this.selectedMarker = null;
  71966. }
  71967. });
  71968. var unselect = e => {
  71969. //取消选中实体或删除后
  71970. if (this.selectedMarker && entity.markers.includes(this.selectedMarker)) {
  71971. this.selectedMarker.dispatchEvent({
  71972. type: 'clickSelect',
  71973. state: false
  71974. });
  71975. this.selectedMarker = null;
  71976. }
  71977. };
  71978. entity.addEventListener('dispose', unselect);
  71979. entity.addEventListener('unselect', unselect);
  71980. }
  71981. //console.log('添加实体:', entity.buildType, entity.sid, entity.uuid)
  71982. this.bus.dispatchEvent('updated');
  71983. entity.addEventListener('startDragging', () => {
  71984. this.history.beforeChange(entity);
  71985. });
  71986. entity.addEventListener('marker_dropped', () => {
  71987. this.bus.dispatchEvent('updated');
  71988. this.history.afterChange(entity);
  71989. });
  71990. },
  71991. removeEntity: function removeEntity(entity) {
  71992. if (!this.entities.includes(entity)) return;
  71993. console.log('删除实体:', entity.buildType, entity.sid);
  71994. if (this.selected == entity) {
  71995. this.height_pull_box && (this.height_pull_box.visible = false);
  71996. this.selectEntity(null);
  71997. }
  71998. if (entity.buildType == 'building') {
  71999. var index = this.buildings.indexOf(entity);
  72000. if (index > -1) {
  72001. this.buildings.splice(index, 1);
  72002. }
  72003. } else {
  72004. var index = entity.buildParent.buildChildren.indexOf(entity);
  72005. if (index > -1) {
  72006. entity.buildParent.buildChildren.splice(index, 1);
  72007. if (entity.buildType == 'floor' && index == 0) {
  72008. this.updateBuildingZ(entity.buildParent);
  72009. }
  72010. }
  72011. }
  72012. var index = this.entities.indexOf(entity);
  72013. if (index > -1) {
  72014. this.entities.splice(index, 1);
  72015. }
  72016. entity.dispose();
  72017. var buildChildren = entity.buildChildren.slice();
  72018. buildChildren.forEach(e => this.removeEntity(e));
  72019. this.bus.dispatchEvent('updated');
  72020. },
  72021. updateBuildingZ: function updateBuildingZ(building) {
  72022. building.buildChildren = building.buildChildren.sort((e, a) => e.zMin - a.zMin); //从低到高排序
  72023. building.buildChildren[0] && (building.zMin = building.zMax = building.buildChildren[0].zMin); //基底高度
  72024. //building.zMax = building.buildChildren[building.buildChildren.length-1].zMax
  72025. if (this.editing) building.update({
  72026. dontUpdateChildren: true
  72027. });
  72028. building.dispatchEvent('updateBuildingZ');
  72029. },
  72030. selectEntity: function selectEntity(entity) {
  72031. var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  72032. viewer.dispatchEvent('content_changed');
  72033. if (state === false) {
  72034. entity.unselect();
  72035. if (this.selected == entity) this.selected = null;
  72036. viewer.controls.setTarget(null, 2);
  72037. return;
  72038. }
  72039. if (this.selected == entity || entity && entity.buildType == 'hole') return;
  72040. //this.buildings.forEach(e=>e.unselect())
  72041. this.selected && this.selected.unselect();
  72042. this.height_pull_box && (this.height_pull_box.visible = false);
  72043. if (entity) {
  72044. entity.select();
  72045. if (!entity.isNew) {
  72046. var boundingBox = entity.getBound();
  72047. var center = boundingBox.getCenter(new Vector3()); //中心点不一定在entity中,比如半环形建筑(所以要不要改成到漫游点呢)
  72048. viewer.controls.setTarget(center, 2);
  72049. }
  72050. } else {
  72051. viewer.controls.setTarget(null, 2);
  72052. }
  72053. this.selected = entity;
  72054. if (entity && !entity.dontDragFloorHeight && (entity.buildType == 'floor' || entity.buildType == 'room')) {
  72055. this.height_pull_box && (this.height_pull_box.visible = true);
  72056. this.fitPullBox();
  72057. }
  72058. if (entity && !entity.isNew && (entity.buildType == 'building' || entity.buildType == 'room') && entity.points.length < 2) {
  72059. this.startInsertion('resume', entity); //继续画
  72060. }
  72061. },
  72062. fitPullBox: function fitPullBox() {
  72063. //自适应拖拽楼层的pullMesh
  72064. if (!this.height_pull_box || !this.selected || this.selected.buildType != 'floor' && this.selected.buildType != 'room') return;
  72065. var bound = new Box3();
  72066. bound.expandByObject(this.selected.box);
  72067. var center = bound.getCenter(new Vector3());
  72068. var size = bound.getSize(new Vector3());
  72069. this.height_pull_box.scale.copy(size);
  72070. this.height_pull_box.position.copy(center);
  72071. },
  72072. changeZ: function changeZ(entity, dirType, value) {
  72073. // floor or room 修改zMin or zMax
  72074. var max, min; //limit
  72075. if (entity.buildType == 'floor') {
  72076. //楼层
  72077. var index = entity.buildParent.buildChildren.indexOf(entity);
  72078. if (dirType == 'zMax') {
  72079. var upper = entity.buildParent.buildChildren[index + 1];
  72080. entity.zMax = Math.min(Limit.zMax, value);
  72081. min = entity.zMin + minFloorHeight;
  72082. if (entity.zMax < min) {
  72083. entity.zMax = min;
  72084. } else {
  72085. if (upper) {
  72086. max = upper.zMax - minFloorHeight;
  72087. if (entity.zMax > max) {
  72088. entity.zMax = max;
  72089. }
  72090. }
  72091. }
  72092. if (upper) {
  72093. upper.zMin = entity.zMax;
  72094. upper.update();
  72095. upper.dispatchEvent({
  72096. type: 'changeHeight'
  72097. });
  72098. }
  72099. } else {
  72100. var lower = entity.buildParent.buildChildren[index - 1];
  72101. entity.zMin = Math.max(Limit.zMin, value);
  72102. max = entity.zMax - minFloorHeight;
  72103. if (entity.zMin > max) {
  72104. entity.zMin = max;
  72105. } else {
  72106. if (lower) {
  72107. min = lower.zMin + minFloorHeight;
  72108. if (entity.zMin < min) {
  72109. entity.zMin = min;
  72110. }
  72111. }
  72112. }
  72113. if (lower) {
  72114. lower.zMax = entity.zMin;
  72115. lower.update();
  72116. lower.dispatchEvent({
  72117. type: 'changeHeight'
  72118. });
  72119. }
  72120. if (index == 0) this.updateBuildingZ(entity.buildParent);
  72121. }
  72122. } else if (entity.buildType == 'room') {
  72123. //房间
  72124. //按照navvis的是不一定限制在当前楼层,只要高度不超过当前楼层即可。
  72125. var maxHeight = entity.buildParent.zMax - entity.buildParent.zMin;
  72126. if (dirType == 'zMax') {
  72127. min = entity.zMin + minFloorHeight;
  72128. max = entity.zMin + maxHeight;
  72129. entity.zMax = MathUtils.clamp(value, min, max);
  72130. } else {
  72131. min = entity.zMax - maxHeight;
  72132. max = entity.zMax - minFloorHeight;
  72133. entity.zMin = MathUtils.clamp(value, min, max);
  72134. }
  72135. }
  72136. entity.update();
  72137. entity.dispatchEvent({
  72138. type: 'changeHeight'
  72139. });
  72140. //this.selected.emit('update')
  72141. this.fitPullBox();
  72142. this.bus.dispatchEvent('updated');
  72143. },
  72144. createHeightPull: function createHeightPull() {
  72145. //拖拽楼层的bounding box
  72146. var boxGeo = new BoxBufferGeometry(1, 1, 1 / 4);
  72147. var boxMat = new MeshBasicMaterial({
  72148. color: "#F00",
  72149. opacity: 0,
  72150. transparent: true,
  72151. depthTest: false,
  72152. side: 2
  72153. });
  72154. var height_pull_box_up = new Mesh(boxGeo, boxMat);
  72155. var height_pull_box_down = new Mesh(boxGeo, boxMat);
  72156. height_pull_box_up.name = 'height_pull_box_up';
  72157. height_pull_box_down.name = 'height_pull_box_down';
  72158. this.height_pull_box = new Object3D();
  72159. this.height_pull_box.name = 'height_pull_box';
  72160. this.height_pull_box.add(height_pull_box_up);
  72161. this.height_pull_box.add(height_pull_box_down);
  72162. this.height_pull_box.visible = false;
  72163. this.meshGroup.add(this.height_pull_box);
  72164. height_pull_box_up.position.set(0, 0, 1 / 2 /* 3/8 */);
  72165. height_pull_box_down.position.set(0, 0, -1 / 2 /* -3/8 */);
  72166. Potree.Utils.setObjectLayers(this.height_pull_box, 'sideVisi');
  72167. var mouseover = e => {
  72168. viewer.dispatchEvent({
  72169. type: "CursorChange",
  72170. action: "add",
  72171. name: "siteModelFloorDrag"
  72172. });
  72173. };
  72174. var mouseleave = e => {
  72175. viewer.dispatchEvent({
  72176. type: "CursorChange",
  72177. action: "remove",
  72178. name: "siteModelFloorDrag"
  72179. });
  72180. };
  72181. var firstZ, firstIntersect;
  72182. var drag = e => {
  72183. var intersect = e.intersect.orthoIntersect; //不要点云的intersect,只要orthocamera算出的平面intersect
  72184. if (firstIntersect != void 0) {
  72185. var moveZ = intersect.z - firstIntersect;
  72186. if (this.selected.buildType == 'floor') {
  72187. //楼层
  72188. //限制高度不能超过上下
  72189. if (e.target == height_pull_box_up) {
  72190. if (firstZ == void 0) firstZ = this.selected.zMax;
  72191. this.changeZ(this.selected, 'zMax', firstZ + moveZ);
  72192. } else {
  72193. if (firstZ == void 0) firstZ = this.selected.zMin;
  72194. this.changeZ(this.selected, 'zMin', firstZ + moveZ);
  72195. }
  72196. } else if (this.selected.buildType == 'room') {
  72197. //房屋
  72198. if (e.target == height_pull_box_up) {
  72199. if (firstZ == void 0) firstZ = this.selected.zMax;
  72200. this.changeZ(this.selected, 'zMax', firstZ + moveZ);
  72201. } else {
  72202. if (firstZ == void 0) firstZ = this.selected.zMin;
  72203. this.changeZ(this.selected, 'zMin', firstZ + moveZ);
  72204. }
  72205. }
  72206. } else {
  72207. firstIntersect = intersect.z;
  72208. }
  72209. };
  72210. var drop = e => {
  72211. firstZ = firstIntersect = null;
  72212. };
  72213. height_pull_box_up.addEventListener('mousemove', mouseover);
  72214. height_pull_box_down.addEventListener('mousemove', mouseover);
  72215. height_pull_box_up.addEventListener('mouseleave', mouseleave);
  72216. height_pull_box_down.addEventListener('mouseleave', mouseleave);
  72217. height_pull_box_up.addEventListener('drag', drag);
  72218. height_pull_box_down.addEventListener('drag', drag);
  72219. height_pull_box_up.addEventListener('drop', drop);
  72220. height_pull_box_down.addEventListener('drop', drop);
  72221. },
  72222. pointInWhichEntity(location, buildType, ifIgnoreHole) {
  72223. //buildType是要找的建筑类型
  72224. //location 可以是pano或者坐标
  72225. //由于房间可能在building外,所以房间要另外单独识别。
  72226. var lastResult; //最接近的上一层结果,如果没有result返回这个
  72227. var result;
  72228. var level = {
  72229. building: 0,
  72230. floor: 1,
  72231. room: 2
  72232. };
  72233. var traverse = (parent, buildType) => {
  72234. //返回第一个符合标准的实体
  72235. var contains;
  72236. if (location instanceof Vector3) {
  72237. contains = parent.ifContainsPoint(location);
  72238. } else {
  72239. //is pano
  72240. contains = parent.panos.includes(location);
  72241. }
  72242. if (contains) {
  72243. if (!lastResult || level[lastResult.buildType] < level[parent.buildType]) lastResult = parent;
  72244. if (parent.buildType == buildType) {
  72245. return parent;
  72246. } else {
  72247. for (var i = 0, len = parent.buildChildren.length; i < len; i++) {
  72248. var result1 = traverse(parent.buildChildren[i]);
  72249. if (result1) return result1;
  72250. }
  72251. }
  72252. }
  72253. };
  72254. //因为建筑可能重叠,所以需要先找到最接近其中心的建筑物
  72255. result = Common$1.sortByScore(this.buildings, [building => {
  72256. return traverse(building, 'building'); //在building中
  72257. }], [building => {
  72258. //写法类似pointInWhichPointcloud
  72259. var boundingBox = building.getBound();
  72260. var center = boundingBox.getCenter(new Vector3());
  72261. var position = location instanceof Vector3 ? location : location.position;
  72262. var dis = position.distanceTo(center);
  72263. var size = boundingBox.getSize(new Vector3());
  72264. var length = size.length() / 2;
  72265. return length / dis;
  72266. }]);
  72267. var building = result && result[0] && result[0].score > 1 && result[0].item;
  72268. if (buildType == 'building' || !building) return building;
  72269. result = traverse(building, buildType);
  72270. /* if(!result && buildType == 'room'){//如果要找的是room, 且按刚才的顺序找不到的话,就单独从所有rooms中找一遍。因为room可能不在floor和building内。
  72271. let rooms = this.entities.filter(e=>e.buildType == 'room');
  72272. result = rooms.find(e=>e.ifContainsPoint(position))
  72273. }*/
  72274. //虽然房间可以画到上级之外,但是为了方便起见,假定房间绝对在楼层之内。找不到的话要调整空间模型了。
  72275. return result || lastResult;
  72276. },
  72277. findPanos: function findPanos() {
  72278. {
  72279. this.entities.forEach(entity => {
  72280. //清空:
  72281. entity.panos = [];
  72282. entity.flagPano = null;
  72283. viewer.images360.panos.forEach(pano => {
  72284. if (entity.ifContainsPoint(pano.position)) {
  72285. entity.panos.push(pano);
  72286. }
  72287. });
  72288. });
  72289. }
  72290. /* viewer.images360.panos.forEach(pano=>{ //一个漫游点只对应一个实体的话
  72291. let result = this.pointInWhichEntity(pano.position, 'room');
  72292. {//get panos for every entities
  72293. let entity = result
  72294. while(entity){
  72295. entity.panos.push(pano);
  72296. entity = entity.buildParent
  72297. }
  72298. }
  72299. }) */
  72300. {
  72301. //search center pano
  72302. this.entities.forEach(entity => {
  72303. var panos = entity.panos;
  72304. if (panos.length == 0) return;
  72305. var bound = entity.getBound();
  72306. var center = bound.getCenter(new Vector3());
  72307. var request = [];
  72308. var rank = [Images360.scoreFunctions.distanceSquared({
  72309. position: center
  72310. })];
  72311. //let panos = entity.panos && entity.panos.length ? entity.panos : viewer.images360.panos //entity没有panos的话,就扩大到所有panos
  72312. var r = Common$1.sortByScore(panos, request, rank);
  72313. if (r && r.length) {
  72314. entity.flagPano = r[0].item;
  72315. } else {
  72316. console.error('no flagPano??');
  72317. }
  72318. });
  72319. }
  72320. },
  72321. findEntityForDataset: function findEntityForDataset() {
  72322. //为每一个数据集寻找它所属的最小实体
  72323. /* var entities = this.entities.filter(e=>e.buildType == 'room' || e.buildType == 'floor' && e.buildChildren.length == 0)
  72324. viewer.scene.pointclouds.forEach(pointcloud=>{
  72325. let cloudVolume = pointcloud.getVolume()
  72326. let scores = []
  72327. entities.forEach(entity=>{
  72328. let volume = entity.intersectPointcloudVolume(pointcloud)
  72329. //注:默认已经findPanos过
  72330. let panos = entity.panos.filter(e=>pointcloud.panos.includes(e));
  72331. let panoCount = panos.length
  72332. let score = volume / cloudVolume + panoCount / pointcloud.panos.length
  72333. scores.push({entity, volume, panoCount, score})
  72334. })
  72335. scores.sort((a,b)=>{ return b.score-a.score })
  72336. if(scores.length == 0 || scores[0].volume/cloudVolume < 0.0001 && scores[0].volume < 3 ){//如果约等于0
  72337. pointcloud.belongToEntity = null
  72338. }else{
  72339. pointcloud.belongToEntity = scores[0].entity;
  72340. }
  72341. }) */
  72342. var getScores = (pointcloud, entities, cloudVolume) => {
  72343. var scores = [];
  72344. entities.forEach(entity => {
  72345. var volume = entity.intersectPointcloudVolume(pointcloud);
  72346. //注:默认已经findPanos过
  72347. var panos = entity.panos.filter(e => pointcloud.panos.includes(e));
  72348. var panoCount = panos.length;
  72349. var score = volume / cloudVolume;
  72350. if (pointcloud.panos.length > 0) {
  72351. score += panoCount / pointcloud.panos.length;
  72352. } else {
  72353. //score += 1
  72354. }
  72355. scores.push({
  72356. entity,
  72357. volume,
  72358. panoCount,
  72359. score
  72360. });
  72361. });
  72362. scores.sort((a, b) => {
  72363. return b.score - a.score;
  72364. });
  72365. return scores;
  72366. };
  72367. viewer.scene.pointclouds.forEach(pointcloud => {
  72368. //先判断父级,如果父集不通过就不判断子级。
  72369. var cloudVolume = pointcloud.getVolume();
  72370. var entities = this.buildings;
  72371. while (1) {
  72372. var scores = getScores(pointcloud, entities, cloudVolume);
  72373. if (scores.length == 0 || scores[0].volume / cloudVolume < 0.0001 && scores[0].volume < 3) {
  72374. //如果约等于0
  72375. if (scores[0] && scores[0].entity.buildType == 'room') {
  72376. pointcloud.belongToEntity = scores[0].entity; //当该数据集在楼层中,但不在楼层中的任意一个房间时,任意挂载在其中一个房间上。
  72377. break;
  72378. }
  72379. pointcloud.belongToEntity = null;
  72380. break;
  72381. } else {
  72382. entities = scores[0].entity.buildChildren;
  72383. if (entities.length == 0) {
  72384. pointcloud.belongToEntity = scores[0].entity;
  72385. break;
  72386. }
  72387. }
  72388. }
  72389. });
  72390. /*
  72391. 旧版:
  72392. 只需要考虑 floor 和 room, 因为building的只有一个基底没高度
  72393. floor 和 room 在空间中没有完全的从属关系,因为room可以超出floor之外。所以直接混在一起来查找,但要排除有房间的楼层。
  72394. (现在改为层层递进查找,否则数据集包含entity多的,会直接挂载到体积最大的房间里,即使看起来主体点云并不在该房间)
  72395. 有的数据集虽然很高,但只有近地面的部分才是主体,这部分一般含有全部漫游点。为了防止上层的实体因体积较大而分数高,就把包含漫游点的个数也加入考虑。
  72396. 重叠体积大、且包含漫游点最多的最小实体将会拥有该点云。
  72397. 期望: 最好不挂载到最小子级,因为现在有房间都到房间里了。
  72398. */
  72399. },
  72400. clear: function clear() {
  72401. //清空
  72402. /* entities:[], //所有实体
  72403. buildings:[], //所有建筑父集
  72404. meshGroup: new THREE.Object3D, */
  72405. this.selectEntity(null);
  72406. var length = this.entities.length;
  72407. for (var i = 0; i < length; i++) {
  72408. this.entities[i].dispose();
  72409. }
  72410. this.entities = [];
  72411. this.buildings = [];
  72412. this.inEntity = null;
  72413. },
  72414. gotoEntity(id, isNearBy) {
  72415. var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1000;
  72416. var entity = this.entities.find(e => e.sid == id);
  72417. var aimPano;
  72418. if (!entity) {
  72419. return console.error('没找到entity ');
  72420. }
  72421. if (Potree.settings.displayMode == 'showPanos') {
  72422. if (isNearBy && entity.panos.length) {
  72423. var _r$;
  72424. if (entity.panos.includes(viewer.images360.currentPano)) return 'posNoChange'; //已在当前实体中
  72425. var position = viewer.scene.getActiveCamera().position;
  72426. var request = [Images360.filters.isEnabled()];
  72427. var rank = [Images360.scoreFunctions.distanceSquared({
  72428. position
  72429. })];
  72430. var r = Common$1.sortByScore(entity.panos, request, rank);
  72431. aimPano = (_r$ = r[0]) === null || _r$ === void 0 ? void 0 : _r$.item;
  72432. } else {
  72433. if (!entity.flagPano) {
  72434. return console.log('没有flagPano');
  72435. }
  72436. aimPano = entity.flagPano;
  72437. }
  72438. if (aimPano == viewer.images360.currentPano) return 'posNoChange';
  72439. aimPano && viewer.images360.flyToPano(aimPano);
  72440. } else {
  72441. if (isNearBy && entity.ifContainsPoint(viewer.images360.position)) {
  72442. return 'posNoChange'; //已在当前实体中
  72443. }
  72444. var boundingBox = entity.getBound();
  72445. var _position = boundingBox.getCenter(new Vector3()); //中心点不一定在entity中,比如半环形建筑(所以要不要改成到漫游点呢)
  72446. var size = boundingBox.getSize(new Vector3());
  72447. if (viewer.modules.Clip && viewer.modules.Clip.editing) {
  72448. viewer.modules.Clip.bus.dispatchEvent({
  72449. type: 'flyToPos',
  72450. position: _position
  72451. });
  72452. } else {
  72453. if (math.closeTo(_position, viewer.images360.position)) return 'posNoChange';
  72454. viewer.scene.view.setView({
  72455. position: _position,
  72456. duration
  72457. });
  72458. }
  72459. viewer.mapViewer.moveTo(_position, size, duration);
  72460. }
  72461. return true;
  72462. },
  72463. focusEntity(id) {
  72464. var entity = this.entities.find(e => e.sid == id);
  72465. var boundingBox = entity.getBound();
  72466. //let boundSize = boundingBox.getSize(new THREE.Vector3())
  72467. var center = boundingBox.getCenter(new Vector3());
  72468. this.SplitScreen.focusOnObject(boundingBox, center);
  72469. this.gotoEntity(id, false, 0);
  72470. },
  72471. removeIlligalArchi() {
  72472. //删除marker数量小于3个的建筑,当保存时
  72473. var needDelete = [];
  72474. this.entities.forEach(e => {
  72475. if (e.points.length < 3) {
  72476. needDelete.push(e);
  72477. }
  72478. });
  72479. needDelete.forEach(e => this.removeEntity(e));
  72480. }
  72481. };
  72482. // Author: Fyrestar https://mevedia.com (https://github.com/Fyrestar/THREE.InfiniteGridHelper)
  72483. class InfiniteGridHelper extends Mesh {
  72484. constructor(size1, size2, color, distance) {
  72485. var opacity1 = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0.2;
  72486. var opacity2 = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
  72487. color = color || new Color('white');
  72488. size1 = size1 || 10;
  72489. size2 = size2 || 100;
  72490. distance = distance || 8000; //可视距离?越远越模糊
  72491. var geometry = new PlaneBufferGeometry(2, 2, 1, 1);
  72492. var material = new ShaderMaterial({
  72493. side: DoubleSide,
  72494. uniforms: {
  72495. uSize1: {
  72496. value: size1
  72497. },
  72498. uSize2: {
  72499. value: size2
  72500. },
  72501. opacity1: {
  72502. //线条1的 小格子
  72503. value: opacity1
  72504. },
  72505. opacity2: {
  72506. //线条2的
  72507. value: opacity2
  72508. },
  72509. uColor: {
  72510. value: color
  72511. },
  72512. uDistance: {
  72513. value: distance
  72514. }
  72515. },
  72516. transparent: true,
  72517. vertexShader: "\n \n varying vec3 worldPosition;\n \n uniform float uDistance;\n \n void main() {\n \n vec3 pos = position.xyz * uDistance;\n pos.xy += cameraPosition.xy;\n \n worldPosition = pos;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n \n }\n ",
  72518. fragmentShader: "\n \n varying vec3 worldPosition;\n \n uniform float uSize1;\n uniform float uSize2;\n uniform float opacity1;\n uniform float opacity2;\n uniform vec3 uColor;\n uniform float uDistance;\n \n \n \n float getGrid(float size) {\n \n vec2 r = worldPosition.xy / size;\n \n \n vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);\n float line = min(grid.x, grid.y);\n \n \n return 1.0 - min(line, 1.0);\n }\n //\u4E3A\u4F55\u4FA7\u9762\u770B\u4E0D\u5230\u7EBF\uFF0C\u56E0\u4E3Amesh\u7684\u6B63\u4FA7\u9762\u90FD\u770B\u4E0D\u5230\uFF1F\n\n void main() {\n \n \n float d = 1.0 - min(distance(cameraPosition.xy, worldPosition.xy) / uDistance, 1.0);\n \n float g1 = getGrid(uSize1);\n float g2 = getGrid(uSize2);\n \n \n gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));\n //gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);\n gl_FragColor.a = mix(opacity1 * gl_FragColor.a, opacity2 * gl_FragColor.a, g2);\n \n \n if ( gl_FragColor.a <= 0.0 ) discard;\n \n \n }\n \n ",
  72519. extensions: {
  72520. derivatives: true
  72521. }
  72522. });
  72523. super(geometry, material);
  72524. this.frustumCulled = false;
  72525. }
  72526. }
  72527. ;
  72528. /*
  72529. THREE.InfiniteGridHelper.prototype = {
  72530. ...THREE.Mesh.prototype,
  72531. ...THREE.Object3D.prototype,
  72532. ...THREE.EventDispatcher.prototype
  72533. };
  72534. */
  72535. var texLoader$d = new TextureLoader();
  72536. texLoader$d.crossOrigin = "anonymous";
  72537. var edgeStrengths = {
  72538. pointcloud: 4,
  72539. glb: 100
  72540. };
  72541. var viewportProps$1 = [{
  72542. left: 0,
  72543. bottom: 0,
  72544. width: 0.5,
  72545. height: 1,
  72546. name: 'top',
  72547. axis: ["x", "y"],
  72548. direction: new Vector3(0, 0, -1),
  72549. //镜头朝向
  72550. active: true,
  72551. //相机位置在z轴正向
  72552. limitBound: new Box3(new Vector3(-Infinity, -Infinity, 1), new Vector3(Infinity, Infinity, 5000)),
  72553. //在地面以上
  72554. margin: {
  72555. x: 50,
  72556. y: 150
  72557. }
  72558. }, {
  72559. left: 0.5,
  72560. bottom: 0,
  72561. width: 0.5,
  72562. height: 1,
  72563. name: 'right',
  72564. axis: ["y", "z"],
  72565. direction: new Vector3(1, 0, 0),
  72566. active: true,
  72567. //相机位置在x轴负向 右下角屏
  72568. viewContainsPoints: [new Vector3(0, 0, 0)],
  72569. margin: {
  72570. x: 300,
  72571. y: 250
  72572. }
  72573. }];
  72574. var cylinderSkyGeo, oldSkyGeo;
  72575. var MergeEditor = {
  72576. bus: new EventDispatcher(),
  72577. SplitScreen: new SplitScreen(),
  72578. init() {
  72579. this.boxHelper = new Box3Helper$1(new Box3(new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, 0.5, 0.5)));
  72580. viewer.scene.scene.add(this.boxHelper);
  72581. Potree.Utils.updateVisible(this.boxHelper, 'unselect', false);
  72582. this.boxHelper.material.opacity = 0.8;
  72583. var boxHelper2 = new Box3Helper$1(new Box3(new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, 0.5, 0.5)));
  72584. boxHelper2.material.opacity = 0.2;
  72585. boxHelper2.material.transparent = true, boxHelper2.material.depthTest = false;
  72586. this.boxHelper.add(boxHelper2); //透明一点的boxHelper */
  72587. this.lastMemoryState = {};
  72588. this.history = new History({
  72589. applyData: data => {
  72590. if (data.object.parent /* && data.object == this.selected */) {
  72591. data = Potree.Common.CloneObject(data); //避免使用后更改数据又被使用
  72592. var matrix = data.object.parent ? data.object.parent.matrixWorld.clone().invert().multiply(data.matrixWorld) : data.matrixWorld;
  72593. matrix.decompose(data.object.position, data.object.quaternion, data.object.scale);
  72594. data.object.dispatchEvent('changeByHistory');
  72595. data.object.dispatchEvent('transformChanged');
  72596. this.getBoundCenter(data.object);
  72597. viewer.dispatchEvent('content_changed');
  72598. //回退到上一次编辑的全局位置
  72599. return true;
  72600. }
  72601. },
  72602. getData: object => {
  72603. return {
  72604. object,
  72605. matrixWorld: object.matrixWorld.clone()
  72606. };
  72607. }
  72608. });
  72609. {
  72610. Potree.settings.notAdditiveBlending = true;
  72611. var ground = this.ground = new InfiniteGridHelper(1, 10000, new Color('#eee'), 10000, 0.2, 0.3);
  72612. viewer.scene.scene.add(ground);
  72613. //再加两条线否则在正侧边看不到
  72614. var line1 = LineDraw.createLine([new Vector3(-10000, 0, 0), new Vector3(10000, 0, 0)], {
  72615. color: '#aaa'
  72616. });
  72617. var line2 = LineDraw.createLine([new Vector3(0, -10000, 0), new Vector3(0, 10000, 0)], {
  72618. mat: line1.material
  72619. });
  72620. ground.renderOrder = Potree.config.renderOrders.model + 1; //line1.renderOrder + 1 //要比模型低,否则模型透明时效果不对
  72621. ground.add(line1);
  72622. ground.add(line2);
  72623. ground.material.opacity = 0.9; //为了滞后渲染,否则被rt遮住
  72624. ground.material.polygonOffset = true; //多边形偏移(视觉上没有移动模型位置),防止闪烁
  72625. ground.material.polygonOffsetFactor = 100; //多边形偏移因子
  72626. ground.material.polygonOffsetUnits = 10; //多边形偏移单位
  72627. ground.material.depthWrite = false;
  72628. //ground.material.depthTest = false
  72629. line1.material.polygonOffset = true;
  72630. line1.material.polygonOffsetFactor = 130;
  72631. line1.material.polygonOffsetUnits = 10;
  72632. line1.material.depthWrite = false;
  72633. //见笔记:透明物体的材质设置
  72634. }
  72635. var oriEdgeStrength = viewer.outlinePass.edgeStrength;
  72636. {
  72637. this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea, {
  72638. //dontHideWhenFaceCamera: true,
  72639. showRotXYZE: true,
  72640. minScale: new Vector3(0.00001, 0.00001, 0.00001)
  72641. });
  72642. //this.transformControls.space = 'local'//为了在当前方向上平移
  72643. this.transformControls.setSize(1.5);
  72644. viewer.scene.scene.add(this.transformControls);
  72645. this.transformControls._gizmo.hideAxis = {
  72646. rotate: ['e'],
  72647. scale: ['x', 'y', 'z']
  72648. };
  72649. this.transformControls._gizmo.showAxis = {
  72650. scale: ['XYZY']
  72651. }; //仅显示 等于而非包含
  72652. this.transformControls.setRotateMethod(2);
  72653. //右屏
  72654. this.transformControls2 = new TransformControls(viewer.mainViewport.camera, viewer.renderArea, {
  72655. //dontHideWhenFaceCamera: true,
  72656. });
  72657. this.transformControls2.setSize(1.5);
  72658. viewer.scene.scene.add(this.transformControls2);
  72659. Potree.Utils.setObjectLayers(this.transformControls2, 'layer2');
  72660. var mouseDown = e => {
  72661. viewer.outlinePass.edgeStrength = 0; //暂时消失线
  72662. };
  72663. var mouseUp = e => {
  72664. //this.updateEdgeStrength()
  72665. viewer.outlinePass.edgeStrength = oriEdgeStrength;
  72666. };
  72667. this.transformControls.addEventListener('mouseDown', mouseDown);
  72668. this.transformControls2.addEventListener('mouseDown', mouseDown);
  72669. this.transformControls.addEventListener('mouseUp', mouseUp);
  72670. this.transformControls2.addEventListener('mouseUp', mouseUp);
  72671. this.transformControls.addEventListener('mouseDown', () => {
  72672. //dragstart
  72673. this.history.beforeChange(this.selected);
  72674. });
  72675. this.transformControls.addEventListener('mouseUp', () => {
  72676. this.history.afterChange(this.selected);
  72677. });
  72678. }
  72679. {
  72680. this.secondCompass = new Compass(null);
  72681. }
  72682. viewer.setControls(viewer.orbitControls);
  72683. //viewer.mainViewport.view.fixZWhenPan = true
  72684. viewer.orbitControls.constantlyForward = true;
  72685. viewer.addEventListener('global_single_click', e => {
  72686. var _e$intersect, _e$intersect2;
  72687. if (e.button != MOUSE.LEFT || this.noNeedSelection //如模型查看页
  72688. || viewer.scene.cameraAnimations.some(c => c.onUpdate) //正在播放
  72689. || e.drag && e.drag.notPressMouse //在加测量线
  72690. || viewer.mainViewport.view.isFlying() //有其他校准
  72691. || this.split //分屏中
  72692. || e.clickElement //触发别的点击事件,如测量时click marker /* && e.clickElement != e.intersect.object */
  72693. ) {
  72694. return;
  72695. }
  72696. var object = ((_e$intersect = e.intersect) === null || _e$intersect === void 0 ? void 0 : _e$intersect.object) || ((_e$intersect2 = e.intersect) === null || _e$intersect2 === void 0 ? void 0 : _e$intersect2.pointcloud);
  72697. var objects = this.getAllObjects();
  72698. if (!objects.includes(object) || Potree.settings.displayMode == 'showPanos' && object.panos.length) object = null; //不是可选的
  72699. if (object) {
  72700. var posInModel = Potree.Utils.datasetPosTransform({
  72701. toDataset: true,
  72702. position: e.intersect.location.clone(),
  72703. object
  72704. });
  72705. if (this.selected != object) {
  72706. this.selectModel(object, posInModel);
  72707. } else {
  72708. //if(!viewer.inputHandler.selection[0]){//正在平移和旋转,不允许取消
  72709. if (this.selected == object && this.transformControls.object == object && this.transformControls.mode == 'translate') {
  72710. this.selectModel(object, posInModel); //update click pos
  72711. } else {
  72712. this.selectModel(null);
  72713. }
  72714. //}
  72715. }
  72716. } else {
  72717. //if(!viewer.inputHandler.selection[0]){
  72718. this.selectModel(null);
  72719. //}
  72720. }
  72721. /* if(e.intersect){
  72722. let object = e.intersect.object || e.intersect.pointcloud
  72723. let objects = this.getAllObjects()
  72724. let posInModel = Potree.Utils.datasetPosTransform({ toDataset: true, position: e.intersect.location.clone(), object })
  72725. if(objects.includes(object) && this.selected != object){
  72726. this.selectModel(object, posInModel)
  72727. }else{
  72728. //if(!viewer.inputHandler.selection[0]){//正在平移和旋转,不允许取消
  72729. if(this.selected == object && this.transformControls.object == object && this.transformControls.mode == 'translate'){
  72730. this.selectModel(object, posInModel) //update click pos
  72731. }else{
  72732. this.selectModel(null)
  72733. }
  72734. //}
  72735. }
  72736. }else{
  72737. //if(!viewer.inputHandler.selection[0]){
  72738. this.selectModel(null)
  72739. //}
  72740. } */
  72741. });
  72742. viewer.inputHandler.addEventListener('keydown', e => {
  72743. if (e.event.key.toLowerCase() == "h") {
  72744. this.fadeOutlineAuto = !this.fadeOutlineAuto;
  72745. this.showModelOutline(this.selected, !!this.selected);
  72746. }
  72747. });
  72748. //viewer.fxaaPass.enabled = false//viewer.ssaaRenderPass.enabled = false
  72749. viewer.outlinePass.enabled = true;
  72750. //Potree.settings.intersectWhenHover = false
  72751. //Potree.Utils.updateVisible(viewer.reticule, 'force', false)
  72752. viewer.composer.scaleRatio = 1;
  72753. viewer.composer.readTarget = false;
  72754. viewer.addEventListener('updateModelBound', e => {
  72755. if (this.split) {
  72756. this.SplitScreen.updateCameraOutOfModel( /* this.selected && [this.selected] */);
  72757. }
  72758. });
  72759. {
  72760. //校准页面拖拽
  72761. //左右屏都可以拖拽模型,旋转只能左屏
  72762. var dragInfo;
  72763. var drag = e => {
  72764. if (this.split && this.selected && this.transformState && (e.dragViewport.name == 'top' || this.transformState == 'translate') && e.buttons == Potree.defines.Buttons.LEFT) {
  72765. if (e.type == 'global_mousedown') {
  72766. //开始
  72767. //if((e.intersect.object || e.intersect.pointcloud) == this.selected){
  72768. if (e.intersect.pointclouds.includes(this.selected) || e.intersect.allElements.some(e => e.object == this.selected)) {
  72769. dragInfo = {};
  72770. //if(this.selected.isPointcloud){
  72771. viewer.outlinePass.edgeStrength = 0; //暂时消失线
  72772. //}
  72773. this.history.beforeChange(this.selected);
  72774. }
  72775. }
  72776. if (e.type == 'global_drag' && dragInfo) {
  72777. if (this.transformState == 'translate') {
  72778. var moveVec = Potree.Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, e.dragViewport.camera); //最近一次移动向量
  72779. this.selected.position.add(moveVec);
  72780. this.selected.dispatchEvent("position_changed");
  72781. } else if (this.transformState == 'rotate') {
  72782. var vec = new Vector3().subVectors(e.intersect.orthoIntersect || e.intersect.location, this.selected.boundCenter).setZ(0);
  72783. if (dragInfo.lastVec == void 0) {
  72784. //global_mousedown
  72785. dragInfo.lastVec = vec;
  72786. return;
  72787. }
  72788. var angle = math.getAngle(dragInfo.lastVec, vec, 'z');
  72789. dragInfo.lastVec = vec;
  72790. //this.selected.rotation.z += angle //局部
  72791. /* object.quaternion.copy( .setFromAxisAngle( new THREE.Vector3(0,0,1), angle ) );
  72792. object.quaternion.multiply( quaternionStart ).normalize(); */
  72793. var diffQua = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), angle);
  72794. this.selected.quaternion.premultiply(diffQua); //世界
  72795. this.selected.dispatchEvent("rotation_changed");
  72796. }
  72797. return {
  72798. stopContinue: true
  72799. };
  72800. }
  72801. }
  72802. };
  72803. viewer.addEventListener('global_mousedown', drag);
  72804. viewer.addEventListener('global_drag', drag, {
  72805. importance: 10
  72806. });
  72807. viewer.addEventListener('global_mousemove', e => {
  72808. if (this.split && this.transformState && !e.drag && (e.hoverViewport.name == 'top' || this.transformState == 'translate')) {
  72809. /* if(this.lastHoverViewport != e.hoverViewport){
  72810. this.lastHoverViewport = e.hoverViewport
  72811. this.transformControls.view = e.hoverViewport.view
  72812. this.transformControls.camera = e.hoverViewport.camera
  72813. this.transformControls.hideAxis( this.transformState, e.hoverViewport.name == 'top' ? [z] : [x,y]);
  72814. } */
  72815. var mouseover = e.intersect.pointclouds.includes(this.selected) || e.intersect.allElements.some(e => e.object == this.selected);
  72816. //let mouseover = (e.intersect.object || e.intersect.pointcloud) == this.selected
  72817. if (mouseover) {
  72818. if (this.transformState == 'translate') {
  72819. viewer.dispatchEvent({
  72820. type: "CursorChange",
  72821. action: "add",
  72822. name: "movePointcloud"
  72823. });
  72824. } else {
  72825. viewer.dispatchEvent({
  72826. type: "CursorChange",
  72827. action: "add",
  72828. name: "rotatePointcloud"
  72829. });
  72830. }
  72831. } else {
  72832. this.clearTranCursor();
  72833. }
  72834. }
  72835. });
  72836. viewer.addEventListener('global_drop', e => {
  72837. dragInfo = null;
  72838. this.clearTranCursor();
  72839. this.history.afterChange(this.selected);
  72840. //this.updateEdgeStrength()
  72841. viewer.outlinePass.edgeStrength = oriEdgeStrength;
  72842. });
  72843. }
  72844. /* viewer.addEventListener('background_changed',()=>{
  72845. }) */
  72846. viewer.addEventListener('camera_changed', () => {
  72847. //其实静止时内存也会变,因为在加载
  72848. this.lastMemoryState.history = []; //clear
  72849. Common$1.intervalTool.isWaiting('updateMemoryUsage', () => {
  72850. return this.updateMemoryUsage();
  72851. }, 1000);
  72852. });
  72853. viewer.addEventListener('setDisplay', this.updateMemoryUsage.bind(this));
  72854. },
  72855. clearTranCursor() {
  72856. viewer.dispatchEvent({
  72857. type: "CursorChange",
  72858. action: "remove",
  72859. name: "movePointcloud"
  72860. });
  72861. viewer.dispatchEvent({
  72862. type: "CursorChange",
  72863. action: "remove",
  72864. name: "rotatePointcloud"
  72865. });
  72866. },
  72867. enterSplit() {
  72868. var _this$selected, _this$selected2;
  72869. this.split = true;
  72870. if (this.selected) this.SplitScreen.focusCenter = this.selected.boundCenter; //旋转中心。注意 boundCenter不能直接赋值,否则改变后focusCenter也要改
  72871. else this.SplitScreen.focusCenter = null;
  72872. this.SplitScreen.splitStart(viewportProps$1, (_this$selected = this.selected) === null || _this$selected === void 0 ? void 0 : _this$selected.bound, (_this$selected2 = this.selected) === null || _this$selected2 === void 0 ? void 0 : _this$selected2.boundCenter);
  72873. this.beforeSplit = {
  72874. pointDensity: Potree.settings.pointDensity
  72875. };
  72876. Potree.settings.pointDensity = 'fourViewports'; //强制降低点云质量
  72877. viewer.setControls(viewer.fpControls);
  72878. var rightViewport = viewer.viewports.find(e => e.name == 'right');
  72879. var topViewport = viewer.viewports.find(e => e.name == 'top');
  72880. topViewport.alignment = true;
  72881. rightViewport.rotateSide = true;
  72882. rightViewport.skyboxFixPos = true;
  72883. rightViewport.skyboxMinZoom = 10;
  72884. rightViewport.skyboxRenderFun = () => {
  72885. // 使cube的一面永远正向镜头。 因侧视图的camera是ortho类型,需要平视mesh才不会拉伸
  72886. viewer.skybox.scene.children[0].rotation.copy(rightViewport.camera.rotation);
  72887. };
  72888. topViewport.skyboxRenderFun = () => {
  72889. viewer.skybox.scene.children[0].rotation.set(0, 0, 0);
  72890. };
  72891. viewer.viewports[1].layersAdd('layer2');
  72892. viewer.viewports[0].layersAdd('layer1');
  72893. Potree.Utils.setObjectLayers(this.transformControls, 'layer1');
  72894. this.transformControls.view = viewer.viewports[0].view;
  72895. this.transformControls.camera = viewer.viewports[0].camera;
  72896. this.transformControls._gizmo.hideAxis = {
  72897. translate: ['z'],
  72898. rotate: ['x', 'y', 'z'],
  72899. scale: ['x', 'y', 'z']
  72900. };
  72901. this.transformControls2.view = viewer.viewports[1].view;
  72902. this.transformControls2.camera = viewer.viewports[1].camera;
  72903. this.transformControls2._gizmo.hideAxis = {
  72904. translate: ['x', 'y'],
  72905. rotate: ['x', 'y', 'z'],
  72906. scale: ['x', 'y', 'z']
  72907. };
  72908. this.secondCompass.changeViewport(viewer.viewports[0]);
  72909. this.secondCompass.setDomPos();
  72910. this.secondCompass.setDisplay(true);
  72911. viewer.compass.changeViewport(viewer.viewports[1]);
  72912. viewer.compass.setDomPos();
  72913. //this.changeSkyboxGeo(true)
  72914. },
  72915. leaveSplit() {
  72916. this.split = false;
  72917. this.SplitScreen.unSplit();
  72918. viewer.setControls(viewer.orbitControls);
  72919. Potree.settings.pointDensity = this.beforeSplit.pointDensity;
  72920. /* if(this.selected && this.selected.isPointcloud){
  72921. this.showModelOutline(this.selected, true)
  72922. this.selected.material.activeAttributeName = "rgba"
  72923. } */
  72924. this.transformControls.camera = viewer.viewports[0].camera;
  72925. this.transformControls.view = viewer.viewports[0].view;
  72926. this.transformControls._gizmo.hideAxis = {
  72927. rotate: ['e'],
  72928. scale: ['x', 'y', 'z']
  72929. };
  72930. Potree.Utils.setObjectLayers(this.transformControls, 'sceneObjects'); //恢复
  72931. viewer.compass.changeViewport(viewer.viewports[0]); //恢复
  72932. viewer.compass.setDomPos();
  72933. this.secondCompass.setDisplay(false);
  72934. },
  72935. rotateSideCamera(angle) {
  72936. this.SplitScreen.rotateSideCamera(viewer.viewports.find(e => e.name == 'right'), angle);
  72937. },
  72938. setTransformState(state) {
  72939. //校准时
  72940. this.transformState = state;
  72941. this.clearTranCursor();
  72942. },
  72943. //---------------------------
  72944. getAllObjects() {
  72945. return viewer.objs.children.concat(viewer.scene.pointclouds);
  72946. },
  72947. getModel(id) {
  72948. var models = this.getAllObjects();
  72949. return models.find(e => e.dataset_id == id);
  72950. },
  72951. changeModelPointCount(object, type) {
  72952. if (object.fileType == '3dTiles' || object.isPointcloud) return;
  72953. var posCount, texArea;
  72954. if (type == 'add') {
  72955. var o = viewer.getObjectPointCount(object);
  72956. posCount = o.posCount, texArea = o.texArea;
  72957. object.posCount = posCount, object.texArea = texArea;
  72958. } else {
  72959. posCount = -object.posCount, texArea = -object.texArea;
  72960. }
  72961. viewer.memoryModelCountInfo.otherPosCount += posCount;
  72962. viewer.memoryModelCountInfo.otherTexArea += texArea;
  72963. },
  72964. modelAdded(model) {
  72965. /* model.addEventListener('isVisible',(e)=>{
  72966. if(e.reason == "overlinePass")return
  72967. //console.log(e)
  72968. viewer.addEventListener('update',()=>{ //下一次更新结束后
  72969. this.updateMemoryUsage()
  72970. },{once:true})
  72971. }) */
  72972. this.getBoundCenter(model); //保险起见加一下
  72973. var weightUpdate = () => {
  72974. this.changeModelPointCount(model, 'add');
  72975. this.updateMemoryUsage();
  72976. };
  72977. if (model.fileType == 'obj') {
  72978. //要等待贴图都加载完
  72979. if (viewer.fileManager.loading) {
  72980. viewer.addEventListener('managerOnLoad', e => {
  72981. weightUpdate();
  72982. }, {
  72983. once: true
  72984. }); //如果onError了咋办,暂时无法定位manager加载的哪个模型的
  72985. }
  72986. } else {
  72987. weightUpdate();
  72988. }
  72989. },
  72990. removeModel(model) {
  72991. var _model$titleLabel, _model$panos;
  72992. if (this.selected == model) this.selectModel(null);
  72993. var dispose = e => {
  72994. e.geometry && e.geometry.dispose();
  72995. e.material && e.material.dispose();
  72996. };
  72997. model.skeletonHelper && model.add(model.skeletonHelper); //打包一起dispose
  72998. (_model$titleLabel = model.titleLabel) === null || _model$titleLabel === void 0 || _model$titleLabel.dispose();
  72999. if (model.isPointcloud) {
  73000. dispose(model);
  73001. viewer.scene.removePointCloud(model);
  73002. } else {
  73003. model.traverse(e => {
  73004. dispose(e);
  73005. });
  73006. viewer.objs.remove(model);
  73007. }
  73008. (_model$panos = model.panos) === null || _model$panos === void 0 || _model$panos.slice().forEach(e => {
  73009. e.dispose();
  73010. });
  73011. viewer.images360.tileDownloader.setPanoData(viewer.images360.panos, []);
  73012. if (model.fileType == '3dTiles') {
  73013. model.traverse(child => {
  73014. if (child.runtime) {
  73015. child.runtime.getTileset().destroy();
  73016. return {
  73017. stopContinue: true
  73018. };
  73019. }
  73020. });
  73021. }
  73022. this.changeModelPointCount(model, 'sub');
  73023. this.updateMemoryUsage();
  73024. },
  73025. selectModel(model) {
  73026. var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  73027. var focus = arguments.length > 2 ? arguments[2] : undefined;
  73028. var by2d = arguments.length > 3 ? arguments[3] : undefined;
  73029. if (!model) {
  73030. model = this.selected;
  73031. state = false;
  73032. }
  73033. if (!by2d && model) {
  73034. model.dispatchEvent({
  73035. type: 'changeSelect',
  73036. selected: state,
  73037. clickPos: state
  73038. });
  73039. }
  73040. if (state) {
  73041. if (this.selected) {
  73042. if (this.selected == model) return;else {
  73043. var transToolAttached = !!this.transformControls.object;
  73044. this.selectModel(this.selected, false, focus /* , by2d */);
  73045. transToolAttached && this.transformControls.attach(model);
  73046. }
  73047. }
  73048. this.selected = model;
  73049. MergeEditor.focusOn(model, 500, !!focus); //通过在场景里点击模型的话,不focus
  73050. this.showModelOutline(model);
  73051. //this.updateEdgeStrength()
  73052. //console.log('selectModel', model)
  73053. } else {
  73054. if (this.selected != model) return; //model本来就没选中,不需要处理(防止2d先选中新的再取消旧的)
  73055. this.showModelOutline(model, false);
  73056. this.selected = null;
  73057. this.transformControls.detach(); //viewer.transformObject(null);
  73058. //console.log('selectModel', null)
  73059. }
  73060. this.bus.dispatchEvent('changeSelect');
  73061. },
  73062. updateBoxHelper(model) {
  73063. var size = new Vector3();
  73064. model.boundingBox.getSize(size);
  73065. size.multiply(model.getWorldScale(new Vector3()));
  73066. this.boxHelper.scale.copy(size);
  73067. var center = new Vector3();
  73068. model.boundingBox.getCenter(center);
  73069. center.applyMatrix4(model.matrixWorld);
  73070. this.boxHelper.position.copy(center);
  73071. model.getWorldQuaternion(this.boxHelper.quaternion);
  73072. viewer.dispatchEvent('content_changed');
  73073. },
  73074. showModelOutline(model, state) {
  73075. if (Potree.settings.selectShowBox || (model ? model.fileType == '3dgs' : this.boxHelper.visible)) {
  73076. //高斯很卡
  73077. if (state !== false) {
  73078. this.updateBoxHelper(model);
  73079. Potree.Utils.updateVisible(this.boxHelper, 'unselect', true);
  73080. } else {
  73081. Potree.Utils.updateVisible(this.boxHelper, 'unselect', false);
  73082. }
  73083. return;
  73084. }
  73085. if (this.fadeOutlineAuto) {
  73086. if (state === false) {
  73087. viewer.outlinePass.selectedObjects = [];
  73088. clearTimeout(this.timer);
  73089. return;
  73090. }
  73091. viewer.outlinePass.selectedObjects = [model];
  73092. if (this.timer) {
  73093. clearTimeout(this.timer);
  73094. }
  73095. this.timer = setTimeout(() => {
  73096. viewer.outlinePass.selectedObjects = [];
  73097. viewer.dispatchEvent('content_changed');
  73098. }, 1000);
  73099. } else {
  73100. if (state === false) {
  73101. viewer.outlinePass.selectedObjects = [];
  73102. } else {
  73103. viewer.outlinePass.selectedObjects = [model];
  73104. }
  73105. }
  73106. viewer.dispatchEvent('content_changed');
  73107. },
  73108. /*updateEdgeStrength(){
  73109. if(!this.selected)return
  73110. if(this.selected.isPointcloud){
  73111. viewer.outlinePass.edgeStrength = edgeStrengths.pointcloud// / this.selected.material.opacity
  73112. }else{
  73113. viewer.outlinePass.edgeStrength = edgeStrengths.glb
  73114. }
  73115. },*/
  73116. focusOn(objects) {
  73117. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 400;
  73118. var focus = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  73119. var dontLookUp = arguments.length > 3 ? arguments[3] : undefined;
  73120. var dir = arguments.length > 4 ? arguments[4] : undefined;
  73121. if (!(objects instanceof Array)) {
  73122. objects = [objects];
  73123. }
  73124. var points = []; //用points会更近一些准一点
  73125. var boundingBox = new Box3();
  73126. objects.forEach(object => {
  73127. points.push(...Common$1.getBoundPoints(object.boundingBox, object.matrixWorld));
  73128. boundingBox.union(object.bound /* object.boundingBox.clone().applyMatrix4(object.matrixWorld) */);
  73129. });
  73130. var len = boundingBox.getSize(new Vector3()).length();
  73131. Potree.settings.cameraFar = Math.max(Potree.settings.cameraFar, len * 3);
  73132. if (focus) {
  73133. viewer.focusOnObject({
  73134. boundingBox,
  73135. points
  73136. }, 'boundingBox', duration, {
  73137. boundScale: 0.8,
  73138. dontLookUp,
  73139. dontChangeCamDir: dir ? false : true,
  73140. dir
  73141. }); //boundScale小一点离近一点
  73142. } else {
  73143. /*
  73144. let position = viewer.inputHandler.intersect ? viewer.inputHandler.intersect.location : boundingBox.getCenter(new THREE.Vector3)
  73145. position && viewer.focusOnObject({position}, 'point', duration, {dontChangePos: true})
  73146. */
  73147. var position = viewer.inputHandler.intersect ? viewer.inputHandler.intersect.location : boundingBox.getCenter(new Vector3());
  73148. if (!position) return;
  73149. /* let targetOld = viewer.mainViewport.view.getPivot()
  73150. let projected1 = targetOld.clone().project(viewer.mainViewport.camera);
  73151. let projected2 = position.clone().project(viewer.mainViewport.camera); //使用其z
  73152. let targetNew = projected1.clone().setZ(projected2.z).unproject(viewer.mainViewport.camera);
  73153. viewer.mainViewport.view.lookAt(targetNew) */
  73154. viewer.mainViewport.view.radius = viewer.mainViewport.camera.position.distanceTo(position);
  73155. //为了不改画面,不调节方向了,只能调调radius,一定程度将target靠近model
  73156. }
  73157. },
  73158. moveBoundCenterTo(model, pos) {
  73159. //使boundCenter在所要的位置
  73160. var diff = new Vector3().subVectors(pos, model.boundCenter);
  73161. model.position.add(diff);
  73162. },
  73163. getBoundCenter(model) {
  73164. if (!model.boundCenter) {
  73165. model.boundCenter = new Vector3();
  73166. model.boundSize = new Vector3();
  73167. }
  73168. var bound = model.boundingBox.clone().applyMatrix4(model.matrixWorld);
  73169. bound.getCenter(model.boundCenter);
  73170. bound.getSize(model.boundSize);
  73171. model.bound = bound;
  73172. //model.boundingBox.getCenter(model.boundCenter).applyMatrix4(model.matrixWorld)
  73173. },
  73174. setModelBtmHeight(model, z) {
  73175. //无论模型怎么缩放、旋转,都使最低点为z
  73176. if (z == void 0) z = model.btmHeight; //维持离地高度
  73177. else model.btmHeight = z;
  73178. if (model.btmHeight == void 0) return;
  73179. model.updateMatrixWorld();
  73180. this.getBoundCenter(model);
  73181. /* let boundingBox2 = model.boundingBox.clone().applyMatrix4(model.matrixWorld)
  73182. let size = boundingBox2.getSize(new THREE.Vector3);
  73183. let center = boundingBox2.getCenter(new THREE.Vector3); */
  73184. var hopeZ = z + model.boundSize.z / 2;
  73185. //model.position.z = z + size.z / 2 - center.z
  73186. model.position.z += hopeZ - model.boundCenter.z;
  73187. },
  73188. computeBtmHeight(model) {
  73189. //位移之后重新计算btmHeight
  73190. model.updateMatrixWorld();
  73191. /* let boundingBox2 = model.boundingBox.clone().applyMatrix4(model.matrixWorld)
  73192. let size = boundingBox2.getSize(new THREE.Vector3);
  73193. let center = boundingBox2.getCenter(new THREE.Vector3); */
  73194. this.getBoundCenter(model);
  73195. model.btmHeight = model.boundCenter.z - model.boundSize.z / 2;
  73196. },
  73197. maintainBoundXY(model) {
  73198. //在旋转和缩放后,立即执行这个函数,使boundCenter保持原位
  73199. model.updateMatrixWorld();
  73200. var center1 = model.boundCenter.clone(); //还未更新的
  73201. this.getBoundCenter(model); //更新
  73202. var center2 = model.boundCenter.clone();
  73203. var diff = new Vector2().subVectors(center1, center2);
  73204. model.position.x += diff.x;
  73205. model.position.y += diff.y;
  73206. model.boundCenter.copy(center1);
  73207. },
  73208. maintainBoundCenter(model) {
  73209. model.updateMatrixWorld();
  73210. var center1 = model.boundCenter.clone(); //还未更新的
  73211. this.getBoundCenter(model); //更新
  73212. var center2 = model.boundCenter.clone();
  73213. var diff = new Vector3().subVectors(center1, center2);
  73214. model.position.add(diff);
  73215. model.boundCenter.copy(center1);
  73216. },
  73217. modelTransformCallback(model, force) {
  73218. model.updateMatrixWorld();
  73219. if (!force && model.matrixWorld.equals(model.lastMatrixWorld)) return;
  73220. viewer.scene.measurements.forEach(measure => {
  73221. var changed;
  73222. measure.points_datasets.forEach((dataset_id, i) => {
  73223. if (dataset_id == model.dataset_id) {
  73224. changed = true;
  73225. measure.points[i] = Potree.Utils.datasetPosTransform({
  73226. fromDataset: true,
  73227. datasetId: dataset_id,
  73228. position: measure.dataset_points[i].clone()
  73229. });
  73230. measure.updateMarker(measure.markers[i], measure.points[i]);
  73231. }
  73232. });
  73233. if (changed) {
  73234. //仿transformByPointcloud
  73235. measure.getPoint2dInfo(measure.points);
  73236. measure.update();
  73237. measure.setSelected(false); //隐藏edgelabel
  73238. }
  73239. });
  73240. viewer.tags.children.forEach(tag => {
  73241. if (tag.root == model) {
  73242. tag.titleLabel.updatePose();
  73243. }
  73244. });
  73245. viewer.scene.overlays.forEach(e => {
  73246. if (e.model == model) {
  73247. MergeEditor.getBoundCenter(e);
  73248. e.dispatchEvent('transformChanged');
  73249. }
  73250. });
  73251. //反向求transformMatrix 参考Alignment.js 移动漫游点
  73252. if (model.isPointcloud && model.transformMatrix) {
  73253. model.transformMatrix.multiplyMatrices(model.matrix, model.pos1MatrixInvert);
  73254. model.rotateMatrix = new Matrix4().makeRotationFromEuler(model.rotation);
  73255. model.panos.forEach(e => e.transformByPointcloud());
  73256. } else if (model.panos) {
  73257. model.rotateMatrix = new Matrix4().makeRotationFromEuler(model.rotation).multiply(model.rot1MatrixInvert);
  73258. model.transformMatrix.multiplyMatrices(model.matrix, model.posRot1MatrixInvert);
  73259. model.panos.forEach(e => e.transformByPointcloud());
  73260. //model.bound = model.boundingBox.clone().applyMatrix4(model.matrixWorld)
  73261. }
  73262. if (model.panos) {
  73263. model.transformInvMatrix.copy(model.transformMatrix).invert();
  73264. model.rotateInvMatrix.copy(model.rotateMatrix).invert();
  73265. model.panos.forEach(e => {
  73266. e.marker.scale.copy(model.scale);
  73267. });
  73268. }
  73269. model.lastMatrixWorld = model.matrixWorld.clone();
  73270. viewer.dispatchEvent('content_changed');
  73271. viewer.mapViewer && Potree.settings.showObjectsOnMap && viewer.mapViewer.dispatchEvent('content_changed');
  73272. //--------
  73273. this.selected == model && this.updateBoxHelper(model);
  73274. },
  73275. changeOpacity(model, opacity) {
  73276. var isRoot = model.dataset_id != void 0; //是否是最外层
  73277. if (model.isPointcloud) {
  73278. model.changePointOpacity(opacity);
  73279. //MergeEditor.updateEdgeStrength()
  73280. } else {
  73281. //model.traverse(e=>e.material && setOp(e, opacity))
  73282. model.traverse(mesh => {
  73283. if (mesh.material) {
  73284. var mats = mesh.material instanceof Array ? mesh.material : [mesh.material];
  73285. mats.forEach(mat => {
  73286. if (mat.originOpacity == void 0) {
  73287. mat.originOpacity = mesh.material.opacity;
  73288. mat.oriTransparent = mesh.material.oriTransparent;
  73289. }
  73290. mat.opacity = mat.originOpacity * opacity;
  73291. if (mat.opacity < 1) {
  73292. mat.transparent = true;
  73293. /* if(model.isPointcloud){
  73294. mesh.changePointOpacity(realOpacity)
  73295. }else{
  73296. mesh.material.opacity = realOpacity
  73297. } */
  73298. mesh.renderOrder = Potree.config.renderOrders.model + 1; //如果是一个mesh多个material咋整? obj的。 暂时默认全部opacity一样吧
  73299. //mesh.material.depthWrite = false
  73300. } else {
  73301. mat.transparent = model.is4dkkModel || model.fileType == '3dTiles' ? false : mat.oriTransparent; //有的贴图含透明度
  73302. mesh.renderOrder = Potree.config.renderOrders.model;
  73303. //mesh.material.depthWrite = true
  73304. }
  73305. mat.depthWrite = mat.opacity > 0.5; //防止的mesh之间完全遮挡,去掉write。write为true会完全遮挡后排的物体。没有write之后需要对渲染排序(three会排序,但有的角度会错)
  73306. });
  73307. }
  73308. });
  73309. }
  73310. isRoot && (model.opacity = opacity); //记录在最外层
  73311. viewer.dispatchEvent('content_changed');
  73312. },
  73313. addTitleForModel(model) {
  73314. var titleLabel = new TextSprite$2({
  73315. startClipDis: 0.5,
  73316. clipDistance: 1,
  73317. //消失距离
  73318. startOcclusDis: 0.5,
  73319. occlusionDistance: 0.9,
  73320. //变为backColor距离
  73321. maxOcclusionFactor: 0.7,
  73322. maxClipFactor: 1,
  73323. text: model.name,
  73324. sizeInfo: {
  73325. width2d: 200
  73326. },
  73327. rectBorderThick: 1,
  73328. borderColor: {
  73329. r: 200,
  73330. g: 200,
  73331. b: 200,
  73332. a: 0.5
  73333. },
  73334. textColor: {
  73335. r: 255,
  73336. g: 255,
  73337. b: 255,
  73338. a: 1.0
  73339. },
  73340. //textshadowColor:'black',
  73341. backgroundColor: {
  73342. r: 0,
  73343. g: 0,
  73344. b: 0,
  73345. a: 0.3
  73346. },
  73347. borderRadius: 6,
  73348. fontsize: 20,
  73349. fontWeight: '',
  73350. //thick
  73351. renderOrder: Potree.config.renderOrders.tag.label,
  73352. pickOrder: Potree.config.renderOrders.tag.label,
  73353. useDepth: true,
  73354. maxLineWidth: 300,
  73355. transform2Dpercent: {
  73356. x: 0,
  73357. y: 0.5
  73358. },
  73359. //向上移动一半
  73360. textAlign: Potree.settings.isOfficial && 'left'
  73361. });
  73362. model.titleLabel = titleLabel;
  73363. viewer.scene.scene.add(titleLabel);
  73364. var updatePos = () => {
  73365. titleLabel.position.copy(model.boundCenter);
  73366. titleLabel.position.z += model.boundSize.z * 0.55; //暂时加载模型顶部,但也可能如果旋转了要在头顶
  73367. titleLabel.updatePose();
  73368. };
  73369. var setVisible = () => {
  73370. Potree.Utils.updateVisible(titleLabel, 'followModel', model.visible);
  73371. viewer.dispatchEvent('content_changed');
  73372. };
  73373. model.addEventListener('transformChanged', updatePos);
  73374. model.addEventListener('isVisible', setVisible);
  73375. titleLabel.addEventListener('isVisible', () => {
  73376. titleLabel.visible && updatePos();
  73377. });
  73378. setVisible();
  73379. updatePos();
  73380. },
  73381. updateMemoryUsage1() {
  73382. //obj暂时不管其贴图大小, 因为顶点造成的不仅是内存还有卡顿所以先只看顶点
  73383. var maxMemory = Potree.config.tiles3DMaxMemory + 100; //M 实际估计是这个的10倍
  73384. var eachObjPosWeight = 100 / 1000 / 1000; //M 每个顶点pos是3*4个字节?法线3*4和uv2*4 其实还有贴图
  73385. var eachCloudPointWeight = 12 / 1000 / 1000; //M 每个点 pos + 颜色 + 法线 大概
  73386. var eachVisiCPointWeight = eachCloudPointWeight * 5; // 或 maxMemory / (6*1000*1000) 大概值接近 (再除以一个数是因为显示的要比内存中的耗更多资源
  73387. var eachGltfPosWeight = 100 / 1000 / 1000; //M 每个顶点pos是3*4个字节?法线3*4和uv2*4 其实还有贴图
  73388. var posCount = 0;
  73389. var eachTexPxWeight = 1 / 10 / 1000 / 1000; //不知道“图片缓存”会不会引起崩溃, 它不在“内存占用空间”中, 所以单位weight值设置小一点
  73390. var panosWeight = viewer.images360.panos.filter(e => e.depthTex).length * 0.7 + viewer.images360.tileDownloader.tilesCount * 512 * 512 * eachTexPxWeight; //深度图和全景图
  73391. var texArea = 0;
  73392. viewer.objs.children.forEach(e => {
  73393. if (!e.visible) return;
  73394. if (e.fileType == 'glb' || e.fileType == 'obj') {
  73395. e.traverse(mesh => {
  73396. var _mesh$material;
  73397. if (mesh.geometry) {
  73398. posCount += mesh.geometry.attributes.position.count;
  73399. }
  73400. if ((_mesh$material = mesh.material) !== null && _mesh$material !== void 0 && _mesh$material.map) {
  73401. var _mesh$material2, _mesh$material3;
  73402. texArea += ((_mesh$material2 = mesh.material) === null || _mesh$material2 === void 0 ? void 0 : _mesh$material2.map.image.width) * ((_mesh$material3 = mesh.material) === null || _mesh$material3 === void 0 ? void 0 : _mesh$material3.map.image.height);
  73403. }
  73404. });
  73405. } else if (e.fileType == '3dTiles') {}
  73406. });
  73407. //获取点云的内存限制
  73408. var objWeight = posCount * eachObjPosWeight + texArea * eachTexPxWeight;
  73409. var laserWeight = Potree.numVisiblePoints * eachCloudPointWeight; //点云实际显示所占大小
  73410. var laserMemoryWeight = Potree.lru.numPoints * eachCloudPointWeight; //点云所使用内存大小
  73411. var tiles3DWeight = (viewer.visiVertexCount || 0) * eachGltfPosWeight; //M 3dTiles所占内存大小
  73412. var tiles3DMemoryWeight = viewer.tiles3dMemoryUsage / 1000 / 1000; //M 3dTiles显示的所占内存大小
  73413. /* let min = 0.1, max = 6, minP = 100, maxP = 1000000;
  73414. let ratio = Math.round(math.linearClamp(score, minP, maxP, max, min )); */
  73415. var rest = maxMemory - objWeight - tiles3DWeight - panosWeight;
  73416. Potree.pointBudget = MathUtils.clamp(Math.round(rest / eachVisiCPointWeight), Potree.config.pointDensity.low.pointBudget, 1.5 * Potree.config.pointDensity.high.pointBudget);
  73417. //Potree.settings.maxLRUPoints
  73418. //获取3dTiles的内存限制
  73419. var tiles3DMaxMemory = maxMemory - Math.round(objWeight + laserWeight + panosWeight);
  73420. window.cesiumViewer && (tiles3DMaxMemory -= 30);
  73421. Potree.settings.tiles3DMaxMemory = MathUtils.clamp(tiles3DMaxMemory, 30, Potree.config.tiles3DMaxMemory);
  73422. //还存在的问题:仍然有隐患,因为没用到真实缓存的大小: tiles3DMemoryWeight laserMemoryWeight, 它们比真实可见的要多。不使用是因为它们无法反应出实际需要的内存量,缓存是只增不减
  73423. //obj等普通mesh限制不了
  73424. //console.log('objWeight',objWeight.toFixed(1), 'laserMemoryWeight',laserMemoryWeight.toFixed(1), 'tiles3DWeight',tiles3DWeight.toFixed(1), 'pointBudget',Potree.pointBudget, 'tiles3DMaxMemory',tiles3DMaxMemory)
  73425. //总内存 = 内存占用空间+图片缓存 , obj的缓存比较多在图片中
  73426. //尽量使任务管理器里的内存占用空间不超过2G
  73427. /*
  73428. 崩溃历史:
  73429. cesium容易先崩溃,并弹窗报An error occurred while rendering. Rendering has stopped.
  73430. 体育中心:http://192.168.0.140/index.html?caseId=1&app=1&token=1#/fuseEdit/path
  73431. 罗敏电脑崩溃 ,报了ces的崩溃错误。内存占用空间2196M, memory.usedJSheapSize:1812M 崩溃时正在外部浏览模型(导览崩溃过),可能是3dtiles
  73432. */
  73433. },
  73434. updateMemoryUsage() {
  73435. //新 注意 模型即使隐藏也不会降低内存占用,只是会降低卡顿。 未支持3dgs
  73436. //疑问:1 在不超过最大内存的前提下会因为显示太多模型崩溃吗? 2如何获知每个浏览器最大内存支持?看了一圈,jsHeapSizeLimit都一样怎么办?
  73437. //3dtiles(或模型)的大小是直接用文件大小还是根据点和贴图尺寸计算呢,感觉它会分成两部分,加载的和显示的,都需要考虑。
  73438. //obj暂时不管其贴图大小, 因为顶点造成的不仅是内存还有卡顿所以先只看顶点
  73439. if (window.stopUpdateM) return;
  73440. //let start = performance.now();
  73441. var old = {
  73442. pointBudget: Potree.pointBudget,
  73443. tiles3DMaxMemory: Potree.settings.tiles3DMaxMemory,
  73444. maxLRUPoints: Potree.settings.maxLRUPoints
  73445. };
  73446. var maxMemory = 1500; //1500 //M 整体占用内存限制 (不考虑峰值,要等静止后退下来的值) //什么都不加载可能就占了300M
  73447. var eachObjPosWeight = 100 / 1000 / 1000; //M 每个顶点pos是3*4个字节?法线3*4和uv2*4 + faceIndex比较难说
  73448. var eachCloudPointWeight = 70 / 1000 / 1000; //M 每个点 pos + 颜色 + 法线 大概 根据测试算出来也是这个值 0.00007
  73449. //const eachVisiCPointWeight = eachCloudPointWeight * 5 // 或 maxMemory / (6*1000*1000) 大概值接近 (再除以一个数是因为显示的要比内存中的耗更多资源
  73450. var eachTexPxWeight = 1 / 10 / 1000 / 1000; //每个模型都不一样只能取个大概
  73451. var eachTexPxWeightTiles = eachTexPxWeight * 1.5; //感觉3dtiles的比glb和obj都高很多,是因为文件还在缓存里吗
  73452. var posCount = 0,
  73453. posCount3dTiles = 0,
  73454. visiPosCount = 0;
  73455. var panosWeight = 0.1 * (viewer.images360.panos.filter(e => e.depthTex).length * 0.7 + viewer.images360.tileDownloader.tilesCount * 512 * 512 * eachTexPxWeight); //深度图和全景图(但似乎是额外放图片缓存里?因为没有增加tex, panoExit后就dispose了, 所以乘以一个小系数。担心图片缓存也可能导致崩溃)
  73456. //let texArea = 0, texArea3dTiles = 0, visiTexArea = 0
  73457. //texArea = viewer.memoryModelCountInfo.otherTexArea + viewer.memoryModelCountInfo.tileTexArea
  73458. //posCount = viewer.memoryModelCountInfo.otherPosCount + viewer.memoryModelCountInfo.tilePosCount
  73459. //posCount3dTiles = viewer.memoryModelCountInfo.tilePosCount
  73460. //texArea3dTiles = viewer.memoryModelCountInfo.tileTexArea
  73461. var otherModelWeight = viewer.memoryModelCountInfo.otherPosCount * eachObjPosWeight + viewer.memoryModelCountInfo.otherTexArea * eachTexPxWeight;
  73462. var tilesWeight = (viewer.memoryModelCountInfo.tilePosCount * eachObjPosWeight + viewer.memoryModelCountInfo.tileTexArea * eachTexPxWeightTiles) * 1.5; //3dtiles太占内存了
  73463. var modelWeight = tilesWeight + otherModelWeight; //posCount*eachObjPosWeight + texArea * eachTexPxWeight
  73464. //为何obj、glb过后会降很多,而3dtiles降的很少? 不过考虑到glb更卡,且加载瞬间确实占用高,还是不把otherModelWeight改少了吧
  73465. Potree.tilesWeight = tilesWeight;
  73466. Potree.modelWeight = modelWeight; //所有模型
  73467. //Potree.modelVisiWeight = visiPosCount*eachObjPosWeight + visiTexArea * eachTexPxWeight
  73468. //经测试,发现模型并不会因为不可见而降低内存,3dtiles加载满了之后拉远,可见weight下降了但内存没降。
  73469. //so,需要测试崩溃是否只与内存有关,如果内存爆了,但都不可见,非常流畅,还会崩溃吗
  73470. var laserVisiWeight = Potree.numVisiblePoints * eachCloudPointWeight; //点云实际显示所占大小
  73471. var laserWeight = Potree.lru.numPoints * eachCloudPointWeight; //点云所使用内存大小
  73472. Potree.laserWeight = laserWeight;
  73473. var fixedPart = modelWeight - tilesWeight + panosWeight + (window.cesiumViewer ? 30 : 0); //ces:刚加载时60,静止一段时间后20
  73474. Potree.allWeight = Potree.laserWeight + fixedPart + tilesWeight;
  73475. var tiles3dMemoryUsage = viewer.tiles3dMemoryUsage / 1024 / 1024;
  73476. var overRatio = Potree.allWeight / maxMemory;
  73477. var visiRatio1 = posCount3dTiles == 0 ? Infinity : viewer.visiVertexCount / posCount3dTiles;
  73478. var visiRatio2 = Potree.lru.numPoints == 0 ? Infinity : Potree.numVisiblePoints / Potree.lru.numPoints;
  73479. var resolved;
  73480. var restMemory = maxMemory - fixedPart; //去除固定的part后
  73481. if (overRatio > 1) {
  73482. var MinRestMemory = 400;
  73483. if (restMemory < MinRestMemory) {
  73484. Common$1.intervalTool.isWaiting('updateMemoryUsage', () => {
  73485. var warnText;
  73486. if (this.lastMemoryState.restMemory < 0) {
  73487. warnText = '固定内存已经超额!没有剩余空间给点云和3dtiles。';
  73488. } else if (this.lastMemoryState.restMemory < MinRestMemory) {
  73489. warnText = '固定内存过多!';
  73490. }
  73491. if (warnText) {
  73492. warnText += '请减少glb类模型, 当前固定内存占用大小:' + fixedPart;
  73493. console.error(warnText);
  73494. }
  73495. }, 10000);
  73496. }
  73497. if (visiRatio1 < visiRatio2 || Potree.lru.numPoints <= Potree.config.pointDensity.low.pointBudget / 10 * 1.1) {
  73498. //占比小的需要缩减缓存容器
  73499. if (Potree.settings.tiles3DMaxMemory < tiles3dMemoryUsage / 2 && this.lastMemoryState.tiles3dMemoryUsage == tiles3dMemoryUsage //已经很难减少了,这时候tiles3DMaxMemory很可能降到个位数
  73500. || Potree.settings.tiles3DMaxMemory < 2) {
  73501. resolved = false;
  73502. } else {
  73503. Potree.settings.tiles3DMaxMemory = Math.min(tiles3dMemoryUsage, Potree.settings.tiles3DMaxMemory); //先降到已使用的数据量
  73504. Potree.settings.tiles3DMaxMemory > 1 && (Potree.settings.tiles3DMaxMemory *= 0.8); //注意,降低该值不一定会降低 tiles3dMemoryUsage,只有后续改变sse才行 viewer.tiles3dMemoryUsage / tiles3DMaxMemory 可能大于1
  73505. resolved = true;
  73506. }
  73507. }
  73508. if (!resolved) {
  73509. // visiRatio1 > visiRatio2
  73510. if (visiRatio2 > 0.9) {
  73511. //压缩太小了,或者说没什么缓存就超额了,只能继续减少显示个数
  73512. if (Potree.pointBudget < Potree.config.pointDensity.low.pointBudget) {
  73513. //console.error('Potree.pointBudget已经很小了!', Potree.pointBudget)
  73514. } else {
  73515. Potree.pointBudget *= 0.85;
  73516. resolved = true;
  73517. }
  73518. } else {
  73519. Potree.pointBudget = MathUtils.clamp(Potree.numVisiblePoints, Potree.config.pointDensity.low.pointBudget / 10, Potree.pointBudget * 0.8); //先往降到可见数量方向降 (当画面中可见点确实很少时允许降低到low之下)
  73520. Potree.settings.maxLRUPoints = Math.min(Potree.lru.numPoints, Potree.settings.maxLRUPoints); //先降到已使用的数量
  73521. Potree.settings.maxLRUPoints *= 0.8;
  73522. resolved = true;
  73523. }
  73524. }
  73525. } else {
  73526. //恢复部分好难写
  73527. //优先恢复实际使用(可见)内存,然后是缓存
  73528. //额外缓存少的,实际使用内存被压缩的概率也大
  73529. //visiRatio1 == Infinity && (visiRatio1 = 0) //因这里大的才会被改所以改一下
  73530. visiRatio1 *= tiles3dMemoryUsage / Potree.settings.tiles3DMaxMemory; //用point数量有时候不准,明明内存不够了不可见的tile还存在,所以×memory的占比
  73531. visiRatio2 = Potree.pointBudget == 0 ? 0 : Potree.numVisiblePoints / Potree.pointBudget; //使用率越高,说明越需要内存. 因为恢复时先提高使用内存所以改一下
  73532. var r = Math.min(1, visiRatio1, visiRatio2); //如果另一个visiRatio 很小,s就可以再小一些,使内存超过一点,然后朝另一方倾斜,另一方去缩减
  73533. var s = 1 - Math.max(0.8, overRatio * r);
  73534. //太难判断是哪个更需要内存了,所以两个都涨吧
  73535. if (visiRatio2 > visiRatio1) {
  73536. var s_ = visiRatio2 / (visiRatio1 + visiRatio2) * s + 1;
  73537. var addCount = 500000 * s_;
  73538. if (Potree.pointBudget < Potree.config.pointDensity.high.pointBudget * 0.9) {
  73539. Potree.pointBudget += addCount;
  73540. } else {
  73541. Potree.settings.maxLRUPoints += addCount;
  73542. }
  73543. }
  73544. if (Potree.settings.tiles3DMaxMemory < Potree.config.tiles3DMaxMemory) {
  73545. var _s_ = visiRatio1 / (visiRatio1 + visiRatio2) * s + 1;
  73546. var _addCount = 20 * _s_;
  73547. Potree.settings.tiles3DMaxMemory += _addCount;
  73548. Potree.settings.tiles3DMaxMemory = Math.min(Potree.settings.tiles3DMaxMemory, Potree.config.tiles3DMaxMemory);
  73549. }
  73550. resolved = true;
  73551. }
  73552. var min = overRatio > 1 ? 1.1 : 1.5,
  73553. max = 5;
  73554. Potree.settings.maxLRUPoints = MathUtils.clamp(Potree.settings.maxLRUPoints, Potree.pointBudget * min, Potree.pointBudget * max);
  73555. //压缩时先压缩缓存,然后是使用内存; 恢复时相反。
  73556. //3dtiles不像点云那样可以在加载时拦截,使不高于tiles3DMaxMemory,只能自动动态调节maxSSE,所以有可能调节完还是降低不了
  73557. //一次只更新一点,一点点调节,因为可能不是一个原因造成
  73558. var changed;
  73559. if (old.pointBudget != Potree.pointBudget || old.tiles3DMaxMemory != Potree.settings.tiles3DMaxMemory || old.maxLRUPoints != Potree.settings.maxLRUPoints) {
  73560. if (old.tiles3DMaxMemory != Potree.settings.tiles3DMaxMemory) {
  73561. viewer.setAllTilesets(model => {
  73562. model.runtime.getTileset().nextForceUpdate = true;
  73563. model.runtime.getTileset().needRenderNext = true;
  73564. });
  73565. } else {
  73566. viewer.dispatchEvent('content_changed');
  73567. }
  73568. changed = true;
  73569. }
  73570. {
  73571. var mSSE = math.linearClamp(Potree.fpsRendered2, [2, 52], [500, 70]); //有效降低卡顿 和贴图变白概率。越卡越提高msse
  73572. var _r = tiles3dMemoryUsage / Potree.settings.tiles3DMaxMemory;
  73573. viewer.setAllTilesets(model => {
  73574. var tileset = model.runtime.getTileset();
  73575. tileset.options.initialMaxSSE = mSSE;
  73576. var e = tileset.options.maximumScreenSpaceError * MathUtils.clamp(_r, 0.8, 1.2);
  73577. e = MathUtils.clamp(e, mSSE, mSSE + 400); //如果有很卡的模型可能需要1000,但太高了降回来很慢,就假设模型都正常的吧
  73578. tileset.options.maximumScreenSpaceError = e;
  73579. });
  73580. }
  73581. //针对很卡的设备:(卡的也容易崩溃)
  73582. Potree.config.pointDensity.high.pointBudget = math.linearClamp(Potree.fpsRendered2, [2, 50], [1e6, 6e6]);
  73583. var history = this.lastMemoryState.history || [];
  73584. history.push(overRatio);
  73585. this.lastMemoryState = {
  73586. tiles3dMemoryUsage,
  73587. history,
  73588. restMemory
  73589. };
  73590. //console.log('cost', performance.now() - start)
  73591. return changed && (overRatio > 1.1 || overRatio < 0.9 || history.slice(-7).length < 7 || history.slice(-7).some(overRatio => overRatio > 1.1 || overRatio < 0.9) //后十个都在最大内存范围左右抖动,则不继续更新,直到相机变化
  73592. );
  73593. //难点:要防止抖动,否则3dtiles的sse变大变小,相机静止时还在清晰和模糊间变来变去。好在点云是可以较精细调节,tile是间接控制的
  73594. //模型删除后还会占用一定内存,尤其是3dtile几乎降不了,怎么回事?是否删除的模型还要算进来
  73595. },
  73596. setGroundPlaneImg(src, scale, angle) {
  73597. //设置地面图
  73598. this.goundScale = scale || 1, this.goundAngle = angle || 0;
  73599. var oldSrc = this.curGroundImgSrc;
  73600. this.curGroundImgSrc = src;
  73601. var ratio = 0.03;
  73602. if (src) {
  73603. if (oldSrc == src && this.groundPlane.material.map.image) {
  73604. //仅修改大小
  73605. var s = ratio * this.goundScale;
  73606. var {
  73607. width,
  73608. height
  73609. } = this.groundPlane.material.map.image;
  73610. this.groundPlane.scale.set(width * s, height * s);
  73611. viewer.dispatchEvent('content_changed');
  73612. this.groundPlane.rotation.z = MathUtils.degToRad(this.goundAngle);
  73613. return;
  73614. }
  73615. var map = texLoader$d.load(src, tex => {
  73616. if (this.curGroundImgSrc == src) {
  73617. var _s = ratio * this.goundScale;
  73618. this.groundPlane.scale.set(tex.image.width * _s, tex.image.height * _s);
  73619. this.groundPlane.rotation.z = MathUtils.degToRad(this.goundAngle);
  73620. viewer.dispatchEvent('content_changed');
  73621. }
  73622. });
  73623. Potree.Utils.makeTexDontResize(map);
  73624. if (!this.groundPlane) {
  73625. this.groundPlane = new Mesh(new PlaneBufferGeometry(1, 1, 1), new MeshBasicMaterial({
  73626. map,
  73627. side: 2
  73628. }));
  73629. viewer.scene.scene.add(this.groundPlane);
  73630. this.groundPlane.position.z = 0.1;
  73631. } else {
  73632. this.groundPlane.material.map = map;
  73633. }
  73634. Potree.Utils.updateVisible(this.groundPlane, 'show', true);
  73635. } else {
  73636. this.groundPlane && Potree.Utils.updateVisible(this.groundPlane, 'show', false);
  73637. }
  73638. }
  73639. };
  73640. /* class titleLabel extends THREE.Shim.FollowRootObject{
  73641. constructor(o){
  73642. super(o.root)
  73643. this.l
  73644. }
  73645. } */
  73646. /*
  73647. note:
  73648. 要注意getHoveredElements只在getIntersect时才使interactables包含加载的model, 也就是model上不能有使之成为interactables的事件,否则在鼠标hover到模型上开始转动的一瞬间很卡。
  73649. 控制台断开完全重合的漫游点的方法
  73650. window.pano1 = viewer.modules.PanoEditor.selectedPano //选中第一个点后输入这行,得到第一个漫游点
  73651. window.pano2 = viewer.modules.PanoEditor.selectedPano //选中第二个点后输入这行,得到第二个漫游点
  73652. viewer.modules.PanoEditor.linkChange(window.pano1, window.pano2, 'remove') //断开链接
  73653. 如果直接刷新,内存管理器中的内存会有之前的残留。不知道是不是真实的加入这次的内存了。
  73654. 并且,如果第一次加载的是几乎不占内存的模型,如glb,内存也会一下子涨30,不过等一会儿会降。4M的3dtiles会涨60. 每次加载模型后都会内存突增,但过后会降。 为何obj、glb过后会降很多,而3dtiles降的很少。?
  73655. 国产系统8192贴图直接出错,4096的贴图过多也出错。texImage: Driver ran out of memory during upload.
  73656. ======和4dkk的对应=========
  73657. 4dkk模型无论是否是3dtiles都能和点云的坐标对应。
  73658. 如3dtiles的导入后能和其panos对应,见load4dkkPanos。要和点云对应的话搜prop.raw.orientation
  73659. 而4dkk非3dtile的模型导入融合后模型一致bound不变。
  73660. 关键:4dkk和laser的panos坐标一致(laser的originPosition)
  73661. ===========================
  73662. */
  73663. var texLoader$e = new TextureLoader();
  73664. var arrowSpacing = 1; //间隔
  73665. var arrowSize = arrowSpacing * 0.5;
  73666. var planeGeo$5 = new PlaneBufferGeometry(1, 1);
  73667. var sphereSizeInfo = {
  73668. nearBound: 0.1,
  73669. farBound: 25,
  73670. minSize: 50,
  73671. maxSize: 200 //scale:arrowSize, restricMeshScale : true,
  73672. };
  73673. //const arrowsShowingCount = 25; //场景里最多展示多少个箭头
  73674. var arrowShowMinDis = 10;
  73675. class RouteGuider extends EventDispatcher {
  73676. constructor() {
  73677. super();
  73678. this.route = [];
  73679. this.curve = [];
  73680. this.scenePoints = [];
  73681. this.sceneMeshGroup = new Object3D();
  73682. this.mapMeshGroup = new Object3D();
  73683. this.generateDeferred;
  73684. viewer.addEventListener('loadPointCloudDone', this.init.bind(this));
  73685. this.lastResult; //保存上一个的结果,以便于反向
  73686. this.datasetIds = []; //起始和终点的datasetId
  73687. }
  73688. init() {
  73689. if (this.inited) return;
  73690. var zoom,
  73691. resolution = new Vector2();
  73692. viewer.mapViewer.addEventListener('camera_changed', e => {
  73693. if (!this.routeStart || !this.routeEnd) return;
  73694. var camera = e.viewport.camera;
  73695. if (camera.zoom != zoom || !resolution.equals(e.viewport.resolution)) {
  73696. Common$1.intervalTool.isWaiting('routeCameraInterval', () => {
  73697. //延时update,防止卡顿
  73698. if (camera.zoom != zoom || !resolution.equals(e.viewport.resolution)) {
  73699. //console.log('updateMapArrows')
  73700. this.updateMapArrows(true);
  73701. zoom = camera.zoom;
  73702. resolution.copy(e.viewport.resolution);
  73703. }
  73704. }, browser.isMobile() ? 500 : 200);
  73705. }
  73706. });
  73707. viewer.addEventListener('camera_changed', e => {
  73708. if (!this.routeStart || !this.routeEnd || !e.changeInfo.positionChanged) return;
  73709. Common$1.intervalTool.isWaiting('routeCameraInterval2', () => {
  73710. //延时update,防止卡顿
  73711. this.updateArrowDisplay();
  73712. }, 1000);
  73713. });
  73714. var polesMats = {
  73715. shadowMat: new MeshBasicMaterial({
  73716. transparent: true,
  73717. depthTest: false,
  73718. map: texLoader$e.load(Potree.resourcePath + '/textures/pano_instruction_bottomMarker.png')
  73719. }),
  73720. sphereMat: new MeshBasicMaterial({
  73721. transparent: true,
  73722. depthTest: false,
  73723. map: texLoader$e.load(Potree.resourcePath + '/textures/whiteCircle.png')
  73724. }),
  73725. hatMats: {
  73726. start: new MeshBasicMaterial({
  73727. transparent: true,
  73728. depthTest: false,
  73729. map: texLoader$e.load(Potree.resourcePath + '/textures/pano_instruction_start_route.png')
  73730. }),
  73731. end: new MeshBasicMaterial({
  73732. transparent: true,
  73733. depthTest: false,
  73734. map: texLoader$e.load(Potree.resourcePath + '/textures/pano_instruction_target_reached.png')
  73735. })
  73736. }
  73737. };
  73738. polesMats.shadowMat.map.anisotropy = 4;
  73739. this.poleStart = this.createPole(polesMats, 'start');
  73740. this.poleEnd = this.createPole(polesMats, 'end');
  73741. this.sceneMeshGroup.add(this.poleStart);
  73742. this.sceneMeshGroup.add(this.poleEnd);
  73743. var map = texLoader$e.load(Potree.resourcePath + '/textures/routePoint_panorama.png');
  73744. map.anisotropy = 4; // 各向异性过滤 .防止倾斜模糊
  73745. this.arrow = new Mesh(planeGeo$5, new MeshBasicMaterial({
  73746. transparent: true,
  73747. depthTest: false,
  73748. map
  73749. }));
  73750. this.arrow.scale.set(arrowSize, arrowSize, arrowSize);
  73751. Potree.Utils.setObjectLayers(this.arrow, 'sceneObjects');
  73752. /* this.testArrow = this.arrow.clone();
  73753. this.testArrow.material = this.arrow.material.clone()
  73754. this.testArrow.material.color = 'red' */
  73755. this.arrows = new Object3D();
  73756. this.sceneMeshGroup.add(this.arrows);
  73757. Potree.Utils.setObjectLayers(this.sceneMeshGroup, 'sceneObjects');
  73758. //this.sceneMeshGroup.traverse(e=>e.renderOrder = 90)
  73759. viewer.scene.scene.add(this.sceneMeshGroup);
  73760. this.sceneMeshGroup.visible = false;
  73761. this.poleStart.visible = false;
  73762. this.poleEnd.visible = false;
  73763. //-------------map---------------------
  73764. /* this.mapMarkStart = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  73765. transparent:true, depthTest:false,
  73766. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_start_route.png' )
  73767. }))
  73768. this.mapMarkEnd = new THREE.Mesh( planeGeo, new THREE.MeshBasicMaterial({
  73769. transparent:true, depthTest:false,
  73770. map: texLoader.load(Potree.resourcePath+'/textures/map_instruction_target_reached.png' )
  73771. }))
  73772. this.mapMarkStart.renderOrder = this.mapMarkEnd.renderOrder = 2//在箭头之上 */
  73773. var map2 = texLoader$e.load(Potree.resourcePath + '/textures/routePoint_map_fsna.png');
  73774. this.mapArrowMats = {
  73775. default: new MeshBasicMaterial({
  73776. transparent: true,
  73777. depthTest: false,
  73778. map: map2
  73779. }),
  73780. fade: new MeshBasicMaterial({
  73781. transparent: true,
  73782. depthTest: false,
  73783. map: map2,
  73784. opacity: 0.4
  73785. })
  73786. };
  73787. this.mapArrow = new Mesh(planeGeo$5, this.mapArrowMats.default);
  73788. this.mapArrow.scale.set(arrowSize, arrowSize, arrowSize);
  73789. this.mapArrows = new Object3D();
  73790. this.mapArrows.name = 'mapArrows';
  73791. this.mapMeshGroup.add(this.mapArrows);
  73792. this.mapMeshGroup.name = 'mapRouteLayer';
  73793. this.mapMeshGroup.visible = false;
  73794. viewer.mapViewer.dispatchEvent({
  73795. type: 'add',
  73796. object: this.mapMeshGroup,
  73797. name: 'route'
  73798. });
  73799. this.mapArrow.layers.mask = this.mapArrows.layers.mask; // 修改成和map中的layer一样的
  73800. viewer.modules.SiteModel.bus.addEventListener('FloorChange', () => {
  73801. if (this.routeStart && this.routeEnd) {
  73802. this.updateOpacityAtMap();
  73803. }
  73804. });
  73805. this.inited = true;
  73806. }
  73807. updateOpacityAtMap() {
  73808. //只有当前楼层的透明度为1
  73809. var currentFloor = viewer.modules.SiteModel.currentFloor;
  73810. //console.log('updateOpacityAtMap', currentFloor && currentFloor.name)
  73811. var lift = 0.3; // 因为发送请求时用的是floorPosition的高度,而它可能会到画好的floor之下,所以有误差
  73812. this.mapArrows.children.forEach((arrow, index) => {
  73813. var pos = this.mapPoints[index].clone();
  73814. pos.z += lift;
  73815. var inSide = currentFloor && currentFloor.ifContainsPoint(pos);
  73816. arrow.material = inSide ? this.mapArrowMats.default : this.mapArrowMats.fade;
  73817. //console.log('arrow',index, arrow.material.opacity)
  73818. });
  73819. viewer.mapViewer.dispatchEvent('content_changed');
  73820. } //但是如果楼层刚好只框柱相机位置而没框住地面位置就不好了……
  73821. createPole(polesMats, name) {
  73822. var height = 1.5,
  73823. sphereCount = 6,
  73824. shadowSize = 0.5 /* sphereSizeInfo.scale */,
  73825. sphereSize = 0.05;
  73826. var group = new Object3D();
  73827. group.name = 'pole_' + name;
  73828. var shadow = new Mesh(planeGeo$5, polesMats.shadowMat);
  73829. shadow.scale.set(shadowSize, shadowSize, shadowSize);
  73830. var sliceDis = height / (sphereCount + 1);
  73831. group.add(shadow);
  73832. for (var i = 0; i < sphereCount; i++) {
  73833. var sphere = new Sprite$2({
  73834. mat: polesMats.sphereMat,
  73835. renderOrder: 3
  73836. });
  73837. sphere.position.set(0, 0, sliceDis * (i + 1));
  73838. sphere.scale.set(sphereSize, sphereSize, sphereSize);
  73839. //sphere.visible = false
  73840. group.add(sphere);
  73841. }
  73842. var hatSphere = new Sprite$2({
  73843. mat: polesMats.hatMats[name],
  73844. sizeInfo: sphereSizeInfo,
  73845. renderOrder: 4
  73846. });
  73847. //sphere.visible = false
  73848. hatSphere.position.set(0, 0, height);
  73849. hatSphere.scale.copy(shadow.scale);
  73850. group.add(hatSphere);
  73851. group.hatSphere = hatSphere;
  73852. return group;
  73853. }
  73854. addTestArrow() {}
  73855. addArrow(position) {
  73856. var arrow = this.arrow.clone();
  73857. arrow.position.copy(position);
  73858. this.arrows.add(arrow);
  73859. }
  73860. addMapArrow(position) {
  73861. var mapArrow = this.mapArrow.clone();
  73862. mapArrow.position.copy(position).setZ(0);
  73863. this.mapArrows.add(mapArrow);
  73864. }
  73865. setArrowDir(arrows, index) {
  73866. var arrow = arrows[index];
  73867. var nextOne = arrows[index + 1];
  73868. var nextPos = nextOne ? nextOne.position : this.endPolePos; //routeEnd
  73869. var direction = new Vector3().subVectors(arrow.position, nextPos).setZ(0);
  73870. //direction.normalize();
  73871. //console.log(direction.toArray())
  73872. var angle = Math.atan2(direction.y, direction.x) + Math.PI / 2; //Math.PI/2是因为贴图本身箭头方向不朝x
  73873. arrow.rotation.z = angle;
  73874. //console.log(angle)
  73875. }
  73876. setRouteStart(pos, dealZ, datasetId) {
  73877. if (this.routeStart && pos && this.routeStart.equals(pos)) return; //可能重复设置
  73878. this.routeStart = pos && new Vector3().copy(pos);
  73879. if (dealZ && this.routeStart) {
  73880. this.routeStart.setZ(this.getZAtMap());
  73881. this.bus && this.bus.emit('reposStartMarker', this.routeStart);
  73882. }
  73883. console.log('setRouteStart', this.routeStart && this.routeStart.toArray());
  73884. this.datasetIds[0] = datasetId;
  73885. //this.setStartPole(pos)
  73886. this.poleStart.visible = !!pos;
  73887. pos && this.poleStart.position.copy(this.routeStart);
  73888. pos && this.poleStart.hatSphere.waitUpdate();
  73889. this.generateRoute();
  73890. viewer.dispatchEvent('content_changed');
  73891. }
  73892. setStartPole(pos) {
  73893. this.startPolePos = pos;
  73894. this.bus && this.bus.emit('reposStartMarker', pos);
  73895. }
  73896. setRouteEnd(pos, dealZ, datasetId) {
  73897. if (this.routeEnd && pos && this.routeEnd.equals(pos)) return;
  73898. this.routeEnd = pos && new Vector3().copy(pos);
  73899. if (dealZ && this.routeEnd) {
  73900. this.routeEnd.setZ(this.getZAtMap());
  73901. this.bus && this.bus.emit('reposEndMarker', this.routeEnd);
  73902. }
  73903. console.log('setRouteEnd', this.routeEnd && this.routeEnd.toArray());
  73904. this.datasetIds[1] = datasetId;
  73905. //this.setEndPole(pos)
  73906. this.poleEnd.visible = !!pos;
  73907. pos && this.poleEnd.position.copy(this.routeEnd);
  73908. pos && this.poleEnd.hatSphere.waitUpdate();
  73909. this.generateRoute();
  73910. viewer.dispatchEvent('content_changed');
  73911. }
  73912. getZAtMap() {
  73913. //找到position.z与当前高度最接近的漫游点
  73914. var result = Common$1.sortByScore(viewer.images360.panos, [], [e => -Math.abs(e.position.z - viewer.images360.position.z)]);
  73915. var pano = result && result[0] && result[0].item;
  73916. return pano ? pano.floorPosition.z : viewer.bound.boundingBox.min.z + 1;
  73917. //若在平面图上画实在得不到当前楼层的,大概率是楼层画得不好,那就只能去获取当前楼层的了
  73918. //navvis的高度取的是主视图所在楼层的中心高度(可能再高些)
  73919. }
  73920. setEndPole(pos) {
  73921. this.endPolePos = pos;
  73922. this.bus && this.bus.emit('reposEndMarker', pos);
  73923. }
  73924. getSourceProjectionIndex(route) {
  73925. //真正的起始
  73926. var e = route.findIndex(function (t) {
  73927. return t.instruction && t.instruction.type === 'source_projection_to_navgraph';
  73928. });
  73929. return e < 0 ? 0 : e;
  73930. }
  73931. getDestinationProjectionIndex(route) {
  73932. //真正的终点
  73933. var e = route.findIndex(function (t) {
  73934. return t.instruction && t.instruction.type === "destination_projection_to_navgraph";
  73935. });
  73936. return e < 0 ? route.length - 1 : e;
  73937. }
  73938. generateRoute() {
  73939. this.sceneMeshGroup.visible = true;
  73940. if (!this.routeStart || !this.routeEnd) {
  73941. return;
  73942. }
  73943. var initialPointcloud = viewer.scene.pointclouds.find(e => e.dataset_id == Potree.settings.originDatasetId);
  73944. //array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
  73945. var create = () => {
  73946. this.routeLength = this.route.reduce((total, currentValue, currentIndex, arr) => {
  73947. if (currentIndex == 0) return 0;
  73948. return total + currentValue.distanceTo(arr[currentIndex - 1]);
  73949. }, 0);
  73950. var count = Math.max(2, Math.round(this.routeLength / arrowSpacing)); //点数
  73951. var curve = new CatmullRomCurve3(this.route);
  73952. curve.curveType = 'chordal'; //'centripetal' 'catmullrom'这个可能会超出路径外
  73953. this.curve = curve;
  73954. var scenePoints = curve.getSpacedPoints(count); //更平均
  73955. //const scenePoints = curve.getPoints( count );
  73956. scenePoints.splice(0, 1); //去掉首尾
  73957. scenePoints.pop();
  73958. this.scenePoints = scenePoints;
  73959. this.updateMapArrows();
  73960. this.displayRoute();
  73961. {
  73962. //map focus on this area
  73963. var minBound = new Vector2(1, 1); //针对垂直线,在地图上只有一个点
  73964. var bound = new Box2();
  73965. this.route.forEach(e => {
  73966. bound.expandByPoint(e);
  73967. });
  73968. var size = bound.getSize(new Vector2());
  73969. var markerSize = new Vector2(115, 40); //起始和终点的标识呈长方形
  73970. var areaSize = viewer.mapViewer.viewports[0].resolution2;
  73971. var areaArea = areaSize.x * areaSize.y;
  73972. if (areaArea > 800 * 400) {
  73973. //是放大的
  73974. markerSize.multiplyScalar(areaArea / (800 * 400) /* / (size.x * size.y) */);
  73975. }
  73976. var margin = size.clone().divide(viewer.mapViewer.viewports[0].resolution2).multiply(markerSize); ///边距 重点是起始和终点的标识占据较大
  73977. size.add(margin);
  73978. var center = bound.getCenter(new Vector2());
  73979. size.x = Math.max(size.x, minBound.x);
  73980. size.y = Math.max(size.y, minBound.y);
  73981. var duration = 1000;
  73982. viewer.mapViewer.moveTo(center, size, duration);
  73983. }
  73984. this.bus.emit('gotResult', {
  73985. dis: this.routeLength
  73986. });
  73987. /* this.generateDeferred && this.generateDeferred.resolve({dis:this.routeLength})
  73988. this.generateDeferred = null */
  73989. };
  73990. if (Potree.fileServer) {
  73991. var dealData = data => {
  73992. if (!data.data) {
  73993. console.log('没有数据');
  73994. var result;
  73995. if (data && data.code == 4002) {
  73996. result = data; //正被修改数据集
  73997. } else if (this.routeStart.distanceTo(this.routeEnd) < 1) {
  73998. result = {
  73999. code: 500,
  74000. msg: '距离太短,无法规划路线'
  74001. };
  74002. } else {
  74003. result = {
  74004. code: 500,
  74005. msg: '超出数据集范围,无法规划路线'
  74006. };
  74007. }
  74008. this.clearRoute();
  74009. this.setStartPole(this.routeStart);
  74010. this.setEndPole(this.routeEnd);
  74011. this.displayRoute(); //还是要显示一下起始
  74012. this.bus && this.bus.emit('gotResult', result);
  74013. return; //this.generateDeferred && this.generateDeferred.resolve()
  74014. }
  74015. data = data.data;
  74016. this.clearRoute();
  74017. var length = data.length;
  74018. if (length < 2) {
  74019. //可能距离太短
  74020. console.log('路径点数为' + length + ',直接取起点和终点连线');
  74021. this.route = [this.routeStart, this.routeEnd];
  74022. } else {
  74023. var startIndex = this.getSourceProjectionIndex(data);
  74024. var endIndex = this.getDestinationProjectionIndex(data);
  74025. var effectiveItems = data.slice(startIndex, endIndex + 1); //只要点云范围内的点
  74026. effectiveItems.forEach((item, i) => {
  74027. //let pos = viewer.transform.lonlatToLocal.forward(item.location.slice(0)/* ,true */)
  74028. var pos = item.location.slice(0);
  74029. pos = new Vector3().fromArray(pos); //.setZ(item.z)
  74030. pos.z -= initialPointcloud.datasetData.location[2];
  74031. this.route.push(pos);
  74032. });
  74033. //console.log('route', this.route)
  74034. }
  74035. this.setStartPole(this.route[0]);
  74036. this.setEndPole(this.route[this.route.length - 1]);
  74037. create();
  74038. /*
  74039. distance: 0.17581000000000116
  74040. distance_to_previous: 0.17581000000000116
  74041. id: 567
  74042. instruction: {type: 'source_projection_to_navgraph'}
  74043. latitude: 22.366605927999238
  74044. location: (3) [113.5957510575092, 22.366605927999238, -1.12419]
  74045. longitude: 113.5957510575092
  74046. z: -1.12419
  74047. */
  74048. };
  74049. if (this.lastResult && (this.lastResult.data || this.lastResult.data.code != 4002)) {
  74050. //正被修改数据集的话要重新计算
  74051. var data = Common$1.CloneObject(this.lastResult.data),
  74052. use; //直接用上次的结果
  74053. if (this.lastResult.routeStart.equals(this.routeStart) && this.lastResult.routeEnd.equals(this.routeEnd)) {
  74054. //和上次请求相同
  74055. use = true;
  74056. } else if (this.lastResult.routeStart.equals(this.routeEnd) && this.lastResult.routeEnd.equals(this.routeStart)) {
  74057. //..反向
  74058. use = true;
  74059. if (data.data) {
  74060. data.data = this.lastResult.data.data.slice(0).reverse();
  74061. }
  74062. }
  74063. if (use) {
  74064. console.log('直接用上次的结果');
  74065. return setTimeout(() => {
  74066. dealData(data);
  74067. }, 1); //延迟是为了等待获得 RouteGuider.generateDeferred
  74068. }
  74069. }
  74070. var start = this.routeStart.clone();
  74071. var end = this.routeEnd.clone();
  74072. //let startLonlat = viewer.transform.lonlatToLocal.inverse(start/* , true */)
  74073. //let endLonlat = viewer.transform.lonlatToLocal.inverse(end/* , true */)
  74074. /* var query = {
  74075. source_longitude: start.x,
  74076. source_latitude: start.y,
  74077. source_z: start.z,
  74078. destination_longitude: end.x,
  74079. destination_latitude: end.y,
  74080. destination_z: end.z
  74081. }; */
  74082. var query = {
  74083. source_longitude: start.x,
  74084. source_latitude: start.y,
  74085. source_z: start.z + initialPointcloud.datasetData.location[2],
  74086. destination_longitude: end.x,
  74087. destination_latitude: end.y,
  74088. destination_z: end.z + initialPointcloud.datasetData.location[2]
  74089. };
  74090. /* var query = {
  74091. source_longitude: startLonlat.x,
  74092. source_latitude: startLonlat.y,
  74093. source_z: start.z,
  74094. destination_longitude: endLonlat.x,
  74095. destination_latitude: endLonlat.y,
  74096. destination_z: end.z
  74097. }; */
  74098. //let url = `/laser/route/${Potree.settings.number}/getRoute/${this.datasetIds[0]}/${this.datasetIds[1]}?`
  74099. var url = "/laser/route/".concat(Potree.settings.number, "/getRoute/").concat(Potree.settings.originDatasetId, "?");
  74100. for (var i in query) {
  74101. url += i + '=' + query[i] + '&';
  74102. }
  74103. Potree.fileServer.get(url).then(data => {
  74104. //console.log('data', data.data)
  74105. if (!this.routeStart || !this.routeEnd) return;
  74106. this.lastResult = {
  74107. //保存数据
  74108. routeStart: this.routeStart.clone(),
  74109. routeEnd: this.routeEnd.clone(),
  74110. data
  74111. };
  74112. dealData(data);
  74113. });
  74114. } else {
  74115. //创个直线
  74116. /* const sliceDis = 1
  74117. let dis = this.routeStart.distanceTo(this.routeEnd);
  74118. let count = Math.max(2,Math.round(dis / sliceDis))//点数
  74119. let realSlideDis = dis / (count-1);
  74120. let dir = new THREE.Vector3().subVectors(this.routeEnd, this.routeStart).normalize().multiplyScalar(realSlideDis);
  74121. this.route = [this.routeStart];
  74122. for(let i=0;i<count-1;i++){
  74123. let lastOne = this.route[i];
  74124. this.route.push(new THREE.Vector3().addVectors(lastOne,dir))
  74125. }
  74126. this.route.splice(0,1) //route不用包含收尾 */
  74127. this.clearRoute();
  74128. this.route = [this.routeStart, this.routeEnd];
  74129. create();
  74130. }
  74131. }
  74132. updateMapArrows(ifReset) {
  74133. if (this.route.length == 0) return;
  74134. var zoom = viewer.mapViewer.camera.zoom;
  74135. var isBig = viewer.mapViewer.viewports[0].resolution.y > 300;
  74136. var count = Math.max(2, Math.round(this.routeLength * zoom / arrowSpacing / (isBig ? 35 : 30))); //点数
  74137. if (count == this.mapPoints.length + 1) return; //没变
  74138. var mapPoints = this.curve.getSpacedPoints(count);
  74139. mapPoints.splice(0, 1); //去掉首尾
  74140. mapPoints.pop();
  74141. this.mapPoints = mapPoints;
  74142. var scale = (isBig ? 26 : 22) / zoom;
  74143. this.mapArrow.scale.set(scale, scale, scale);
  74144. /* this.mapMarkStart.scale.set(scale,scale,scale)
  74145. this.mapMarkEnd.scale.set(scale,scale,scale) */
  74146. if (ifReset) {
  74147. //因为缩放而重新排布箭头
  74148. this.clearRoute({
  74149. resetMap: true
  74150. });
  74151. this.displayRoute({
  74152. resetMap: true
  74153. });
  74154. }
  74155. this.updateOpacityAtMap();
  74156. }
  74157. updateArrowDisplay() {
  74158. //根据当前位置更新显示一定范围内的箭头
  74159. if (this.scenePoints.length == 0) return;
  74160. /* var a = Common.sortByScore(this.scenePoints , null, [(point)=>{ //是否还要再requires里限制最远距离?
  74161. var playerPos = viewer.scene.getActiveCamera().position.clone().setZ(0)
  74162. var pos = point.clone().setZ(0)
  74163. return -pos.distanceTo(playerPos);
  74164. }]);
  74165. //获得展示的起始点
  74166. let start = a[0].item
  74167. let startIndex = this.scenePoints.indexOf(start)
  74168. this.arrows.children.forEach((e,i)=>{
  74169. if(i<startIndex || i>startIndex+arrowsShowingCount)e.visible = false
  74170. else e.visible = true
  74171. }) */
  74172. var cameraPos = viewer.scene.getActiveCamera().position;
  74173. this.arrows.children.forEach((e, i) => {
  74174. if (e.position.distanceTo(cameraPos) < arrowShowMinDis) e.visible = true;else e.visible = false;
  74175. });
  74176. viewer.dispatchEvent('content_changed');
  74177. }
  74178. displayRoute() {
  74179. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  74180. if (!o.resetMap) {
  74181. this.poleStart.position.copy(this.startPolePos || this.routeStart);
  74182. this.poleEnd.position.copy(this.endPolePos || this.routeEnd);
  74183. /* this.mapMarkStart.position.copy(this.routeStart).setZ(0)
  74184. this.mapMarkEnd.position.copy(this.routeEnd).setZ(0) */
  74185. this.scenePoints.forEach(e => this.addArrow(e));
  74186. this.arrows.children.forEach((e, i) => this.setArrowDir(this.arrows.children, i));
  74187. }
  74188. this.sceneMeshGroup.visible = true; //.traverse(e=>e.visible = true)
  74189. this.mapMeshGroup.visible = true;
  74190. this.mapPoints.forEach(e => this.addMapArrow(e));
  74191. this.mapArrows.children.forEach((e, i) => this.setArrowDir(this.mapArrows.children, i));
  74192. viewer.mapViewer.dispatchEvent({
  74193. 'type': 'content_changed'
  74194. });
  74195. this.updateArrowDisplay();
  74196. }
  74197. clearRoute() {
  74198. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  74199. if (!o.resetMap) {
  74200. this.routeLength = 0;
  74201. this.route = [];
  74202. this.scenePoints = [];
  74203. this.mapPoints = [];
  74204. var arrows = this.arrows.children.slice(0);
  74205. arrows.forEach(e => {
  74206. this.arrows.remove(e);
  74207. });
  74208. }
  74209. var mapArrows = this.mapArrows.children.slice(0);
  74210. mapArrows.forEach(e => {
  74211. this.mapArrows.remove(e);
  74212. });
  74213. this.sceneMeshGroup.visible = false;
  74214. //this.sceneMeshGroup.traverse(e=>e.visible = false) //包括sprite也要设置,防止update
  74215. this.mapMeshGroup.visible = false;
  74216. viewer.mapViewer.dispatchEvent({
  74217. 'type': 'content_changed'
  74218. });
  74219. viewer.dispatchEvent('content_changed');
  74220. }
  74221. clear() {
  74222. //退出
  74223. console.log('导航clear');
  74224. this.routeStart = null;
  74225. this.routeEnd = null;
  74226. this.clearRoute();
  74227. }
  74228. }
  74229. //大概每十米要花一秒
  74230. /*
  74231. 存在的问题:
  74232. 路径不准确。起始点和终点偏移。
  74233. https://uat-laser.4dkankan.com/routeDebug/ 可查整个map的通路点位图
  74234. */
  74235. //import History from "../../utils/History.js"
  74236. var cameraProps$1 = [{
  74237. name: 'top',
  74238. axis: ["x", "y"],
  74239. direction: new Vector3(0, 0, -1),
  74240. //镜头朝向
  74241. openCount: 0
  74242. }];
  74243. class Clipping extends EventDispatcher {
  74244. //实时剪裁
  74245. constructor() {
  74246. super();
  74247. this.views = {};
  74248. this.cameras = {};
  74249. this.orthoCamera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  74250. this.orthoCamera.up.set(0, 0, 1);
  74251. }
  74252. init() {
  74253. if (this.inited) return;
  74254. this.initViews();
  74255. this.inited = true;
  74256. this.prepareRecord = true;
  74257. this.activeViewName = 'mainView';
  74258. this.events = {
  74259. transfromCallback: e => {
  74260. //拖拽变化时
  74261. this.adjustCamHeight();
  74262. //检测漫游点、回退等
  74263. /* if(this.prepareRecord){
  74264. let box = viewer.transformationTool.selection[0]
  74265. this.history.writeIn({box, matrix:box.matrix.clone()})
  74266. this.prepareRecord = false
  74267. } */
  74268. },
  74269. /* onTransfromEnd:(e)=>{//拖拽结束、松开
  74270. this.prepareRecord = true
  74271. }, */
  74272. selectCallback: e => {
  74273. this.adjustCamHeight();
  74274. var unableNavigate = this.activeViewName != 'mainView' || e.selection.length > 0;
  74275. if (Potree.settings.unableNavigate && !unableNavigate) {
  74276. setTimeout(() => {
  74277. Potree.settings.unableNavigate = this.activeViewName != 'mainView' || e.selection.length > 0;
  74278. }, 300); //延迟是因为点击时取消选择后可能立即就会触发flyToPano。 而且有的人喜欢点两下
  74279. } else Potree.settings.unableNavigate = unableNavigate;
  74280. },
  74281. onkeydown: e => {
  74282. if (e.keyCode == 8 || e.keyCode == 46) {
  74283. // Backspace or Delete
  74284. viewer.inputHandler.selection[0] && viewer.scene.removeVolume(viewer.inputHandler.selection[0]);
  74285. }
  74286. }
  74287. };
  74288. /* this.history = new History({ //也可以写到全局,但需要加个判断物品是否存在的函数
  74289. applyData: (data)=>{
  74290. if(viewer.scene.volumes.includes(data.box)){
  74291. data.matrix.decompose( data.box.position, data.box.quaternion, data.box.scale );
  74292. }else{
  74293. this.history.undo()//找不到就回退下一个。(直接写这?)
  74294. }
  74295. }
  74296. }) */
  74297. }
  74298. initViews() {
  74299. this.splitScreenTool = new SplitScreen();
  74300. for (var i = 0; i < 1; i++) {
  74301. var prop = cameraProps$1[i];
  74302. var view = new ExtendView();
  74303. this.views[prop.name] = view;
  74304. this.cameras[prop.name] = this.orthoCamera;
  74305. view.direction = prop.direction;
  74306. }
  74307. this.views.mainView = viewer.mainViewport.view;
  74308. this.cameras.mainView = viewer.mainViewport.camera;
  74309. }
  74310. switchView(name) {
  74311. //替换view和camera到mainViewport
  74312. if (this.activeViewName == name) return;
  74313. var view = this.views[name];
  74314. var camera = this.cameras[name];
  74315. var prop = cameraProps$1.find(e => e.name == name);
  74316. var {
  74317. boundSize,
  74318. center,
  74319. boundingBox
  74320. } = viewer.bound;
  74321. this.lastViewName = this.activeViewName;
  74322. this.activeViewName = name;
  74323. var lastView = this.views[this.lastViewName];
  74324. var lastCamera = this.cameras[this.lastViewName];
  74325. viewer.mainViewport.view = view;
  74326. viewer.mainViewport.camera = camera;
  74327. if (lastCamera) lastView.zoom = lastCamera.zoom;
  74328. /* if(lastView){//2d->3d
  74329. view.copy(lastView)
  74330. } */
  74331. if (name == 'mainView') {
  74332. Potree.settings.unableNavigate = false;
  74333. /* viewer.transformationTool.handles['scale.z+'].node.visible = true
  74334. viewer.transformationTool.handles['scale.z-'].node.visible = true */
  74335. } else {
  74336. Potree.settings.unableNavigate = true;
  74337. /* viewer.transformationTool.handles['scale.z+'].node.visible = false
  74338. viewer.transformationTool.handles['scale.z-'].node.visible = false */
  74339. if (prop.openCount == 0) {
  74340. //至多执行一次
  74341. //this.viewportFitBound(name, boundSize, center)
  74342. this.orthoMoveFit(center, {
  74343. bound: boundingBox
  74344. }, 0);
  74345. this.camHeightOutOfModel = view.position.z; //记录下此刻相机高度。
  74346. }
  74347. prop.openCount++;
  74348. this.adjustCamHeight();
  74349. /* this.targetPlane.setFromNormalAndCoplanarPoint( view.direction.clone(), center )
  74350. this.targetPlane.projectPoint(view.position, this.shiftTarget ) //target转换到过模型中心的平面,以保证镜头一定在模型外
  74351. view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport)) */
  74352. if (view.zoom) camera.zoom = view.zoom; //恢复上次的zoom
  74353. }
  74354. viewer.updateScreenSize({
  74355. forceUpdateSize: true
  74356. }); //更新camera aspect left等
  74357. if (viewer.inputHandler.selection.length) {
  74358. this.focusOnObject(viewer.inputHandler.selection[0]);
  74359. }
  74360. }
  74361. focusOnObject(box) {
  74362. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  74363. if (this.activeViewName == 'mainView') {
  74364. viewer.focusOnObject({
  74365. boundingBox: box.boundingBox.clone().applyMatrix4(box.matrixWorld)
  74366. }, 'boundingBox', duration);
  74367. } else {
  74368. this.orthoMoveFit(box.position, {
  74369. bound: box.boundingBox.clone().applyMatrix4(box.matrixWorld)
  74370. }, duration);
  74371. }
  74372. this.adjustCamHeight();
  74373. }
  74374. orthoMoveFit(pos, info, duration) {
  74375. var margin = {
  74376. x: viewer.mainViewport.resolution.x * 0.4,
  74377. y: viewer.mainViewport.resolution.y * 0.4
  74378. };
  74379. this.splitScreenTool.viewportFitBound(viewer.mainViewport, info.bound, pos, duration, margin);
  74380. }
  74381. adjustCamHeight() {
  74382. if (this.activeViewName != 'top') return;
  74383. var view = this.views.top;
  74384. var height;
  74385. if (viewer.inputHandler.selection.length) {
  74386. //相机高度位于选中的box的顶部
  74387. var box = viewer.inputHandler.selection[0];
  74388. height = box.boundingBox.clone().applyMatrix4(box.matrixWorld).max.z;
  74389. } else {
  74390. height = this.camHeightOutOfModel; //显示全部点云
  74391. }
  74392. view.position.z = height;
  74393. //console.log('adjustCamHeight',height)
  74394. //缺点:1 会导致缩放很小的时候,transformationTool的轴因放大到了相机背面。(只有scale轴做了处理)
  74395. //2 无法直接切换 看不到的box,但可以先取消选择
  74396. //3 但是俯视图中无法切换到被上层盖住的box(不过把俯视图作为辅助,只针对单个box调动的话,问题不大)
  74397. }
  74398. enter() {
  74399. this.init();
  74400. viewer.transformationTool.setModeEnable(['translation']);
  74401. //viewer.transformationTool.handles['rotation.x'].node.visible = false
  74402. viewer.transformationTool.frame.material.visible = false; //不盖住boxVolume的frame
  74403. this.targetPlane = viewer.mainViewport.targetPlane = new Plane();
  74404. this.shiftTarget = viewer.mainViewport.shiftTarget = new Vector3(); //project在targetPlane上的位置
  74405. this.getAllBoxes().forEach(box => {
  74406. Potree.Utils.updateVisible(box, 'hidden', true); //显现
  74407. });
  74408. viewer.transformationTool.history.clear();
  74409. viewer.transformationTool.addEventListener('transformed', this.events.transfromCallback);
  74410. //viewer.transformationTool.addEventListener('stopDrag', this.events.onTransfromEnd)
  74411. viewer.inputHandler.addEventListener('selection_changed', this.events.selectCallback);
  74412. viewer.inputHandler.addEventListener('keydown', this.events.onkeydown);
  74413. this.setPointLevelAuto();
  74414. var initialPointcloud = viewer.scene.pointclouds.find(p => p.dataset_id == Potree.settings.originDatasetId);
  74415. //隐藏 初始数据集以外的数据集
  74416. viewer.scene.pointclouds.forEach(e => {
  74417. if (e.dataset_id != Potree.settings.originDatasetId) {
  74418. Potree.Utils.updateVisible(e, 'enterClipping', false);
  74419. //Potree.settings.floorplanEnables[e.dataset_id] = false
  74420. e.panos.forEach(pano => pano.setEnable(false)); //禁止漫游
  74421. } else {
  74422. Potree.Utils.updateVisible(e, 'enterClipping', true, 1, 'add');
  74423. //Potree.settings.floorplanEnables[e.dataset_id] = true
  74424. }
  74425. });
  74426. viewer.flyToDataset({
  74427. pointcloud: initialPointcloud,
  74428. duration: 0
  74429. });
  74430. }
  74431. enter2() {
  74432. //在土方量界面的
  74433. viewer.transformationTool.setModeEnable(['translation']);
  74434. viewer.transformationTool.frame.material.visible = false; //不盖住boxVolume的frame
  74435. viewer.transformationTool.history.clear();
  74436. //viewer.inputHandler.addEventListener('keydown', this.events.onkeydown)
  74437. }
  74438. leave() {
  74439. viewer.transformationTool.setModeEnable(['scale', 'translation', 'rotation']);
  74440. viewer.transformationTool.frame.material.visible = true; //恢复
  74441. this.switchView('mainView');
  74442. this.getAllBoxes().forEach(box => {
  74443. Potree.Utils.updateVisible(box, 'hidden', false); //隐身
  74444. });
  74445. viewer.transformationTool.removeEventListener('transformed', this.events.transfromCallback);
  74446. //viewer.transformationTool.removeEventListener('stopDrag', this.events.onTransfromEnd)
  74447. viewer.inputHandler.removeEventListener('selection_changed', this.events.selectCallback);
  74448. //viewer.inputHandler.removeEventListener('keydown', this.events.onkeydown)
  74449. viewer.transformObject(null);
  74450. viewer.transformationTool.history.clear();
  74451. //恢复 初始数据集以外的数据集
  74452. viewer.scene.pointclouds.forEach(e => {
  74453. if (e.dataset_id != Potree.settings.originDatasetId) {
  74454. Potree.Utils.updateVisible(e, 'enterClipping', true);
  74455. e.panos.forEach(pano => pano.setEnable(true));
  74456. } else {
  74457. Potree.Utils.updateVisible(e, 'enterClipping', false, 0, 'cancel');
  74458. }
  74459. });
  74460. }
  74461. setTranMode(mode) {
  74462. //rotate or translate
  74463. this.tranMode = mode;
  74464. viewer.transformationTool.setModeEnable([mode]);
  74465. viewer.dispatchEvent('content_changed');
  74466. }
  74467. //问:是否要显示其他数据集
  74468. setPointLevelAuto() {
  74469. /*
  74470. let visiCount = viewer.images360.panos.length
  74471. let maxCount = 200, minCount = 20, minPer = 0.7, maxPer = 1
  74472. let percent = maxPer - ( maxPer - minPer) * THREE.Math.clamp((visiCount - minCount) / (maxCount - minCount),0,1)
  74473. Potree.settings.UserDensityPercent = percent ---还是不限制了,尤其是平面图希望更细致点,毕竟剪裁主要要看清剪裁的部位。
  74474. */
  74475. viewer.setPointBudget(5 * 1000 * 1000); //给个中等到高等之间的质量
  74476. Potree.settings.sizeFitToLevel = true;
  74477. viewer.setPointLevels();
  74478. }
  74479. getAllBoxes() {
  74480. return viewer.scene.volumes.filter(v => v.clip && v instanceof Potree.BoxVolume);
  74481. }
  74482. getCalcData() {
  74483. //给后台矩阵数据,以裁剪点云。
  74484. var Clip = viewer.modules.Clip; //裁剪下载模块
  74485. var data = {
  74486. transformation_matrix: viewer.scene.pointclouds.filter(p => p.dataset_id == Potree.settings.originDatasetId).map(cloud => {
  74487. var data = {
  74488. id: cloud.dataset_id,
  74489. matrix: new Matrix4().elements,
  74490. //参照downloadNoCrop,给默认值,表示没有最外层裁剪
  74491. visiMatrixes: cloud.material.clipBoxes_in.filter(e => !e.box.isNew).map(e => Clip.getTransformationMatrix(cloud, e.inverse).elements),
  74492. unVisiMatrixes: cloud.material.clipBoxes_out.filter(e => !e.box.isNew).map(e => Clip.getTransformationMatrix(cloud, e.inverse).elements),
  74493. modelMatrix: new Matrix4().elements //(new THREE.Matrix4).copy(cloud.transformMatrix).transpose().elements //需要保证没有位移,否则剪裁后的模型位置会变化
  74494. };
  74495. return data;
  74496. }),
  74497. aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //剪裁空间
  74498. };
  74499. return data;
  74500. }
  74501. saveClipData(boxes) {
  74502. //输出所有的clip volumeBox
  74503. var oldState = !viewer.clipUnabled;
  74504. //viewer.setClipState(true)
  74505. var data = (boxes || this.getAllBoxes()).filter(e => !e.isNew).map(volume => {
  74506. return {
  74507. clipTask: volume.clipTask,
  74508. position: Potree.Utils.datasetPosTransform({
  74509. position: volume.position,
  74510. toDataset: true,
  74511. datasetId: Potree.settings.originDatasetId
  74512. }).toArray(),
  74513. rotation: Potree.Utils.datasetRotTransform({
  74514. rotation: volume.rotation,
  74515. toDataset: true,
  74516. datasetId: Potree.settings.originDatasetId,
  74517. getRotation: true
  74518. }).toArray().slice(0, 3),
  74519. scale: volume.scale.toArray()
  74520. };
  74521. });
  74522. //console.log(data)
  74523. //console.log(JSON.stringify(data))
  74524. //viewer.setClipState(oldState)
  74525. return data;
  74526. }
  74527. loadFromData() {
  74528. var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  74529. data.forEach(v => {
  74530. var volume = new Potree.BoxVolume({
  74531. clip: true,
  74532. clipTask: v.clipTask
  74533. });
  74534. volume.scale.fromArray(v.scale);
  74535. volume.position.fromArray(v.position);
  74536. volume.rotation.fromArray(v.rotation);
  74537. volume.position.copy(Potree.Utils.datasetPosTransform({
  74538. position: volume.position,
  74539. fromDataset: true,
  74540. datasetId: Potree.settings.originDatasetId
  74541. }));
  74542. volume.rotation.copy(Potree.Utils.datasetRotTransform({
  74543. rotation: volume.rotation,
  74544. fromDataset: true,
  74545. datasetId: Potree.settings.originDatasetId,
  74546. getRotation: true
  74547. }));
  74548. viewer.scene.addVolume(volume);
  74549. viewer.volumeTool.scene.add(volume);
  74550. });
  74551. }
  74552. }
  74553. //注意:实时裁剪只对初始数据集有效,其他数据集已经隐藏
  74554. /*
  74555. 备注:
  74556. 2023
  74557. 发送给后台数据样例:
  74558. {"transformation_matrix":[{"id":"1626189981883699200","matrix":[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],"visiMatrixes":[],"unVisiMatrixes":[[0.18610746638254325,-0.0005022517888587003,0,-0.01638495865566026,0.0002721420073982042,0.10084117292688818,0,0.25897037181878035,0,0,0.17066427841288187,-0.1913158687770112,0,0,0,1]],"modelMatrix":[0.999996358477288,-0.0026987093514294095,0,3.275872500136923e-8,0.0026987093514294095,0.999996358477288,0,-4.2486927309681385e-9,0,0,1,0,0,0,0,1]}],"aabb":"b-12742000 -12742000 -12742000 12742000 12742000 12742000"}
  74559. 发送给算法部的数据样例:
  74560. {
  74561. "model": [
  74562. {
  74563. "cut_transformation": "1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0",
  74564. "file": "/mnt/data/pvt000004/1079784714115481600/pvt000004_202302271512444930_laserData/laserData/laser.las",
  74565. "visiMatrixes": [[..],[..]],
  74566. "dataSetId": "1630105213031026688",
  74567. "sceneCode": "SS-t-MVQ1Jb80oMG",
  74568. "modelMatrix": "-0.9338946595415051 -0.35754826930060274 0.0 -3.483651134875185E-8 0.35754826930060274 -0.9338946595415051 0.0 5.664923641290965E-9 0.0 0.0 0.9999999999999999 0.0 0.0 0.0 0.0 1.0",
  74569. "unVisiMatrixes": [[..],[..]]
  74570. }
  74571. ],
  74572. "aabb": "b-12742000 -12742000 -12742000 12742000 12742000 12742000"
  74573. }
  74574. */
  74575. var vertexShader = "\n attribute float randam;\n attribute float sprite;\n attribute float centerHeight; //add\n \n //uniform float fireHeight; //add \n uniform float time;\n uniform float size;\n uniform float heightOfNearPlane;\n \n \n \n \n //varying float heightRatio;\n varying float vSprite;\n varying float vOpacity; \n float PI = 3.14;\n\n float quadraticIn( float t ) \n { \n float tt = t * t;\n return tt * tt; \n //\u53D8\u5316\u66F2\u7EBF \u8D8A\u6765\u8D8A\u5FEB\n } \n \n void main() {\n float progress = fract( time + ( 2.0 * randam - 1.0 ) );\n float progressNeg = 1.0 - progress;\n float ease = quadraticIn( progress );\n float influence = sin( PI * ease );\n //vec3 newPosition = position * vec3( 1.0, 1.0 , ease);\n vec3 newPosition = position;\n newPosition.z = (newPosition.z - centerHeight) * ease + centerHeight;\n \n gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );\n gl_PointSize = ( heightOfNearPlane * size ) / gl_Position.w;\n vOpacity = min( influence * 4.0, 1.0 ) * progressNeg;\n vSprite = sprite;\n \n //heightRatio = (newPosition.z - centerHeight) / fireHeight ;\n \n }\n";
  74576. var fragmentShader = "\n uniform vec3 color;\n uniform sampler2D u_sampler;\n\n varying float vSprite;\n varying float vOpacity;\n //varying float heightRatio;\n\n void main() \n {\n \n \n vec2 texCoord = vec2(gl_PointCoord.x * 0.25 + vSprite, gl_PointCoord.y);\n \n gl_FragColor = vec4( texture2D( u_sampler, texCoord ).xyz * color * vOpacity, 1.0 );\n \n \n }\n";
  74577. // import { vertexShader, fragmentShader } from './shaders'
  74578. var ONE_SPRITE_ROW_LENGTH = 0.25; //对应着色器的0.25
  74579. var texture;
  74580. var getTexture = () => {
  74581. if (!texture) {
  74582. texture = new TextureLoader().load(Potree.resourcePath + '/textures/fire.png');
  74583. }
  74584. return texture;
  74585. };
  74586. var boxGeo = new BoxBufferGeometry(1, 1, 1, 1);
  74587. var boxMat = new MeshBasicMaterial({
  74588. wireframe: true,
  74589. color: "#ffffff"
  74590. });
  74591. class FireParticle extends Points {
  74592. constructor(prop) {
  74593. super();
  74594. for (var key in prop) {
  74595. this[key] = prop[key];
  74596. }
  74597. this.strength = this.strength || 1;
  74598. this.radius = prop.radius || 1;
  74599. this.height = prop.height || 5;
  74600. this.computeParams();
  74601. this.geometry = this.createGeometry(this.radius, this.height, this.particleCount);
  74602. if (this.color == void 0) this.color = 0xff3200;
  74603. this.createMaterial(); //小蓝火:0x00338f
  74604. //---?:
  74605. this.velocity = new Vector3();
  74606. this.acceleration = new Vector3();
  74607. this.angle = 0;
  74608. this.angleVelocity = 0;
  74609. this.angleAcceleration = 0;
  74610. this.size = 16;
  74611. this.opacity = 1;
  74612. this.age = 0;
  74613. this.alive = 0;
  74614. this.sizeTween = null;
  74615. this.colorTween = null;
  74616. this.opacityTween = null;
  74617. this.setSize({
  74618. viewport: viewer.mainViewport
  74619. });
  74620. this.setFov(viewer.fov);
  74621. var setSize = e => {
  74622. if (e.viewport.name != "MainView") return;
  74623. this.setSize(e);
  74624. };
  74625. var setFov = e => {
  74626. this.setFov(e.fov);
  74627. };
  74628. viewer.addEventListener('resize', setSize);
  74629. viewer.addEventListener('fov_changed', setFov);
  74630. this.addEventListener('dispose', () => {
  74631. viewer.removeEventListener('resize', setSize);
  74632. viewer.removeEventListener('fov_changed', setFov);
  74633. });
  74634. }
  74635. computeParams() {
  74636. var length = (this.curve ? this.curve.wholeLength : 0) + this.radius * 2; //加上首尾的半径
  74637. var minSize = 0.3,
  74638. maxSize = 3,
  74639. minRadiusBound = 0.3,
  74640. maxRadiusBound = 10;
  74641. this.size = minSize + (maxSize - minSize) * MathUtils.smoothstep(this.radius, minRadiusBound, maxRadiusBound);
  74642. //console.log('fire material particle size:', size )
  74643. this.particleCount = Math.ceil(length * Math.sqrt(this.strength * this.height) * this.radius / (this.size * this.size) * 25);
  74644. //console.log('fire particleCount',this.particleCount)
  74645. }
  74646. getPointsForBound() {
  74647. return this.boundPoints; //可以用于expand实时bound的点, 不含particle的size等边距
  74648. }
  74649. getBound(points) {
  74650. // points为生成点(圆心)
  74651. this.boundPoints = [];
  74652. var boundingBox = new Box3();
  74653. var margin = this.size * 0.13 + 0.3;
  74654. points.forEach(bottom => {
  74655. var top = bottom.clone();
  74656. top.z += this.height;
  74657. boundingBox.expandByPoint(bottom);
  74658. boundingBox.expandByPoint(top);
  74659. this.boundPoints.push(bottom, top);
  74660. });
  74661. var xyExpand = this.radius + margin;
  74662. boundingBox.expandByVector(new Vector3(xyExpand, xyExpand, margin));
  74663. this.boundingBox = boundingBox;
  74664. /* if(!this.debugBox){
  74665. this.debugBox = new THREE.Mesh(boxGeo, boxMat)
  74666. this.add(this.debugBox)
  74667. }
  74668. this.debugBox.scale.copy(boundingBox.getSize(new THREE.Vector3))
  74669. this.debugBox.position.copy(boundingBox.getCenter(new THREE.Vector3)) */
  74670. }
  74671. createGeometry(radius, height, particleCount) {
  74672. var geometry = new BufferGeometry();
  74673. var count, points;
  74674. if (this.positions.length > 1) {
  74675. var spaceDis = 0.2; //间隔距离
  74676. count = Math.ceil(this.curve.wholeLength / spaceDis) + 1;
  74677. //console.log('count', count)
  74678. points = this.curve.getSpacedPoints(count); //得到的数量会比count多一个
  74679. count = points.length;
  74680. //得到的点不太均匀,两端容易点少。
  74681. this.getBound(points);
  74682. } else {
  74683. this.getBound(this.positions);
  74684. }
  74685. var position = new Float32Array(particleCount * 3);
  74686. var randam = new Float32Array(particleCount);
  74687. var sprite = new Float32Array(particleCount);
  74688. var centerHeight = new Float32Array(particleCount);
  74689. for (var i = 0; i < particleCount; i++) {
  74690. var center = new Vector3().copy(this.positions.length > 1 ? points[Math.floor(i / particleCount * count)] : this.positions[0]);
  74691. centerHeight[i] = center.z;
  74692. if (i === 0) {
  74693. // to avoid going out of Frustum
  74694. position[i * 3 + 0] = center.x;
  74695. position[i * 3 + 1] = center.y;
  74696. position[i * 3 + 2] = center.z;
  74697. } else {
  74698. var r = Math.sqrt(Math.random()) * radius;
  74699. var angle = Math.random() * 2 * Math.PI;
  74700. position[i * 3 + 0] = center.x + Math.cos(angle) * r;
  74701. position[i * 3 + 1] = center.y + Math.sin(angle) * r;
  74702. position[i * 3 + 2] = center.z + (radius - r) / radius * height / 2 + height / 2; //不太明白这句为什么能达到height高度
  74703. sprite[i] = 0.25 * (Math.random() * 4 | 0);
  74704. randam[i] = Math.random();
  74705. //center在底部
  74706. }
  74707. }
  74708. geometry.setAttribute('centerHeight', new BufferAttribute(centerHeight, 1));
  74709. geometry.setAttribute('position', new BufferAttribute(position, 3));
  74710. geometry.setAttribute('randam', new BufferAttribute(randam, 1));
  74711. geometry.setAttribute('sprite', new BufferAttribute(sprite, 1));
  74712. return geometry;
  74713. }
  74714. updateGeometry() {
  74715. this.computeParams();
  74716. this.geometry.dispose();
  74717. this.geometry = this.createGeometry(this.radius, this.height, this.particleCount);
  74718. this.material.uniforms.size.value = this.size;
  74719. }
  74720. createMaterial() {
  74721. var material = new ShaderMaterial({
  74722. uniforms: {
  74723. color: {
  74724. type: "c",
  74725. value: new Color(this.color)
  74726. },
  74727. size: {
  74728. type: "f",
  74729. value: this.size
  74730. },
  74731. u_sampler: {
  74732. type: "t",
  74733. value: getTexture()
  74734. },
  74735. time: {
  74736. type: "f",
  74737. value: 0.0
  74738. },
  74739. heightOfNearPlane: {
  74740. type: "f",
  74741. value: 0
  74742. },
  74743. //相对far ,以确保画面缩放时点的大小也会缩放
  74744. height: {
  74745. type: "f",
  74746. value: this.height
  74747. }
  74748. },
  74749. vertexShader,
  74750. fragmentShader,
  74751. blending: AdditiveBlending,
  74752. //加法融合模式 glBlendFunc(GL_ONE, GL_ONE)
  74753. depthTest: true,
  74754. depthWrite: false,
  74755. transparent: true
  74756. });
  74757. this.material = material;
  74758. this.setPerspective(this.fov, this.screenHeight);
  74759. }
  74760. setSize(e) {
  74761. var viewport = e.viewport;
  74762. this.screenHeight = viewport.resolution.y;
  74763. this.setPerspective(this.fov, this.screenHeight);
  74764. }
  74765. setFov(fov) {
  74766. this.fov = fov;
  74767. this.setPerspective(this.fov, this.screenHeight);
  74768. }
  74769. setPerspective(fov, height) {
  74770. //this.uniforms.heightOfNearPlane.value = Math.abs(height / (2 * Math.tan(THREE.Math.degToRad(fov * 0.5))));
  74771. var far = Math.abs(height / (2 * Math.tan(MathUtils.degToRad(fov * 0.5))));
  74772. this.material.uniforms.heightOfNearPlane.value = far;
  74773. }
  74774. update(delta) {
  74775. if (!Potree.Utils.getObjVisiByReason(this, 'force')) {
  74776. //被手动隐藏了
  74777. return;
  74778. }
  74779. if (!Potree.Utils.isInsideFrustum(this.boundingBox, viewer.scene.getActiveCamera())) {
  74780. Potree.Utils.updateVisible(this, 'isInsideFrustum', false); //不在视野范围
  74781. //console.log('unvi')
  74782. return;
  74783. } else {
  74784. Potree.Utils.updateVisible(this, 'isInsideFrustum', true);
  74785. }
  74786. delta *= 1; //更改速度
  74787. this.material.uniforms.time.value = (this.material.uniforms.time.value + delta) % 1;
  74788. viewer.dispatchEvent('content_changed');
  74789. }
  74790. dispose() {
  74791. this.geometry.dispose();
  74792. this.material.dispose();
  74793. this.dispatchEvent('dispose');
  74794. }
  74795. }
  74796. class Tween {
  74797. constructor(times, values) {
  74798. this.times = times || [];
  74799. this.values = values || [];
  74800. }
  74801. lerp(t) {
  74802. if (this.times.length == 0) return;
  74803. var i = 0,
  74804. n = this.times.length;
  74805. while (i < n && t > this.times[i]) i++;
  74806. if (i == 0) return this.values[0];
  74807. if (i == n) return this.values[n - 1];
  74808. var ratio = (t - this.times[i - 1]) / (this.times[i] - this.times[i - 1]);
  74809. if (this.values[0] instanceof Vector3) {
  74810. return this.values[i - 1].clone().lerp(this.values[i], ratio);
  74811. } else {
  74812. return this.values[i - 1] + ratio * (this.values[i] - this.values[i - 1]);
  74813. }
  74814. }
  74815. clone() {
  74816. return Common$1.CloneClassObject(this);
  74817. }
  74818. }
  74819. class Particle$1 {
  74820. constructor() {
  74821. var prop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  74822. this.position = new Vector3();
  74823. this.velocity = new Vector3(); // units per second
  74824. this.angle = 0;
  74825. this.angleVelocity = 0; // degrees per second
  74826. this.angleAcceleration = 0; // degrees per second, per second
  74827. this.size = 16.0;
  74828. this.color = new Color();
  74829. this.opacity = 1.0;
  74830. this.age = 0;
  74831. this.alive = 0; // use float instead of boolean for shader purposes
  74832. this.lastChangeVage = 0; //add
  74833. this.sizeTween = prop.sizeTween || new Tween([0, 1], [32, 128]);
  74834. this.opacityTween = prop.opacityTween || new Tween([0.8, 2], [0.5, 0]);
  74835. this.colorTween = prop.colorTween || new Tween([0.4, 1], [new Vector3(0, 0, 0.2), new Vector3(0, 0, 0.5)]);
  74836. }
  74837. update(dt) {
  74838. this.position.add(this.velocity.clone().multiplyScalar(dt));
  74839. this.velocity.multiplyScalar(1 + this.acceleration * dt);
  74840. // convert from degrees to radians: 0.01745329251 = Math.PI/180
  74841. this.angle += this.angleVelocity * 0.01745329251 * dt;
  74842. this.angleVelocity += this.angleAcceleration * 0.01745329251 * dt;
  74843. this.age += dt;
  74844. // if the tween for a given attribute is nonempty,
  74845. // then use it to update the attribute's value
  74846. if (this.sizeTween.times.length > 0) this.size = this.sizeTween.lerp(this.age / this.deathAge);
  74847. if (this.colorTween.times.length > 0) {
  74848. var colorHSL = this.colorTween.lerp(this.age / this.deathAge);
  74849. this.color = new Color().setHSL(colorHSL.x, colorHSL.y, colorHSL.z);
  74850. }
  74851. if (this.opacityTween.times.length > 0) {
  74852. this.opacity = this.opacityTween.lerp(this.age / this.deathAge);
  74853. }
  74854. viewer.dispatchEvent('content_changed');
  74855. }
  74856. }
  74857. var vertexShader$1 = "\n attribute vec3 customColor;\n attribute float customOpacity;\n attribute float customSize;\n attribute float customAngle;\n attribute float customVisible; \n uniform float heightOfNearPlane;\n \n \n varying vec4 vColor;\n varying float vAngle;\n void main()\n {\n if ( customVisible > 0.5 ) \t\t\t\t\n vColor = vec4( customColor, customOpacity ); \n else\t\t\t\t\t\t\t\n vColor = vec4(0.0, 0.0, 0.0, 0.0);\t\t\n \n vAngle = customAngle;\n\n vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n //gl_PointSize = customSize * ( 300.0 / length( mvPosition.xyz ) ); \n gl_Position = projectionMatrix * mvPosition;\n gl_PointSize = ( heightOfNearPlane * customSize ) / gl_Position.w;\n \n \n }\n";
  74858. var fragmentShader$1 = "\n uniform sampler2D u_sampler;\n varying vec4 vColor;\t\n varying float vAngle; \n void main()\n {\n gl_FragColor = vColor;\n \n float c = cos(vAngle);\n float s = sin(vAngle);\n vec2 rotatedUV = vec2(c * (gl_PointCoord.x - 0.5) + s * (gl_PointCoord.y - 0.5) + 0.5, c * (gl_PointCoord.y - 0.5) - s * (gl_PointCoord.x - 0.5) + 0.5); \n vec4 rotatedTexture = texture2D( u_sampler, rotatedUV );\n gl_FragColor = gl_FragColor * rotatedTexture; \n }\n";
  74859. var Type$1 = Object.freeze({
  74860. "CUBE": 1,
  74861. "SPHERE": 2
  74862. });
  74863. var particleTexture;
  74864. var getTexture$1 = () => {
  74865. if (!particleTexture) {
  74866. particleTexture = new TextureLoader().load(Potree.resourcePath + '/textures/smokeparticle.png');
  74867. }
  74868. return particleTexture;
  74869. };
  74870. var boxGeo$1 = new BoxBufferGeometry(1, 1, 1, 1);
  74871. var boxMat$1 = new MeshBasicMaterial({
  74872. wireframe: true,
  74873. color: "#ffffff"
  74874. });
  74875. var defaults = {
  74876. positions: [],
  74877. positionStyle: "sphere",
  74878. positionBase: new Vector3(0, 0, 0),
  74879. positionSpread: new Vector3(1, 1, 0),
  74880. //cube
  74881. radius: 1,
  74882. // sphere
  74883. velocityStyle: 'cube',
  74884. velocityBase: new Vector3(0, 0, 0.5),
  74885. // cube 基础速度
  74886. velocitySpread: new Vector3(1, 1, 0.3),
  74887. accelerationBase: 0.3,
  74888. //基础加速度
  74889. accelerationSpread: 0.6,
  74890. //没使用
  74891. speedBase: 0.1,
  74892. //sphere
  74893. speedSpread: 0.5,
  74894. angleBase: 0,
  74895. angleSpread: 360,
  74896. angleVelocityBase: 1,
  74897. angleVelocitySpread: 30,
  74898. angleAccelerationBase: 1,
  74899. angleAccelerationSpread: 5,
  74900. sizeBase: 0,
  74901. sizeSpread: 0,
  74902. sizeTween: [[0, 0.3, 1], [0.3, 1.4, 6]],
  74903. colorBase: new Vector3(0.0, 1.0, 0.5),
  74904. colorSpread: new Vector3(0.0, 0.0, 0.0),
  74905. colorTween: new Tween([0.2, 1], [new Vector3(0, 0, 0.4), new Vector3(0, 0, 0.1)]),
  74906. opacityBase: 0.1,
  74907. //1.0,
  74908. opacitySpread: 0.2,
  74909. opacityTween: [[0, 0.1, 0.9, 1], [0.1, 0.4, 0.03, 0]],
  74910. //particlesPerSecond : 20,
  74911. strength: 1,
  74912. particleDeathAge: 3,
  74913. //从底下升起后能持续的时间
  74914. //emitterDeathAge : 60 // time (seconds) at which to stop creating particles.
  74915. height: 3
  74916. };
  74917. var debugSphere = new Mesh(new SphereBufferGeometry(0.03, 5, 5), new MeshBasicMaterial({
  74918. color: 'white',
  74919. depthTest: false
  74920. }));
  74921. class SmokeParticle extends Points {
  74922. constructor() {
  74923. var prop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  74924. super();
  74925. this.blendStyle = NormalBlending; // false;
  74926. this.emitterAge = 0.0;
  74927. //this.emitterAlive = true;
  74928. prop = $.extend({}, defaults, prop);
  74929. for (var key in prop) {
  74930. var value = prop[key];
  74931. if (value instanceof Array && value[0] instanceof Array) this[key] = new Tween(...value);else if (value instanceof Vector3 || value instanceof Color) {
  74932. this[key] = value.clone();
  74933. } else {
  74934. this[key] = value;
  74935. }
  74936. }
  74937. this.defaultSizeTween = this.sizeTween.clone();
  74938. this.defaultOpacityTween = this.opacityTween.clone();
  74939. this.geometry = new BufferGeometry();
  74940. this.computeParams();
  74941. this.createMaterial();
  74942. this.createGeometry();
  74943. this.dynamic = true;
  74944. this.sortParticles = true;
  74945. this.frustumCulled = false; //似乎是禁止相机裁剪,否则会在某些角度消失。但是会不会更耗性能呢?
  74946. prop.position && this.position.copy(prop.position);
  74947. //---------------------------------------
  74948. this.setSize({
  74949. viewport: viewer.mainViewport
  74950. });
  74951. this.setFov(viewer.fov);
  74952. var setSize = e => {
  74953. if (e.viewport.name != "MainView") return;
  74954. this.setSize(e);
  74955. };
  74956. var setFov = e => {
  74957. this.setFov(e.fov);
  74958. };
  74959. /* let reStart = (e)=>{
  74960. if(e.v){//重新一个个放出粒子,否则会一股脑儿全部出来,因为同时大于粒子周期了一起重新生成出现。
  74961. setTimeout(()=>{//会先update一次delta为pageUnvisile的时间才触发
  74962. //console.log('归零')
  74963. //this.reStart()
  74964. },1)
  74965. }
  74966. } */
  74967. viewer.addEventListener('resize', setSize);
  74968. viewer.addEventListener('fov_changed', setFov);
  74969. //viewer.addEventListener('pageVisible', reStart)
  74970. this.addEventListener('dispose', () => {
  74971. viewer.removeEventListener('resize', setSize);
  74972. viewer.removeEventListener('fov_changed', setFov);
  74973. //viewer.removeEventListener('pageVisible', reStart)
  74974. });
  74975. }
  74976. computeParams() {
  74977. var length = (this.curve ? this.curve.wholeLength : 0) + this.radius * 2; //加上首尾的半径
  74978. //注意:烟最低高度一米, 0<strength<1
  74979. if (this.positionStyle == 'cube') {
  74980. this.positionSpread.set(this.radius, this.radius, 0);
  74981. }
  74982. this.velocityBase.set(0, 0, (this.height - 0.5 * this.accelerationBase * this.particleDeathAge * this.particleDeathAge) / this.particleDeathAge);
  74983. //let height = this.velocityBase.z * this.particleDeathAge + 0.5 * this.accelerationBase * this.particleDeathAge * this.particleDeathAge;//s = V0 * t + 0.5 * a * t*t ;
  74984. this.velocityBase.z = Math.max(0, this.velocityBase.z);
  74985. this.particleCount = Math.ceil(length * Math.sqrt(this.strength * this.height * this.radius));
  74986. this.particleCount = Math.max(5, this.particleCount);
  74987. {
  74988. var minSize = 1,
  74989. maxSize = 2,
  74990. minBound = 0.01,
  74991. maxBound = 1;
  74992. var size = minSize + (maxSize - minSize) * MathUtils.smoothstep(this.strength, minBound, maxBound);
  74993. this.sizeTween.values = this.defaultSizeTween.values.map(e => e * size);
  74994. }
  74995. {
  74996. var _minSize = 1,
  74997. _maxSize = 1.5,
  74998. _minBound = 0.01,
  74999. _maxBound = 1;
  75000. var opac = _minSize + (_maxSize - _minSize) * MathUtils.smoothstep(this.strength, _minBound, _maxBound);
  75001. this.opacityTween.values = this.defaultOpacityTween.values.map(e => e * opac);
  75002. }
  75003. //console.log('smoke particleCount',this.particleCount)
  75004. }
  75005. reStart() {
  75006. this.emitterAge = 0;
  75007. this.createGeometry();
  75008. }
  75009. updateGeometry() {
  75010. this.computeParams();
  75011. this.reStart();
  75012. }
  75013. createParticle(center) {
  75014. var particle = new Particle$1({
  75015. sizeTween: this.sizeTween,
  75016. opacityTween: this.opacityTween,
  75017. colorTween: this.colorTween
  75018. });
  75019. particle.deathAge = this.particleDeathAge;
  75020. particle.center = center;
  75021. if (this.positionStyle == 'cube') particle.position = this.randomVector3(this.positionBase, this.positionSpread);
  75022. if (this.positionStyle == 'sphere') {
  75023. /* var z = 2 * Math.random() - 1
  75024. var t = Math.PI * 2 * Math.random();
  75025. var r = Math.sqrt( 1 - z*z ) ;
  75026. var vec3 = new THREE.Vector3( r * Math.cos(t), r * Math.sin(t), z );
  75027. particle.position = new THREE.Vector3().addVectors( this.positionBase, vec3.multiplyScalar( this.radius ) );
  75028. */
  75029. //怎么改半径
  75030. var y = 2 * Math.random() - 1;
  75031. var t = Math.PI * 2 * Math.random();
  75032. var r = Math.sqrt(1 - y * y); //因为 r*r = 1-y*y = x*x + z*z = r*r(cos^2 + sin^2 );
  75033. var lowDownRatio = 0.2; //压低近平面
  75034. var vec3 = new Vector3(r * Math.cos(t), y, Math.abs(r * Math.sin(t)) * lowDownRatio);
  75035. particle.position = new Vector3().addVectors(this.positionBase, vec3.multiplyScalar(this.radius));
  75036. }
  75037. particle.position.add(center); //add
  75038. if (this.velocityStyle == 'cube') {
  75039. particle.velocity = this.randomVector3(this.velocityBase, this.velocitySpread);
  75040. }
  75041. if (this.velocityStyle == 'sphere') {
  75042. //var direction = particle.position.clone()
  75043. var direction = new Vector3(0, 0, 1); //烟应该都是向上的
  75044. var speed = this.randomValue(this.speedBase, this.speedSpread);
  75045. particle.velocity = direction.normalize().multiplyScalar(speed);
  75046. }
  75047. particle.acceleration = this.randomValue(this.accelerationBase, this.accelerationSpread);
  75048. particle.angle = this.randomValue(this.angleBase, this.angleSpread);
  75049. particle.angleVelocity = this.randomValue(this.angleVelocityBase, this.angleVelocitySpread);
  75050. particle.angleAcceleration = this.randomValue(this.angleAccelerationBase, this.angleAccelerationSpread);
  75051. particle.size = this.randomValue(this.sizeBase, this.sizeSpread);
  75052. var color = this.randomVector3(this.colorBase, this.colorSpread);
  75053. particle.color = new Color().setHSL(color.x, color.y, color.z);
  75054. particle.opacity = this.randomValue(this.opacityBase, this.opacitySpread);
  75055. particle.age = 0;
  75056. particle.alive = 0; // particles initialize as inactive
  75057. return particle;
  75058. }
  75059. getPointsForBound() {
  75060. return this.boundPoints; //可以用于expand实时bound的点, 不含particle的size等边距
  75061. }
  75062. getBound(points) {
  75063. // points为生成点(圆心)
  75064. this.boundPoints = [];
  75065. var boundingBox = new Box3();
  75066. var maxSize = this.sizeTween.values.slice().sort((a, b) => b - a)[0];
  75067. var margin0 = maxSize * 0.11;
  75068. var margin1 = margin0 + 0.5; //保守估计还会飘出这么多距离吧: size + 飘动
  75069. points.forEach(bottom => {
  75070. var top = bottom.clone();
  75071. top.z += this.height;
  75072. boundingBox.expandByPoint(bottom);
  75073. boundingBox.expandByPoint(top);
  75074. this.boundPoints.push(bottom, top);
  75075. });
  75076. var xyExpand = this.radius + margin1;
  75077. boundingBox.expandByVector(new Vector3(xyExpand, xyExpand, 0));
  75078. boundingBox.min.z -= margin0;
  75079. boundingBox.max.z += margin1;
  75080. this.boundingBox = boundingBox;
  75081. /* if(!this.debugBox){
  75082. this.debugBox = new THREE.Mesh(boxGeo, boxMat)
  75083. this.add(this.debugBox)
  75084. }
  75085. this.debugBox.scale.copy(boundingBox.getSize(new THREE.Vector3))
  75086. this.debugBox.position.copy(boundingBox.getCenter(new THREE.Vector3)) */
  75087. }
  75088. createGeometry() {
  75089. this.particleArray = [];
  75090. var positions = [];
  75091. var colors = [];
  75092. var alives = [];
  75093. var opacitys = [];
  75094. var sizes = [];
  75095. var angles = [];
  75096. var count, points;
  75097. if (this.positions.length > 1) {
  75098. var spaceDis = 0.6; //间隔距离
  75099. count = Math.ceil(this.curve.wholeLength / spaceDis) + 1;
  75100. points = this.curve.getSpacedPoints(count);
  75101. count = points.length;
  75102. /* points.forEach(e=> {
  75103. var sphere = debugSphere.clone();
  75104. sphere.position.copy(e)
  75105. viewer.scene.scene.add(sphere)
  75106. }) */
  75107. var haventGetPoints = points.slice();
  75108. var getRanPoints = function getRanPoints(i) {
  75109. var a = Math.random();
  75110. var choseIndex = Math.floor(haventGetPoints.length * a);
  75111. var point = haventGetPoints[choseIndex];
  75112. if (haventGetPoints.length == 1) {
  75113. haventGetPoints = points.slice();
  75114. } else {
  75115. haventGetPoints.splice(choseIndex, 1);
  75116. }
  75117. return point;
  75118. };
  75119. this.getBound(points);
  75120. } else {
  75121. this.getBound(this.positions);
  75122. }
  75123. for (var i = 0; i < this.particleCount; i++) {
  75124. var center = new Vector3().copy(this.positions.length > 1 ? getRanPoints(i) : this.positions[0]);
  75125. //var center = new THREE.Vector3().copy(this.positions.length>1 ? points[Math.floor(i/this.particleCount * count)] : this.positions[0])
  75126. // remove duplicate code somehow, here and in update function below.
  75127. this.particleArray[i] = this.createParticle(center);
  75128. positions[3 * i] = this.particleArray[i].position.x;
  75129. positions[3 * i + 1] = this.particleArray[i].position.y;
  75130. positions[3 * i + 2] = this.particleArray[i].position.z;
  75131. colors[3 * i] = this.particleArray[i].color.r;
  75132. colors[3 * i + 1] = this.particleArray[i].color.g;
  75133. colors[3 * i + 2] = this.particleArray[i].color.b;
  75134. alives[i] = this.particleArray[i].alive;
  75135. opacitys[i] = this.particleArray[i].opacity;
  75136. sizes[i] = this.particleArray[i].size;
  75137. angles[i] = this.particleArray[i].angle;
  75138. }
  75139. this.geometry.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));
  75140. this.geometry.setAttribute('customColor', new BufferAttribute(new Float32Array(colors), 3));
  75141. this.geometry.setAttribute('customVisible', new BufferAttribute(new Float32Array(alives), 1));
  75142. this.geometry.setAttribute('customOpacity', new BufferAttribute(new Float32Array(opacitys), 1));
  75143. this.geometry.setAttribute('customSize', new BufferAttribute(new Float32Array(sizes), 1));
  75144. this.geometry.setAttribute('customAngle', new BufferAttribute(new Float32Array(angles), 1));
  75145. }
  75146. createMaterial() {
  75147. this.material = new ShaderMaterial({
  75148. uniforms: {
  75149. u_sampler: {
  75150. type: "t",
  75151. value: getTexture$1()
  75152. },
  75153. heightOfNearPlane: {
  75154. type: "f",
  75155. value: 0
  75156. } //相对far ,以确保画面缩放时点的大小也会缩放
  75157. },
  75158. vertexShader: vertexShader$1,
  75159. vertexShader: vertexShader$1,
  75160. fragmentShader: fragmentShader$1,
  75161. transparent: true,
  75162. alphaTest: 0.5,
  75163. // if having transparency issues, try including: alphaTest: 0.5,
  75164. blending: this.blendStyle,
  75165. depthTest: this.blendStyle != NormalBlending
  75166. });
  75167. this.setPerspective(this.fov, this.screenHeight);
  75168. }
  75169. update(dt) {
  75170. if (!Potree.Utils.getObjVisiByReason(this, 'force')) {
  75171. //被手动隐藏了
  75172. return;
  75173. }
  75174. if (!Potree.Utils.isInsideFrustum(this.boundingBox, viewer.scene.getActiveCamera())) {
  75175. Potree.Utils.updateVisible(this, 'isInsideFrustum', false); //不在视野范围
  75176. //console.log('unvi')
  75177. return;
  75178. } else {
  75179. Potree.Utils.updateVisible(this, 'isInsideFrustum', true);
  75180. }
  75181. if (dt > 1) {
  75182. console.log('update dt>1', dt);
  75183. }
  75184. //dt *= 0.5;
  75185. var recycleIndices = [];
  75186. var recycleAges = [];
  75187. var positions = [];
  75188. var colors = [];
  75189. var alives = [];
  75190. var opacitys = [];
  75191. var sizes = [];
  75192. var angles = [];
  75193. for (var i = 0; i < this.particleCount; i++) {
  75194. if (this.particleArray[i].alive) {
  75195. if (this.velocityStyle == 'cube') {
  75196. //一定几率改变下方向
  75197. var ratio = Math.random();
  75198. if (this.particleArray[i].age - this.particleArray[i].lastChangeVage > this.particleDeathAge * ratio) {
  75199. this.particleArray[i].velocity = this.randomVector3(this.velocityBase, this.velocitySpread);
  75200. this.particleArray[i].lastChangeVage = this.particleArray[i].age;
  75201. }
  75202. } else {
  75203. /* if(this.particleArray[i].age - this.particleArray[i].lastChangeVage > this.particleDeathAge*0.3 ){
  75204. if( Math.random()>0.1){//一定几率改变下方向
  75205. var speed = this.randomValue( this.speedBase, this.speedSpread );
  75206. this.particleArray[i].velocity = this.randomVector3( new THREE.Vector3, new THREE.Vector3(1,1,1) );
  75207. this.particleArray[i].velocity.normalize().multiplyScalar( speed );
  75208. }
  75209. this.particleArray[i].lastChangeVage = this.particleArray[i].age
  75210. } */
  75211. }
  75212. this.particleArray[i].update(dt);
  75213. // check if particle should expire
  75214. // could also use: death by size<0 or alpha<0.
  75215. if (this.particleArray[i].age > this.particleDeathAge) {
  75216. this.particleArray[i].alive = 0.0;
  75217. recycleIndices.push(i);
  75218. recycleAges.push((this.particleArray[i].age - this.particleDeathAge) % this.particleDeathAge);
  75219. }
  75220. // update particle properties in shader
  75221. positions[3 * i] = this.particleArray[i].position.x;
  75222. positions[3 * i + 1] = this.particleArray[i].position.y;
  75223. positions[3 * i + 2] = this.particleArray[i].position.z;
  75224. colors[3 * i] = this.particleArray[i].color.r;
  75225. colors[3 * i + 1] = this.particleArray[i].color.g;
  75226. colors[3 * i + 2] = this.particleArray[i].color.b;
  75227. alives[i] = this.particleArray[i].alive;
  75228. opacitys[i] = this.particleArray[i].opacity;
  75229. sizes[i] = this.particleArray[i].size;
  75230. angles[i] = this.particleArray[i].angle;
  75231. }
  75232. }
  75233. // check if particle emitter is still running
  75234. //if ( !this.emitterAlive ) return;
  75235. this.geometry.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));
  75236. this.geometry.setAttribute('customColor', new BufferAttribute(new Float32Array(colors), 3));
  75237. this.geometry.setAttribute('customVisible', new BufferAttribute(new Float32Array(alives), 1));
  75238. this.geometry.setAttribute('customOpacity', new BufferAttribute(new Float32Array(opacitys), 1));
  75239. this.geometry.setAttribute('customSize', new BufferAttribute(new Float32Array(sizes), 1));
  75240. this.geometry.setAttribute('customAngle', new BufferAttribute(new Float32Array(angles), 1));
  75241. this.geometry.attributes.customColor.needsUpdate = true;
  75242. this.geometry.attributes.customVisible.needsUpdate = true;
  75243. this.geometry.attributes.customOpacity.needsUpdate = true;
  75244. this.geometry.attributes.customSize.needsUpdate = true;
  75245. this.geometry.attributes.customAngle.needsUpdate = true;
  75246. // if no particles have died yet, then there are still particles to activate
  75247. if (this.emitterAge < this.particleDeathAge)
  75248. //开始时一个个放出来
  75249. {
  75250. var particlesPerSecond = this.particleCount / this.particleDeathAge;
  75251. // determine indices of particles to activate
  75252. var startIndex = Math.round(particlesPerSecond * (this.emitterAge + 0));
  75253. var endIndex = Math.round(particlesPerSecond * (this.emitterAge + dt));
  75254. if (endIndex > this.particleCount) endIndex = this.particleCount;
  75255. for (var i = startIndex; i < endIndex; i++) this.particleArray[i].alive = 1.0;
  75256. }
  75257. // if any particles have died while the emitter is still running, we imediately recycle them
  75258. for (var j = 0; j < recycleIndices.length; j++) {
  75259. var i = recycleIndices[j];
  75260. this.particleArray[i] = this.createParticle(this.particleArray[i].center);
  75261. this.particleArray[i].alive = 1.0; // activate right away
  75262. this.particleArray[i].age = recycleAges[j];
  75263. positions[3 * i] = this.particleArray[i].position.x;
  75264. positions[3 * i + 1] = this.particleArray[i].position.y;
  75265. positions[3 * i + 2] = this.particleArray[i].position.z;
  75266. }
  75267. this.geometry.setAttribute('position', new BufferAttribute(new Float32Array(positions), 3));
  75268. this.geometry.attributes.position.needsUpdate = true;
  75269. // stop emitter?
  75270. this.emitterAge += dt;
  75271. //if ( this.emitterAge > this.emitterDeathAge ) this.emitterAlive = false;
  75272. }
  75273. randomValue(base, spread) {
  75274. //return base + spread * (Math.random() - 0.5);
  75275. var p = Math.random();
  75276. return base * p + spread * (1 - p);
  75277. }
  75278. randomVector3(base, spread) {
  75279. var rand3 = new Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5);
  75280. return new Vector3().addVectors(base, new Vector3().multiplyVectors(spread, rand3));
  75281. }
  75282. setSize(e) {
  75283. var viewport = e.viewport;
  75284. this.screenHeight = viewport.resolution.y;
  75285. this.setPerspective(this.fov, this.screenHeight);
  75286. }
  75287. setFov(fov) {
  75288. this.fov = fov;
  75289. this.setPerspective(this.fov, this.screenHeight);
  75290. }
  75291. setPerspective(fov, height) {
  75292. //this.uniforms.heightOfNearPlane.value = Math.abs(height / (2 * Math.tan(THREE.Math.degToRad(fov * 0.5))));
  75293. var far = Math.abs(height / (2 * Math.tan(MathUtils.degToRad(fov * 0.5))));
  75294. this.material.uniforms.heightOfNearPlane.value = far;
  75295. }
  75296. dispose() {
  75297. this.geometry.dispose();
  75298. this.material.dispose();
  75299. this.dispatchEvent('dispose');
  75300. }
  75301. }
  75302. /*
  75303. 改进:如果有必要
  75304. 根据curve中分成的点,分成多个簇,每个簇掌管该部分的可见性和particle的数量。
  75305. 在camera_changed时根据远近修改每个簇的particle的数量,当然不会大于初始创建的个数。多出的随机隐藏。
  75306. */
  75307. var vertexShader$2 = "\n attribute vec3 color;\n attribute float size;\n attribute float angle;\n attribute float opacity;\n attribute float visible;\n varying vec4 vColor;\n varying float vAngle;\n uniform float heightOfNearPlane;\n \n void main() {\n if(visible > 0.5) {\n vColor = vec4(color, opacity);\n } else {\n vColor = vec4(0.0, 0.0, 0.0, 0.0);\n }\n vAngle = angle;\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\n gl_Position = projectionMatrix * mvPosition;\n \n gl_PointSize = ( heightOfNearPlane * size ) / gl_Position.w;\n }\n";
  75308. var fragmentShader$2 = "\n uniform sampler2D u_sampler;\n varying vec4 vColor;\n varying float vAngle;\n void main() {\n gl_FragColor = vColor;\n float u = cos(vAngle);\n float v = sin(vAngle);\n vec2 uv = vec2(\n u * (gl_PointCoord.x - 0.5) + v * (gl_PointCoord.y - 0.5) + 0.5, \n u * (gl_PointCoord.y - 0.5) - v * (gl_PointCoord.x - 0.5) + 0.5\n );\n vec4 texture = texture2D(u_sampler, uv);\n gl_FragColor = gl_FragColor * texture;\n }\n";
  75309. // import { vertexShader, fragmentShader } from './shader'
  75310. var DEG2RAD = Math.PI / 180;
  75311. class Particle$2 {
  75312. constructor() {
  75313. this.position = new Vector3();
  75314. this.velocity = new Vector3();
  75315. this.angle = 0;
  75316. this.angleVelocity = 0;
  75317. this.angleAcceleration = 0;
  75318. this.size = 16;
  75319. this.color = new Color();
  75320. this.opacity = 1;
  75321. this.rebornCount = 0; //重生次数
  75322. this.age = 0;
  75323. this.alive = 0; //注意,一开始时是未出生的
  75324. this.deadAge = 0; //已死亡时间
  75325. this.sizeTween = null;
  75326. this.colorTween = null;
  75327. this.opacityTween = null;
  75328. }
  75329. update(dt) {
  75330. //s = s0 + (v0 + at) * t 或 lastS + delta(vt)
  75331. this.position.add(this.velocity.clone().multiplyScalar(dt));
  75332. this.velocity.multiplyScalar(1 + this.acceleration * dt);
  75333. this.angle += this.angleVelocity * DEG2RAD * dt;
  75334. this.angleVelocity += this.angleAcceleration * DEG2RAD * dt;
  75335. this.age += dt;
  75336. if (this.sizeTween.times.length > 0) {
  75337. this.size = this.sizeTween.lerp(this.age / this.deathAge);
  75338. }
  75339. if (this.colorTween.times.length > 0) {
  75340. var colorHSL = this.colorTween.lerp(this.age / this.deathAge);
  75341. this.color = new Color().setHSL(colorHSL.x, colorHSL.y, colorHSL.z);
  75342. }
  75343. if (this.opacityTween.times.length > 0) {
  75344. this.opacity = this.opacityTween.lerp(this.age / this.deathAge);
  75345. }
  75346. viewer.dispatchEvent('content_changed');
  75347. }
  75348. }
  75349. class Util {
  75350. constructor() {}
  75351. randomValue(min, max) {
  75352. //return min + max * (Math.random() - 0.5)
  75353. var p = Math.random();
  75354. return min * p + max * (1 - p);
  75355. }
  75356. randomVector3(min, max) {
  75357. var rand3 = new Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5);
  75358. return new Vector3().addVectors(min, new Vector3().multiplyVectors(max, rand3));
  75359. }
  75360. }
  75361. var util$1 = new Util();
  75362. var Shape$1 = {
  75363. CUBE: 1,
  75364. SPHERE: 2
  75365. };
  75366. var particleTexture$1;
  75367. var getTexture$2 = () => {
  75368. if (!particleTexture$1) {
  75369. particleTexture$1 = new TextureLoader().load(Potree.resourcePath + '/textures/explode.png');
  75370. }
  75371. return particleTexture$1;
  75372. };
  75373. var sphereGeo = new SphereBufferGeometry(1, 10, 4);
  75374. var sphereMat = new MeshBasicMaterial({
  75375. wireframe: true,
  75376. color: "#ffffff"
  75377. });
  75378. var defaults$1 = {
  75379. position: new Vector3(0, 0, 1),
  75380. positionShape: Shape$1.SPHERE,
  75381. positionRange: new Vector3(1, 1, 1),
  75382. //cube
  75383. radius: 1.3,
  75384. //sphere
  75385. velocityShape: Shape$1.SPHERE,
  75386. velocity: new Vector3(0, 0, 2),
  75387. //cube
  75388. velocityRange: new Vector3(0, 0, 3),
  75389. //sphere
  75390. speed: 0.4,
  75391. speedRange: 1,
  75392. size: 0.4,
  75393. sizeRange: 2,
  75394. //sizeTween: new Tween( [0, 0.05, 0.3, 0.45], [0, 1, 3, 0.1] ),
  75395. sizeTween: [[0, 0.04, 0.2, 1], [0.1, 1, 6, 8]],
  75396. color: new Vector3(1.0, 1.0, 1.0),
  75397. colorRange: new Vector3(0, 0, 0),
  75398. colorTween: new Tween(),
  75399. opacity: 1.0,
  75400. opacityRange: 0.0,
  75401. opacityTween: new Tween([0, 0.06, 0.3, 0.8, 1], [0, 1, 0.3, 0.05, 0]),
  75402. blendMode: AdditiveBlending,
  75403. acceleration: 0.5,
  75404. accelerationRange: 0,
  75405. angle: 0,
  75406. angleRange: 0,
  75407. angleVelocity: 0,
  75408. angleVelocityRange: 0,
  75409. angleAcceleration: 0,
  75410. angleAccelerationRange: 0,
  75411. strength: 1,
  75412. //particlesPerSecond: 8,
  75413. particleDeathAge: 0.7,
  75414. recycleTimes: 3,
  75415. //每个粒子在一次爆炸后循环次数,循环完毕进入particleSpaceTime,等待下一次爆炸.
  75416. //爆炸时长: particleDeathAge * (recycleTimes+1)
  75417. particleSpaceTime: 3 //间隔
  75418. };
  75419. class ExplodeParticle extends Points {
  75420. constructor(params) {
  75421. super();
  75422. this.age = 0;
  75423. this.alive = true;
  75424. //this.deathAge = 60
  75425. this.loop = true;
  75426. this.blendMode = NormalBlending;
  75427. this.setParameters(params);
  75428. this.createParticles();
  75429. this.frustumCulled = false; //似乎是禁止相机裁剪,否则会在某些角度消失。但是会不会更耗性能呢?
  75430. //------------------------------------
  75431. this.setSize({
  75432. viewport: viewer.mainViewport
  75433. });
  75434. this.setFov(viewer.fov);
  75435. var setSize = e => {
  75436. if (e.viewport.name != "MainView") return;
  75437. this.setSize(e);
  75438. };
  75439. var setFov = e => {
  75440. this.setFov(e.fov);
  75441. };
  75442. /* let reStart = (e)=>{
  75443. if(e.v){//重新一个个放出粒子,否则会一股脑儿全部出来,因为同时大于粒子周期了一起重新生成出现。
  75444. setTimeout(()=>{//会先update一次delta为pageUnvisile的时间才触发
  75445. //console.log('归零')
  75446. //this.reStart()
  75447. },1)
  75448. }
  75449. } */
  75450. viewer.addEventListener('resize', setSize);
  75451. viewer.addEventListener('fov_changed', setFov);
  75452. //viewer.addEventListener('pageVisible', reStart)
  75453. this.addEventListener('dispose', () => {
  75454. viewer.removeEventListener('resize', setSize);
  75455. viewer.removeEventListener('fov_changed', setFov);
  75456. //viewer.removeEventListener('pageVisible', reStart)
  75457. });
  75458. }
  75459. computeParams() {
  75460. if (this.curve) {
  75461. this.position.copy(this.curve.points[0]);
  75462. }
  75463. var minSize = 0.8,
  75464. maxSize = 10,
  75465. minRadiusBound = 0.2,
  75466. maxRadiusBound = 20;
  75467. var size = minSize + (maxSize - minSize) * MathUtils.smoothstep(this.radius * this.strength, minRadiusBound, maxRadiusBound);
  75468. this.sizeTween.values = this.defaultSizeTween.values.map(e => e * size);
  75469. this.particleCount = Math.ceil(this.strength * this.radius * 5 /* * this.radius * this.radius */);
  75470. this.speed = defaults$1.speed * this.radius;
  75471. this.speedRange = defaults$1.speedRange * this.radius;
  75472. console.log(this.particleCount);
  75473. {
  75474. this.boundPoints = [];
  75475. this.boundPoints.push(this.position.clone());
  75476. var _maxSize = this.sizeTween.values.slice().sort((a, b) => b - a)[0];
  75477. var margin = _maxSize * 0.35 + 0.5;
  75478. var scale = this.radius + margin;
  75479. var sphere = new Sphere(this.position, scale); //加上防止剪裁
  75480. this.boundingSphere = sphere; //虽然还是会有一些后续移动的会超出
  75481. this.boundingBox = new Box3().setFromCenterAndSize(this.position, new Vector3(scale * 2, scale * 2, scale * 2));
  75482. /* if(!this.debugSphere){
  75483. this.debugSphere = new THREE.Mesh(sphereGeo, sphereMat)
  75484. this.add(this.debugSphere)
  75485. }
  75486. this.debugSphere.scale.set(scale,scale,scale) */
  75487. }
  75488. }
  75489. getPointsForBound() {
  75490. return this.boundPoints; //可以用于expand实时bound的点, 不含particle的size等边距
  75491. }
  75492. reStart() {
  75493. this.age = 0;
  75494. this.createParticles();
  75495. }
  75496. setParameters(params) {
  75497. params = $.extend({}, defaults$1, params);
  75498. for (var key in params) {
  75499. var value = params[key];
  75500. if (key == 'position') this.position.copy(value);else if (value instanceof Array && value[0] instanceof Array) {
  75501. this[key] = new Tween(...value);
  75502. } else if (value instanceof Vector3 || value instanceof Color) {
  75503. this[key] = value.clone();
  75504. } else {
  75505. this[key] = value;
  75506. }
  75507. }
  75508. this.defaultSizeTween = this.sizeTween.clone();
  75509. //Object.assign(this, params)
  75510. this.particles = [];
  75511. this.age = 0.0;
  75512. this.alive = true;
  75513. this.geometry = new BufferGeometry();
  75514. this.computeParams();
  75515. this.material = new ShaderMaterial({
  75516. uniforms: {
  75517. u_sampler: {
  75518. value: this.texture || getTexture$2()
  75519. },
  75520. heightOfNearPlane: {
  75521. type: "f",
  75522. value: 0
  75523. } //相对far ,以确保画面缩放时点的大小也会缩放
  75524. },
  75525. vertexShader: vertexShader$2,
  75526. fragmentShader: fragmentShader$2,
  75527. transparent: true,
  75528. alphaTest: 0.5,
  75529. depthTest: this.blendMode == NormalBlending,
  75530. blending: this.blendMode
  75531. });
  75532. }
  75533. createParticles() {
  75534. this.particles = [];
  75535. var count = this.particleCount;
  75536. var positionArray = new Float32Array(count * 3);
  75537. var colorArray = new Float32Array(count * 3);
  75538. var sizeArray = new Float32Array(count);
  75539. var angleArray = new Float32Array(count);
  75540. var opacityArray = new Float32Array(count);
  75541. var visibleArray = new Float32Array(count);
  75542. for (var i = 0; i < count; i++) {
  75543. var particle = this.createParticle();
  75544. /* positionArray[i * 3] = particle.position.x
  75545. positionArray[i * 3 + 1] = particle.position.y
  75546. positionArray[i * 3 + 2] = particle.position.z
  75547. colorArray[i * 3] = particle.color.r
  75548. colorArray[i * 3 + 1] = particle.color.g
  75549. colorArray[i * 3 + 2] = particle.color.b
  75550. sizeArray[i] = particle.size
  75551. angleArray[i] = particle.angel
  75552. opacityArray[i] = particle.opacity
  75553. visibleArray[i] = particle.alive */
  75554. this.particles[i] = particle;
  75555. }
  75556. this.geometry.setAttribute('position', new BufferAttribute(positionArray, 3));
  75557. this.geometry.setAttribute('color', new BufferAttribute(colorArray, 3));
  75558. this.geometry.setAttribute('angle', new BufferAttribute(angleArray, 1));
  75559. this.geometry.setAttribute('size', new BufferAttribute(sizeArray, 1));
  75560. this.geometry.setAttribute('visible', new BufferAttribute(visibleArray, 1));
  75561. this.geometry.setAttribute('opacity', new BufferAttribute(opacityArray, 1));
  75562. }
  75563. createParticle() {
  75564. var particle = new Particle$2();
  75565. particle.sizeTween = this.sizeTween;
  75566. particle.colorTween = this.colorTween;
  75567. particle.opacityTween = this.opacityTween;
  75568. particle.deathAge = this.particleDeathAge;
  75569. if (this.positionShape == Shape$1.CUBE) {
  75570. particle.position = util$1.randomVector3(new Vector3(), this.positionRange);
  75571. }
  75572. if (this.positionShape == Shape$1.SPHERE) {
  75573. /* const z = 2 * Math.random() - 1
  75574. const t = Math.PI * 2 * Math.random()
  75575. const r = Math.sqrt(1 - z*z)
  75576. const vec3 = new THREE.Vector3(r * Math.cos(t), r * Math.sin(t), z)
  75577. particle.position = vec3.multiplyScalar(this.radius) */
  75578. var y = 2 * Math.random() - 1;
  75579. var t = Math.PI * 2 * Math.random();
  75580. var r = Math.sqrt(1 - y * y);
  75581. var vec3 = new Vector3(r * Math.cos(t), y, r * Math.sin(t));
  75582. particle.position = vec3.multiplyScalar(this.radius);
  75583. }
  75584. if (this.velocityShape == Shape$1.CUBE) {
  75585. particle.velocity = util$1.randomVector3(this.velocity, this.velocityRange);
  75586. }
  75587. if (this.velocityShape == Shape$1.SPHERE) {
  75588. var direction = new Vector3().addVectors(particle.position, new Vector3(0, 0, this.radius * 2)); //向上升?
  75589. var speed = util$1.randomValue(this.speed, this.speedRange);
  75590. particle.velocity = direction.normalize().multiplyScalar(speed);
  75591. }
  75592. particle.acceleration = util$1.randomValue(this.acceleration, this.accelerationRange);
  75593. particle.angle = util$1.randomValue(this.angle, this.angleRange);
  75594. particle.angleVelocity = util$1.randomValue(this.angleVelocity, this.angleVelocityRange);
  75595. particle.angleAcceleration = util$1.randomValue(this.angleAcceleration, this.angleAccelerationRange);
  75596. particle.size = util$1.randomValue(this.size, this.sizeRange);
  75597. var color = util$1.randomVector3(this.color, this.colorRange);
  75598. particle.color = new Color().setHSL(color.x, color.y, color.z);
  75599. particle.opacity = util$1.randomValue(this.opacity, this.opacityRange);
  75600. return particle;
  75601. }
  75602. update(dt) {
  75603. if (!Potree.Utils.getObjVisiByReason(this, 'force')) {
  75604. //被手动隐藏了
  75605. return;
  75606. }
  75607. if (this.delayStartTime > 0) {
  75608. // 爆炸延迟
  75609. return this.delayStartTime -= dt;
  75610. }
  75611. if (!Potree.Utils.isInsideFrustum(this.boundingSphere, viewer.scene.getActiveCamera())) {
  75612. Potree.Utils.updateVisible(this, 'isInsideFrustum', false); //不在视野范围
  75613. return;
  75614. } else {
  75615. Potree.Utils.updateVisible(this, 'isInsideFrustum', true);
  75616. }
  75617. //const timeRatio = 0.5
  75618. if (dt > 1) {
  75619. console.log('update dt>1', dt);
  75620. }
  75621. //dt *= timeRatio
  75622. var particleDeathAge = this.particleDeathAge; /* * timeRatio */
  75623. var particleSpaceTime = this.particleSpaceTime; /* * timeRatio */
  75624. var recycleIndices = [];
  75625. var recycleAges = [];
  75626. var recycleRebornCount = [];
  75627. var positionArray = this.geometry.attributes.position.array;
  75628. var opacityArray = this.geometry.attributes.opacity.array;
  75629. var visibleArray = this.geometry.attributes.visible.array;
  75630. var colorArray = this.geometry.attributes.color.array;
  75631. var angleArray = this.geometry.attributes.angle.array;
  75632. var sizeArray = this.geometry.attributes.size.array;
  75633. for (var i = 0; i < this.particleCount; i++) {
  75634. var particle = this.particles[i];
  75635. if (particle.alive) {
  75636. particle.update(dt);
  75637. if (particle.age > particleDeathAge) {
  75638. particle.alive = 0.0;
  75639. if (particle.rebornCount >= this.recycleTimes) {
  75640. particle.deadAge = particle.age - particleDeathAge; //已死亡时间
  75641. } else {
  75642. //直接循环
  75643. recycleIndices.push(i);
  75644. recycleAges.push( /* ( */particle.age - particleDeathAge /* )%(this.particleDeathAge ) */);
  75645. recycleRebornCount.push(particle.rebornCount + 1);
  75646. }
  75647. }
  75648. positionArray[i * 3] = particle.position.x;
  75649. positionArray[i * 3 + 1] = particle.position.y;
  75650. positionArray[i * 3 + 2] = particle.position.z;
  75651. colorArray[i * 3] = particle.color.r;
  75652. colorArray[i * 3 + 1] = particle.color.g;
  75653. colorArray[i * 3 + 2] = particle.color.b;
  75654. visibleArray[i] = particle.alive;
  75655. opacityArray[i] = particle.opacity;
  75656. angleArray[i] = particle.angle;
  75657. sizeArray[i] = particle.size;
  75658. } else {
  75659. if (particle.rebornCount >= this.recycleTimes) {
  75660. if (particle.age > particleDeathAge) {
  75661. //其他已经死亡的粒子的时间继续增加
  75662. particle.deadAge += dt;
  75663. }
  75664. }
  75665. }
  75666. if (particle.rebornCount >= this.recycleTimes && particle.age > particleDeathAge) {
  75667. //已经死亡
  75668. if (particle.deadAge >= particleSpaceTime) {
  75669. //死亡时间超过设定的间隔时间后重启
  75670. recycleIndices.push(i);
  75671. var wholeTime = particleDeathAge * (this.recycleTimes + 1) + particleSpaceTime;
  75672. recycleAges.push((particle.deadAge - particleSpaceTime) % wholeTime); //剩余时间就是重生后的age
  75673. recycleRebornCount.push(0);
  75674. }
  75675. }
  75676. }
  75677. this.geometry.attributes.size.needsUpdate = true;
  75678. this.geometry.attributes.color.needsUpdate = true;
  75679. this.geometry.attributes.angle.needsUpdate = true;
  75680. this.geometry.attributes.visible.needsUpdate = true;
  75681. this.geometry.attributes.opacity.needsUpdate = true;
  75682. this.geometry.attributes.position.needsUpdate = true;
  75683. if (!this.alive) return;
  75684. if (this.age < particleDeathAge) {
  75685. var startIndex = Math.round(this.particleCount * (this.age + 0) / particleDeathAge);
  75686. var endIndex = Math.round(this.particleCount * (this.age + dt) / particleDeathAge);
  75687. if (endIndex > this.particleCount) {
  75688. endIndex = this.particleCount;
  75689. }
  75690. for (var _i = startIndex; _i < endIndex; _i++) {
  75691. this.particles[_i].alive = 1.0;
  75692. }
  75693. }
  75694. for (var j = 0; j < recycleIndices.length; j++) {
  75695. var _i2 = recycleIndices[j];
  75696. this.particles[_i2] = this.createParticle();
  75697. this.particles[_i2].alive = 1.0; //出生
  75698. this.particles[_i2].age = recycleAges[j];
  75699. this.particles[_i2].rebornCount = recycleRebornCount[j];
  75700. /* if(this.particles[i].age < particleDeathAge){
  75701. positionArray[i * 3] = this.particles[i].position.x
  75702. positionArray[i * 3 + 1] = this.particles[i].position.y
  75703. positionArray[i * 3 + 2] = this.particles[i].position.z
  75704. visibleArray[i] = particle.alive?
  75705. } */
  75706. }
  75707. this.geometry.attributes.position.needsUpdate = true;
  75708. this.age += dt;
  75709. if (this.age > this.deathAge && !this.loop) {
  75710. this.alive = false;
  75711. }
  75712. }
  75713. setSize(e) {
  75714. var viewport = e.viewport;
  75715. this.screenHeight = viewport.resolution.y;
  75716. this.setPerspective(this.fov, this.screenHeight);
  75717. }
  75718. setFov(fov) {
  75719. this.fov = fov;
  75720. this.setPerspective(this.fov, this.screenHeight);
  75721. }
  75722. setPerspective(fov, height) {
  75723. //this.uniforms.heightOfNearPlane.value = Math.abs(height / (2 * Math.tan(THREE.Math.degToRad(fov * 0.5))));
  75724. var far = Math.abs(height / (2 * Math.tan(MathUtils.degToRad(fov * 0.5))));
  75725. this.material.uniforms.heightOfNearPlane.value = far;
  75726. }
  75727. updateGeometry() {
  75728. this.computeParams();
  75729. this.reStart();
  75730. }
  75731. dispose() {
  75732. this.geometry.dispose();
  75733. this.material.dispose();
  75734. this.dispatchEvent('dispose');
  75735. }
  75736. }
  75737. var colors$2 = {
  75738. 'fire+smoke': 0xffffff,
  75739. 'smoke': 0xffffff,
  75740. 'explode': 0xffffff
  75741. };
  75742. var depthMatPrefix = {
  75743. clipDistance: 100,
  75744. occlusionDistance: 60,
  75745. /* 变为backColor距离 */
  75746. maxClipFactor: 0.5,
  75747. backColor: "#777",
  75748. useDepth: true,
  75749. transparent: !0
  75750. };
  75751. var lineMats$1;
  75752. var getLineMat$1 = function getLineMat(type) {
  75753. if (!lineMats$1) {
  75754. lineMats$1 = {
  75755. 'fire+smoke': LineDraw.createFatLineMat($.extend(depthMatPrefix, {
  75756. color: colors$2['fire+smoke'],
  75757. lineWidth: 2
  75758. })),
  75759. 'smoke': LineDraw.createFatLineMat($.extend(depthMatPrefix, {
  75760. color: colors$2['smoke'],
  75761. lineWidth: 2
  75762. })),
  75763. 'explode': LineDraw.createFatLineMat($.extend(depthMatPrefix, {
  75764. color: colors$2['explode'],
  75765. lineWidth: 2
  75766. }))
  75767. };
  75768. }
  75769. return lineMats$1[type];
  75770. };
  75771. var handleMats;
  75772. var getHandleMat = function getHandleMat(type) {
  75773. if (!handleMats) {
  75774. var texLoader = new TextureLoader();
  75775. handleMats = {
  75776. "fire+smoke": new DepthBasicMaterial($.extend(depthMatPrefix, {
  75777. map: texLoader.load(Potree.resourcePath + '/textures/icon-fire.png'),
  75778. color: colors$2['fire+smoke']
  75779. })),
  75780. "smoke": new DepthBasicMaterial($.extend(depthMatPrefix, {
  75781. map: texLoader.load(Potree.resourcePath + '/textures/icon-smoke.png'),
  75782. color: colors$2['smoke']
  75783. })),
  75784. "explode": new DepthBasicMaterial($.extend(depthMatPrefix, {
  75785. map: texLoader.load(Potree.resourcePath + '/textures/icon-explode.png'),
  75786. color: colors$2['explode']
  75787. }))
  75788. };
  75789. }
  75790. return handleMats[type];
  75791. };
  75792. var ParticleEditor = {
  75793. bus: new EventDispatcher(),
  75794. particleGroup: new Object3D(),
  75795. curveGroup: new Object3D(),
  75796. init: function init() {
  75797. this.particleGroup.name = 'particles';
  75798. viewer.scene.scene.add(this.particleGroup);
  75799. this.curveGroup.name = 'particles-curves';
  75800. viewer.scene.scene.add(this.curveGroup);
  75801. },
  75802. addParticle: function addParticle() {
  75803. var prop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  75804. var particle;
  75805. if (prop.type == 'fire') {
  75806. particle = new FireParticle(prop);
  75807. } else if (prop.type == 'smoke') {
  75808. particle = new SmokeParticle(prop);
  75809. } else if (prop.type == 'explode') {
  75810. particle = new ExplodeParticle(prop);
  75811. }
  75812. this.particleGroup.add(particle);
  75813. return particle;
  75814. },
  75815. removeParticle(particle) {
  75816. //particle.dispatchEvent('delete')
  75817. particle.dispose();
  75818. this.particleGroup.remove(particle);
  75819. particle.curve.dispose();
  75820. },
  75821. update(delta) {
  75822. this.particleGroup.children.forEach(e => e.update(delta));
  75823. },
  75824. startInsertion() {
  75825. var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'fire';
  75826. var prop = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  75827. //viewer.modules.ParticleEditor.startInsertion()
  75828. var deferred = $.Deferred();
  75829. var particles = [];
  75830. var finish = ifDone => {
  75831. if (ifDone) {
  75832. deferred.resolve(particles);
  75833. }
  75834. viewer.dispatchEvent({
  75835. type: "CursorChange",
  75836. action: "remove",
  75837. name: "addSth"
  75838. });
  75839. viewer.removeEventListener('global_click', click);
  75840. this.bus.removeEventListener('cancel_insertions', cancel);
  75841. };
  75842. var curve = new CurveCtrl([], getLineMat$1(type), colors$2[type], type + '_curve', {
  75843. handleMat: getHandleMat(type)
  75844. });
  75845. this.curveGroup.add(curve);
  75846. prop.curve = curve;
  75847. prop.type = type;
  75848. //console.log('创建curve',type,curve.uuid)
  75849. var cancel = () => {
  75850. console.log('cancel_insertions', curve.uuid);
  75851. curve.dispose();
  75852. finish(false);
  75853. };
  75854. this.bus.dispatchEvent('cancel_insertions'); //删除旧的
  75855. this.bus.addEventListener('cancel_insertions', cancel);
  75856. var click = e => {
  75857. if (e.button === MOUSE.RIGHT) {
  75858. if (curve.points.length >= 1) {
  75859. //if(type.includes('fire') || type.includes('smoke') ){
  75860. particles = this.createFromData(prop);
  75861. finish(true);
  75862. }
  75863. return;
  75864. }
  75865. var I = e.intersect && (e.intersect.orthoIntersect || e.intersect.location);
  75866. if (!I) return;
  75867. curve.addPoint(I, null, true);
  75868. if (type == 'explode') {
  75869. particles = this.createFromData(prop);
  75870. finish(true);
  75871. }
  75872. return {
  75873. stopContinue: true
  75874. }; //防止继续执行别的侦听,如flytopano
  75875. };
  75876. viewer.addEventListener('global_click', click, {
  75877. importance: 10
  75878. }); //add importance
  75879. viewer.dispatchEvent({
  75880. type: "CursorChange",
  75881. action: "add",
  75882. name: "addSth"
  75883. });
  75884. return deferred.promise();
  75885. },
  75886. createFromData(prop) {
  75887. var type = prop.type;
  75888. var particles = [];
  75889. var curve = prop.curve;
  75890. if (!curve) {
  75891. curve = new CurveCtrl(prop.points, getLineMat$1(type), colors$2[type], type + '_curve', {
  75892. handleMat: getHandleMat(type)
  75893. });
  75894. this.curveGroup.add(curve);
  75895. }
  75896. if (type.includes('fire') || type.includes('smoke')) {
  75897. if (type.includes('fire')) {
  75898. var fire = this.addParticle({
  75899. type: 'fire',
  75900. positions: curve.points,
  75901. curve,
  75902. radius: prop.radius,
  75903. height: prop.height,
  75904. strength: prop.strength
  75905. });
  75906. particles.push(fire);
  75907. }
  75908. if (type.includes('smoke')) {
  75909. var smoke = this.addParticle({
  75910. type: 'smoke',
  75911. positions: curve.points,
  75912. curve,
  75913. positionStyle: 'sphere',
  75914. strength: prop.smokeStrength,
  75915. radius: prop.smokeRadius,
  75916. height: prop.smokeHeight
  75917. });
  75918. particles.push(smoke);
  75919. }
  75920. } else if (type == 'explode') {
  75921. var explode = this.addParticle({
  75922. type: 'explode',
  75923. position: curve.points[0],
  75924. strength: prop.strength,
  75925. radius: prop.radius,
  75926. particleSpaceTime: prop.particleSpaceTime,
  75927. curve,
  75928. delayStartTime: prop.delayStartTime
  75929. });
  75930. particles.push(explode);
  75931. }
  75932. curve.addEventListener('dragCurvePoint', () => {
  75933. Common$1.intervalTool.isWaiting('particlePointChange', () => {
  75934. //延时update,防止卡顿
  75935. particles.forEach(e => e.updateGeometry());
  75936. //geoNeedsUpdate = false
  75937. curve.dispatchEvent('sendUpdatePoints');
  75938. }, 400);
  75939. });
  75940. return particles;
  75941. }
  75942. };
  75943. class CameraAnimationCurve extends EventDispatcher {
  75944. //沿着curve轨迹的相机动画,不指定target,因视线沿着路线
  75945. constructor(curve, duration, tangentDt) {
  75946. //直接传入curve得到的points和UtoTMapArr
  75947. //简单写
  75948. super();
  75949. this.quaFromCurveTan = true;
  75950. this.viewer = viewer;
  75951. //this.curve = curve
  75952. this.duration = duration;
  75953. this.cameraAniSmoothRatio = 5; //缓动系数设置小点,尽量贴合路径,尤其速度快时
  75954. //this.newPointsPercents = UtoTMapArr.slice()
  75955. //this.posInterpolate = true //不直接在curve上取点,因为UtoTMapArr也是getUtoTmapping得来的, curve上getUtoTmapping后和这个不对应。否则要再算一遍pointsPercent
  75956. /* this.posCurve = { points getPointAt(t){
  75957. return curve.getPointAt(t)
  75958. } } */
  75959. this.posCurve = curve;
  75960. //每个点直接朝向前面那个点
  75961. /* this.quaternions = []
  75962. let quaternion, length = points.length
  75963. for(let i=0; i<length-1; i++){
  75964. quaternion = math.getQuaFromPosAim( points[i], points[i+1])
  75965. this.quaternions.push(quaternion)
  75966. }
  75967. this.quaternions.push(quaternion)//最后一个点的朝向和前一个相同即可 */
  75968. }
  75969. setVisible() {}
  75970. updateFrustum() {}
  75971. }
  75972. CameraAnimationCurve.prototype.play = CameraAnimation$1.prototype.play;
  75973. CameraAnimationCurve.prototype.at = CameraAnimation$1.prototype.at;
  75974. CameraAnimationCurve.prototype.set = CameraAnimation$1.prototype.set;
  75975. CameraAnimationCurve.prototype.pause = CameraAnimation$1.prototype.pause;
  75976. var CamAniEditor = {
  75977. createAnimation(data) {
  75978. var animation = new CameraAnimation$1(viewer, data.tension);
  75979. if (data) {
  75980. animation.name = data.name;
  75981. animation.duration = data.duration;
  75982. animation.useDurSlice = data.useDurSlice;
  75983. for (var cpdata of data.points) {
  75984. /* const position = Potree.Utils.datasetPosTransform({ fromDataset: true, position: cpdata.position, datasetId: Potree.settings.originDatasetId })
  75985. const target = Potree.Utils.datasetPosTransform({ fromDataset: true, position: cpdata.target, datasetId: Potree.settings.originDatasetId })
  75986. */
  75987. var position = new Vector3().copy(cpdata.position);
  75988. var target = new Vector3().copy(cpdata.target);
  75989. var duration = cpdata.time;
  75990. var cp = animation.createControlPoint(null, {
  75991. position,
  75992. target,
  75993. duration
  75994. });
  75995. }
  75996. }
  75997. animation.changeCallback();
  75998. viewer.scene.addCameraAnimation(animation);
  75999. return animation;
  76000. },
  76001. removeAnimation(animation) {
  76002. animation.dispatchEvent('dispose');
  76003. viewer.scene.removeCameraAnimation(animation);
  76004. },
  76005. createMulAnimation(data) {
  76006. //新版,包含漫游点
  76007. var event_ = new EventDispatcher();
  76008. var sections = []; //分段, 分成animation和漫游点
  76009. var aniIndex = 0;
  76010. var curAni,
  76011. addAnimation = () => {
  76012. if (curAni) {
  76013. var data_ = {
  76014. name: 'animation_' + aniIndex,
  76015. duration: curAni.slice(0, curAni.length - 1).reduce(function (total, currentValue) {
  76016. return total + currentValue.time;
  76017. }, 0),
  76018. //总时长(要去掉最后一个,因为已到终点,该点time无意义)
  76019. useDurSlice: data.useDurSlice,
  76020. points: curAni
  76021. };
  76022. var ani = this.createAnimation(data_);
  76023. sections.push(ani);
  76024. ani.originIndexStart = data.points.indexOf(curAni[0]);
  76025. ani.addEventListener('updateCurrentIndex', e => {
  76026. emitIndex(e.currentIndex);
  76027. });
  76028. curAni = null;
  76029. }
  76030. };
  76031. data.points.forEach((e, i) => {
  76032. //切分为若干个animation,中间是漫游点的衔接
  76033. if (e.panoId != void 0) {
  76034. //暂定:有panoId的都是全景图模式
  76035. var pano = e.model.panos.find(a => a.originID == e.panoId);
  76036. if (pano) {
  76037. addAnimation(); //如果前面是动画,先截断
  76038. e.pano = pano;
  76039. e.rotInModel = new Quaternion().fromArray(e.rotInModel);
  76040. e.quaternion = Potree.Utils.datasetRotTransform({
  76041. fromDataset: true,
  76042. quaternion: e.rotInModel,
  76043. getQuaternion: true,
  76044. object: e.model
  76045. });
  76046. sections.push(e);
  76047. }
  76048. } else {
  76049. if (curAni) {
  76050. curAni.push(e);
  76051. } else {
  76052. //非pano
  76053. if (sections.length > 0) {
  76054. var last = sections[sections.length - 1]; //因为要从上一个pano出来,所以起始点是上一个pano
  76055. last.position = last.pano.position;
  76056. last.target = last.position.clone().add(new Vector3(0, 0, -1).applyQuaternion(last.quaternion));
  76057. curAni = [last, e];
  76058. } else {
  76059. curAni = [e];
  76060. }
  76061. }
  76062. }
  76063. });
  76064. addAnimation();
  76065. var currentPlay;
  76066. var emitIndex = function emitIndex() {
  76067. var indexInAni = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  76068. //更新当前飞到的index
  76069. var ani = sections[currentPlay];
  76070. var currentIndex = 0;
  76071. if (ani instanceof CameraAnimation$1) {
  76072. currentIndex = ani.originIndexStart + indexInAni;
  76073. } else {
  76074. currentIndex = Math.max(0, data.points.indexOf(ani) /* - 1 */); //因为是开始飞,还没飞到所以-1
  76075. }
  76076. event_.dispatchEvent({
  76077. type: 'updateCurrentIndex',
  76078. currentIndex
  76079. });
  76080. };
  76081. var result = {
  76082. event_,
  76083. play() {
  76084. //从头播放
  76085. var playNext = index => {
  76086. if (index == sections.length) {
  76087. return event_.dispatchEvent('playDone');
  76088. }
  76089. console.log('playNext', index);
  76090. var ani = sections[index];
  76091. currentPlay = index;
  76092. if (ani instanceof CameraAnimation$1) {
  76093. Potree.settings.displayMode = 'showPointCloud';
  76094. ani.addEventListener('playDone', () => {
  76095. playNext(index + 1);
  76096. }, {
  76097. once: true
  76098. });
  76099. ani.play();
  76100. } else {
  76101. var pano = ani.pano;
  76102. var last = sections[index - 1],
  76103. duration,
  76104. quaternion = ani.quaternion;
  76105. if (last) {
  76106. if (last instanceof CameraAnimation$1) {
  76107. duration = last.durations[last.durations.length - 1]; //最后一个时间
  76108. } else {
  76109. duration = last.time;
  76110. }
  76111. duration *= 1000;
  76112. } else {
  76113. duration = 600; //起始
  76114. }
  76115. viewer.images360.flyToPano({
  76116. pano,
  76117. quaternion,
  76118. duration,
  76119. callback: () => {
  76120. emitIndex();
  76121. var next = () => {
  76122. var stayTime = (!sections[index - 1] || sections[index - 1] instanceof CameraAnimation$1) && sections[index + 1] && sections[index + 1] instanceof CameraAnimation$1 ? 1000 : 300; //前后都是点云模式的话停留久一点。最好在页面上能设置
  76123. //console.log('stayTime',stayTime)
  76124. setTimeout(() => {
  76125. currentPlay != void 0 && playNext(index + 1);
  76126. }, stayTime); //稍作停留,不然点云-全景-点云的话根本看不到全景
  76127. };
  76128. if ( /* ani.displayMode == 'showPanos' && */Potree.settings.displayMode != 'showPanos') {
  76129. //刚加载完就飞走吗?
  76130. Potree.settings.displayMode = 'showPanos';
  76131. viewer.images360.addEventListener('endChangeMode', () => {
  76132. console.log(2);
  76133. next();
  76134. }, {
  76135. once: true
  76136. });
  76137. } else {
  76138. next();
  76139. }
  76140. //
  76141. },
  76142. retryUntilArrive: true
  76143. });
  76144. }
  76145. };
  76146. playNext(0);
  76147. emitIndex(); //0
  76148. },
  76149. stop() {
  76150. var ani = sections[currentPlay];
  76151. if (ani instanceof CameraAnimation$1) {
  76152. ani.pause();
  76153. } else {
  76154. var view = viewer.mainViewport.view;
  76155. if (!view.isFlying('pos')) {
  76156. //前后是相同漫游点,仅旋转
  76157. view.cancelFlying('rotate');
  76158. } else {
  76159. //加快结束
  76160. var o = transitions.getById(view.FlyTransition)[0];
  76161. var restDur = o.duration - o.current;
  76162. var hopeStopTime = 300; //希望最多等待时间
  76163. if (restDur > hopeStopTime) {
  76164. var r = o.duration / (o.current + hopeStopTime);
  76165. transitions.adjustSpeed(view.FlyTransition, r);
  76166. transitions.adjustSpeed(view.LookTransition, r);
  76167. }
  76168. }
  76169. //如果有地图,还要改地图的view
  76170. }
  76171. currentPlay = null;
  76172. },
  76173. remove() {
  76174. sections.forEach(ani => {
  76175. if (ani instanceof CameraAnimation$1) {
  76176. CamAniEditor.removeAnimation(ani);
  76177. }
  76178. });
  76179. }
  76180. //再把中间的缓动去除
  76181. };
  76182. return result;
  76183. },
  76184. createCurveAni(curve, duration, tangentDt) {
  76185. var ani = new CameraAnimationCurve(curve, duration, tangentDt);
  76186. return ani;
  76187. }
  76188. };
  76189. var clickPanoToDisLink = false; //是否在编辑漫游点连接时,通过点击漫游点能断开连接
  76190. var images360, Alignment$1, SiteModel$1, suggestCircleMat;
  76191. var texLoader$f = new TextureLoader();
  76192. texLoader$f.crossOrigin = "anonymous";
  76193. var rotQua = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI / 2);
  76194. var rotQua2$1 = new Quaternion().setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI);
  76195. var lineMats$2 = {};
  76196. var circleMats = {};
  76197. var renderOrders = {
  76198. circleSelected: 3,
  76199. circle: 2,
  76200. line: 1
  76201. };
  76202. var pointColor = {
  76203. /* selected:"#c80",
  76204. default:'#1ac' */
  76205. selected: "#c60",
  76206. default: '#17c'
  76207. };
  76208. var opacitys = {
  76209. //点云透明度
  76210. 'topView': {
  76211. default: 0.4,
  76212. selected: 0.6
  76213. },
  76214. 'sideView': {
  76215. //侧面重叠概率高
  76216. default: 0.2,
  76217. selected: 0.5
  76218. }
  76219. }; //调这么低是因为有的重叠边缘太亮了
  76220. var cameraProps$2 = [{
  76221. name: 'top',
  76222. axis: ["x", "y"],
  76223. direction: new Vector3(0, 0, -1),
  76224. //镜头朝向
  76225. openCount: 0
  76226. }, {
  76227. name: 'right',
  76228. axis: ["y", "z"],
  76229. direction: new Vector3(1, 0, 0),
  76230. openCount: 0
  76231. }, {
  76232. name: 'mainView',
  76233. openCount: 0
  76234. }];
  76235. class PanoEditor extends EventDispatcher {
  76236. constructor() {
  76237. super();
  76238. this.viewports = {}, this.panoMeshs = new Object3D(), this.lineMeshes = new Object3D();
  76239. this.views = {};
  76240. this.cameras = {};
  76241. this.orthoCamera = new OrthographicCamera(-100, 100, 100, 100, 0.01, 10000);
  76242. this.orthoCamera.up.set(0, 0, 1);
  76243. this.selectedPano;
  76244. this.selectedGroup;
  76245. this.operation;
  76246. this.visiblePanos = [];
  76247. this.suggestLines = [];
  76248. }
  76249. initPanoLink() {
  76250. this.panoGroup = []; //分组
  76251. this.panoLink = {};
  76252. images360.panos.forEach(pano => {
  76253. this.panoLink[pano.id] = {};
  76254. this.panoGroup.push([pano]);
  76255. });
  76256. images360.panos.forEach(pano => {
  76257. pano.visibles = pano.panoData.visibles || pano.panoData.links_data.map(e => e.index); //后者为新版
  76258. pano.rtkState = pano.panoData.has_rtk ? pano.panoData.use_rtk : null;
  76259. pano.visibles.forEach(index => {
  76260. //visibles中存的是下标!
  76261. this.linkChange(pano, images360.getPano(index, 'index'), 'add');
  76262. });
  76263. });
  76264. //console.log('panoLink',this.panoLink)
  76265. }
  76266. init() {
  76267. Alignment$1 = viewer.modules.Alignment;
  76268. {
  76269. //init lineMats
  76270. lineMats$2.default = LineDraw.createFatLineMat({
  76271. color: '#eeeeee',
  76272. lineWidth: 2,
  76273. depthTest: false
  76274. });
  76275. lineMats$2.hovered = LineDraw.createFatLineMat({
  76276. color: '#00c8af',
  76277. lineWidth: 2,
  76278. depthTest: false
  76279. });
  76280. lineMats$2.selected = LineDraw.createFatLineMat({
  76281. color: '#00c8af',
  76282. lineWidth: 3,
  76283. depthTest: false
  76284. });
  76285. lineMats$2.suggestLink = LineDraw.createFatLineMat({
  76286. color: '#ff2222',
  76287. lineWidth: 4,
  76288. dashed: true,
  76289. depthTest: false
  76290. });
  76291. }
  76292. suggestCircleMat = new MeshBasicMaterial({
  76293. map: texLoader$f.load(Potree.resourcePath + '/textures/whiteCircle.png'),
  76294. color: '#ff2222',
  76295. transparent: true,
  76296. depthTest: false,
  76297. depthWrite: false
  76298. });
  76299. this.initViews();
  76300. /* {
  76301. this.box = new BoxVolume({
  76302. clip:true
  76303. })
  76304. this.box.clipTask = ClipTask['SHOW_INSIDE_Big' ]
  76305. this.box.name = "panoEditClipBox";
  76306. } */
  76307. viewer.addEventListener('allLoaded', () => {
  76308. images360 = viewer.images360;
  76309. SiteModel$1 = viewer.modules.SiteModel;
  76310. this.panoMeshs.name = 'panoMeshs';
  76311. viewer.scene.scene.add(this.panoMeshs);
  76312. this.lineMeshes.name = 'lineMeshes';
  76313. viewer.scene.scene.add(this.lineMeshes);
  76314. {
  76315. /* this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
  76316. dontHideWhenFaceCamera: true,
  76317. rotFullCircle:true
  76318. });
  76319. this.transformControls.setSize(1.5)
  76320. viewer.scene.scene.add(this.transformControls)
  76321. this.transformControls._gizmo.hideAxis = { rotate:['e'] }
  76322. this.transformControls.setRotateMethod(2)
  76323. this.fakeMarkerForTran = new THREE.Mesh(new THREE.BoxBufferGeometry(0.3,0.3,0.3) , new THREE.MeshBasicMaterial({
  76324. color:"#FFFFFF", opacity:0.4, transparent:true, visible:false
  76325. }));//一个看不见的mesh,只是为了让transformControls移动点云
  76326. viewer.scene.scene.add(this.fakeMarkerForTran) */
  76327. this.transformControls = Alignment$1.transformControls;
  76328. this.fakeMarkerForTran = Alignment$1.fakeMarkerForTran;
  76329. this.transformControls.setSize(1.5);
  76330. this.transformControls.setSpace('world'); //side view translate vertical
  76331. Alignment$1.afterMoveCtl = type => {
  76332. if (type == 'position') {
  76333. var moveVec = new Vector3().subVectors(this.fakeMarkerForTran.position, this.fakeMarkerForTran.oldState.position);
  76334. this.selectedClouds.forEach(cloud => Alignment$1.translate(cloud, moveVec));
  76335. } else {
  76336. var center = this.selectedPano.position;
  76337. var diffQua = new Quaternion().multiplyQuaternions(this.fakeMarkerForTran.quaternion, this.fakeMarkerForTran.oldState.quaternion.clone().invert());
  76338. this.selectedClouds.forEach(cloud => {
  76339. Alignment$1.rotateAround(center, cloud, diffQua);
  76340. });
  76341. }
  76342. Alignment$1.selectedClouds = this.selectedClouds;
  76343. /* this.fakeMarkerForTran.oldState = {
  76344. position: this.fakeMarkerForTran.position.clone(),
  76345. quaternion: this.fakeMarkerForTran.quaternion.clone(),
  76346. }
  76347. Alignment.history.beforeChange(this.selectedClouds) */
  76348. };
  76349. /* this.fakeMarkerForTran.addEventListener('position_changed', afterMoveCtl.bind(this,'position'))
  76350. this.fakeMarkerForTran.addEventListener("rotation_changed", afterMoveCtl.bind(this,'rotation') )
  76351. this.transformControls.addEventListener('mouseUp',()=>{
  76352. Alignment.history.afterChange(this.selectedClouds)
  76353. }) */
  76354. Alignment$1.updateFakeMarker = this.updateFakeMarker.bind(this);
  76355. Alignment$1.history.addEventListener('undo', () => {
  76356. this.updateFakeMarker();
  76357. });
  76358. }
  76359. this.initPanoLink();
  76360. this.addPanoMesh();
  76361. viewer.scene.pointclouds.forEach(e => {
  76362. e.material.color = pointColor.default;
  76363. });
  76364. /* viewer.setEDLEnabled(true) //为了降一倍的绘制. 同时用描边增强立体感,弥补点云稀疏
  76365. viewer.setEDLRadius(1)
  76366. viewer.setEDLStrength(0.01) */
  76367. Alignment$1.bus.addEventListener('switchHandle', this.updateCursor.bind(this));
  76368. viewer.addEventListener('global_click', e => {
  76369. if (!this.entered) return;
  76370. if (e.button === MOUSE.RIGHT) {
  76371. //取消旋转和平移
  76372. //console.log('right click',e)
  76373. this.setLinkOperateState('addLink', false);
  76374. this.setLinkOperateState('removeLink', false);
  76375. } else if (this.clickToZoomInEnabled) {
  76376. if (this.activeViewName == 'mainView') {
  76377. viewer.controls.zoomToLocation(e.mouse);
  76378. } else {
  76379. this.zoomIn(e.intersect.orthoIntersect, e.pointer);
  76380. }
  76381. this.setZoomInState(false);
  76382. }
  76383. });
  76384. /* {//旋转时的辅助线--绕某个点旋转的版本
  76385. this.rotGuideLine = LineDraw.createLine([], {color:'#aaffee'})
  76386. this.rotGuideLine.visible = false
  76387. this.rotGuideLine.name = 'rotGuideLine'
  76388. this.rotGuideLine.renderOrder = renderOrders.line
  76389. viewer.scene.scene.add(this.rotGuideLine)
  76390. let startPoint
  76391. Alignment.bus.addEventListener('rotateStart', (e)=>{
  76392. startPoint = e.startPoint
  76393. })
  76394. Alignment.bus.addEventListener('rotate', (e)=>{
  76395. LineDraw.updateLine(this.rotGuideLine, [startPoint, e.endPoint] )
  76396. this.rotGuideLine.visible = true
  76397. })
  76398. viewer.fpControls.addEventListener("end",(e)=>{
  76399. startPoint = null
  76400. this.rotGuideLine.visible = false
  76401. })
  76402. } */
  76403. {
  76404. //连接时的辅助线
  76405. this.linkGuideLine = LineDraw.createLine([], {
  76406. color: '#ddd',
  76407. deshed: true,
  76408. dashSize: 0.1,
  76409. gapSize: 0.05,
  76410. depthTest: false
  76411. });
  76412. this.linkGuideLine.visible = false;
  76413. this.linkGuideLine.name = 'linkGuideLine';
  76414. viewer.scene.scene.add(this.linkGuideLine);
  76415. this.linkGuideLine.renderOrder = renderOrders.line;
  76416. var update = e => {
  76417. if (this.operation != 'addLink' || this.activeViewName != 'top' && this.activeViewName != 'mainView' || !this.selectedPano) {
  76418. return this.linkGuideLine.visible = false;
  76419. }
  76420. var endPos;
  76421. if (this.activeViewName == 'top') {
  76422. endPos = e.intersect.orthoIntersect.clone().setZ(this.selectedPano.position.z);
  76423. } else if (this.activeViewName == 'mainView') {
  76424. if (!e.intersect || !e.intersect.point) return;
  76425. endPos = e.intersect.point.position;
  76426. }
  76427. LineDraw.updateLine(this.linkGuideLine, [this.selectedPano.position, endPos]);
  76428. this.linkGuideLine.visible = true;
  76429. viewer.dispatchEvent('content_changed');
  76430. };
  76431. viewer.addEventListener('global_mousemove', e => {
  76432. if (this.entered) update(e);
  76433. });
  76434. //this.addEventListener('updateLinkGuideLine', update)
  76435. }
  76436. this.panoReposCallback = () => {
  76437. //viewer.controls.setTarget(this.selectedPano.position) //3d时绕其为中心转动
  76438. };
  76439. this.inited = true;
  76440. viewer.images360.panos.forEach(pano => {
  76441. //this.setPanoVisible(pano, pano.panoData.exist ,'exist') //在非编辑时初始化,隐藏那些没计算的点
  76442. pano.setEnable(pano.panoData.exist);
  76443. });
  76444. this.dispatchEvent('allLoaded');
  76445. });
  76446. this.leave();
  76447. }
  76448. enter() {
  76449. var _originFloor;
  76450. if (this.entered) return;
  76451. this.requestEnter = true;
  76452. if (!this.inited) {
  76453. if (!this.initCallback) {
  76454. this.initCallback = this.enter.bind(this);
  76455. this.addEventListener('allLoaded', this.initCallback);
  76456. }
  76457. return;
  76458. }
  76459. Potree.settings.displayMode = 'showPointCloud';
  76460. Potree.settings.ifShowMarker = false;
  76461. Potree.Utils.updateVisible(this.panoMeshs, 'entered', true);
  76462. Potree.Utils.updateVisible(this.lineMeshes, 'entered', true);
  76463. Potree.settings.unableNavigate = true;
  76464. viewer.images360.panos.forEach(pano => {
  76465. this.setPanoVisible(pano, true, 'atPanoEditor', 1, 'add'); //覆盖没进入编辑时因exist为false的隐藏
  76466. });
  76467. var originFloor = viewer.modules.SiteModel.inEntity; //还未编辑时的楼层
  76468. if (((_originFloor = originFloor) === null || _originFloor === void 0 ? void 0 : _originFloor.buildType) != 'floor') originFloor = null;
  76469. if (this.lastExitView) this.switchView(this.lastExitView);else {
  76470. /* Potree.settings.isTest || */this.switchView('top');
  76471. }
  76472. viewer.setFOV(100); //最好能把屋顶砍了,这样不用进屋子就能看到墙壁是否互相贴合,但是加clip比较麻烦,就暂时把fov改大吧
  76473. //过后恢复
  76474. {
  76475. //默认选择一个楼层
  76476. var panoVisiReady;
  76477. var floorInit = () => {
  76478. if (!panoVisiReady || !SiteModel$1.initDataDone || !this.entered) return;
  76479. setTimeout(() => {
  76480. if (this.currentFloor == 'all' || !this.currentFloor) {
  76481. //还未选择楼层的话
  76482. var floor = originFloor || SiteModel$1.entities.find(e => e.buildType == 'floor' && e.panos.length); //选择有漫游点的一层
  76483. if (!floor) {
  76484. floor = 'all'; //SiteModel.entities.find(e=>e.buildType == 'floor')
  76485. console.log('没有一层有漫游点?!');
  76486. }
  76487. console.log('initDataDone');
  76488. this.gotoFloor(floor);
  76489. }
  76490. }, 1); //2d那边用了nextTick ,so setTimeout here
  76491. };
  76492. SiteModel$1.bus.addEventListener('initDataDone', () => {
  76493. floorInit();
  76494. }, {
  76495. once: true
  76496. });
  76497. this.addEventListener('panoVisiReady', () => {
  76498. //2d初始化完成,才可以由3d修改pano显示 (因为在之前2d会给每个pano传来显示的消息,在这之前的修改都会别覆盖)
  76499. panoVisiReady = true;
  76500. floorInit();
  76501. }, {
  76502. once: true
  76503. });
  76504. }
  76505. this.entered = true;
  76506. }
  76507. leave() {
  76508. this.requestEnter = false;
  76509. Potree.settings.displayMode = 'showPanos';
  76510. Potree.settings.ifShowMarker = true;
  76511. Potree.Utils.updateVisible(this.panoMeshs, 'entered', false);
  76512. Potree.Utils.updateVisible(this.lineMeshes, 'entered', false);
  76513. Potree.settings.unableNavigate = false;
  76514. viewer.setFOV(Potree.config.view.fov);
  76515. this.selectPano(null);
  76516. this.currentFloor = null;
  76517. this.lastExitView = this.activeViewName;
  76518. if (this.inited) {
  76519. this.activeViewName && this.switchView('mainView', true);
  76520. viewer.images360.panos.forEach(pano => {
  76521. this.switchPanoVisible(pano, true);
  76522. //this.setPanoVisible(pano, pano.panoData.exist ,'exist')
  76523. pano.setEnable(pano.panoData.exist);
  76524. this.setPanoVisible(pano, false, 'atPanoEditor', 1, 'cancel'); //取消硬性显示
  76525. });
  76526. this.setLinkOperateState('addLink', false, false);
  76527. this.setLinkOperateState('removeLink', false, false);
  76528. this.setZoomInState(false, false);
  76529. this.setTranMode(null);
  76530. Alignment$1.history.clear();
  76531. if (!viewer.images360.currentPano.enabled) {
  76532. //切换到可见点
  76533. var enabledPano = viewer.images360.findNearestPano();
  76534. enabledPano && viewer.images360.flyToPano({
  76535. pano: enabledPano,
  76536. duration: 0
  76537. });
  76538. }
  76539. }
  76540. this.entered = false;
  76541. if (this.initCallback) {
  76542. this.removeEventListener('allLoaded', this.initCallback);
  76543. this.initCallback = null;
  76544. }
  76545. }
  76546. setTranMode(mode) {
  76547. //rotate or translate
  76548. console.log('panoeditor setTranMode', mode);
  76549. this.tranMode = mode;
  76550. if (this.activeViewName != 'top') {
  76551. mode && this.transformControls.setMode(mode);
  76552. this.updateFakeMarker();
  76553. }
  76554. Alignment$1.switchHandle(mode);
  76555. this.updateIntersectEnable();
  76556. }
  76557. updateIntersectEnable() {
  76558. //侧面容易因intersect卡住, 如果非必要关闭intersect. 3d页面也会卡,但controls需要所以不能去掉
  76559. Potree.settings.intersectWhenHover = !!(this.activeViewName == 'mainView' || this.selectedPano && this.tranMode);
  76560. }
  76561. //////////////////////////////////
  76562. initViews() {
  76563. this.splitScreenTool = new SplitScreen();
  76564. this.targetPlane = viewer.mainViewport.targetPlane = new Plane();
  76565. this.shiftTarget = viewer.mainViewport.shiftTarget = new Vector3(); //project在targetPlane上的位置
  76566. for (var i = 0; i < 2; i++) {
  76567. var prop = cameraProps$2[i];
  76568. var view = new ExtendView();
  76569. this.views[prop.name] = view;
  76570. this.cameras[prop.name] = this.orthoCamera;
  76571. view.name = prop.name;
  76572. view.direction = prop.direction;
  76573. }
  76574. this.views.mainView = viewer.mainViewport.view;
  76575. this.cameras.mainView = viewer.mainViewport.camera;
  76576. }
  76577. switchView(name, dontChangeView) {
  76578. //替换view和camera到mainViewport
  76579. if (name == this.activeViewName) return;
  76580. var view = this.views[name];
  76581. var camera = this.cameras[name];
  76582. var prop = cameraProps$2.find(e => e.name == name);
  76583. var {
  76584. boundSize,
  76585. center
  76586. } = viewer.bound;
  76587. this.lastViewName = this.activeViewName;
  76588. this.activeViewName = name;
  76589. var lastView = this.views[this.lastViewName];
  76590. var lastCamera = this.cameras[this.lastViewName];
  76591. viewer.mainViewport.view = view;
  76592. viewer.mainViewport.camera = camera;
  76593. if (lastCamera) lastView.zoom = lastCamera.zoom;
  76594. if (name != 'mainView') {
  76595. this.targetPlane.setFromNormalAndCoplanarPoint(view.direction.clone(), center);
  76596. this.targetPlane.projectPoint(view.position, this.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外
  76597. if (!dontChangeView) {
  76598. view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport));
  76599. }
  76600. if (view.zoom) {
  76601. camera.zoom = view.zoom; //恢复上次的zoom
  76602. }
  76603. }
  76604. this.transformControls.setCamera(camera);
  76605. viewer.updateScreenSize({
  76606. forceUpdateSize: true
  76607. }); //更新camera aspect left等
  76608. this.updateCursor();
  76609. if (name == 'mainView') {
  76610. viewer.mainViewport.alignment = null;
  76611. var changeMat = () => {
  76612. viewer.scene.pointclouds.forEach(e => {
  76613. e.material.activeAttributeName = 'rgba';
  76614. e.material.useFilterByNormal = false;
  76615. e.changePointOpacity(1);
  76616. });
  76617. };
  76618. /* if(prop.openCount == 0){ //点数较多时,首次转到3D视角会卡顿,因为要切换材质。
  76619. let delay1 = THREE.Math.clamp(viewer.scene.pointclouds.length*0.5, 1, 200)
  76620. setTimeout(()=>{
  76621. this.activeViewName == 'mainView' && changeMat()
  76622. },delay1)
  76623. //console.log('switchview',delay1 )
  76624. }else{ */
  76625. changeMat();
  76626. //}
  76627. this.transformControls._gizmo.hideAxis = this.version == 'old' ? {
  76628. rotate: ['e', 'x', 'y']
  76629. } : {
  76630. rotate: ['e']
  76631. };
  76632. Potree.Utils.updateVisible(viewer.reticule, 'force', true);
  76633. if (lastView) {
  76634. //2d->3d
  76635. if (!dontChangeView) {
  76636. view.copy(lastView);
  76637. var direction = view.direction;
  76638. var panos = images360.panos.filter(e => e.circle.visible);
  76639. var nearestPano = Common$1.sortByScore(panos, [], [pano => {
  76640. var vec = new Vector3().subVectors(pano.position, view.position);
  76641. return -vec.dot(direction);
  76642. }], true);
  76643. //console.log('最近',nearestPano )
  76644. if (nearestPano && nearestPano[0]) {
  76645. //尽量不变画面范围,使pano点保持原位,转换到mainView
  76646. var halfHeight = lastCamera.top / lastCamera.zoom;
  76647. var dis = halfHeight / Math.tan(MathUtils.degToRad(camera.fov / 2));
  76648. view.position.add(direction.clone().multiplyScalar(-nearestPano[0].score - dis));
  76649. //console.log('getCloser', -nearestPano[0].score - dis)
  76650. this.lastDisToPano = dis; //记录一下
  76651. }
  76652. }
  76653. }
  76654. viewer.fpControls.lockKey = false;
  76655. } else {
  76656. if (this.lastViewName == 'mainView') {
  76657. //3d->2d
  76658. var _direction = lastView.direction;
  76659. var _panos = images360.panos.filter(e => e.circle.visible);
  76660. //尽量靠近画布中心,且距离相机较近
  76661. var vecMap = new Map();
  76662. var _nearestPano = Common$1.sortByScore(_panos, [pano => {
  76663. var vec = new Vector3().subVectors(pano.position, lastView.position);
  76664. vecMap.set(pano, vec);
  76665. return vec.length() > 0; //否则后面算不出
  76666. }], [pano => {
  76667. var vec = vecMap.get(pano);
  76668. var dis = vec.dot(_direction);
  76669. return dis < 0 ? dis * 10 : -dis;
  76670. }, pano => {
  76671. var vec = vecMap.get(pano);
  76672. var angle = vec.angleTo(_direction);
  76673. return -angle * 70;
  76674. }], true);
  76675. //目前还存在的问题就是不知selectedPano和最近点的取舍
  76676. //console.log('panos',nearestPano )
  76677. if (_nearestPano && _nearestPano[0]) {
  76678. //console.log('nearestPano',nearestPano[0].item.id )
  76679. var pos1 = _nearestPano[0].item.position.clone();
  76680. var pos2 = pos1.clone();
  76681. var _dis = new Vector3().subVectors(_nearestPano[0].item.position, lastView.position).dot(_direction); //-nearestPano[0].score
  76682. //根据2d->3d的式子逆求zoom
  76683. var _halfHeight = Math.abs(_dis) * Math.tan(MathUtils.degToRad(lastCamera.fov / 2));
  76684. camera.zoom = camera.top / _halfHeight;
  76685. camera.updateProjectionMatrix();
  76686. if (name == 'right') {
  76687. //侧视图
  76688. view.direction = _direction.clone().setZ(0); //水平方向设定为3d的方向
  76689. this.targetPlane.setFromNormalAndCoplanarPoint(view.direction.clone(), center);
  76690. this.targetPlane.projectPoint(view.position, this.shiftTarget); //target转换到过模型中心的平面,以保证镜头一定在模型外
  76691. view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport));
  76692. }
  76693. view.applyToCamera(camera); //update
  76694. pos1.project(lastCamera);
  76695. pos2.project(camera);
  76696. //目标是找到画面上最接近中心的一点(最好是漫游点,不然就是点云),让其在转换画面后在画面上的位置不变。万一找到的点不在屏幕中(比如当屏幕中没点云时),就默认让那个点移动到屏幕中央,也就是假设当前它pos1在屏幕中央位置。
  76697. //
  76698. if (pos1.z > 1) {
  76699. console.warn('选取的点在相机背后了!?');
  76700. }
  76701. //如果最近点超出屏幕范围 (-1,1), 最好将其拉到边缘,甚至居中 。这样屏幕上就不会没有漫游点了
  76702. var bound = 0.9;
  76703. pos1.x = MathUtils.clamp(pos1.x, -bound, bound);
  76704. pos1.y = MathUtils.clamp(pos1.y, -bound, bound);
  76705. var vecOnscreen = new Vector3().subVectors(pos1, pos2);
  76706. var moveVec = Potree.Utils.getOrthoCameraMoveVec(vecOnscreen, camera);
  76707. //console.log('pos1', pos1)
  76708. view.position.sub(moveVec);
  76709. }
  76710. } else {
  76711. if (prop.openCount == 0) {
  76712. //至多执行一次
  76713. this.viewportFitBound(name, boundSize, center);
  76714. }
  76715. }
  76716. viewer.scene.pointclouds.forEach(e => {
  76717. e.material.activeAttributeName = 'color';
  76718. e.material.useFilterByNormal = true;
  76719. var opaProp = name == 'top' ? opacitys.topView : opacitys.sideView;
  76720. if (this.selectedPano && this.selectedClouds.includes(e)) {
  76721. e.changePointOpacity(opaProp.selected, true);
  76722. e.material.color = pointColor.selected;
  76723. } else {
  76724. e.changePointOpacity(opaProp.default, true);
  76725. e.material.color = pointColor.default;
  76726. }
  76727. });
  76728. Potree.Utils.updateVisible(viewer.reticule, 'force', false);
  76729. if (name == 'top') viewer.mainViewport.alignment = {
  76730. rotate: true,
  76731. translate: true
  76732. };
  76733. if (name == 'right') {
  76734. viewer.mainViewport.alignment = {
  76735. translate: true,
  76736. rotateSide: true,
  76737. translateVec: new Vector3(0, 0, 1)
  76738. }; //只能上下移动
  76739. viewer.mainViewport.rotateSide = true;
  76740. } else {
  76741. viewer.mainViewport.rotateSide = false;
  76742. }
  76743. viewer.fpControls.lockKey = true;
  76744. this.transformControls._gizmo.hideAxis = {
  76745. translate: ['x', 'y'],
  76746. rotate: ['x', 'y', 'z']
  76747. };
  76748. }
  76749. this.updateFakeMarker();
  76750. this.setTranMode(this.tranMode); // update
  76751. this.setZoomInState(false); //取消放大模式
  76752. //this.updatePointLevels()
  76753. this.updateIntersectEnable();
  76754. prop.openCount++;
  76755. }
  76756. viewportFitBound() {
  76757. //使一个viewport聚焦在某个范围
  76758. if (viewer.mainViewport.resolution.x == 0 || viewer.mainViewport.resolution.y == 0) {
  76759. return setTimeout(() => {
  76760. this.viewportFitBound();
  76761. }, 10);
  76762. }
  76763. this.gotoFloor(this.currentFloor, true, 0, null, true);
  76764. }
  76765. rotateSideCamera(angle) {
  76766. //侧视图绕模型中心水平旋转
  76767. this.splitScreenTool.rotateSideCamera(viewer.mainViewport, angle);
  76768. }
  76769. zoomIn(intersect, pointer) {
  76770. var camera = viewer.mainViewport.camera;
  76771. var endZoom = 200;
  76772. //this.orthoMoveFit(intersect, {endZoom:viewer.mainViewport.camera.zoom < aimZoom ? aimZoom : null} , 300)
  76773. var startZoom = camera.zoom;
  76774. if (startZoom >= endZoom) {
  76775. return;
  76776. }
  76777. viewer.mainViewport.view.zoomOrthoCamera(camera, endZoom, pointer, 300);
  76778. }
  76779. orthoMoveFit(pos, info, duration) {
  76780. var margin = {
  76781. x: 200,
  76782. y: 230
  76783. };
  76784. this.splitScreenTool.viewportFitBound(viewer.mainViewport, info.bound, pos, duration, margin);
  76785. }
  76786. setZoomInState(state, informinformBy2d) {
  76787. //是否点击后可放大
  76788. //if(state && this.activeViewName == 'mainView')return console.log('3D不可放大')
  76789. this.clickToZoomInEnabled = !!state;
  76790. if (state) {
  76791. viewer.dispatchEvent({
  76792. type: "CursorChange",
  76793. action: "add",
  76794. name: "zoomInCloud"
  76795. });
  76796. } else {
  76797. viewer.dispatchEvent({
  76798. type: "CursorChange",
  76799. action: "remove",
  76800. name: "zoomInCloud"
  76801. });
  76802. }
  76803. if (!state && !informinformBy2d) {
  76804. this.dispatchEvent({
  76805. type: 'operationCancel',
  76806. operation: 'zoomIn'
  76807. });
  76808. }
  76809. }
  76810. gotoFloor(floor, force) {
  76811. var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 600;
  76812. var informBy2d = arguments.length > 3 ? arguments[3] : undefined;
  76813. var fitBound = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
  76814. // 选择不同楼层, 切换点位显示。 'all'为全部显示
  76815. floor = floor || 'all';
  76816. if (this.currentFloor == floor && !force) return;
  76817. if (this.currentFloor != floor) {
  76818. //如果楼层没变,不修改可视
  76819. //let pointclouds = viewer.findPointcloudsAtFloor(floor)
  76820. var panos = floor == 'all' ? viewer.images360.panos : floor.panos;
  76821. viewer.images360.panos.forEach(pano => {
  76822. var v = panos.includes(pano);
  76823. this.switchPanoVisible(pano, v);
  76824. });
  76825. }
  76826. this.updateLinesVisible();
  76827. //切换楼层时清空选择状态
  76828. if (this.selectedPano && floor != 'all' && !floor.panos.includes(this.selectedPano)) {
  76829. this.selectedPano.circle.dispatchEvent('click');
  76830. }
  76831. if (this.selectedLine) {
  76832. this.selectedLine.dispatchEvent('click');
  76833. }
  76834. var bound, center;
  76835. if (floor == 'all') {
  76836. bound = viewer.images360.bound.bounding;
  76837. center = viewer.images360.bound.center;
  76838. } else {
  76839. bound = this.getPanosBound(floor);
  76840. center = bound.getCenter(new Vector3());
  76841. if (floor.panos.length == 0) console.log(floor.name, 'floor无漫游点');
  76842. }
  76843. if (this.activeViewName != 'mainView') {
  76844. fitBound && this.orthoMoveFit(center, {
  76845. bound
  76846. }, duration);
  76847. } else if (this.activeViewName == 'mainView') {
  76848. //if(floor != 'all'){ //切换一下位置,因为原处点云会消失
  76849. //viewer.scene.view.setView({position:center, duration })
  76850. viewer.focusOnObject({
  76851. boundingBox: bound
  76852. }, 'boundingBox', 800, {
  76853. dontChangeCamDir: true
  76854. });
  76855. //}
  76856. }
  76857. this.currentFloor = floor;
  76858. //if(!informBy2d){ //注释原因:2d居然不会自己变
  76859. this.dispatchEvent({
  76860. type: 'changeFloor',
  76861. floor
  76862. });
  76863. //}
  76864. }
  76865. getPanosBound(floor) {
  76866. if (!floor.panosBound) {
  76867. if (floor.panos.length == 0) {
  76868. floor.panosBound = viewer.images360.bound.bounding.clone();
  76869. } else {
  76870. var minSize = new Vector3(10, 10, 10);
  76871. var bound = math.getBoundByPoints(floor.panos.map(e => e.position), minSize);
  76872. floor.panosBound = bound.bounding;
  76873. }
  76874. }
  76875. return floor.panosBound;
  76876. }
  76877. setPanoVisible(pano, v) {
  76878. var reason = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'default';
  76879. var level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  76880. var type = arguments.length > 4 ? arguments[4] : undefined;
  76881. Potree.Utils.updateVisible(pano.circle, reason, v, level, type);
  76882. Potree.Utils.updateVisible(pano, reason, v, level, type);
  76883. Potree.Utils.updateVisible(pano.pointcloud, reason, v, level, type);
  76884. }
  76885. switchPanoVisible(pano, v, informBy2d) {
  76886. //console.log(pano.id,v)
  76887. this.setPanoVisible(pano, v, 'panoEditorVisi', 2);
  76888. if (v) {
  76889. this.visiblePanos.includes(pano) || this.visiblePanos.push(pano);
  76890. } else {
  76891. var index = this.visiblePanos.indexOf(pano);
  76892. index > -1 && this.visiblePanos.splice(index, 1);
  76893. }
  76894. if (informBy2d) {
  76895. this.dispatchEvent('panoVisiReady');
  76896. this.updateLinesVisible();
  76897. }
  76898. informBy2d || this.dispatchEvent({
  76899. type: "switchPanoVisible",
  76900. pano,
  76901. v
  76902. });
  76903. /* {
  76904. setTimeout(()=>{
  76905. Common.intervalTool.isWaiting('updatePointLevels2', ()=>{
  76906. this.updatePointLevels()
  76907. }, 50)
  76908. },1)//等update过visibleNodes
  76909. } */
  76910. }
  76911. updateLinesVisible() {
  76912. this.lineMeshes.children.forEach(line => {
  76913. var names = line.name.split('-');
  76914. var pano0 = images360.getPano(names[0]);
  76915. var pano1 = images360.getPano(names[1]);
  76916. line.visible = this.visiblePanos.includes(pano0) || this.visiblePanos.includes(pano1);
  76917. });
  76918. }
  76919. updateCursor() {
  76920. var cursor;
  76921. if (this.activeViewName == 'mainView' || !this.selectedPano) {
  76922. cursor = null;
  76923. } else {
  76924. cursor = Alignment$1.handleState;
  76925. }
  76926. if (cursor == 'rotate') {
  76927. viewer.dispatchEvent({
  76928. type: "CursorChange",
  76929. action: "add",
  76930. name: "rotatePointcloud"
  76931. });
  76932. viewer.dispatchEvent({
  76933. type: "CursorChange",
  76934. action: "remove",
  76935. name: "movePointcloud"
  76936. });
  76937. } else if (cursor == 'translate') {
  76938. viewer.dispatchEvent({
  76939. type: "CursorChange",
  76940. action: "add",
  76941. name: "movePointcloud"
  76942. });
  76943. viewer.dispatchEvent({
  76944. type: "CursorChange",
  76945. action: "remove",
  76946. name: "rotatePointcloud"
  76947. });
  76948. } else {
  76949. viewer.dispatchEvent({
  76950. type: "CursorChange",
  76951. action: "remove",
  76952. name: "movePointcloud"
  76953. });
  76954. viewer.dispatchEvent({
  76955. type: "CursorChange",
  76956. action: "remove",
  76957. name: "rotatePointcloud"
  76958. });
  76959. }
  76960. //this.cursorState = cursor
  76961. }
  76962. setLinkOperateState(name, state, informinformBy2d) {
  76963. if (state && name == this.operation || !state && name != this.operation) return;
  76964. var old = this.operation;
  76965. this.operation = state ? name : null;
  76966. if (this.operation == 'removeLink') {
  76967. if (this.selectedLine) {
  76968. this.selectedLine.dispatchEvent('click'); //删除
  76969. }
  76970. if (this.selectedPano && clickPanoToDisLink) {
  76971. this.selectedPano.circle.dispatchEvent('click'); //删除
  76972. }
  76973. }
  76974. if (this.operation != 'addLink') {
  76975. this.linkGuideLine.visible = false;
  76976. }
  76977. if (!state && !informinformBy2d) {
  76978. this.dispatchEvent({
  76979. type: "operationCancel",
  76980. operation: old
  76981. });
  76982. }
  76983. if (this.operation == 'addLink') {
  76984. viewer.dispatchEvent({
  76985. type: "CursorChange",
  76986. action: "add",
  76987. name: "connectPano"
  76988. });
  76989. } else {
  76990. viewer.dispatchEvent({
  76991. type: "CursorChange",
  76992. action: "remove",
  76993. name: "connectPano"
  76994. });
  76995. }
  76996. if (this.operation == 'removeLink') {
  76997. viewer.dispatchEvent({
  76998. type: "CursorChange",
  76999. action: "add",
  77000. name: "disconnectPano"
  77001. });
  77002. } else {
  77003. viewer.dispatchEvent({
  77004. type: "CursorChange",
  77005. action: "remove",
  77006. name: "disconnectPano"
  77007. });
  77008. }
  77009. viewer.dispatchEvent('content_changed');
  77010. }
  77011. /////////////////////////////////
  77012. linkChange(pano0, pano1, type) {
  77013. //修改link (type == 'remove'时,pano1可以为空)
  77014. var temp = [];
  77015. if (type == 'add') {
  77016. if (!pano1) return console.error('不支持add时pano1为空');
  77017. this.panoLink[pano0.id][pano1.id] = this.panoLink[pano0.id][pano1.id] || {};
  77018. this.panoLink[pano1.id][pano0.id] = this.panoLink[pano1.id][pano0.id] || {};
  77019. } else {
  77020. if (!pano1) {
  77021. for (var id in this.panoLink[pano0.id]) {
  77022. if (this.panoLink[pano0.id][id]) {
  77023. this.panoLink[id][pano0.id] = false;
  77024. temp.push(id);
  77025. }
  77026. }
  77027. this.panoLink[pano0.id] = {}; //全部断连
  77028. } else {
  77029. this.panoLink[pano0.id][pano1.id] = false;
  77030. this.panoLink[pano1.id][pano0.id] = false;
  77031. }
  77032. }
  77033. if (!pano1) {
  77034. //全部断连
  77035. temp.forEach(id => {
  77036. this.lineChange(pano0, images360.getPano(id), type);
  77037. });
  77038. } else {
  77039. this.lineChange(pano0, pano1, type);
  77040. }
  77041. this.groupChange(pano0, pano1, type);
  77042. //this.updateSelectGroup()
  77043. this.selectPano(this.selectedPano, false, true); //更新选中点云显示
  77044. }
  77045. lineChange(pano0, pano1, type) {
  77046. //修改line
  77047. if (type == 'add') {
  77048. if (this.panoLink[pano0.id][pano1.id].line) return;
  77049. var line = LineDraw.createFatLine([pano0.position, pano1.position], {
  77050. mat: lineMats$2.default
  77051. });
  77052. line.name = "".concat(pano0.id, "-").concat(pano1.id);
  77053. line.renderOrder = line.pickOrder = renderOrders.line;
  77054. this.lineMeshes.add(line);
  77055. this.panoLink[pano0.id][pano1.id].line = this.panoLink[pano1.id][pano0.id].line = line;
  77056. line.addEventListener('mouseover', () => {
  77057. if (this.clickToZoomInEnabled) return;
  77058. //if(this.activeViewName == 'mainView')return
  77059. if (this.selectedLine != line) line.material = lineMats$2.hovered;
  77060. viewer.dispatchEvent({
  77061. type: "CursorChange",
  77062. action: "add",
  77063. name: "hoverLine"
  77064. });
  77065. });
  77066. line.addEventListener('mouseleave', () => {
  77067. if (this.clickToZoomInEnabled) return;
  77068. //if(this.activeViewName == 'mainView')return
  77069. if (this.selectedLine != line) line.material = lineMats$2.default;
  77070. viewer.dispatchEvent({
  77071. type: "CursorChange",
  77072. action: "remove",
  77073. name: "hoverLine"
  77074. });
  77075. });
  77076. line.addEventListener('click', e => {
  77077. if (this.clickToZoomInEnabled) return;
  77078. //if(this.activeViewName == 'mainView')return
  77079. if (this.operation == 'removeLink') {
  77080. if (this.selectedLine == line) this.selectLine(null);
  77081. return this.linkChange(pano0, pano1, 'remove');
  77082. }
  77083. this.selectLine(line);
  77084. });
  77085. } else {
  77086. var _line = this.lineMeshes.children.find(e => e.name == "".concat(pano0.id, "-").concat(pano1.id) || e.name == "".concat(pano1.id, "-").concat(pano0.id));
  77087. if (_line) {
  77088. this.lineMeshes.remove(_line);
  77089. _line.geometry.dispose();
  77090. }
  77091. }
  77092. }
  77093. groupChange(pano0, pano1, type) {
  77094. //修改group (type == 'remove'时,pano1可以为空)
  77095. if (type == 'add') {
  77096. Common$1.pushToGroupAuto([pano0, pano1], this.panoGroup);
  77097. } else {
  77098. var atGroup = this.panoGroup.find(e => e.includes(pano0) && (e.includes(pano1) || !pano1)); //所在组
  77099. if (!atGroup) {
  77100. if (pano1) {
  77101. console.log('这两个pano原本就不在一个组', pano0.id, pano1.id);
  77102. } else {
  77103. console.log('pano0不在任何组', pano0);
  77104. }
  77105. return;
  77106. }
  77107. //断开连接时,因为组内没有其他成员的连接信息,所以需要清除整组,并将剩余的一个个重新连接
  77108. this.panoGroup.splice(this.panoGroup.indexOf(atGroup), 1); //删除
  77109. atGroup.forEach(pano => {
  77110. //然后再重新生成这两个和组的关系,各自分组
  77111. this.panoGroup.push([pano]);
  77112. for (var id in this.panoLink[pano.id]) {
  77113. if (this.panoLink[pano.id][id]) {
  77114. var pano_ = images360.getPano(id);
  77115. Common$1.pushToGroupAuto([pano, pano_], this.panoGroup);
  77116. }
  77117. }
  77118. });
  77119. }
  77120. }
  77121. selectLine(line) {
  77122. if (this.selectedLine == line) return;
  77123. if (this.selectedLine) {
  77124. this.selectedLine.material = lineMats$2.default;
  77125. }
  77126. if (line) {
  77127. line.material = lineMats$2.selected;
  77128. }
  77129. this.selectedLine = line;
  77130. }
  77131. addPanoMesh() {
  77132. var map = texLoader$f.load(Potree.resourcePath + '/textures/correct_n.png');
  77133. /* circleMats.default_normal = new THREE.MeshBasicMaterial({
  77134. map,
  77135. color: 0xffffff,
  77136. transparent: true,
  77137. depthTest: false,
  77138. depthWrite: false,
  77139. }) */
  77140. window.circleMats = circleMats;
  77141. circleMats.default_normal = new DepthBasicMaterial({
  77142. map,
  77143. color: 0xffffff,
  77144. transparent: true,
  77145. useDepth: true,
  77146. backColor: 0x33ffdd,
  77147. occlusionDistance: 10,
  77148. //变为backColor距离
  77149. clipDistance: 5,
  77150. //消失距离
  77151. maxClipFactor: 0.8,
  77152. maxOcclusionFactor: 0.8
  77153. });
  77154. circleMats.default_rtk_on = circleMats.default_normal.clone();
  77155. circleMats.default_rtk_on.map = texLoader$f.load(Potree.resourcePath + '/textures/rtk-y-n.png');
  77156. circleMats.default_rtk_off = circleMats.default_normal.clone();
  77157. circleMats.default_rtk_off.map = texLoader$f.load(Potree.resourcePath + '/textures/rtk-f-n.png');
  77158. circleMats.selected_normal = circleMats.default_normal.clone();
  77159. circleMats.selected_normal.map = texLoader$f.load(Potree.resourcePath + '/textures/correct_s.png');
  77160. circleMats.selected_normal.useDepth = false;
  77161. circleMats.selected_rtk_on = circleMats.selected_normal.clone();
  77162. circleMats.selected_rtk_on.map = texLoader$f.load(Potree.resourcePath + '/textures/rtk-y-s.png');
  77163. circleMats.selected_rtk_off = circleMats.selected_normal.clone();
  77164. circleMats.selected_rtk_off.map = texLoader$f.load(Potree.resourcePath + '/textures/rtk-f-s.png');
  77165. circleMats.hovered_normal = circleMats.default_normal.clone();
  77166. circleMats.hovered_normal.color.set(0x00ff00);
  77167. circleMats.hovered_normal.useDepth = false;
  77168. circleMats.hovered_rtk_on = circleMats.default_rtk_on.clone();
  77169. circleMats.hovered_rtk_on.color.set(0x00ff00);
  77170. circleMats.hovered_rtk_on.useDepth = false;
  77171. circleMats.hovered_rtk_off = circleMats.default_rtk_off.clone();
  77172. circleMats.hovered_rtk_off.color.set(0x00ff00);
  77173. circleMats.hovered_rtk_off.useDepth = false;
  77174. var setPos = circle => {
  77175. circle.position.copy(circle.pano.position);
  77176. for (var id in this.panoLink[circle.pano.id]) {
  77177. var linkInfo = this.panoLink[circle.pano.id][id];
  77178. if (linkInfo) {
  77179. LineDraw.updateLine(linkInfo.line, [circle.pano.position, images360.getPano(id).position]);
  77180. }
  77181. }
  77182. circle.waitUpdate(); //update sprite Matrix
  77183. };
  77184. images360.panos.forEach(pano => {
  77185. var circle = new Sprite$2({
  77186. mat: circleMats['default' + '_' + this.getPanoRtkState(pano)],
  77187. sizeInfo: {
  77188. minSize: 50,
  77189. maxSize: 120,
  77190. nearBound: 2,
  77191. farBound: 10
  77192. },
  77193. renderOrder: renderOrders.circle,
  77194. pickOrder: renderOrders.circle
  77195. });
  77196. circle.pickDontCheckDis = true;
  77197. circle.name = 'panoCircle';
  77198. circle.sid = pano.id;
  77199. circle.pano = pano;
  77200. pano.circle = circle;
  77201. this.panoMeshs.add(circle);
  77202. setPos(circle);
  77203. pano.addEventListener('rePos', setPos.bind(this, circle));
  77204. var drag = e => {
  77205. /* if(this.activeViewName == 'mainView' && this.tranMode == 'translate'){//如果3d页不禁止xy的话,这段打开
  77206. this.transformControls.dispatchEvent('dragging')//触发拖拽
  77207. return
  77208. } */
  77209. if (this.tranMode != 'translate' || this.activeViewName == 'mainView') return e.refuse();
  77210. this.selectPano(circle.pano); //为了方便拖拽点云,拖动circle就直接选中
  77211. viewer.inputHandler.drag.object = null; //取消拖拽状态,否则不触发点云拖动
  77212. };
  77213. circle.addEventListener('drag', drag);
  77214. circle.addEventListener('mouseover', () => {
  77215. this.hoverPano(pano, true);
  77216. });
  77217. circle.addEventListener('mouseleave', () => {
  77218. this.hoverPano(pano, false);
  77219. });
  77220. circle.addEventListener('click', () => {
  77221. //if(this.activeViewName == 'mainView')return
  77222. if (this.clickToZoomInEnabled) return;
  77223. if (clickPanoToDisLink && this.operation == 'removeLink') {
  77224. this.linkChange(pano, null, 'remove'); //删除所有连接
  77225. }
  77226. if (this.selectedPano == circle.pano) return this.selectPano(null);
  77227. if (this.operation == 'addLink' && this.selectedPano) {
  77228. this.linkChange(this.selectedPano, circle.pano, 'add');
  77229. //this.setLinkOperateState('addLink',false)
  77230. return;
  77231. }
  77232. //if(this.operation == 'removeLink' && this.selectedPano){ //和选择中心点冲突
  77233. // this.linkChange(this.selectedPano, circle.pano, 'remove')
  77234. // //this.setLinkOperateState('removeLink',false)
  77235. // return
  77236. // }
  77237. this.selectPano(circle.pano);
  77238. });
  77239. });
  77240. }
  77241. hoverPano(pano, state) {
  77242. if (this.clickToZoomInEnabled) return;
  77243. if (pano && state) {
  77244. //在hover一个pano之前,一定会先取消已经hover的pano, 最多存在一个hovered的pano
  77245. if (this.hoveredPano == pano) return;
  77246. if (this.hoveredPano) {
  77247. this.hoverPano(this.hoveredPano, false);
  77248. }
  77249. this.hoveredPano = pano;
  77250. pano.hovered = true;
  77251. if ( /* this.activeViewName == 'mainView' || */Alignment$1.handleState && this.selectedPano && this.selectedPano == pano) return;
  77252. if (this.operation != 'addLink' || !this.selectedPano || this.selectedPano == pano) {
  77253. // this.selectedPano == pano?
  77254. viewer.dispatchEvent({
  77255. type: "CursorChange",
  77256. action: "add",
  77257. name: "hoverPano"
  77258. });
  77259. }
  77260. if (this.selectedPano != pano) pano.circle.material = circleMats['hovered' + '_' + this.getPanoRtkState(pano)];
  77261. } else if (pano && !state) {
  77262. //unhover
  77263. if (this.hoveredPano != pano) return;
  77264. pano.hovered = false;
  77265. viewer.dispatchEvent({
  77266. type: "CursorChange",
  77267. action: "remove",
  77268. name: "hoverPano"
  77269. });
  77270. if (this.selectedPano != pano) pano.circle.material = circleMats['default' + '_' + this.getPanoRtkState(pano)];
  77271. this.hoveredPano = null;
  77272. } else {
  77273. //unhover any
  77274. if (this.hoveredPano) {
  77275. this.hoverPano(this.hoveredPano, false);
  77276. }
  77277. }
  77278. }
  77279. selectPano(pano, informinformBy2d, force) {
  77280. if (this.selectedPano == pano && !force) return;
  77281. var lastSeletedPano = this.selectedPano;
  77282. var opaProp = this.activeViewName == 'top' ? opacitys.topView : opacitys.sideView;
  77283. if (this.selectedPano) {
  77284. this.selectedPano.circle.material = circleMats['default' + '_' + this.getPanoRtkState(this.selectedPano)];
  77285. this.selectedPano.circle.renderOrder = renderOrders.circle;
  77286. this.selectedPano.removeEventListener('rePos', this.panoReposCallback);
  77287. if (this.activeViewName == 'mainView') {} else {
  77288. this.selectedClouds.forEach(e => {
  77289. e.changePointOpacity(opaProp.default, true);
  77290. e.material.color = pointColor.default;
  77291. });
  77292. }
  77293. }
  77294. this.selectedPano = pano || null;
  77295. this.updateSelectGroup();
  77296. if (pano) {
  77297. this.selectedPano.circle.material = circleMats['selected' + '_' + this.getPanoRtkState(this.selectedPano)];
  77298. this.selectedPano.circle.renderOrder = this.selectedPano.circle.pickOrder = renderOrders.circleSelected; //侧视图能显示在最前
  77299. //viewer.controls.setTarget(this.selectedPano.position) //3d时绕其为中心转动 (注释原因:不想变来变去不习惯,难以查看任意角落细节)
  77300. this.selectedPano.addEventListener('rePos', this.panoReposCallback);
  77301. if (this.activeViewName == 'mainView') {} else {
  77302. this.selectedClouds.forEach(e => {
  77303. e.changePointOpacity(opaProp.selected, true);
  77304. e.material.color = pointColor.selected;
  77305. });
  77306. }
  77307. if (this.currentFloor != 'all') {
  77308. //如果原本不是展示全部楼层的话,自动切换楼层
  77309. var atFloor = SiteModel$1.entities.find(e => e.buildType == 'floor' && e.panos.includes(pano));
  77310. if (!atFloor) {
  77311. atFloor = 'all';
  77312. } else {}
  77313. this.gotoFloor(atFloor, false, 600);
  77314. }
  77315. } else {
  77316. //viewer.controls.setTarget(null)
  77317. }
  77318. this.updateCursor();
  77319. this.updateFakeMarker();
  77320. if (informinformBy2d) {
  77321. if (this.selectedPano) {
  77322. if (this.activeViewName == 'mainView') {
  77323. //平移,focus选中的pano
  77324. var distance = this.lastDisToPano || 5;
  77325. if (lastSeletedPano) {
  77326. distance = viewer.mainViewport.camera.position.distanceTo(lastSeletedPano.position);
  77327. }
  77328. viewer.focusOnObject({
  77329. position: this.selectedPano.position
  77330. }, 'point', null, {
  77331. distance
  77332. });
  77333. } else {
  77334. this.orthoMoveFit(this.selectedPano.position, {}, 500);
  77335. }
  77336. }
  77337. } else {
  77338. this.dispatchEvent({
  77339. type: 'panoSelect',
  77340. pano
  77341. });
  77342. }
  77343. this.updateIntersectEnable();
  77344. viewer.dispatchEvent('content_changed');
  77345. }
  77346. updateFakeMarker() {
  77347. // 设置3D页面的transformControls相关
  77348. if (!this.tranMode || !this.selectedPano || this.activeViewName == 'top') {
  77349. return this.transformControls.detach();
  77350. } else if (this.checkIfAllLinked({
  77351. group: this.selectedGroup
  77352. })) {
  77353. this.dispatchEvent('needToDisConnect');
  77354. return this.transformControls.detach();
  77355. }
  77356. this.transformControls.attach(this.fakeMarkerForTran);
  77357. var {
  77358. position,
  77359. quaternion
  77360. } = this.getPanoPose(this.selectedPano);
  77361. this.fakeMarkerForTran.position.copy(position);
  77362. this.fakeMarkerForTran.quaternion.copy(quaternion);
  77363. this.fakeMarkerForTran.oldState = {
  77364. position: position.clone(),
  77365. quaternion: quaternion.clone()
  77366. };
  77367. }
  77368. /* updatePointLevels(){
  77369. if(this.pauseUpdateLevels)return
  77370. let maxBudget = Potree.config.pointDensity.panoEdit.pointBudget
  77371. let visiCount1 = viewer.scene.pointclouds.filter(e=>e.visible).length
  77372. let visiCount2 = viewer.scene.pointclouds.filter(e=>e.visibleNodes.length>0).length //屏幕范围内可见的个数
  77373. let maxCount = 200, minCount = 1, minPer = 0.45 , maxPer = 1
  77374. let percent1 = maxPer - ( maxPer - minPer) * THREE.Math.clamp((visiCount1 - minCount) / (maxCount - minCount),0,1)
  77375. let percent2 = maxPer - ( maxPer - minPer) * THREE.Math.clamp((visiCount2 - minCount) / (maxCount - minCount),0,1)
  77376. let percent = percent1*percent2
  77377. if(this.activeViewName == 'mainView' ){
  77378. //假设每个pointcloud所带的点个数大致相同,那么当可见点云个数越多,所能展示的level越低,否则因总个数超过budget的话密度会参差不齐。
  77379. //pointcloud.changePointSize()
  77380. //console.log('updatePointLevels', percent, visiCount)
  77381. Potree.settings.UserDensityPercent = Math.sqrt(percent2)
  77382. viewer.setPointBudget(maxBudget * percent2)
  77383. }else{
  77384. Potree.settings.UserDensityPercent = 1
  77385. viewer.setPointBudget(maxBudget * percent)
  77386. }
  77387. viewer.setPointBudget(maxBudget * percent)
  77388. viewer.setPointLevels()
  77389. //侧面容易卡顿,但和显示的点数无关,似乎是因加载点云多而卡?为何正面不会
  77390. //console.warn('setPointBudget', Potree.pointBudget, visiCount1,visiCount2, Potree.settings.UserDensityPercent)
  77391. } */
  77392. getPanoRtkState(pano) {
  77393. return pano.panoData.has_rtk ? pano.rtkState ? 'rtk_on' : 'rtk_off' : 'normal';
  77394. }
  77395. setPanoRtkState(pano, state) {
  77396. pano.rtkState = state;
  77397. pano.circle.material = circleMats[(this.selectedPano == pano ? 'selected' : 'default') + '_' + this.getPanoRtkState(pano)];
  77398. viewer.dispatchEvent('content_changed');
  77399. }
  77400. updateSelectGroup() {
  77401. //更新选中的组
  77402. this.selectedGroup = this.panoGroup.find(e => e.includes(this.selectedPano));
  77403. if (this.selectedGroup) {
  77404. this.selectedGroup = [this.selectedPano, ...this.selectedGroup.filter(e => e != this.selectedPano)]; //将选中的放第一个,便于旋转时绕其旋转。
  77405. }
  77406. //this.selectedClouds = this.selectedPano ? (this.selectedGroup || [this.selectedPano]).map(e=>e.pointcloud) : []
  77407. this.selectedClouds = this.selectedPano ? this.selectedGroup.map(e => e.pointcloud) : [];
  77408. }
  77409. checkIfCanSave() {
  77410. //如果未全部相连,不能保存
  77411. for (var datasetId in Potree.settings.datasetsPanos) {
  77412. if (!this.checkIfAllLinked({
  77413. datasetId
  77414. })) {
  77415. console.log('没有全部连通,不能保存。其中一个:', datasetId);
  77416. return;
  77417. }
  77418. }
  77419. return true;
  77420. }
  77421. checkIfAllLinked(o) {
  77422. //某个(or组所在的)数据集是否全部连通
  77423. var datasetId, group;
  77424. if (o.group) {
  77425. group = o.group;
  77426. var pano = o.group[0];
  77427. if (!pano) return; //会有没有漫游点的点云来编辑吗
  77428. datasetId = pano.pointcloud.dataset_id;
  77429. } else if (o.datasetId) {
  77430. datasetId = o.datasetId;
  77431. group = this.panoGroup.find(panos => panos[0].pointcloud.dataset_id == datasetId);
  77432. if (!group) return; //要找的数据集的pano全部都孤立了
  77433. }
  77434. if (datasetId == void 0) return;
  77435. var panos = Potree.settings.datasetsPanos[datasetId].panos;
  77436. return panos.length == group.length;
  77437. }
  77438. getSuggestLinkPanos() {
  77439. var _this = this;
  77440. //给出建议连接的点
  77441. var panos = [];
  77442. var startTime = Date.now();
  77443. var _loop = function _loop(datasetId) {
  77444. if (!_this.checkIfAllLinked({
  77445. datasetId
  77446. })) {
  77447. var groups = _this.panoGroup.filter(panos => panos[0].pointcloud.dataset_id == datasetId);
  77448. groups = groups.sort((a, b) => {
  77449. return b.length - a.length;
  77450. }); //找出个数最多的一组来连接其他组
  77451. var mainGroup = groups[0].slice(),
  77452. subGroup;
  77453. for (var i = 1, len = groups.length; i < len; i++) {
  77454. subGroup = groups[i];
  77455. var minDis = {
  77456. dis: Infinity,
  77457. panos: []
  77458. };
  77459. for (var a = 0, len1 = mainGroup.length; a < len1; a++) {
  77460. for (var b = 0, len2 = subGroup.length; b < len2; b++) {
  77461. var dis = mainGroup[a].position.distanceToSquared(subGroup[b].position);
  77462. if (dis < minDis.dis) {
  77463. minDis.dis = dis;
  77464. minDis.panos = [mainGroup[a], subGroup[b]];
  77465. }
  77466. }
  77467. }
  77468. panos.push(minDis.panos);
  77469. //console.log('第i次',minDis)
  77470. mainGroup.push(...subGroup); //连接后,加入集合
  77471. }
  77472. }
  77473. };
  77474. for (var datasetId in Potree.settings.datasetsPanos) {
  77475. _loop(datasetId);
  77476. }
  77477. //console.log('cost', Date.now() - startTime)
  77478. return panos;
  77479. }
  77480. showSuggestLinkPanos() {
  77481. var groups = this.getSuggestLinkPanos();
  77482. var s = 0.7;
  77483. var createCircle = pano => {
  77484. var circle = new Mesh(pano.circle.geometry, suggestCircleMat);
  77485. circle.name = 'suggest-circle';
  77486. circle.scale.set(s, s, s);
  77487. circle.renderOrder = 100;
  77488. pano.circle.add(circle);
  77489. };
  77490. groups.forEach(panos => {
  77491. createCircle(panos[0]);
  77492. createCircle(panos[1]);
  77493. var line = LineDraw.createFatLine([panos[0].position, panos[1].position], {
  77494. mat: lineMats$2.suggestLink
  77495. });
  77496. this.suggestLines.push(line);
  77497. line.renderOrder = renderOrders.line;
  77498. viewer.scene.scene.add(line);
  77499. });
  77500. }
  77501. getPanoPose(pano) {
  77502. var pose = {
  77503. position: pano.position.clone(),
  77504. quaternion: new Quaternion().multiplyQuaternions(new Quaternion().setFromRotationMatrix(pano.panoMatrix), rotQua) //new THREE.Quaternion().setFromRotationMatrix(pano.panoMatrix).premultiply(rotQua) ,
  77505. };
  77506. return pose;
  77507. }
  77508. initCloud(pointcloud) {
  77509. //根据数据重新摆放点位
  77510. var data = pointcloud.panos[0].panoData;
  77511. var dataPosition = new Vector3().copy(data.pose.translation);
  77512. var dataQuaternion = new Quaternion().copy(data.pose.rotation);
  77513. //let dataRotation = new THREE.Euler().setFromQuaternion(dataQuaternion)
  77514. /* if(data.uuid == '0'){
  77515. dataQuaternion.w = -0.6712156629074
  77516. dataQuaternion.x = 0.0085280084224
  77517. dataQuaternion.y = -0.0007020006933
  77518. dataQuaternion.z = 0.741212732038
  77519. } */
  77520. //pointcloud.orientationUser = dataRotation.z + Math.PI
  77521. pointcloud.orientationUser = new Quaternion().multiplyQuaternions(dataQuaternion, rotQua2$1); //新版
  77522. pointcloud.translateUser.copy(dataPosition);
  77523. Alignment$1.setMatrix(pointcloud);
  77524. }
  77525. changeDatas(data, applyToCloud) {
  77526. var _this2 = this;
  77527. var _loop2 = function _loop2(dataset_id) {
  77528. data[dataset_id].panos = [];
  77529. if (data[dataset_id].sweepLocations) {
  77530. //来自exportSavingData
  77531. data[dataset_id].panoData = data[dataset_id].sweepLocations;
  77532. delete data[dataset_id].sweepLocations;
  77533. }
  77534. data[dataset_id].panoData.forEach(e => {
  77535. var pano = viewer.images360.getPano(dataset_id + '|' + e.uuid, 'sid');
  77536. pano.panoData = e;
  77537. data[dataset_id].panos.push(pano);
  77538. if (applyToCloud) {
  77539. _this2.initCloud(pano.pointcloud);
  77540. }
  77541. });
  77542. };
  77543. //替换data
  77544. for (var dataset_id in data) {
  77545. _loop2(dataset_id);
  77546. }
  77547. Potree.settings.datasetsPanos = data;
  77548. }
  77549. cancelEdit() {
  77550. //回退数据
  77551. this.changeDatas(Potree.settings.datasetsPanos, true);
  77552. this.lineMeshes.children.forEach(e => e.geometry.dispose());
  77553. this.lineMeshes.children.length = 0; //clear
  77554. this.initPanoLink();
  77555. }
  77556. save() {
  77557. var data = this.exportSavingData();
  77558. this.changeDatas(Potree.Common.CloneObject(data));
  77559. return data;
  77560. }
  77561. exportSavingData() {
  77562. var _this3 = this;
  77563. //输出漫游点新的坐标和朝向、以及连接信息
  77564. var sweepLocations = {};
  77565. var _loop3 = function _loop3() {
  77566. var {
  77567. panos
  77568. } = Potree.settings.datasetsPanos[datasetId];
  77569. var data = panos.map(pano => {
  77570. var visibles = [];
  77571. for (var id in _this3.panoLink[pano.id]) {
  77572. if (_this3.panoLink[pano.id][id]) {
  77573. visibles.push(viewer.images360.getPano(id).index);
  77574. }
  77575. }
  77576. var {
  77577. position,
  77578. quaternion
  77579. } = _this3.getPanoPose(pano);
  77580. data = Object.assign({}, pano.panoData, {
  77581. pose: {
  77582. translation: dealData(position),
  77583. rotation: dealData(quaternion)
  77584. },
  77585. use_rtk: !!pano.rtkState,
  77586. exist: pano.isCalc == void 0 ? true : pano.isCalc
  77587. });
  77588. if (_this3.version != 'old') {
  77589. if (pano.panoData.visibles) {
  77590. delete data.visibles;
  77591. }
  77592. var old_links_data = pano.panoData.links_data || [];
  77593. data.links_data = visibles.map(e => {
  77594. var old = old_links_data.find(a => a.index == e);
  77595. if (old && (isNaN(old.MAE) || !old.MAE)) old.MAE = 0;
  77596. return old || {
  77597. index: e,
  77598. "MAE": 0,
  77599. "overlap": 0
  77600. }; //随便写一个0
  77601. });
  77602. } else {
  77603. data.visibles = visibles;
  77604. }
  77605. return data;
  77606. });
  77607. sweepLocations[datasetId] = {
  77608. sweepLocations: data
  77609. };
  77610. };
  77611. for (var datasetId in Potree.settings.datasetsPanos) {
  77612. _loop3();
  77613. }
  77614. /* this.lineMeshes.children.forEach(e=>{//从line中搜集连接信息,而不从linkInfo,这样visibles不会重复一次
  77615. let names = e.name.split('-') //是不是该转成数字
  77616. var pano0 = names[0]
  77617. var pano1 = names[1]
  77618. sweepLocations.find(s=>s.uuid == pano0).visibles.push(pano1)
  77619. }) */
  77620. function dealData(value) {
  77621. var v = math.toPrecision(value, 6);
  77622. if (v instanceof Quaternion) {
  77623. return {
  77624. x: v.x,
  77625. y: v.y,
  77626. z: v.z,
  77627. w: v.w
  77628. };
  77629. } else if (v instanceof Vector3) {
  77630. return {
  77631. x: v.x,
  77632. y: v.y,
  77633. z: v.z
  77634. };
  77635. }
  77636. }
  77637. //console.log(sweepLocations)
  77638. return sweepLocations;
  77639. }
  77640. }
  77641. /*
  77642. 不同数据集之间不能连线
  77643. 不同楼层可能也不能
  77644. 如果楼层在不同建筑物怎么办? 楼层切换按钮只能在一个建筑内切换。
  77645. 全部相连时不能移动和旋转
  77646. 如果未全部相连,不能保存
  77647. 点位编辑页加载的漫游点坐标朝向和4dkk与主页的都不一样,是单独的一套。
  77648. 问题:漫游点移动后不改变其楼层吗?(虽然也无法改变,因为上面那句)
  77649. 注:quaternion四个数都取相反数结果不变,即(x,y,z,w) == (-x,-y,-z,-w), 不信都转成Euler就会一样。而用angleTo比较却不是0
  77650. exist为false的点没有深度图,而保存后exist为true不点击计算也没有。
  77651. */
  77652. var PanoEditor$1 = new PanoEditor();
  77653. /*
  77654. import {Utils} from "../../../utils.js";
  77655. import Sprite from '../../objects/Sprite.js'
  77656. import browser from '../../utils/browser.js'
  77657. */
  77658. //import {Prism} from './Prism.js'
  77659. var maxWidth = 4096;
  77660. var surfaceThick = 0.1; //最大表面厚度
  77661. var pointDensity = 'screenshot';
  77662. var maxPointBudge = Potree.config.pointDensity[pointDensity].pointBudget;
  77663. var Shaders$1 = {
  77664. 'modelHeight.vs': " \n precision highp float;\n \n uniform vec2 boundZ;\n varying float heightPercent; \n \n \n \n void main() \n { \n vec3 worldPos = (modelMatrix * vec4(position, 1.0)).xyz; \n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); \n \n float zMin = boundZ.x, zMax = boundZ.y ;\n heightPercent = (worldPos.z - zMin) / (zMax - zMin); \n \n \n }\n \n \n ",
  77665. 'modelHeight.fs': "\n precision highp float;\n varying float heightPercent; \n \n \n \n \n vec3 percentToByte(float num){\n //\u8F93\u51FA\u662F0-1\uFF0C shader\u7CBE\u5EA6\u4E0D\u591F\uFF0C\u53EA\u591F\u5B583\u4E2A\u6570\uFF0C\u56E0\u7B2C\u56DB\u4F4D\u603B\u662F0\n float a = 1.0;\n float result[4];\n for(int i=0;i<3;i++){\n a = i == 2 ? a/255.0 : a / 256.0 ; \n //\u5206\u6210256\u4EFD\uFF0C\u5176\u4E2D255\u4EFD\u7ED9\u5F53\u524D\u4F4D\u7F6E\uFF0C\u6700\u540E\u4E00\u4EFD\u7ED9\u540E\u4E00\u4E2A\u4F4D\u7F6E\uFF0C\u800C\u5230\u4E86\u6700\u540E\u4E00\u4E2A\u4F4D\u7F6E\u65F6\u6CA1\u6709\u4E0B\u4E00\u4E2A\u4F4D\u7F6E\u4E86\u6240\u4EE5\u53EA\u5206\u6210255\u4EFD\n if(num > a){\n float c = num / a;\n float r = floor(c);\n r = min(255.0, r);\n result[i] = r;\n num -= r * a;\n }else{\n result[i] = 0.0;\n }\n } \n return vec3(result[0]/255.0, result[1]/255.0,result[2]/255.0); \n \n } \n \n \n void main() {\n \n gl_FragColor = vec4(percentToByte(heightPercent),1.0); \n \n \n }\n "
  77666. };
  77667. var horizonZ,
  77668. zMin,
  77669. zMax,
  77670. lowest,
  77671. highest,
  77672. wDelta,
  77673. sDelta,
  77674. deferred,
  77675. interrupt,
  77676. timestamp,
  77677. buffer1,
  77678. buffer2,
  77679. modelZs = [];
  77680. var testPoint_ = false;
  77681. //const asyncTimeout = (delay) => new Promise(resolve => setTimeout(resolve, delay))
  77682. var delayForNotify = 5,
  77683. notifyInterval = 500;
  77684. var lastNotifyTime = Date.now();
  77685. var curPercent;
  77686. var notify = (areas, num, str) => {
  77687. //num: 0-1
  77688. return new Promise(resolve => {
  77689. if (!deferred) return resolve();
  77690. var now = Date.now();
  77691. if (now - lastNotifyTime < notifyInterval) {
  77692. return resolve();
  77693. }
  77694. lastNotifyTime = now;
  77695. if (num == void 0) {
  77696. num = curPercent;
  77697. } else {
  77698. var s = 0,
  77699. e = 1;
  77700. if (num instanceof Function) {
  77701. num = num();
  77702. }
  77703. areas.forEach(area => {
  77704. var s_ = e * area[0] + s * (1 - area[0]);
  77705. var e_ = e * area[1] + s * (1 - area[1]);
  77706. s = s_, e = e_;
  77707. });
  77708. var p = e * num + s * (1 - num);
  77709. str == 'loadpoints' && Potree.settings.isTest && console.log('notify pro', p, str);
  77710. deferred.notify(p);
  77711. curPercent = p;
  77712. if (isNaN(p)) {
  77713. console.log('nan');
  77714. }
  77715. }
  77716. setTimeout(resolve, delayForNotify);
  77717. });
  77718. };
  77719. class VolumeComputer extends EventDispatcher {
  77720. constructor() {
  77721. super();
  77722. this.camera = new OrthographicCamera(-100, 100, -100, 100, 0.01, 100);
  77723. this.camera.up.set(0, 0, 1);
  77724. Potree.Utils.setCameraLayers(this.camera, ['model']);
  77725. this.view = new ExtendView();
  77726. this.viewport = new Viewport(this.view, this.camera, {
  77727. left: 0,
  77728. bottom: 0,
  77729. width: 1,
  77730. height: 1
  77731. });
  77732. this.renderTarget = new WebGLRenderTarget(1, 1, {
  77733. minFilter: LinearFilter,
  77734. magFilter: NearestFilter,
  77735. format: RGBAFormat
  77736. });
  77737. this.renderTarget2 = new WebGLRenderTarget(1, 1, {
  77738. minFilter: LinearFilter,
  77739. magFilter: NearestFilter,
  77740. format: RGBAFormat
  77741. });
  77742. this.renderTarget2.texture.name = 'volumeCptModelTex';
  77743. this.material = new ExtendPointCloudMaterial();
  77744. this.material.activeAttributeName = testPoint_ ? "rgba" : 'heightCpt'; // 'rgba' indices prismHeight
  77745. this.prisms = [];
  77746. this.modelMat = new ShaderMaterial({
  77747. uniforms: {
  77748. boundZ: {
  77749. type: "vec2",
  77750. value: new Vector2()
  77751. }
  77752. },
  77753. vertexShader: Shaders$1['modelHeight.vs'],
  77754. fragmentShader: Shaders$1['modelHeight.fs'],
  77755. depthWrite: true,
  77756. depthTest: true,
  77757. transparent: false,
  77758. side: DoubleSide
  77759. });
  77760. this.scene = new Scene();
  77761. }
  77762. init() {
  77763. viewer.scene.addEventListener('measurement_added', e => {
  77764. if (e.measurement.isPrism) this.add(e.measurement);
  77765. });
  77766. viewer.scene.addEventListener('measurement_removed', e => {
  77767. if (e.measurement.isPrism) this.remove(e.measurement);
  77768. });
  77769. var this_ = this;
  77770. this.events = {
  77771. transformCallback: () => {
  77772. if (!this_.currentPrism) return;
  77773. //Common.intervalTool.isWaiting('volCptTransformed', ()=>{ //延时update,防止卡顿
  77774. var object = viewer.transformationTool.selection[0];
  77775. if (object == this_.currentPrism.baseModel) {
  77776. this.updateModelBound({
  77777. modelChange: true
  77778. });
  77779. }
  77780. this_.currentPrism.dispatchEvent('needsCompute'); //模型变动或clipBox变动后要重算
  77781. //}, 1000)
  77782. }
  77783. };
  77784. }
  77785. enter() {
  77786. this.entered = true;
  77787. viewer.measuringTool.history.clear(); //避免撤销到测量线去
  77788. this.oldStates = {
  77789. rotAroundPoint: Potree.settings.rotAroundPoint
  77790. };
  77791. Potree.settings.rotAroundPoint = false;
  77792. //viewer.objs.traverse(e=>e.material && ( e.material = this.material))
  77793. viewer.transformationTool.addEventListener('stopDrag', this.events.transformCallback);
  77794. viewer.transformationTool.addEventListener('changeByHistory', this.events.transformCallback);
  77795. }
  77796. leave() {
  77797. this.entered = false;
  77798. Potree.settings.rotAroundPoint = this.oldStates.rotAroundPoint;
  77799. this.setCurrentPrism(null);
  77800. viewer.transformationTool.removeEventListener('stopDrag', this.events.transformCallback);
  77801. viewer.transformationTool.removeEventListener('changeByHistory', this.events.transformCallback);
  77802. }
  77803. add(prism) {
  77804. this.prisms.push(prism);
  77805. }
  77806. remove(prism) {
  77807. var i = this.prisms.indexOf(prism);
  77808. i > -1 && this.prisms.splice(i, 1);
  77809. }
  77810. cancel() {
  77811. if (this.computingObject) {
  77812. interrupt = true;
  77813. }
  77814. }
  77815. startCompute(model, dontCompute) {
  77816. //test
  77817. this.enter();
  77818. var deferred = $.Deferred();
  77819. deferred.done(e => {
  77820. console.log('done', e);
  77821. });
  77822. deferred.fail(e => {
  77823. console.log('?fail????', e);
  77824. });
  77825. /* deferred.progress((e)=>{
  77826. console.log('progress', e)
  77827. }) */
  77828. if (model) {
  77829. this.prisms[this.prisms.length - 1].setBaseModel(model);
  77830. this.setCurrentPrism(this.prisms[this.prisms.length - 1]);
  77831. dontCompute || this.compute(this.prisms[this.prisms.length - 1]);
  77832. } else {
  77833. this.compute(this.prisms[this.prisms.length - 1], deferred);
  77834. }
  77835. }
  77836. setCurrentPrism(prism) {
  77837. //当进入单个prism编辑后才会高亮点云
  77838. if (this.currentPrism) {
  77839. this.currentPrism.removeEventListeners('updated');
  77840. }
  77841. this.currentPrism = prism; //允许没有model
  77842. if (!prism || !prism.baseModel /* || !prism.baseModel.visible */) {
  77843. viewer.scene.pointclouds.forEach(e => {
  77844. this.updateMatForModel(e.material); //取消高亮
  77845. });
  77846. return;
  77847. }
  77848. prism.addEventListener('updated', () => {
  77849. if (this.currentPrism != prism) {
  77850. return console.log('currentPrism changed? 侦听没删除');
  77851. }
  77852. this.updateModelBound();
  77853. });
  77854. this.updateModelBound({
  77855. regetMap: true
  77856. });
  77857. }
  77858. setModelMat(model, type) {
  77859. if (type == 'recover') {
  77860. model.traverse(e => e.originMat_ && (e.material = e.originMat_));
  77861. } else {
  77862. model.traverse(e => e.material && e.material != this.modelMat && (e.originMat_ = e.material, e.material = this.modelMat));
  77863. }
  77864. }
  77865. updateModelBound() {
  77866. var {
  77867. modelChange,
  77868. regetMap
  77869. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  77870. //regetMap是在更换currentPrism必须重绘map,但不需要needUpdate
  77871. var prism = this.currentPrism;
  77872. var model = this.currentPrism.baseModel;
  77873. if (!model) return;
  77874. model.currentBound = model.boundingBox.clone().applyMatrix4(model.matrixWorld); //作用同prismBound
  77875. var oldBound = model.clipBound && model.clipBound.clone();
  77876. model.clipBound = model.currentBound.clone(); //高亮范围
  77877. model.clipBound.min.max(prism.prismBound.min); //xy为交集
  77878. model.clipBound.max.min(prism.prismBound.max);
  77879. model.clipBound.min.z = Math.min(model.currentBound.min.z, prism.prismBound.min.z); //z为并集,范围覆盖prism点、点云、model三者
  77880. model.clipBound.max.z = Math.max(model.currentBound.max.z, prism.prismBound.max.z);
  77881. this.modelMat.uniforms.boundZ.value.set(model.clipBound.min.z, model.clipBound.max.z);
  77882. var boundChanged = !oldBound || !oldBound.equals(model.clipBound);
  77883. var boundSize = this.currentPrism.baseModel.clipBound.getSize(new Vector3());
  77884. this.boundSizeZero = boundSize.x <= 0 || boundSize.y <= 0 || boundSize.z <= 0; //会造成renderTarget尺寸为0,背景变白,报错:Framebuffer is incomplete: Attachment has zero size 和 The texture is a non-power-of-two texture.
  77885. if ((modelChange || regetMap || boundChanged) && !this.boundSizeZero) {
  77886. this.setModelHeightMap(); //包含cad在俯视中的范围 + 高度信息
  77887. //this.setModelMat(model,this.boundSizeZero ? 'recover' : null)
  77888. }
  77889. viewer.scene.pointclouds.forEach(e => {
  77890. //暂时先只支持一个高亮区域
  77891. this.updateMatForModel(e.material, model);
  77892. });
  77893. //需要重新渲染modelHeightmap的情况:bound改变、模型变动、更换currentPrism后
  77894. //注意,即使上传几种都没发生,仅仅移动prism的marker也要重算,假设一个marker在model范围内,移动后bound可能不变但体积肯定变。
  77895. /* if(boundChanged){
  77896. if(prism.recoverNeedCptNextTime){
  77897. prism.needsCompute = 'byVolume' //初始化,有volume就不用重算
  77898. prism.recoverNeedCptNextTime = false
  77899. }else{
  77900. prism.dispatchEvent('needsCompute')
  77901. }
  77902. } */
  77903. }
  77904. updateMatForModel(material, model) {
  77905. var oldMap = material.uniforms.baseHeightAreaMap.value;
  77906. if (model) {
  77907. material.uniforms.baseHeightAreaMap.value = this.renderTarget2.texture; //model.baseHeightAreaMap ;
  77908. material.uniforms.baseHeightBoundZ.value.set(model.clipBound.min.z, model.clipBound.max.z);
  77909. material.uniforms.baseHeightBoundXY.value.set(model.clipBound.min.x, model.clipBound.max.x, model.clipBound.min.y, model.clipBound.max.y);
  77910. } else {
  77911. material.uniforms.baseHeightAreaMap.value = null;
  77912. }
  77913. if (oldMap != material.uniforms.baseHeightAreaMap.value) {
  77914. material.shaderNeedsUpdate = true;
  77915. }
  77916. }
  77917. setModelHeightMap() {
  77918. var oldTarget = viewer.renderer.getRenderTarget();
  77919. var oldParent = this.currentPrism.baseModel.parent;
  77920. var oldVisi = this.currentPrism.baseModel.visible;
  77921. var boundSize = this.currentPrism.baseModel.clipBound.getSize(new Vector3());
  77922. var boundCenter = this.currentPrism.baseModel.clipBound.getCenter(new Vector3());
  77923. var {
  77924. w,
  77925. h
  77926. } = this.getResByBound(boundSize, 'forModel');
  77927. if (w <= 0 || h <= 0) {
  77928. return console.error('w<=0 || h<=0!!!!!!!!!', w, h);
  77929. }
  77930. /* w = THREE.Math.floorPowerOfTwo( w );
  77931. h = THREE.Math.floorPowerOfTwo( h ); */ //for warning:The texture is a non-power-of-two texture
  77932. this.camera.far = boundSize.z + 10;
  77933. this.camera.right = w / 2;
  77934. this.camera.left = -this.camera.right;
  77935. this.camera.top = h / 2;
  77936. this.camera.bottom = -this.camera.top;
  77937. this.viewport.resolution.set(w, h);
  77938. this.renderTarget2.setSize(w, h);
  77939. viewer.renderer.setRenderTarget(this.renderTarget2);
  77940. console.log('setModelHeightMap');
  77941. //最高处朝下看
  77942. var endPosition = new Vector3();
  77943. endPosition.copy(boundCenter).setZ(this.currentPrism.baseModel.clipBound.max.z + this.camera.near + 0.1);
  77944. this.view.pitch = -Math.PI / 2;
  77945. this.view.moveOrthoCamera(this.viewport, {
  77946. boundSize,
  77947. endPosition
  77948. }, 0);
  77949. this.view.applyToCamera(this.camera);
  77950. this.scene.add(this.currentPrism.baseModel);
  77951. this.setModelMat(this.currentPrism.baseModel);
  77952. this.currentPrism.baseModel.visible = true;
  77953. var gl = viewer.renderer.getContext();
  77954. viewer.renderer.setClearColor(new Color('#000'), 0);
  77955. viewer.renderer.clear();
  77956. viewer.renderer.render(this.scene, this.camera);
  77957. this.setModelMat(this.currentPrism.baseModel, 'recover');
  77958. var pixelCount = this.renderTarget2.width * this.renderTarget2.height;
  77959. buffer2 = new Uint8Array(4 * pixelCount);
  77960. //因为需要渲染完立即readPixels才能获取到,所以只能这时候就read了
  77961. gl.readPixels(0, 0, this.renderTarget2.width, this.renderTarget2.height, gl.RGBA, gl.UNSIGNED_BYTE, buffer2); //这句花费最多时间 pc:2-4, 即使只有1*1像素
  77962. modelZs = []; //等待计算
  77963. if (window.needDownload) {
  77964. var dataUrl = Potree.Utils.renderTargetToDataUrl(this.renderTarget2, this.renderTarget2.width, this.renderTarget2.height, viewer.renderer);
  77965. Common$1.downloadFile(dataUrl, (name || 'screenshot') + '-' + Date.now() + '.png');
  77966. }
  77967. oldParent.add(this.currentPrism.baseModel);
  77968. this.currentPrism.baseModel.visible = oldVisi;
  77969. viewer.renderer.setRenderTarget(oldTarget);
  77970. this.renderTarget2.texture.needsRebuild = true; //renderTarget在resize后会触发dispose, 然后 _gl.deleteTexture( textureProperties.__webglTexture )所以需要重新建立 否则图片变黑
  77971. return this.renderTarget2.texture;
  77972. }
  77973. getResByBound(boundSize, type) {
  77974. //let pxPerMetric = math.linearClamp(Math.max(boundSize.x,boundSize.y), [4, 10, 20, 80, 500, 2000], [300, 200, 100, 30, 6, 3])
  77975. var pxPerMetric = math.linearClamp(Math.max(boundSize.x, boundSize.y), [10, 60, 100, 500, 2000], [150, 60, 40, 6, 3]);
  77976. var w = pxPerMetric * boundSize.x,
  77977. h = boundSize.y * pxPerMetric;
  77978. var cW = 1,
  77979. cH = 1; //横向纵向渲染次数 超过maxWidth时分批渲染
  77980. if (w > maxWidth || h > maxWidth) {
  77981. /* if(){//多数据集判断是否间隔过远,是的话返回
  77982. } */
  77983. if (type == 'forCompute') {
  77984. //计算可以分多次渲染
  77985. cW = Math.ceil(w / maxWidth), cH = Math.ceil(h / maxWidth);
  77986. w /= cW, h /= cH;
  77987. } else if (type == 'forModel') {
  77988. //但是model的贴图只能有一个
  77989. if (w > h) {
  77990. w = maxWidth, h = w * boundSize.y / boundSize.x;
  77991. } else {
  77992. h = maxWidth, w = h * boundSize.x / boundSize.y;
  77993. }
  77994. }
  77995. }
  77996. w = Math.round(w);
  77997. h = Math.round(h);
  77998. return {
  77999. w,
  78000. h,
  78001. pxPerMetric,
  78002. cW,
  78003. cH
  78004. };
  78005. }
  78006. //法1:只用一个顶部相机(当挖方遮挡填方时不准,但好算)
  78007. async compute(prism, deferred_, getResolveResult) {
  78008. var _this = this;
  78009. if (!prism || prism.modelHaventLoad) {
  78010. console.log('prism有问题');
  78011. return deferred_.reject();
  78012. }
  78013. if (this.computingObject) return console.log('正在计算,请稍等');
  78014. var oldCurPrism = this.currentPrism;
  78015. if (prism != this.currentPrism) {
  78016. //在列表外点击计算
  78017. this.setCurrentPrism(prism);
  78018. }
  78019. var computeDone = (_ref, deferred) => {
  78020. var {
  78021. highest,
  78022. lowest,
  78023. Vupper,
  78024. Vlower
  78025. } = _ref;
  78026. prism && prism.setVolumeInfo({
  78027. highest,
  78028. lowest,
  78029. Vupper,
  78030. Vlower
  78031. });
  78032. if (oldCurPrism != prism) {
  78033. this.setCurrentPrism(oldCurPrism);
  78034. }
  78035. deferred && deferred.resolve(getResolveResult && getResolveResult());
  78036. };
  78037. if (prism.baseModel && this.boundSizeZero) {
  78038. //bound没有交集 或 prism的boundsize为0
  78039. return computeDone({
  78040. highest: 0,
  78041. lowest: 0,
  78042. Vupper: 0,
  78043. Vlower: 0
  78044. }, deferred_);
  78045. }
  78046. this.computingObject = {
  78047. prism,
  78048. model: prism.baseModel
  78049. };
  78050. deferred = deferred_;
  78051. var computeFinish = (debugStr, makeit) => {
  78052. makeit || deferred.reject(interrupt ? '主动取消' : debugStr || '');
  78053. this.computingObject = null;
  78054. deferred = null;
  78055. interrupt = false;
  78056. debugStr && console.log('computeFinish', debugStr);
  78057. Potree.settings.displayMode = statesBefore.mode;
  78058. Potree.settings.pointDensity = statesBefore.pointDensity;
  78059. viewer.renderer.setRenderTarget(null);
  78060. viewer.renderer.state.reset();
  78061. viewer.renderer.setScissorTest(false);
  78062. gl.disable(gl.SCISSOR_TEST);
  78063. viewer.screenshoting = false;
  78064. viewer.mainViewport.active = true;
  78065. viewer.mapViewer && (viewer.mapViewer.viewports[0].active = true);
  78066. viewer.magnifier.viewport.active = true;
  78067. viewer.pauseTestMaxLevel = false;
  78068. };
  78069. var pointcloud = viewer.scene.pointclouds[0];
  78070. var center = new Vector3();
  78071. var boundSize = new Vector3();
  78072. var bound;
  78073. var gl = viewer.renderer.getContext();
  78074. var statesBefore = {
  78075. mode: Potree.settings.displayMode,
  78076. pointDensity: Potree.settings.pointDensity
  78077. };
  78078. timestamp = Date.now();
  78079. if (!this.computingObject.model) {
  78080. horizonZ = prism.horizonZ;
  78081. zMin = prism.zMin;
  78082. zMax = prism.zMax;
  78083. bound = new Box3().copy(prism.prismBound);
  78084. /* for(let i=0;i<prism.points.length;i++){
  78085. bound.expandByPoint(prism.points[i])
  78086. } */
  78087. } else {
  78088. zMin = this.computingObject.model.clipBound.min.z;
  78089. zMax = this.computingObject.model.clipBound.max.z;
  78090. bound = this.computingObject.model.clipBound;
  78091. //读取model的高度
  78092. for (var u = 0; u < this.renderTarget2.width; u++) {
  78093. var col = [];
  78094. for (var v = 0; v < this.renderTarget2.height; v++) {
  78095. var offset = u + v * this.renderTarget2.width;
  78096. var rgb = buffer2.slice(4 * offset, 4 * offset + 3),
  78097. a = buffer2[4 * offset + 3];
  78098. if (a == 0) {
  78099. //无点
  78100. col.push(null);
  78101. } else {
  78102. var z = this.convertColorToHeight(rgb, zMin, zMax);
  78103. col.push(z);
  78104. }
  78105. }
  78106. modelZs.push(col);
  78107. }
  78108. }
  78109. lowest = zMax, highest = zMin; //init. to store pixel lowest and highest
  78110. bound.getCenter(center);
  78111. bound.getSize(boundSize);
  78112. this.boundSizeZero = boundSize.x <= 0 || boundSize.y <= 0 || this.computingObject.model && boundSize.z <= 0; //prism的问题
  78113. if (this.boundSizeZero) {
  78114. computeDone({
  78115. highest: 0,
  78116. lowest: 0,
  78117. Vupper: 0,
  78118. Vlower: 0
  78119. }, deferred);
  78120. return computeFinish('finish', true);
  78121. }
  78122. center.z = zMax + this.camera.near + 0.1;
  78123. this.camera.far = zMax - zMin + 10;
  78124. viewer.screenshoting = true;
  78125. viewer.pauseTestMaxLevel = true;
  78126. var {
  78127. w,
  78128. h,
  78129. pxPerMetric,
  78130. cW,
  78131. cH
  78132. } = this.getResByBound(boundSize, 'forCompute');
  78133. this.camera.right = w / 2;
  78134. this.camera.left = -this.camera.right;
  78135. this.camera.top = h / 2;
  78136. this.camera.bottom = -this.camera.top;
  78137. this.viewport.resolution.set(w, h);
  78138. this.renderTarget.setSize(w, h);
  78139. wDelta = boundSize.x / (w * cW);
  78140. sDelta = Math.pow(wDelta, 2);
  78141. //准备
  78142. Potree.settings.displayMode = 'showPointCloud';
  78143. Potree.settings.pointDensity = 'screenshot';
  78144. viewer.mainViewport.active = false; //暂停渲染,否则影响这边点云的加载
  78145. viewer.mapViewer && (viewer.mapViewer.viewports[0].active = false);
  78146. viewer.magnifier.viewport.active = false; //防止页面变白(似乎mainViewport被clear)
  78147. {
  78148. //material
  78149. if (!this.computingObject.model) {
  78150. //this.material.shape = Potree.PointShape.PARABOLOID;//加上之后depth出错,后排点云会挡前排,可pick时为什么不会?
  78151. this.updateMatForModel(this.material, null); //计算时的shader这两种类型只能选一个,要么prism要么model,只能渲染一块区域
  78152. //this.material.opacity = 1;
  78153. } else {
  78154. this.updateMatForModel(this.material, this.computingObject.model);
  78155. //this.material.opacity = 0.9; //为了输出透明度,负数高度的alpha是0.5
  78156. }
  78157. var clipBoxes_out = prism.clipBoxes.map(box => {
  78158. return {
  78159. inverse: box.matrixWorld.clone().invert(),
  78160. box
  78161. };
  78162. });
  78163. this.material.setClipBoxes(null, [], clipBoxes_out, [], [prism]);
  78164. this.material.pointSizeType = 'FIXED'; //'ADAPTIVE' //node会自动根据的其level更改点大小 使用ADAPTIVE后会使baseModelMap整片是黑的,原因未知
  78165. this.material.uniforms.minSize.value = 0.1;
  78166. this.material.uniforms.orthoMaxSize.value = 5; //px
  78167. this.material.classification = pointcloud.material.classification;
  78168. this.material.recomputeClassification();
  78169. this.material.shaderNeedsUpdate = true;
  78170. pointcloud.updateMaterial(this.material, null, this.camera, viewer.renderer, this.viewport.resolution);
  78171. this.material.size = 1; //this.getPointsize(pointcloud.maxLevel) //0.025 米 //视图缩小(截图面积变大)后点会自动缩小,但至少是1个像素大小
  78172. }
  78173. viewer.renderer.state.buffers.depth.setTest(this.material.depthTest);
  78174. viewer.renderer.state.buffers.depth.setMask(this.material.depthWrite);
  78175. viewer.renderer.state.setBlending(NoBlending); //只需要设置不透明即可(使alpha不混合,后方不会影响前方的alpha,否则输出的a通道将没法用)
  78176. var pixelCount = this.renderTarget.width * this.renderTarget.height;
  78177. buffer1 = new Uint8Array(4 * pixelCount);
  78178. viewer.renderer.setRenderTarget(this.renderTarget);
  78179. var results = [];
  78180. var boundSize_ = boundSize.clone();
  78181. boundSize_.x /= cW, boundSize_.y /= cH;
  78182. //分批渲染:从左到右 从下到上
  78183. var _loop = async function _loop(i) {
  78184. var _loop2 = async function _loop2(j) {
  78185. var infos = [];
  78186. var progressStart = (i * cH + j) / (cW * cH),
  78187. progressEnd = (i * cH + j + 1) / (cW * cH);
  78188. if (interrupt) {
  78189. return {
  78190. v: {
  78191. v: computeFinish('23')
  78192. }
  78193. };
  78194. }
  78195. Potree.settings.pointDensity = 'screenshot'; //恢复为nodeMaxLevel
  78196. //最高处朝下看,找挖方的顶部
  78197. _this.view.pitch = -Math.PI / 2;
  78198. var endPosition = new Vector3(center.x + (i - cW / 2 + 0.5) * boundSize_.x, center.y + (j - cH / 2 + 0.5) * boundSize_.y, center.z);
  78199. _this.view.moveOrthoCamera(_this.viewport, {
  78200. boundSize: boundSize_,
  78201. endPosition
  78202. }, 0);
  78203. var endPercent = _this.computingObject.model ? 0.7 : 0.4;
  78204. await _this.render({
  78205. i,
  78206. j,
  78207. index: 1,
  78208. cW,
  78209. cH,
  78210. infos,
  78211. /* maxLevels, */notifyArea: [[progressStart, progressEnd], [0, endPercent]],
  78212. computeFinish
  78213. });
  78214. if (interrupt) {
  78215. return {
  78216. v: {
  78217. v: computeFinish('2123')
  78218. }
  78219. };
  78220. }
  78221. if (!_this.computingObject.model) {
  78222. //水平面朝下看,找填方
  78223. _this.view.position.z = horizonZ + _this.camera.near;
  78224. await _this.render({
  78225. i,
  78226. j,
  78227. index: 2,
  78228. cW,
  78229. cH,
  78230. infos,
  78231. /* maxLevels, */notifyArea: [[progressStart, progressEnd], [0.4, 0.7]],
  78232. computeFinish
  78233. });
  78234. }
  78235. //水平面朝上看,找挖方的底部
  78236. /* this.view.position.z = horizonZ + surfaceThick //排除地面(水平面)上的点
  78237. this.view.pitch = Math.PI / 2;
  78238. await this.render({reverseRow:true,name:'第3张-'+i+'-'+j, infos, buffer,maxLevels }) */ //---土堆上有草地有厚度,还是去掉吧
  78239. var result = {
  78240. index: {
  78241. i,
  78242. j
  78243. },
  78244. allFills: [],
  78245. fillVupper: 0,
  78246. fillVlower: 0,
  78247. Vupper: 0,
  78248. Vlower: infos[1] ? infos[1].Vlower : infos[0].Vlower,
  78249. // >= infos[0].Vlower 因能找到被上方遮挡住的凹槽
  78250. allDiffHeights: [],
  78251. fillVupperCount: 0,
  78252. fillVlowerCount: 0,
  78253. infos
  78254. };
  78255. var waitFill = [];
  78256. waitFill.count = 0;
  78257. var isNeighbor = (a, b) => {
  78258. return Math.abs(a.u - b.u) <= 1 && Math.abs(a.v - b.v) <= 1;
  78259. };
  78260. var isBelongToGroup = (group, item) => {
  78261. if (item[0]) item = item[0];
  78262. var i = group.length;
  78263. while (--i >= 0) {
  78264. //从后往前
  78265. if (item.u - group[i].u > 1 && Math.abs(item.v - group[i].v) > 1) break; //距离超出,前面肯定不相邻了
  78266. if (isNeighbor(group[i], item)) {
  78267. return true;
  78268. }
  78269. }
  78270. };
  78271. //计算挖方(但是边缘附近垂直方向上很多点云,体积被削皮,最终得到的会比infos[0]少)
  78272. var getValue = (u, v) => {
  78273. //当到了左上边界是否需要向前几批的查找?
  78274. if (infos[0].allHeights[u] && infos[0].allHeights[u][v] != void 0) return infos[0].allHeights[u][v];
  78275. return result.allFills[u] && result.allFills[u][v];
  78276. };
  78277. var hasValue = (u, v) => {
  78278. //在边界内
  78279. return u >= 0 && u < infos[0].allHeights.length && v >= 0 && v < infos[0].allHeights[0].length;
  78280. };
  78281. var getFill = (u, v) => {
  78282. //使用周围的八个点的平均值补洞
  78283. var neighbours = [[-1, 0], [0, 1], [1, 0], [0, -1], [-1, -1], [1, -1], [-1, 1], [1, 1]]; //先左右右先上后下
  78284. var i = 0,
  78285. c = 0,
  78286. sum = 0;
  78287. while (c < 4 && i < 8) {
  78288. var x = neighbours[i][0] + u,
  78289. y = neighbours[i][1] + v;
  78290. if (hasValue(x, y)) {
  78291. var neigh = getValue(x, y);
  78292. if (neigh != void 0) {
  78293. c++;
  78294. sum += neigh;
  78295. } else if (i >= 3) {
  78296. //add 2024.5.27
  78297. if (c == 0) break; //节省时间,主要为了大片透明区域
  78298. }
  78299. }
  78300. i++;
  78301. }
  78302. if (c > 0) {
  78303. sum /= c;
  78304. result.allFills[u] || (result.allFills[u] = []);
  78305. result.allFills[u][v] = sum;
  78306. return sum;
  78307. }
  78308. };
  78309. var add = (v, fill, count) => {
  78310. if (v > 0) {
  78311. result.Vupper += v;
  78312. fill && (result.fillVupper += v, result.fillVupperCount += count);
  78313. } else {
  78314. //fill的话才会有
  78315. fill && (result.fillVlower -= v, result.fillVlowerCount += count);
  78316. }
  78317. };
  78318. var compute = async (u, v) => {
  78319. var top = infos[0].allHeights[u][v];
  78320. //let btm = infos[2].allHeights[u][v]
  78321. var fill;
  78322. if (top == void 0) {
  78323. if (prism) {
  78324. var x = endPosition.x - boundSize_.x / 2 + wDelta * (u + 0.5);
  78325. var y = endPosition.y - boundSize_.y / 2 + wDelta * (v + 0.5);
  78326. if (!math.isPointInArea(prism.points, null, {
  78327. x,
  78328. y
  78329. })) {
  78330. return; //出界
  78331. }
  78332. } else {
  78333. if (_this.getModelZByRes(u, v, cW, cH, i, j) == void 0) {
  78334. return; //出界
  78335. }
  78336. }
  78337. fill = true;
  78338. top = getFill(u, v);
  78339. if (top == void 0) {
  78340. //左侧边缘有缺口时会出现
  78341. if (waitFill.cancel || waitFill.count > 1000 && waitFill[waitFill.length - 1][waitFill[waitFill.length - 1].length - 1].u - waitFill[0][0].u > 4) {
  78342. //跨度超过4列
  78343. waitFill.cancel = true; //丢弃,不加入补洞, 降低耗时
  78344. } else {
  78345. Common$1.pushToGroupAuto([{
  78346. u,
  78347. v
  78348. }], waitFill, null, isBelongToGroup); //按邻近点分组
  78349. }
  78350. waitFill.count++; //当数量达到几万以上会在这个地方花很长时间,不过很少出现这种情况
  78351. return;
  78352. }
  78353. }
  78354. /* let diff = top-btm
  78355. let useDiff
  78356. if(btm != void 0 && diff > surfaceThick ){
  78357. useDiff = diff
  78358. result.allDiffHeights.push(useDiff)
  78359. }else{
  78360. useDiff = top //从顶部一直到水平
  78361. }*/
  78362. if (waitFill.length) {
  78363. //补 之前没有值的邻居重新获取
  78364. if (interrupt) {
  78365. return computeFinish('12312');
  78366. }
  78367. if (waitFill.cancel) {
  78368. //console.log('直接清空waitFill', waitFill.count, waitFill.map(list=>[list[0], list[list.length-1]]))
  78369. waitFill.count = 0;
  78370. waitFill.length = 0;
  78371. waitFill.cancel = false;
  78372. } else {
  78373. ///* //Potree.settings.isTest && */ waitFill.count>1000 && console.log('waitFill.count', waitFill.count, 'groupLen', waitFill.length, waitFill[0][0], waitFill[0][waitFill[0].length-1])
  78374. waitFill.slice().forEach(group => {
  78375. //每个组都看看是否跟它相邻
  78376. if (isBelongToGroup(group, {
  78377. u,
  78378. v
  78379. })) {
  78380. var index = waitFill.indexOf(group);
  78381. waitFill.splice(index, 1);
  78382. waitFill.count -= group.length;
  78383. group.forEach(e => {
  78384. result.allFills[e.u] || (result.allFills[e.u] = []);
  78385. result.allFills[e.u][e.v] = top; //该组全部都使用该体积
  78386. });
  78387. var sum = top * group.length;
  78388. add(sum, fill, group.length);
  78389. }
  78390. });
  78391. }
  78392. }
  78393. add(top, fill, 1);
  78394. };
  78395. var lastNotifyTime = Date.now();
  78396. //从左到右,从下到上一列列扫描
  78397. var _loop3 = async function _loop3(_u) {
  78398. for (var _v2 = 0; _v2 < _this.renderTarget.height; _v2++) {
  78399. //数据是从图的下到上存储的
  78400. if (interrupt) {
  78401. return {
  78402. v: {
  78403. v: {
  78404. v: computeFinish('1121')
  78405. }
  78406. }
  78407. };
  78408. }
  78409. compute(_u, _v2);
  78410. }
  78411. await notify([[progressStart, progressEnd], [0.7, 1]], () => {
  78412. return _u / _this.renderTarget.width;
  78413. }, 'compute');
  78414. },
  78415. _ret3;
  78416. for (var _u = 0; _u < _this.renderTarget.width; _u++) {
  78417. _ret3 = await _loop3(_u);
  78418. if (_ret3) return _ret3.v;
  78419. }
  78420. if (waitFill.length) {
  78421. console.log('waitFill怎么还有??', waitFill); //如果是模型的话是有剩的可能,当它的周围刚好是模型的hole时,就被断开在孤立的组里了,如"回"字型,中间的口是有model但无点云处,外面的口是无model处。
  78422. }
  78423. result.Vupper *= sDelta;
  78424. result.fillVlower *= sDelta;
  78425. result.fillVupper *= sDelta;
  78426. result.Vlower += result.fillVlower;
  78427. results.push(result);
  78428. deferred && deferred.notify(progressEnd);
  78429. },
  78430. _ret2;
  78431. for (var j = 0; j < cH; j++) {
  78432. _ret2 = await _loop2(j);
  78433. if (_ret2) return _ret2.v;
  78434. }
  78435. },
  78436. _ret;
  78437. for (var i = 0; i < cW; i++) {
  78438. _ret = await _loop(i);
  78439. if (_ret) return _ret.v;
  78440. }
  78441. var Vupper = 0,
  78442. Vlower = 0,
  78443. fillVlower = 0,
  78444. fillVupper = 0;
  78445. results.forEach(c => {
  78446. Vupper += c.Vupper;
  78447. Vlower += c.Vlower;
  78448. fillVlower += c.fillVlower;
  78449. fillVupper += c.fillVupper;
  78450. });
  78451. computeDone({
  78452. highest,
  78453. lowest,
  78454. Vupper,
  78455. Vlower
  78456. }, deferred);
  78457. computeFinish('finish', true);
  78458. console.log({
  78459. Vupper,
  78460. Vlower,
  78461. oldVupper: Vupper - fillVupper,
  78462. oldVlower: Vlower - fillVlower,
  78463. highest,
  78464. lowest,
  78465. horizonZ,
  78466. wDelta
  78467. }, results, this.viewport.resolution, {
  78468. cW,
  78469. cH
  78470. }, 'cost:', Date.now() - timestamp, 'pxPerMetric', pxPerMetric, 'boundSize', boundSize); //firefox用时是chrome两倍,edge和chrome差不多
  78471. }
  78472. getModelZByRes(u, v, cW, cH, wIndex, hIndex) {
  78473. //传入renderTarget2的像素index
  78474. //如果两个map的尺寸不同
  78475. var x = Math.round(wIndex / cW + u / this.renderTarget.width * this.renderTarget2.width);
  78476. var y = Math.round(hIndex / cH + v / this.renderTarget.height * this.renderTarget2.height);
  78477. var z0 = modelZs[x][y];
  78478. return z0;
  78479. //return modelZs[u][v]
  78480. }
  78481. async render() {
  78482. var _this2 = this;
  78483. var {
  78484. i,
  78485. j,
  78486. index,
  78487. cW,
  78488. cH,
  78489. reverseRow,
  78490. infos,
  78491. /* maxLevels, */notifyArea,
  78492. computeFinish
  78493. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  78494. this.view.applyToCamera(this.camera);
  78495. Potree.updatePointClouds(viewer.scene.pointclouds, this.camera, this.viewport.resolution);
  78496. var gl = viewer.renderer.getContext();
  78497. var screenshot = name => {
  78498. //if(window.testScreen){
  78499. var dataUrl = Potree.Utils.renderTargetToDataUrl(this.renderTarget, this.renderTarget.width, this.renderTarget.height, viewer.renderer);
  78500. Common$1.downloadFile(dataUrl, (name || 'screenshot') + '-' + timestamp + '.png'); //为什么图片上不是只有pickWindowSize区域有颜色??
  78501. //}
  78502. };
  78503. var name = i + '-' + j + '-第' + index + '张';
  78504. console.log('开始渲染', name);
  78505. var camera = this.camera;
  78506. var viewport = this.viewport;
  78507. return new Promise((resolve, reject) => {
  78508. var done = async () => {
  78509. gl.clearColor(0, 0, 0, 0);
  78510. viewer.renderer.clear(true, true, true);
  78511. //viewer.pRenderer.renderOctree(pointcloud, nodes, this.camera, this.renderTarget ,{material:this.material});
  78512. viewer.pRenderer.render(viewer.scene.scenePointCloud, this.camera, this.renderTarget, {
  78513. material: this.material /* transparent:!this.computingObject.isPrism */
  78514. });
  78515. if (interrupt) {
  78516. return reject(), computeFinish('re 23');
  78517. }
  78518. Potree.settings.isTest && screenshot(name);
  78519. gl.readPixels(0, 0, this.renderTarget.width, this.renderTarget.height, gl.RGBA, gl.UNSIGNED_BYTE, buffer1); //这句花费最多时间 pc:2-4, 即使只有1*1像素
  78520. notifyArea.push([progressEnd1, 1]);
  78521. var Vupper = 0,
  78522. Vlower = 0;
  78523. var upperHeights = [],
  78524. lowerHeights = [],
  78525. allHeights = [];
  78526. var _loop4 = async function _loop4(u) {
  78527. var col = [];
  78528. for (var v = 0; v < _this2.renderTarget.height; v++) {
  78529. var _v = reverseRow ? _this2.renderTarget.height - v - 1 : v;
  78530. var offset = u + _v * _this2.renderTarget.width;
  78531. var rgb = buffer1.slice(4 * offset, 4 * offset + 3),
  78532. a = buffer1[4 * offset + 3];
  78533. if (a == 0 /* rgb[0] == 0 && rgb[1] == 0 && rgb[2] == 0 */) {
  78534. //无点
  78535. col.push(null);
  78536. } else {
  78537. var z = _this2.convertColorToHeight(rgb, zMin, zMax);
  78538. var h = void 0;
  78539. if (!_this2.computingObject.model) {
  78540. h = z - horizonZ;
  78541. } else {
  78542. //和baseModel标准面之间的高度差
  78543. /* if(a == 128){//负数
  78544. h = -h
  78545. } ///如果这个也要lowest 那需改shader ,shader不计算高度差
  78546. */
  78547. var z0 = _this2.getModelZByRes(u, v, cW, cH, i, j);
  78548. h = z - z0;
  78549. }
  78550. z < lowest && (lowest = z); //上表面最低点
  78551. z > highest && (highest = z); //上表面最高点
  78552. if (h > 0) {
  78553. Vupper += h;
  78554. upperHeights.push(h); //
  78555. } else {
  78556. Vlower += -h;
  78557. lowerHeights.push(h);
  78558. }
  78559. col.push(h);
  78560. }
  78561. if (interrupt) {
  78562. return {
  78563. v: (reject(), computeFinish('re 023'))
  78564. };
  78565. }
  78566. //notify(notifyArea, (u*this.renderTarget.height + v) /(this.renderTarget.width*this.renderTarget.height))
  78567. }
  78568. allHeights.push(col);
  78569. await notify(notifyArea, () => {
  78570. return u / _this2.renderTarget.width;
  78571. }, 'readPixels get');
  78572. },
  78573. _ret4;
  78574. for (var u = 0; u < this.renderTarget.width; u++) {
  78575. _ret4 = await _loop4(u);
  78576. if (_ret4) return _ret4.v;
  78577. }
  78578. Vupper *= sDelta;
  78579. Vlower *= sDelta;
  78580. infos.push({
  78581. Vupper,
  78582. Vlower,
  78583. sDelta,
  78584. upperHeights,
  78585. lowerHeights,
  78586. allHeights
  78587. });
  78588. resolve();
  78589. };
  78590. //let finish , maxTime = 1e6
  78591. var progressEnd1 = math.linearClamp(this.camera.zoom, [1, 1000], [0.8, 0.2]); //放得越大,实际加载的点云相对越少,费时越少
  78592. var notifyArea_ = [...notifyArea, [0, progressEnd1]];
  78593. if (Potree.pointsLoading) {
  78594. //如果有要加载的node
  78595. var curProgress = 0,
  78596. beginTime = Date.now(),
  78597. unloadBefore,
  78598. tryPreLoadTime = Math.round(math.linearClamp(buffer1.length / this.camera.zoom / this.camera.zoom, [50, 10000], [1000, 15000]));
  78599. //console.log('tryPreLoadTime',tryPreLoadTime)
  78600. var decreaseLevel = () => {
  78601. //降点云level
  78602. //暂时先都一起降1
  78603. var pointclouds = viewer.scene.pointclouds.filter(e => e.visibleNodes.length);
  78604. console.log('准备decreaseLevel, numVisiblePoints', Potree.numVisiblePoints, '最小numVisiblePoints占比', 1 / pointclouds.length);
  78605. pointclouds.forEach(e => {
  78606. var percent = e.numVisiblePoints / Potree.numVisiblePoints;
  78607. console.log('numVisiblePoints占总比', e.dataset_id, percent);
  78608. if (percent < 1 / pointclouds.length) return;
  78609. var old = e.maxLevel;
  78610. var levels = e.visibleNodes.map(e => e.getLevel());
  78611. var actMaxLevel = Math.max.apply(null, levels); //实际加载到的最高的node level
  78612. e.maxLevel = actMaxLevel - 1;
  78613. console.warn(e.dataset_id, 'decreaseLevel,新maxLevel', actMaxLevel - 1, '原maxlevel', old);
  78614. //this.material.size = this.getPointsize(e.maxLevel)
  78615. //this.material.size *= 2
  78616. });
  78617. };
  78618. var finish = makeit => {
  78619. //viewer.removeEventListener('overPointBudget',decreaseLevel)
  78620. makeit && done();
  78621. viewer.removeEventListener('update', update);
  78622. viewer.removeEventListener('pointsLoaded', loaded);
  78623. };
  78624. var update = () => {
  78625. Potree.updatePointClouds(viewer.scene.pointclouds, camera, viewport.resolution);
  78626. /* if( Potree.numVisiblePoints > maxPointBudge * 0.9){
  78627. decreaseLevel()
  78628. */
  78629. notify(notifyArea_, () => {
  78630. /* console.log('unloadedGeometry',Potree.unloadedGeometry.length)
  78631. return curProgress */
  78632. /* curProgress = THREE.Math.clamp(Potree.numVisiblePoints/predictPointCount,curProgress,1) //如果decreaseLevel了点会减少,也不管它,就停住吧,反正很快就加载好了
  78633. return curProgress */
  78634. if (!unloadBefore && Date.now() - beginTime < tryPreLoadTime) {
  78635. curProgress = (Date.now() - beginTime) / tryPreLoadTime * 0.5;
  78636. } else {
  78637. if (!unloadBefore) {
  78638. unloadBefore = Potree.unloadedGeometry.length;
  78639. //console.log('unloadBefore', unloadBefore)
  78640. }
  78641. unloadBefore = Math.max(Potree.unloadedGeometry.length, unloadBefore); //unloadedGeometry 刚开始可能越涨越多 - - 所以进度条会卡住
  78642. var curProgress_ = 0.5 + 0.5 * (1 - Potree.unloadedGeometry.length / unloadBefore);
  78643. curProgress = Math.max(curProgress, curProgress_);
  78644. }
  78645. //console.log('curProgress ', curProgress, 'numVisiblePoints', Potree.numVisiblePoints, 'unloadedGeometry',Potree.unloadedGeometry.length)
  78646. return curProgress;
  78647. }, 'loadpoints');
  78648. interrupt && (finish(false), reject(), computeFinish('正在loadPoints,unloadedGeometry个数' + Potree.unloadedGeometry.length)); //曾经遇到遇到bug 不发送pointsLoaded 一直update 一直有3个unloadedGeometry加载不了。。 是否为每个加载的node加个计时?
  78649. };
  78650. viewer.addEventListener('update', update);
  78651. var loaded = () => {
  78652. //点云加载完时(不一定准确)
  78653. console.warn('加载完毕', ' numVisiblePoints', Potree.numVisiblePoints);
  78654. finish(true);
  78655. };
  78656. viewer.addEventListener('pointsLoaded', loaded);
  78657. /* let predictPointCount = Math.round(math.linearClamp(buffer.length, [1e5, maxWidth*maxWidth*4],[1e6, maxPointBudge ]))//最终要加载到的数目
  78658. */
  78659. /* let overTime = ()=>{
  78660. if(document.hidden){
  78661. return setTimeout(overTime, maxTime)
  78662. }
  78663. if(!finish)console.warn('超时, numVisiblePoints', Potree.numVisiblePoints)
  78664. dealDone()
  78665. }
  78666. setTimeout(overTime, maxTime) */
  78667. } else {
  78668. notify(notifyArea_, 1);
  78669. done();
  78670. }
  78671. });
  78672. }
  78673. convertColorToHeight(color, zMin, zMax) {
  78674. var percent = 0;
  78675. var a = 1;
  78676. for (var i = 0; i < 3; i++) {
  78677. a = i == 2 ? a / 255 : a / 256;
  78678. percent += a * color[i];
  78679. }
  78680. var height = (zMax - zMin) * percent;
  78681. return height + zMin;
  78682. }
  78683. getPointsize(maxLevel) {
  78684. //尽量铺满 size单位是米,需要和点云缝隙同宽
  78685. return 0.01; /* adaptive:0.2 */
  78686. var s = /* this.material.spacing */100 / Math.pow(2, maxLevel - 1); //adaptive的话在shader中已经乘了spacing
  78687. console.log('getPointsize', s, 'maxLevel', maxLevel);
  78688. return s; //会不会直接返回1就好?
  78689. //不能太小。假如gl_pointsize计算结果是0.1,那么显示就是1px;当level将级后,放大2倍为0.2,也还是1px,看起来就稀疏了。所以要保证这个数在最大level时gl_pointsize计算结果差不多是1px.(虽然我会在渲染大尺寸面积时降画布尺寸,但不能保证刚刚好,且因点云个数不可控不会降尺寸太狠)
  78690. }
  78691. download(prisms) {
  78692. if (this.prisms.length == 0) {
  78693. return null;
  78694. }
  78695. var visiPointclouds = viewer.scene.pointclouds.filter(e => Potree.Utils.getObjVisiByReason(e, 'datasetSelection'));
  78696. visiPointclouds.sort((a, b) => {
  78697. return a.dataset_id - b.dataset_id;
  78698. }); //缓存需要固定排序好比较
  78699. var data = {
  78700. transformation_matrix: visiPointclouds.map(cloud => {
  78701. var data = {
  78702. id: cloud.dataset_id,
  78703. matrix: new Matrix4().elements,
  78704. //参照downloadNoCrop,给默认值,表示没有最外层裁剪
  78705. visiMatrixes: prisms.map(prism => {
  78706. return {
  78707. matrix: prism.getTransformationMatrix(cloud).elements,
  78708. //剪裁框
  78709. points: prism.points.map(p => {
  78710. return {
  78711. x: p.x,
  78712. y: p.y
  78713. };
  78714. })
  78715. };
  78716. }),
  78717. modelMatrix: new Matrix4().copy(cloud.transformMatrix).transpose().elements
  78718. };
  78719. return data;
  78720. }),
  78721. aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //剪裁空间
  78722. };
  78723. return data;
  78724. }
  78725. //体积多边形棱柱,z需要变换到-0.5 ~ 0.5
  78726. }
  78727. /* VolumeComputer.prototype.setClipBoxes = function(){
  78728. let lastPrisms = []
  78729. return function(){
  78730. let prismPolygons = this.prisms.filter(e=>!e.isNew && e.visible)
  78731. let prismList = [], prismPoints = [], maxPointsCount
  78732. if(prismPolygons.length){
  78733. let pointsCount = prismPolygons.pointsCount = prismPolygons.reduce((w,c)=>{return w+c.points.length},0)
  78734. prismList = new Float32Array(9 * prismPolygons.length);
  78735. prismPoints = new Float32Array(2 * pointsCount);
  78736. prismPolygons.maxPointsCount = 0//单个prism最大点个数
  78737. if(!this.entered)this.enter()
  78738. let pointIndex = 0
  78739. for(let i=0;i<prismPolygons.length;i++ ){
  78740. let bound = prismPolygons[i].prismBound
  78741. let z = prismPolygons[i].horizonZ
  78742. //z = Potree.browser.urlHasValue('zmin',true) || zs[0]
  78743. prismList.set([bound.min.z, z, bound.max.z, bound.min.x, bound.max.x, bound.min.y, bound.max.y, prismPolygons[i].points.length ],9*i);
  78744. //prismList.push(new THREE.Matrix3().fromArray([bound.min.z, z, bound.max.z, bound.min.x, bound.max.x, bound.min.y, bound.max.y, prismPolygons[i].points.length,0 ]))
  78745. for(let j=0;j<prismPolygons[i].points.length;j++){
  78746. prismPoints.set([prismPolygons[i].points[j].x, prismPolygons[i].points[j].y] , 2*j+pointIndex);
  78747. //prismPoints.push( new THREE.Vector2().copy(prismPolygons[i].points[j]))
  78748. }
  78749. pointIndex += 2 * prismPolygons[i].points.length
  78750. prismPolygons.maxPointsCount = Math.max(prismPolygons.maxPointsCount, prismPolygons[i].points.length)
  78751. }
  78752. }
  78753. let doUpdate = ( lastPrisms.length != prismPolygons.length) || lastPrisms.maxPointsCount != prismPolygons.maxPointsCount
  78754. let materials = viewer.scene.pointclouds.map(e=>e.material).concat([this.material])
  78755. materials.forEach(e=>{
  78756. e.uniforms.prismList.value = prismList
  78757. e.uniforms.prismPoints.value = prismPoints
  78758. e.shaderNeedsUpdate = e.shaderNeedsUpdate || doUpdate
  78759. e.prisms = prismPolygons
  78760. })
  78761. //修改obj材质
  78762. this.material.defines.num_prism = this.material.prisms.length//土方量数
  78763. this.material.defines.prismPointCountSum = this.material.prisms.pointsCount //点总个数
  78764. this.material.defines.prism_maxPointsCount = this.material.prisms.maxPointsCount //单个prism最大点个数
  78765. if(doUpdate){
  78766. this.material.needsUpdate = true
  78767. viewer.dispatchEvent('content_changed')
  78768. }
  78769. lastPrisms = prismPolygons
  78770. }
  78771. }(); */
  78772. /*
  78773. 渲染像素pxPerMetric越高,边缘越细腻、准确; 点size越小,越不容易遮盖住下方点云,造成体积偏大。但会不会有底部点云透出来?
  78774. 该版本计算用到两张截图,第一张为整体的俯视图,包括挖方和填方;第二张仅包含填方。
  78775. 缺陷:在补洞时,只利用第一张图的结果,所以整体的挖方会偏多,填方偏少(因为在挖方填方同时存在时,没有分别补挖方和填方,而是放在一起,而上方可能遮盖下方的)
  78776. 尝试过第一张只绘制挖方部分,但是在遍历时就需要多遍历一次,测得的用时更多一些,结果却没变化
  78777. 也尝试过补洞时挖方填方分别补各自的,但这样要考虑更多的东西,用时多了两倍以上。(因为目前规定无论范围内实际有没有点云都补上,非挖即填;如果分开的话,填方边缘也都补上肯定是错的,无法找到挖和填的界限,无法分清是只有挖还是填还是两者均有。如果要探测周围点,耗时很多)
  78778. 如果数据集修改了,土方量需要手动重算。所以场景刷新后显示的体积有可能是错的。
  78779. 之前记的,太麻烦了,延期处理:
  78780. 1 一般情况:我需要记录每个土方量范围内存在的数据集的位置,如
  78781. {datasetId:"1745733728954093568", location:[113.59550104511611, 22.36677932324081, 0] ,orientation: 0.1}
  78782. 如果刷新后土方量范围内存在的数据集发生改变,将重算。
  78783. 数据集也可能显示或隐藏
  78784. 2 其他特殊情况,如裁剪,难以知道裁剪了哪块,所以只能全部重算
  78785. ------------------
  78786. baseModel 基于模型的挖方填方
  78787. 由于模型高度不一致,只能把相机放最高处朝下看,而无法像prism那样在horizonZ处再渲染一张,所以更加不能有多层点云干扰。
  78788. 如模型在一个房间屋顶上方,那么填方会得到两个高度,屋顶和地板的高度,地板是从屋顶的点云缝隙而得。
  78789. 如果模型放房间中间,并不能按理想的那样得到其上的挖方和其下的填方,因为相机朝下看时屋顶会遮住屋底,导致填方减少挖方增多。虽然能在bound底部朝上再拍一张,但若是有更复杂的情况依旧不能保证正确。
  78790. 故需要设置好zMin zMax
  78791. 如果模型有可能很大,但数据集不大,可以将bound只取交集
  78792. */
  78793. class Tween$1 {
  78794. constructor(times, values) {
  78795. this.times = times || [];
  78796. this.values = values || [];
  78797. }
  78798. lerp(t) {
  78799. if (this.times.length == 0) return;
  78800. var i = 0,
  78801. n = this.times.length;
  78802. while (i < n && t > this.times[i]) i++;
  78803. if (i == 0) return this.values[0];
  78804. if (i == n) return this.values[n - 1];
  78805. var ratio = (t - this.times[i - 1]) / (this.times[i] - this.times[i - 1]);
  78806. /* if(this.values[0] instanceof THREE.Vector3 || ) {
  78807. return this.values[i-1].clone().lerp(this.values[i], ratio)
  78808. } else {
  78809. return this.values[i-1] + ratio * (this.values[i] - this.values[i-1])
  78810. } */
  78811. if (typeof this.values[0] == 'number') {
  78812. return this.values[i - 1] + ratio * (this.values[i] - this.values[i - 1]);
  78813. } else {
  78814. var lerpFun = this.values[i - 1].isQuaternion ? 'slerp' : 'lerp';
  78815. return this.values[i - 1].clone()[lerpFun](this.values[i], ratio);
  78816. }
  78817. }
  78818. clone() {
  78819. return Common$1.CloneClassObject(this);
  78820. }
  78821. }
  78822. //有的动画,如小狗,进来如果不play停在第一帧,mesh会错,爪子在前面;但如果都停在第一帧,动作有可能很奇怪
  78823. var tweens = {};
  78824. var maxClipFadeTime = Potree.settings.maxClipFadeTime; //渐变时间 s
  78825. /* const pathStates = new Map */
  78826. //actions中可能包含没有动作的 如TPose
  78827. //包括无动画的模型在内的各项属性的过渡
  78828. var rot90Qua = new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2);
  78829. class AnimationEditor extends EventDispatcher {
  78830. constructor() {
  78831. super();
  78832. this.poseKeys = new Map(); //transform
  78833. this.descKeys = new Map(); //字幕
  78834. this.pathKeys = new Map(); //之前设置好的Path , 优先级高于pose
  78835. this.clipKeys = new Map(); //glb animation actions
  78836. this.duration = 0; //动画时长
  78837. this.time = 0; //当前播放时间
  78838. this.cursorTime = 0; //时间轴指针时间
  78839. this.keepDistance = true; //focus的物体和相机保持不变的距离
  78840. this.poseTransition = false; //pose缓动
  78841. if (Potree.settings.isOfficial) {
  78842. viewer.modules.MergeEditor.bus.addEventListener('changeSelect', () => {
  78843. var targetObject = viewer.modules.MergeEditor.selected;
  78844. targetObject = this.ifContainsModel(targetObject) ? targetObject : null;
  78845. this.setCameraFollow(targetObject);
  78846. });
  78847. }
  78848. }
  78849. addKey(model, keyType, key) {
  78850. var keys = this[keyType + 'Keys'].get(model);
  78851. if (!keys) {
  78852. keys = [];
  78853. }
  78854. var index = keys.findIndex(e => e.time > key.time);
  78855. if (index == -1) {
  78856. index = keys.length;
  78857. }
  78858. keys = [...keys.slice(0, index), key, ...keys.slice(index, keys.length)];
  78859. this[keyType + 'Keys'].set(model, keys);
  78860. this.updateTimeRange();
  78861. }
  78862. removeKey(model, keyType, key) {
  78863. var keys = this[keyType + 'Keys'].get(model);
  78864. if (!keys) return console.warn('removeKey没找到key');
  78865. var index = keys.indexOf(key);
  78866. if (index > -1) {
  78867. if (keyType == 'clip') {
  78868. key.action.stop();
  78869. }
  78870. keys.splice(index, 1);
  78871. this.updateTimeRange();
  78872. }
  78873. }
  78874. reOrderKey(model, keyType, key) {
  78875. this.removeKey(model, keyType, key);
  78876. this.addKey(model, keyType, key);
  78877. }
  78878. at(time, delta, force) {
  78879. var _this$camFollowObject;
  78880. this.dispatchEvent({
  78881. type: 'atTime',
  78882. time
  78883. }); //该时间可以大于本动画持续时间
  78884. this.cursorTime = time;
  78885. /* if(time > this.duration + maxClipFadeTime/2){
  78886. for(let [model, keys] of this.clipKeys){
  78887. model.actions.forEach(a=>a.stop())
  78888. }
  78889. } */
  78890. var maxTime = this.duration + maxClipFadeTime / 2;
  78891. if (time >= maxTime) time = maxTime;
  78892. if (this.time == time && !force) return;
  78893. this.time = time; //真实值
  78894. var oldDisToCam = ((_this$camFollowObject = this.camFollowObject) === null || _this$camFollowObject === void 0 ? void 0 : _this$camFollowObject.length) == 1 && this.keepDistance && this.camFollowObject[0].boundCenter.distanceTo(viewer.mainViewport.view.position);
  78895. var transitionRatio = 0.05 * delta * 60; //渐变系数,越小缓动程度越高,越平滑 //假设标准帧率为60fps,当帧率低时(delta大时) 降低缓动。速度快时缓动太高会偏移路径
  78896. var transitionRatio2 = 0.8 * delta * 60;
  78897. var posePathModels = [];
  78898. [this.poseKeys, this.pathKeys /* , this.clipKeys */].forEach(map => {
  78899. Array.from(map.keys()).forEach(model => {
  78900. posePathModels.includes(model) || posePathModels.push(model);
  78901. });
  78902. });
  78903. /*
  78904. 路径>关键帧。但是如果每条路径开头和结尾以及过渡时没有关键帧,保持路径开头和结尾的姿态
  78905. */
  78906. posePathModels.forEach(model => {
  78907. var pathKeys = this.pathKeys.get(model) || [];
  78908. var poseKeys = this.poseKeys.get(model) || [];
  78909. var atPath; //是否在path中 至多只有一个
  78910. var lastPath;
  78911. var nextPath;
  78912. if (pathKeys.length) {
  78913. pathKeys.find(key => {
  78914. if (key.path.points.length < 2) return;
  78915. var startToFade = key.time - maxClipFadeTime / 2;
  78916. var endFade = key.time + key.dur + maxClipFadeTime / 2;
  78917. atPath = time >= key.time && time <= key.time + key.dur;
  78918. if (atPath) {
  78919. atPath = key; //找到一个就退出
  78920. return true;
  78921. }
  78922. if (key.time + key.dur < time) lastPath = key;else if (key.time > time && !nextPath) nextPath = key;
  78923. });
  78924. }
  78925. if (poseKeys.length) {
  78926. tweens.scale = new Tween$1(poseKeys.map(e => e.time), poseKeys.map(e => e.scale));
  78927. model.scale.copy(tweens.scale.lerp(time));
  78928. } else {
  78929. /* if(pathKeys.length){
  78930. model.quaternion.copy(model.defaultAniPose?.quaternion || new THREE.Quaternion()) //设置路径朝向前要先还原
  78931. } */
  78932. }
  78933. if (atPath) {
  78934. //沿着curve行走,目视curve前方 (参照CameraAnimationCurve,搜quaFromCurveTan)
  78935. var percent = MathUtils.clamp((time - atPath.time) / atPath.dur, 0, 1);
  78936. var {
  78937. position,
  78938. quaternion
  78939. } = this.getPoseAtPathKey(atPath, percent, model); //模型文件先保证其center在脚底,如果要我手动将bound底部对齐路径高度再说
  78940. model.position.copy(position);
  78941. model.quaternion.copy(quaternion);
  78942. model.atPath = atPath;
  78943. } else {
  78944. model.atPath = null;
  78945. poseKeys = poseKeys.slice();
  78946. var addPathToPoseKey = (pathKey, percent) => {
  78947. //把当前前后的path姿态加入帧
  78948. var {
  78949. position,
  78950. quaternion
  78951. } = this.getPoseAtPathKey(pathKey, percent, model);
  78952. var fakeKey = {
  78953. isPath: true,
  78954. time: pathKey.time + pathKey.dur * percent,
  78955. pos: position,
  78956. qua: quaternion
  78957. };
  78958. var index = poseKeys.findIndex(e => e.time > fakeKey.time);
  78959. if (index == -1) {
  78960. index = poseKeys.length;
  78961. }
  78962. poseKeys = [...poseKeys.slice(0, index), fakeKey, ...poseKeys.slice(index, poseKeys.length)];
  78963. };
  78964. lastPath && addPathToPoseKey(lastPath, 1);
  78965. nextPath && addPathToPoseKey(nextPath, 0);
  78966. if (poseKeys.length) {
  78967. tweens.pos = new Tween$1(poseKeys.map(e => e.time), poseKeys.map(e => e.pos));
  78968. model.position.copy(tweens.pos.lerp(time));
  78969. tweens.qua = new Tween$1(poseKeys.map(e => e.time), poseKeys.map(e => e.qua));
  78970. model.quaternion.copy(tweens.qua.lerp(time));
  78971. /* let poseKeys2 = poseKeys.filter(e=>e.isPath)//妈呀为什么这么写我忘了
  78972. if(poseKeys2.length ){
  78973. tweens.qua = new Tween(poseKeys2.map(e=>e.time), poseKeys2.map(e=>e.qua))
  78974. model.quaternion.copy(tweens.qua.lerp(time))
  78975. } */
  78976. }
  78977. }
  78978. if (poseKeys.length || pathKeys.length) {
  78979. model.dispatchEvent('position_changed');
  78980. model.dispatchEvent('rotation_changed');
  78981. }
  78982. });
  78983. var _loop = function _loop(keys) {
  78984. if (keys.length == 0) return 1; // continue
  78985. var weights = keys.map((key, i) => {
  78986. var _keys, _keys2;
  78987. //计算每个动作权重(幅度)。
  78988. /* if(delta == void 0){//无缓动 但会造成和缓动时动作time不同
  78989. return time >= key.time && time <= key.time + key.dur ? 1 : 0
  78990. } */
  78991. key.index_ = i;
  78992. var fadeTimeStart = Math.min(maxClipFadeTime, key.dur, ((_keys = keys[i - 1]) === null || _keys === void 0 ? void 0 : _keys.dur) || maxClipFadeTime) / 2; //过渡时间不超过当前和前一个的 half of dur
  78993. var fadeTimeEnd = Math.min(maxClipFadeTime, key.dur, ((_keys2 = keys[i + 1]) === null || _keys2 === void 0 ? void 0 : _keys2.dur) || maxClipFadeTime) / 2; //过渡时间不超过当前和后一个的 half of dur
  78994. var startTime1 = key.time - fadeTimeStart;
  78995. var endTime1 = key.time + key.dur + fadeTimeEnd;
  78996. var startTime2 = key.time + fadeTimeStart;
  78997. var endTime2 = key.time + key.dur - fadeTimeEnd;
  78998. key.action.tempSW_ = {
  78999. scale: 0,
  79000. weight: 0,
  79001. time: null,
  79002. sameLinks: []
  79003. }, key.tempTime_ = MathUtils.clamp(time - key.time, 0, key.dur); //time - startTime1 //当前动作时间
  79004. key.startTime1 = startTime1;
  79005. key.endTime1 = endTime1;
  79006. if (i == 0 && time < startTime2) {
  79007. //开始前维持第一个动作
  79008. return 1;
  79009. } else if (i == keys.length - 1 && time > endTime2) {
  79010. //所有动作播完后维持最后一个动作
  79011. return 1;
  79012. } else {
  79013. if (time < startTime1 || time > endTime1) return 0; //out bound
  79014. if (time >= startTime2 && time <= endTime2) return 1;
  79015. if (time < startTime2) {
  79016. return Potree.math.linearClamp(time, [startTime1, startTime2], [0, 1]);
  79017. } else {
  79018. return Potree.math.linearClamp(time, [endTime2, endTime1], [1, 0]);
  79019. }
  79020. }
  79021. }); //最多有两个>0的,在过渡
  79022. var animateActions = []; //在播的动作
  79023. keys.forEach((key, i) => {
  79024. weights[i] > 0 && !animateActions.includes(key.action) && (key.action.tempSW_ = {
  79025. scale: 0,
  79026. weight: 0,
  79027. time: null,
  79028. sameLinks: []
  79029. }, animateActions.push(key.action));
  79030. });
  79031. //万一前后是一个动作…… 所以用tempSW_计算总值
  79032. keys.forEach((key, i) => {
  79033. //要找到当前action之前所有不间断的所有key,他们之间要连续播放
  79034. if (animateActions.includes(key.action)) {
  79035. if (key.startTime1 < time) {
  79036. //已播部分的key
  79037. var last = key.action.tempSW_.sameLinks[key.action.tempSW_.sameLinks.length - 1];
  79038. if (last) {
  79039. if (key.index_ == last.index_ + 1 && key.startTime1 <= last.endTime1) {
  79040. //相连
  79041. key.action.tempSW_.sameLinks.push(key);
  79042. } else {
  79043. key.action.tempSW_.sameLinks = [key]; //clear
  79044. }
  79045. } else {
  79046. key.action.tempSW_.sameLinks = [key];
  79047. }
  79048. }
  79049. }
  79050. });
  79051. keys.forEach((key, i) => {
  79052. if (animateActions.includes(key.action)) {
  79053. var weight = weights[i] * key.weight; //权重乘以自身幅度
  79054. if (weight > 0) {
  79055. //最多两个
  79056. key.action.play();
  79057. key.action.paused = true; //停在某帧 //如果没有点击该动作块的话 不停
  79058. key.action.tempSW_.weight += weight;
  79059. key.tempTime_ >= 0 && (key.action.tempSW_.scale = key.speed); //相同动作不允许叠加速度
  79060. if (key.action.tempSW_.time == null) {
  79061. //如果两个动作相同 只需在第一个计算出总和
  79062. var timeSum = 0;
  79063. key.action.tempSW_.sameLinks.forEach(key_ => {
  79064. timeSum += key_.tempTime_ % (key_.action._clip.duration / key_.speed) * key_.speed; //相同动作可能速度不同,算出每个clip的时间
  79065. });
  79066. key.action.tempSW_.time = timeSum % key.action._clip.duration;
  79067. }
  79068. //(老版本,过渡时播放时间会延长一点,有交集):
  79069. //key.action.tempSW_.time == null && (key.action.tempSW_.time = key.tempTime_) //相同动作优先用前一个的时间
  79070. //key.action.tempSW_.scale += key.speed // * weights[i] //乘以weight在开始和结束作为缓动效果好,但是不好计算实时time
  79071. //speed time都没有交集,只有weight有,为了过渡
  79072. }
  79073. } else {
  79074. key.action.stop(); //不启动动画
  79075. }
  79076. });
  79077. animateActions.forEach(action => {
  79078. action.setEffectiveTimeScale(action.tempSW_.scale); //speed 只有没paused时有效 这里都paused的所以没用
  79079. action.setEffectiveWeight(action.tempSW_.weight);
  79080. action.time = action.tempSW_.time; //(action.tempSW_.time % (action._clip.duration / action.tempSW_.scale)) * action.tempSW_.scale //只有paused时有效
  79081. //console.log('action', action._clip.name, action.time, action.weight, action.tempSW_.scale )
  79082. });
  79083. //model.mixer.timeScale = 1 ;
  79084. };
  79085. for (var [model, keys] of this.clipKeys) {
  79086. if (_loop(keys)) continue;
  79087. }
  79088. viewer.objs.children.forEach(obj => {
  79089. var _obj$actions;
  79090. if (!((_obj$actions = obj.actions) !== null && _obj$actions !== void 0 && _obj$actions.length)) return;
  79091. var clipState = obj.actions.map(action => {
  79092. var played = action._mixer._isActiveAction(action);
  79093. var paused = action.paused;
  79094. var time = action.time;
  79095. var weight = action.weight;
  79096. return {
  79097. played,
  79098. paused,
  79099. time,
  79100. weight
  79101. };
  79102. });
  79103. clipState = JSON.stringify(clipState);
  79104. if (obj.clipState != clipState) {
  79105. //动作是否改变
  79106. obj.traverse(e => e.isSkinnedMesh && (e.boundingSphere = null)); //动画会导致bound改变,清空,raycast时重新计算bound,否则hover不到模型
  79107. obj.clipChanged = true;
  79108. }
  79109. obj.clipState = clipState;
  79110. });
  79111. {
  79112. if (this.camFollowObject && !viewer.scene.monitors.some(e => e.isWatching)) {
  79113. //in front of model
  79114. if (this.camFollowObject.length == 1) {
  79115. var _model = this.camFollowObject[0];
  79116. if (viewer.images360.latestRequestMode == 'showPointCloud') {
  79117. if (this.camFaceToObject) {
  79118. var dis = 4;
  79119. var dir = new Vector3(0, 0.1, 1).normalize(); //稍微朝上
  79120. dir.multiplyScalar(dis).applyQuaternion(_model.quaternion);
  79121. var pos = new Vector3().addVectors(_model.boundCenter, dir);
  79122. viewer.mainViewport.view.position.copy(pos);
  79123. viewer.mainViewport.view.lookAt(_model.boundCenter);
  79124. } else if (this.keepDistance) {
  79125. //不改镜头方向 保持一定角度。如果要改镜头方向,把lookAt提前
  79126. viewer.mainViewport.view.position.subVectors(_model.boundCenter, viewer.mainViewport.view.direction.clone().multiplyScalar(oldDisToCam));
  79127. viewer.mainViewport.view.radius = oldDisToCam;
  79128. } else {
  79129. viewer.mainViewport.view.lookAt(_model.boundCenter);
  79130. }
  79131. } else {
  79132. viewer.mainViewport.view.lookAt(_model.boundCenter);
  79133. }
  79134. } else {
  79135. viewer.modules.MergeEditor.focusOn(this.camFollowObject, 0, true /* ,false,dirAve */);
  79136. }
  79137. }
  79138. }
  79139. viewer.dispatchEvent('content_changed');
  79140. }
  79141. getPoseAtPathKey(key, percent, model) {
  79142. var delta = 0.001;
  79143. var percent2 = percent + delta;
  79144. var curve = key.path.curve.clone();
  79145. if (key.reverse) curve.points.reverse();
  79146. var position = curve.getPointAt(percent);
  79147. var pathQua, quaternion;
  79148. if (percent2 <= 1) {
  79149. var position2 = curve.getPointAt(percent2);
  79150. pathQua = math.getQuaFromPosAim(position2, position);
  79151. } else {
  79152. percent2 = percent - delta;
  79153. var _position = curve.getPointAt(percent2);
  79154. pathQua = math.getQuaFromPosAim(position, _position);
  79155. }
  79156. pathQua.multiplyQuaternions(pathQua, rot90Qua); //这是当模型导进来就旋转正确时的quaternion
  79157. key.curQua_ = pathQua.clone(); //记录下
  79158. if (model.quaAtPath) {
  79159. quaternion = new Quaternion().multiplyQuaternions(pathQua, model.quaAtPath);
  79160. } else {
  79161. quaternion = pathQua.clone();
  79162. }
  79163. //model && quaternion.multiplyQuaternions( quaternion, model.quaternion ); //应用当前已有的quaternion
  79164. //如果要将模型底部中心对准路径,需要先修改好模型scale ,然后boundingBox中心应用scale和qua, 加到position里
  79165. //目前两个人物模型刚好模型pivot在脚底,如果是其他物体甚至直接用curve的朝向不太对,没有明确朝向。除非所有模型都保持上路径前的朝向
  79166. //或者pos的z还用之前的
  79167. //产品说位置偏移不管它,因为路径可以隐藏和修改。只要记录相对旋转即可。
  79168. return {
  79169. position,
  79170. quaternion
  79171. };
  79172. }
  79173. getModelQuaAtPath(model) {
  79174. //当前时间在路径上时,旋转模型后立即执行该函数,获取相对旋转值
  79175. if (!model.atPath) return;
  79176. var qua = new Quaternion().multiplyQuaternions(model.atPath.curQua_.clone().invert(), model.quaternion);
  79177. //console.log('getModelQuaAtPath',qua)
  79178. model.quaAtPath = qua; //相对旋转
  79179. return qua;
  79180. }
  79181. play() {
  79182. var {
  79183. time = -maxClipFadeTime / 2
  79184. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  79185. //动画时长比duration多一个maxClipFadeTime,为了给开始和结束动画过渡
  79186. this.updateTimeRange();
  79187. this.playing && this.pause();
  79188. var maxTime = this.duration + maxClipFadeTime / 2;
  79189. this.playing = true;
  79190. this.cursorTime = time;
  79191. this.onUpdate = e => {
  79192. this.cursorTime += e.delta;
  79193. if (!Potree.settings.isOfficial && time > maxTime) this.cursorTime = maxTime;
  79194. this.at(this.cursorTime, e.delta);
  79195. if (!Potree.settings.isOfficial && time > maxTime) {
  79196. this.dispatchEvent('stop');
  79197. for (var [model, keys] of this.clipKeys) {
  79198. model.actions.forEach(a => a.stop());
  79199. }
  79200. this.pause();
  79201. }
  79202. };
  79203. viewer.addEventListener("update_start", this.onUpdate);
  79204. }
  79205. pause() {
  79206. this.playing = false;
  79207. viewer.removeEventListener("update_start", this.onUpdate);
  79208. /* for(let [model, keys] of this.clipKeys){
  79209. model.actions.forEach(a=>a.stop())
  79210. } */
  79211. viewer.dispatchEvent('content_changed');
  79212. }
  79213. setCameraFollow(camFollowObject) {
  79214. //for test
  79215. this.camFollowObject = camFollowObject;
  79216. if (!camFollowObject) return;
  79217. //Potree.settings.displayMode = 'showPointCloud'
  79218. if (!(this.camFollowObject instanceof Array)) {
  79219. //支持相机跟随多个物体,对着bound的中心
  79220. this.camFollowObject = [this.camFollowObject];
  79221. }
  79222. this.camFollowObject = this.camFollowObject.map(object => {
  79223. if (typeof object == 'string') {
  79224. return viewer.objs.children.find(e => e.name == object);
  79225. } else {
  79226. return object;
  79227. }
  79228. });
  79229. }
  79230. updateTimeRange() {
  79231. var maxTime = 0;
  79232. for (var [model, keys] of this.poseKeys) {
  79233. keys.length > 0 && (maxTime = Math.max(maxTime, keys[keys.length - 1].time));
  79234. }
  79235. for (var [_model2, _keys3] of this.clipKeys) {
  79236. _keys3.length > 0 && (maxTime = Math.max(maxTime, _keys3[_keys3.length - 1].time + _keys3[_keys3.length - 1].dur));
  79237. }
  79238. for (var [_model3, _keys4] of this.pathKeys) {
  79239. _keys4.length > 0 && (maxTime = Math.max(maxTime, _keys4[_keys4.length - 1].time + _keys4[_keys4.length - 1].dur));
  79240. }
  79241. this.duration = maxTime; //不算开始和结束动画的过渡时间的话
  79242. /* for(let [model, keys] of this.clipKeys){
  79243. max = Math.max(maxTime, keys[keys.length - 1].time + keys[keys.length - 1].dur)
  79244. } */
  79245. }
  79246. /* removeModelCallback(model){
  79247. this.poseKeys.get
  79248. } */
  79249. /////////////////////////////////
  79250. addPoseKey() {
  79251. var {
  79252. model,
  79253. time,
  79254. index
  79255. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  79256. /* if(replace){
  79257. this.removeKey(model,'pose', index)
  79258. } */
  79259. var keys = this.poseKeys.get(model);
  79260. if (!keys) {
  79261. keys = [];
  79262. }
  79263. var key = {
  79264. time,
  79265. qua: model.quaternion.clone(),
  79266. scale: model.scale.clone(),
  79267. pos: model.position.clone()
  79268. };
  79269. if (index == void 0) index = keys.length;
  79270. keys = [...keys.slice(0, index), key, ...keys.slice(index, keys.length)];
  79271. this.poseKeys.set(model, keys);
  79272. return key;
  79273. }
  79274. addClipKey() {
  79275. var {
  79276. model,
  79277. time,
  79278. index,
  79279. dur,
  79280. actionIndex,
  79281. weight = 1,
  79282. speed = 1 /* , replace */
  79283. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  79284. /* if(replace){
  79285. this.removeKey(model,'clip',index)
  79286. } */
  79287. var keys = this.clipKeys.get(model);
  79288. if (!keys) {
  79289. keys = [];
  79290. }
  79291. var key = {
  79292. time,
  79293. //startTime
  79294. dur,
  79295. action: model.actions[actionIndex],
  79296. speed,
  79297. weight
  79298. };
  79299. if (index == void 0) index = keys.length;
  79300. keys = [...keys.slice(0, index), key, ...keys.slice(index, keys.length)];
  79301. this.clipKeys.set(model, keys);
  79302. }
  79303. addPathKey() {
  79304. var {
  79305. model,
  79306. time,
  79307. index,
  79308. dur,
  79309. path /* , replace */
  79310. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  79311. //what if path is deleted ?
  79312. /* if(replace){
  79313. this.removeKey(model,'path',index)
  79314. } */
  79315. var keys = this.pathKeys.get(model);
  79316. if (!keys) {
  79317. keys = [];
  79318. }
  79319. var key = {
  79320. time,
  79321. //startTime
  79322. dur,
  79323. path
  79324. };
  79325. if (index == void 0) index = keys.length;
  79326. keys = [...keys.slice(0, index), key, ...keys.slice(index, keys.length)];
  79327. this.pathKeys.set(model, keys);
  79328. }
  79329. addDescKey() {
  79330. var {
  79331. model,
  79332. time,
  79333. index,
  79334. dur,
  79335. desc /* , replace */
  79336. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  79337. /* if(replace){
  79338. this.removeKey(model,'desc',index)
  79339. } */
  79340. var keys = this.descKeys.get(model);
  79341. if (!keys) {
  79342. keys = [];
  79343. }
  79344. var key = {
  79345. time,
  79346. //startTime
  79347. dur,
  79348. desc
  79349. };
  79350. if (index == void 0) index = keys.length;
  79351. keys = [...keys.slice(0, index), key, ...keys.slice(index, keys.length)];
  79352. this.descKeys.set(model, keys);
  79353. }
  79354. save() {
  79355. //for test, 注意保证每个模型名字不同
  79356. var data = {
  79357. poseKeys: {},
  79358. clipKeys: {}
  79359. };
  79360. var _loop2 = function _loop2(model) {
  79361. data.clipKeys[model.name] = keys.map(key => {
  79362. return {
  79363. actionIndex: model.actions.indexOf(key.action),
  79364. time: key.time,
  79365. dur: key.dur,
  79366. weight: key.weight,
  79367. speed: key.speed
  79368. };
  79369. });
  79370. };
  79371. for (var [model, keys] of this.clipKeys) {
  79372. _loop2(model);
  79373. }
  79374. for (var [_model4, _keys5] of this.poseKeys) {
  79375. data.poseKeys[_model4.name] = _keys5.map(key => {
  79376. return {
  79377. qua: key.qua.toArray(),
  79378. pos: key.pos.toArray(),
  79379. scale: key.scale.toArray(),
  79380. time: key.time
  79381. };
  79382. });
  79383. }
  79384. console.log(JSON.stringify(data));
  79385. return data;
  79386. }
  79387. buildFromData(data) {
  79388. var _this = this;
  79389. if (typeof data == 'string') {
  79390. data = JSON.parse(data);
  79391. }
  79392. var _loop3 = function _loop3(name) {
  79393. var model = viewer.objs.children.find(e => e.name == name);
  79394. if (!model) {
  79395. console.warn('没找到pose模型', name);
  79396. return 1; // continue
  79397. }
  79398. var keys = data.poseKeys[name].map(e => {
  79399. return {
  79400. qua: new Quaternion().fromArray(e.qua),
  79401. pos: new Vector3().fromArray(e.pos),
  79402. scale: new Vector3().fromArray(e.scale),
  79403. time: e.time
  79404. };
  79405. });
  79406. _this.poseKeys.set(model, keys);
  79407. };
  79408. for (var name in data.poseKeys) {
  79409. if (_loop3(name)) continue;
  79410. }
  79411. var _loop4 = function _loop4(_name) {
  79412. var model = viewer.objs.children.find(e => e.name == _name);
  79413. if (!model) {
  79414. console.warn('没找到clip模型', _name);
  79415. return 1; // continue
  79416. }
  79417. var keys = data.clipKeys[_name].map(e => {
  79418. return {
  79419. action: model.actions[e.actionIndex],
  79420. time: e.time,
  79421. dur: e.dur,
  79422. weight: e.weight,
  79423. speed: e.speed
  79424. };
  79425. });
  79426. _this.clipKeys.set(model, keys);
  79427. };
  79428. for (var _name in data.clipKeys) {
  79429. if (_loop4(_name)) continue;
  79430. }
  79431. }
  79432. ifContainsModel(model) {
  79433. //动画帧里是否包含它
  79434. return [this.poseKeys, this.pathKeys, this.clipKeys].some(e => {
  79435. return e.has(model);
  79436. });
  79437. }
  79438. }
  79439. /*
  79440. function executeCrossFade( startAction, endAction, duration ) {
  79441. // Not only the start action, but also the end action must get a weight of 1 before fading
  79442. // (concerning the start action this is already guaranteed in this place)
  79443. if ( endAction ) {
  79444. setWeight( endAction, 1 );
  79445. endAction.time = 0;
  79446. if ( startAction ) {
  79447. // Crossfade with warping
  79448. startAction.crossFadeTo( endAction, duration, true );
  79449. } else {
  79450. // Fade in
  79451. endAction.fadeIn( duration );
  79452. }
  79453. } else {
  79454. // Fade out
  79455. startAction.fadeOut( duration );
  79456. }
  79457. }
  79458. function setWeight( action, weight ) {
  79459. action.enabled = true;
  79460. window.ani1 || action.setEffectiveTimeScale( 1 );
  79461. action.setEffectiveWeight( weight );
  79462. } */
  79463. /* autoActionSpeed(action){ //要获取这段时间走过的路程很难,还是延期吧. 而且一段动作要对应多个速度不同的位移,是不可能的。
  79464. return dis / dur
  79465. } */
  79466. /*
  79467. 动作自动计算步伐 幅度(weight)或 速度
  79468. timeScale * modelStepSizeRatio * weight = dis / dur
  79469. 速度 每个模型的步长系数 幅度
  79470. 如果人的bone attach 物品,物品就被add到人身上,需要click出物品
  79471. //测试:为人加物体, 需要先选中物品
  79472. let obj = viewer.modules.MergeEditor.selected
  79473. viewer.objs.children.find(e=>e.name == 'Man.glb').skeletonHelper.bones[34].attach(obj); //左手骨和物品绑定
  79474. //viewer.objs.children.find(e=>e.name == 'Soldier.glb').skeletonHelper.bones[9].attach(obj); //右手骨和物品绑定
  79475. obj.updateMatrixWorld()
  79476. obj.dispatchEvent({type:'position_changed',byControl:true })
  79477. obj.dispatchEvent({type:'rotation_changed',byControl:true })
  79478. 物体带动骨骼自动做动作 setAniIK
  79479. */
  79480. var texLoader$g = new TextureLoader();
  79481. var circleGeo = new CircleGeometry(1.45, 100);
  79482. var sphereGeo$1 = new SphereBufferGeometry(0.008, 8, 8);
  79483. var magDisMin = 1; //相机离目标位置的距离的分界线,当离得远时要缩小fov以使看到的视野固定(望远镜效果)
  79484. var magDisMax = 20;
  79485. /* const radius_ = 0.2; //当相机离目标位置的距离>magDistance_时,希望看到的视野的半径
  79486. const maxFov = THREE.Math.radToDeg(Math.atan(radius_ / magDisMin )) * 2//提前计算出当相机离目标位置的距离<magDisMin时的fov,均使用=magDisMin时的fov。只要保证该fov大于主相机的fov就会有放大效果
  79487. */
  79488. var w$2 = 230 / 1.43;
  79489. var maxPX = 1366 * 1024; //ipad pro. 大于这个分辨率的就直接用devicePixelRatio, 如macbook也是
  79490. var width2dPX = Math.round(window.devicePixelRatio >= 2 ? (window.screen.width * window.screen.height >= maxPX ? window.devicePixelRatio / 1.2 : window.devicePixelRatio / 1.5) * w$2 : w$2); //触屏或高分辨率的可能要放大些。但在手机上不能太大
  79491. //console.log('width2dPX', width2dPX)
  79492. var orthoView = new ExtendView();
  79493. class Magnifier extends Object3D {
  79494. //放大镜or望远镜
  79495. constructor(viewer) {
  79496. super();
  79497. this.width = this.height = width2dPX /* * window.devicePixelRatio */;
  79498. this.camera = new PerspectiveCamera(50, 1, 0.01, 10000); //fov aspect near far
  79499. this.camera.up = new Vector3(0, 0, 1);
  79500. this.viewport = new Viewport(null, this.camera, {
  79501. left: 0,
  79502. bottom: 0,
  79503. width: 1,
  79504. height: 1,
  79505. name: 'magnifier',
  79506. cameraLayers: ['magnifierContent'],
  79507. pixelRatio: 1
  79508. });
  79509. this.viewport.setResolution(this.width, this.height, 0, 0);
  79510. {
  79511. var density;
  79512. var sizeType;
  79513. var colorType = new Map();
  79514. var opacityBefore = new Map();
  79515. var sizeBefore = new Map();
  79516. var visiMap = new Map();
  79517. this.viewport.beforeRender = () => {
  79518. viewer.scene.pointclouds.forEach(e => {
  79519. //因为更改pointDensity时会自动变opacity,所以这项最先获取
  79520. visiMap.set(e, e.visible);
  79521. e.visible = Potree.Utils.getObjVisiByReason(e, 'datasetSelection'); //先将隐藏的点云显示
  79522. colorType.set(e, e.material.activeAttributeName);
  79523. opacityBefore.set(e, e.temp.pointOpacity);
  79524. sizeBefore.set(e, e.temp.pointSize);
  79525. });
  79526. //使放大镜里的pointDensity是'magnifier' 最高质量。
  79527. density = Potree.settings.pointDensity;
  79528. Potree.settings.pointDensity = 'magnifier';
  79529. viewer.scene.pointclouds.forEach(e => {
  79530. //因为全景模式的pointSizeType是fixed所以要还原下
  79531. sizeType = e.material.pointSizeType;
  79532. e.material.pointSizeType = Potree.config.material.pointSizeType;
  79533. //材质
  79534. e.material.activeAttributeName = 'rgba';
  79535. e.changePointOpacity(1);
  79536. //e.changePointSize(Potree.config.material.realPointSize, true)
  79537. });
  79538. };
  79539. this.viewport.afterRender = () => {
  79540. Potree.settings.pointDensity = density;
  79541. viewer.scene.pointclouds.forEach(e => {
  79542. e.visible = visiMap.get(e);
  79543. e.material.pointSizeType = sizeType;
  79544. e.material.activeAttributeName = colorType.get(e);
  79545. e.changePointOpacity(opacityBefore.get(e));
  79546. //e.changePointSize(sizeBefore.get(e))
  79547. });
  79548. };
  79549. }
  79550. this.renderTarget = new WebGLRenderTarget(this.width, this.height, {
  79551. minFilter: LinearFilter,
  79552. magFilter: LinearFilter,
  79553. format: RGBAFormat
  79554. /* type: THREE.FloatType,
  79555. minFilter: THREE.NearestFilter,
  79556. magFilter: THREE.NearestFilter,
  79557. */
  79558. });
  79559. this.rtEDL = new WebGLRenderTarget(this.width, this.height, {
  79560. //好像没用到? 因为这里不绘制测量线
  79561. minFilter: NearestFilter,
  79562. magFilter: NearestFilter,
  79563. format: RGBAFormat,
  79564. type: FloatType,
  79565. depthTexture: new DepthTexture(undefined, undefined, UnsignedIntType)
  79566. });
  79567. this.mesh = new Mesh(circleGeo, new MeshBasicMaterial({
  79568. side: DoubleSide,
  79569. map: this.renderTarget.texture,
  79570. transparent: true,
  79571. depthTest: !1
  79572. //depthWrite: !1,
  79573. }));
  79574. this.overlayMesh = new Mesh(circleGeo, new MeshBasicMaterial({
  79575. side: DoubleSide,
  79576. map: texLoader$g.load(Potree.resourcePath + '/textures/crosshair.png'),
  79577. transparent: true,
  79578. depthTest: !1
  79579. //depthWrite: !1,
  79580. }));
  79581. this.targetPoint = new Object3D();
  79582. this.targetPoint.add(new Mesh(sphereGeo$1, new MeshBasicMaterial({
  79583. color: "#ff0000",
  79584. transparent: true,
  79585. opacity: 0.7
  79586. })));
  79587. this.targetPoint.add(new Mesh(sphereGeo$1, new MeshBasicMaterial({
  79588. color: "#ff0000",
  79589. transparent: true,
  79590. opacity: 0.3,
  79591. depthTest: false //被遮挡层
  79592. })));
  79593. this.targetPoint.name = 'magnifierPointTarget';
  79594. viewer.scene.scene.add(this.targetPoint);
  79595. Potree.Utils.setObjectLayers(this.targetPoint, 'magnifierContent');
  79596. this.add(this.mesh);
  79597. this.add(this.overlayMesh);
  79598. this.position.set(-1000, -1000, -100000); //令它看不见
  79599. this.mesh.renderOrder = Potree.config.renderOrders.magnifier;
  79600. this.overlayMesh.renderOrder = Potree.config.renderOrders.magnifier + 1;
  79601. this.aimPos;
  79602. Potree.Utils.setObjectLayers(this, 'magnifier');
  79603. //viewer.inputHandler.addInputListener(this)
  79604. viewer.addEventListener('camera_changed', e => {
  79605. // 平移、滚轮时更新
  79606. if (e.viewport == viewer.mainViewport) this.update(); //不过intersectPoint没更新
  79607. });
  79608. this.mesh.layers.set(Potree.config.renderLayers.magnifier);
  79609. this.overlayMesh.layers.set(Potree.config.renderLayers.magnifier);
  79610. //this.layers.set(Potree.config.renderLayers.magnifier);//这句在外层写没用
  79611. this.dontRender = false;
  79612. viewer.addEventListener('global_drag', e => {
  79613. //拖拽时不渲染。主要是右键平移时渲染延迟了,会闪烁。
  79614. this.dontRender = true;
  79615. });
  79616. viewer.addEventListener('global_drop', e => {
  79617. this.dontRender = false;
  79618. });
  79619. viewer.addEventListener('global_mouseup', e => {
  79620. //测量时拖拽场景再mouseup
  79621. this.dontRender = false;
  79622. });
  79623. var updateVisi = e => {
  79624. if (e.hoverViewport == viewer.mainViewport) {
  79625. Potree.Utils.updateVisible(this, "atViewport", true);
  79626. this.update(e.intersect && e.intersect.location);
  79627. } else {
  79628. Potree.Utils.updateVisible(this, "atViewport", false); //小地图不显示
  79629. }
  79630. };
  79631. viewer.addEventListener('global_mousemove', updateVisi);
  79632. viewer.addEventListener('global_touchstart', updateVisi);
  79633. viewer.addEventListener('updateMagnifier', updateVisi);
  79634. /* viewer.addEventListener("beginSplitView",()=>{
  79635. this.updateVisible("splitView", false)
  79636. })
  79637. viewer.addEventListener("finishSplitView",()=>{
  79638. this.updateVisible("splitView", true)
  79639. }) */
  79640. this.addEventListener("setEnable", e => {
  79641. Potree.Utils.updateVisible(this, "enable", e.value); //界面开关
  79642. /* if(Potree.settings.displayMode == 'showPanos') && e.value){
  79643. Potree.settings.pointDensity = 'magnifier'
  79644. }else if() */
  79645. viewer.dispatchEvent('content_changed');
  79646. });
  79647. if (Potree.settings.isOfficial) {
  79648. Potree.Utils.updateVisible(this, "enable", false);
  79649. } else {
  79650. Potree.Utils.updateVisible(this, "measure", false);
  79651. viewer.addEventListener("measureMovePoint", () => {//测量开始
  79652. //Potree.Utils.updateVisible(this, "measure", true)
  79653. });
  79654. viewer.addEventListener("endMeasureMove", () => {
  79655. Potree.Utils.updateVisible(this, "measure", false);
  79656. viewer.dispatchEvent('content_changed');
  79657. });
  79658. }
  79659. this.addEventListener('isVisible', e => {
  79660. if (!this.visible) Potree.settings.pointDensity = Potree.settings.pointDensity; //恢复pointBudget
  79661. });
  79662. viewer.scene.view.addEventListener('flyingDone', () => {
  79663. if (!this.visible) return;
  79664. var pickWindowSize = 100;
  79665. var intersect = viewer.inputHandler.getIntersect({
  79666. viewport: viewer.mainViewport,
  79667. usePointcloud: true,
  79668. pickWindowSize
  79669. });
  79670. this.update(intersect && intersect.location);
  79671. });
  79672. }
  79673. //注意:在鼠标没有移动的时候,无法获取到最新的intersect, 放大镜内的内容可能是错误的。全景模式下更奇怪,原因未知
  79674. update(aimPos) {
  79675. //相机靠近 navvis的做法
  79676. var dontRender = this.dontRender || !(aimPos instanceof Vector3) || Potree.settings.displayMode == 'showPanos' && viewer.images360.flying;
  79677. aimPos = aimPos instanceof Vector3 ? aimPos : this.aimPos;
  79678. if (!aimPos || !this.visible) return;
  79679. var playerCamera = viewer.scene.getActiveCamera();
  79680. var playerPos = playerCamera.position; //viewer.scene.view.getPivot()
  79681. var dis = playerPos.distanceTo(aimPos);
  79682. var dirToCamera = new Vector3().subVectors(playerPos, aimPos).normalize();
  79683. var fareast = 300;
  79684. //相机位置
  79685. if (playerCamera.type == 'OrthographicCamera') {
  79686. var finalDisToAim = 2;
  79687. } else {
  79688. var finalDisToAim = dis > magDisMin ? dis > fareast ? magDisMax : (dis - magDisMin) / (fareast - magDisMin) * (magDisMax - magDisMin) + magDisMin : dis / 2; //dis>magDistance_ ? magDistance_ : dis / 2;
  79689. }
  79690. this.camera.fov = playerCamera.type == 'OrthographicCamera' ? 30 : playerCamera.fov / 2;
  79691. this.camera.updateProjectionMatrix();
  79692. if (playerCamera.type == 'OrthographicCamera') {
  79693. orthoView.position.copy(aimPos).sub(viewer.mainViewport.view.direction.multiplyScalar(finalDisToAim));
  79694. orthoView.yaw = viewer.mainViewport.view.yaw;
  79695. orthoView.pitch = viewer.mainViewport.view.pitch;
  79696. orthoView.applyToCamera(this.camera);
  79697. } else {
  79698. this.camera.position.copy(aimPos).add(dirToCamera.multiplyScalar(finalDisToAim));
  79699. this.camera.lookAt(aimPos);
  79700. }
  79701. //自身位置
  79702. //let pos2d = viewer.inputHandler.pointer.clone(); //跟随鼠标
  79703. var pos2d_ = Potree.Utils.getPos2d(aimPos, viewer.mainViewport, viewer.renderArea); //更新目标点的实时二维位置
  79704. var pos2d = pos2d_.vector;
  79705. var margin = width2dPX * 1.1 / viewer.mainViewport.resolution2.y * 2; //确保到鼠标的间距占放大镜的比例不变(检查mobile、上下分屏后的变化)
  79706. var screenPos = pos2d.clone().setY(pos2d.y + (pos2d.y > 0 ? -margin : margin));
  79707. var newPos = new Vector3(screenPos.x, screenPos.y, 0.8).unproject(playerCamera); //z:-1朝外
  79708. if (playerCamera.type != 'OrthographicCamera') {
  79709. var dir = newPos.clone().sub(playerPos).normalize().multiplyScalar(10); //这个数值要大于playerCamera.near
  79710. this.position.copy(playerPos.clone().add(dir));
  79711. } else {
  79712. viewer.navCubeViewer.splitScreen.setShiftTarget(viewer.mainViewport, viewer.bound.center);
  79713. viewer.mainViewport.targetPlane.setFromNormalAndCoplanarPoint(viewer.mainViewport.view.direction.clone(), viewer.bound.center);
  79714. viewer.mainViewport.targetPlane.projectPoint(newPos, viewer.mainViewport.shiftTarget);
  79715. this.position.copy(viewer.mainViewport.shiftTarget.clone());
  79716. //this.position.copy(playerPos.clone().add(dir))
  79717. }
  79718. var s = finalDisToAim * this.camera.fov / 30;
  79719. this.quaternion.copy(playerCamera.quaternion);
  79720. this.targetPoint.position.copy(aimPos);
  79721. this.targetPoint.scale.set(s, s, s);
  79722. this.aimPos = aimPos;
  79723. var scale = math.getScaleForConstantSize({
  79724. //
  79725. width2d: width2dPX,
  79726. camera: viewer.scene.getActiveCamera(),
  79727. position: this.getWorldPosition(new Vector3()),
  79728. resolution: viewer.mainViewport.resolution2
  79729. });
  79730. this.scale.set(scale, scale, scale);
  79731. if (!dontRender) {
  79732. this.waitRender = true;
  79733. }
  79734. viewer.dispatchEvent('content_changed');
  79735. }
  79736. /* update(aimPos){ //仅改fov的版本
  79737. aimPos = aimPos instanceof THREE.Vector3 ? aimPos : this.aimPos
  79738. if(!aimPos || !this.visible)return
  79739. //相机位置
  79740. var playerCamera = viewer.scene.getActiveCamera()
  79741. var playerPos = playerCamera.position;//viewer.scene.view.getPivot()
  79742. var dis = playerPos.distanceTo(aimPos);
  79743. if(dis<magDisMin){
  79744. this.camera.fov = maxFov
  79745. }else{
  79746. this.camera.fov = THREE.Math.radToDeg(Math.atan(radius_ / dis )) * 2 //radius_是能看到的范围半径。当dis大于magDisMin时就放大,否则维持fov为maxFov
  79747. }
  79748. this.camera.updateProjectionMatrix()
  79749. this.camera.position.copy(playerPos)
  79750. this.camera.lookAt(aimPos)
  79751. this.quaternion.copy(playerCamera.quaternion);
  79752. let pointer = viewer.inputHandler.pointer.clone();
  79753. let margin = 0.4, maxY = 0.4
  79754. let screenPos = pointer.clone().setY(pointer.y + (pointer.y>maxY ? -margin : margin ))
  79755. let newPos = new THREE.Vector3(screenPos.x,screenPos.y,0.8).unproject(playerCamera); //z:-1朝外
  79756. let dir = newPos.clone().sub(playerPos).normalize().multiplyScalar(10);//这个数值要大于playerCamera.near
  79757. this.position.copy(playerPos.clone().add(dir))
  79758. this.aimPos = aimPos
  79759. this.targetPoint.position.copy(aimPos);
  79760. var scale = math.getScaleForConstantSize({//
  79761. width2d : width2dPX,
  79762. camera:viewer.scene.getActiveCamera(), position: this.getWorldPosition(new THREE.Vector3()),
  79763. resolution: viewer.mainViewport.resolution2
  79764. })
  79765. this.scale.set(scale, scale, scale);
  79766. if(!this.dontRender){
  79767. this.waitRender = true
  79768. }
  79769. }//位置需要计算,不仅仅是点云,所以需要深度图
  79770. */
  79771. render() {
  79772. if (!this.visible || !this.waitRender && !viewer.needRender) return; //viewer.needRender为true要渲染是因为可能是点云node加载完
  79773. viewer.render({
  79774. target: this.renderTarget,
  79775. viewports: [this.viewport],
  79776. camera: this.camera,
  79777. magnifier: true,
  79778. rtEDL: this.rtEDL
  79779. /* width :this.renderTarget.width,
  79780. height: this.renderTarget.height, */
  79781. });
  79782. this.waitRender = false;
  79783. viewer.dispatchEvent('content_changed');
  79784. }
  79785. }
  79786. /*
  79787. 如果遇到放大镜内点云很不正常,应该是深度图错误(可能全景和点云没匹配上)。
  79788. */
  79789. var texLoader$h = new TextureLoader();
  79790. var defaultOpacity = 0.6;
  79791. var Buttons$2 = Potree.defines.Buttons;
  79792. //鼠标指示小圆片
  79793. class Reticule extends Mesh {
  79794. constructor(viewer) {
  79795. var defaultTex = texLoader$h.load(Potree.resourcePath + '/textures/whiteCircle.png' /* reticule-256x256.png' */);
  79796. super(new PlaneBufferGeometry(0.11, 0.11, 1, 1), new MeshBasicMaterial({
  79797. side: DoubleSide,
  79798. map: defaultTex,
  79799. transparent: true,
  79800. depthTest: !1,
  79801. opacity: defaultOpacity
  79802. //depthWrite: !1,
  79803. }));
  79804. this.name = 'reticule';
  79805. this.defaultTex = defaultTex;
  79806. this.crosshairTex = texLoader$h.load(Potree.resourcePath + '/textures/reticule_cross_hair.png');
  79807. this.forbitTex = texLoader$h.load(Potree.resourcePath + '/textures/pic-forbid.png');
  79808. this.defaultTex.anisotropy = 4;
  79809. this.crosshairTex.anisotropy = 4;
  79810. this.forbitTex.anisotropy = 4;
  79811. //this.layers.set(0/* RenderLayers.RETICULE */);
  79812. this.renderOrder = Potree.config.renderOrders.reticule;
  79813. this.layers.set(Potree.config.renderLayers.marker);
  79814. this.direction = new Vector3();
  79815. this.mouseLastMoveTime = Date.now();
  79816. this.hoverViewport;
  79817. this.matrixMap = new Map();
  79818. this.matrixAutoUpdate = false;
  79819. this.hide(0);
  79820. //viewer.inputHandler.addInputListener(this);
  79821. Potree.settings.intersectWhenHover && viewer.addEventListener('global_mousemove', this.move.bind(this));
  79822. //viewer.addEventListener('global_click',this.move.bind(this))
  79823. viewer.addEventListener('global_mousedown', this.move.bind(this)); //主要针对触屏
  79824. this.state = {};
  79825. var startCrossStyle = () => {
  79826. this.state.cross = true;
  79827. this.judgeTex();
  79828. };
  79829. var endCrossStyle = () => {
  79830. this.state.cross = false;
  79831. this.judgeTex();
  79832. };
  79833. viewer.addEventListener('measureMovePoint', startCrossStyle);
  79834. viewer.addEventListener('endMeasureMove', endCrossStyle);
  79835. viewer.addEventListener('startBuildEntity', startCrossStyle);
  79836. viewer.addEventListener('endBuildEntity', endCrossStyle);
  79837. viewer.addEventListener('start_inserting_tag', startCrossStyle);
  79838. viewer.addEventListener('endTagMove', endCrossStyle);
  79839. viewer.addEventListener('reticule_forbit', e => {
  79840. if (this.state.forbit != e.v) {
  79841. console.log('change forbit ', e.v);
  79842. }
  79843. this.state.forbit = e.v;
  79844. this.judgeTex();
  79845. });
  79846. Potree.Utils.setObjectLayers(this, 'sceneObjects');
  79847. }
  79848. judgeTex() {
  79849. if (this.state.forbit) {
  79850. this.material.map = this.forbitTex;
  79851. } else if (this.state.cross) {
  79852. this.material.map = this.crosshairTex;
  79853. } else {
  79854. this.material.map = this.defaultTex;
  79855. }
  79856. viewer.mapViewer && viewer.mapViewer.dispatchEvent({
  79857. type: 'content_changed'
  79858. });
  79859. }
  79860. move(e) {
  79861. if (e.type == "global_mousemove" && (e.isTouch || e.buttons != Buttons$2.NONE) && !this.state.cross) {
  79862. return; //按下时不更新,除非拖拽测量
  79863. }
  79864. this.mouseLastMoveTime = Date.now();
  79865. this.updatePosition(e.intersect, e.hoverViewport);
  79866. }
  79867. hide() {
  79868. var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 500;
  79869. if (this.hidden) return;
  79870. this.hidden = !0;
  79871. transitions.start(lerp.property(this.material, "opacity", 0, () => {
  79872. //progress
  79873. this.dispatchEvent({
  79874. type: 'update'
  79875. });
  79876. //viewer.dispatchEvent('content_changed')
  79877. }), duration, () => {
  79878. //done
  79879. this.dispatchEvent({
  79880. type: 'update',
  79881. visible: false
  79882. });
  79883. });
  79884. this.dispatchEvent({
  79885. type: 'update',
  79886. visible: false
  79887. });
  79888. setTimeout(() => {}, duration);
  79889. }
  79890. show() {
  79891. var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;
  79892. if (!Potree.Utils.getObjVisiByReason(this, 'force')) return;
  79893. //console.log("show Reticule")
  79894. this.hidden = !1;
  79895. if (this.material.opacity <= 0) {
  79896. transitions.start(lerp.property(this.material, "opacity", defaultOpacity, () => {
  79897. //progress
  79898. this.dispatchEvent({
  79899. type: 'update'
  79900. });
  79901. //viewer.dispatchEvent('content_changed')
  79902. }), duration, () => {
  79903. //done
  79904. this.dispatchEvent({
  79905. type: 'update',
  79906. visible: false
  79907. });
  79908. });
  79909. this.dispatchEvent({
  79910. type: 'update',
  79911. visible: true
  79912. });
  79913. }
  79914. }
  79915. //鼠标静止一段时间它就会消失
  79916. updateVisible() {
  79917. Date.now() - this.mouseLastMoveTime > 1500 && !this.hidden && this.hide();
  79918. }
  79919. updateScale(viewport) {
  79920. var s,
  79921. camera = viewport.camera;
  79922. if (camera.type == "OrthographicCamera") {
  79923. var sizeInfo = this.state.cross ? {
  79924. width2d: 500
  79925. } : {
  79926. minSize: 100,
  79927. maxSize: 400,
  79928. nearBound: 100,
  79929. farBound: 700
  79930. };
  79931. s = math.getScaleForConstantSize($.extend(sizeInfo, {
  79932. position: this.position,
  79933. camera,
  79934. resolution: viewport.resolution /* 2 */
  79935. }));
  79936. } else {
  79937. var n = camera.position.distanceTo(this.position);
  79938. s = 0.8 * Math.log2(n + 1); //底数为2 ( Math.log()底数为e )
  79939. if (this.state.cross) {
  79940. //测量时更精细些
  79941. s /= viewer.images360.zoomLevel;
  79942. }
  79943. }
  79944. this.scale.set(s, s, s);
  79945. }
  79946. updateAtViewports(viewport) {
  79947. //当多个viewports时更新。更新大小等
  79948. if (viewport.name == 'magnifier') return;
  79949. if (this.orthoPos && this.hoverViewport && this.hoverViewport.name == 'mapViewport' && viewport != this.hoverViewport) {
  79950. //若是在地图上更新,在其他viewport要隐藏。因为在地图上无法得知高度。
  79951. Potree.Utils.updateVisible(this, 'hoverMap', false);
  79952. return;
  79953. }
  79954. Potree.Utils.updateVisible(this, 'hoverMap', true);
  79955. if (viewport.name == 'mapViewport') {
  79956. Potree.Utils.setObjectLayers(this, "bothMapAndScene");
  79957. } else {
  79958. //通常地图不显示reticule,只有在特殊编辑时才显示
  79959. Potree.Utils.setObjectLayers(this, 'sceneObjects');
  79960. }
  79961. var matrix = this.matrixMap.get(viewport);
  79962. if (!matrix) {
  79963. this.updateScale(viewport);
  79964. this.updateMatrix();
  79965. //this.updateMatrixWorld()
  79966. this.matrixMap.set(viewport, this.matrix.clone());
  79967. } else {
  79968. this.matrix.copy(matrix);
  79969. //this.updateMatrixWorld()
  79970. }
  79971. }
  79972. updatePosition(intersect, viewport) {
  79973. //在地图(当地图融合到viewer时)和场景里都显示且完全相同(大小可能不同)
  79974. if (Potree.Utils.getObjVisiByReason(this, 'force')) {
  79975. //没有被强制隐藏,如进入某个页面后强制不显示
  79976. if (!intersect /* || !intersect.point.normal */) {
  79977. /* let {origin,direction} = viewer.inputHandler.getMouseDirection()//---防止无depthTex的场景全景时画面中只有一个mesh的话会变黑
  79978. intersect = {location:new THREE.Vector3().addVectors(direction, origin), normal:direction} */
  79979. return;
  79980. }
  79981. var atMap = !intersect.location;
  79982. var location = intersect.location || intersect.orthoIntersect.clone();
  79983. var normal;
  79984. this.orthoPos = atMap;
  79985. //地图上要瞬间变化 , 因为要使needRender为true很麻烦
  79986. this.show(atMap ? 0 : 300);
  79987. if (atMap) {
  79988. normal = new Vector3(0, 0, 1); //地图无normal
  79989. location.setZ(0); //低于相机高度即可
  79990. this.direction = normal.clone();
  79991. } else {
  79992. /* if(intersect.point){
  79993. if(intersect.pointcloud){
  79994. normal = new THREE.Vector3().fromArray(intersect.point.normal ).applyMatrix4( intersect.pointcloud.rotateMatrix );
  79995. }else{//mesh
  79996. normal = new THREE.Vector3().copy(intersect.point.normal).applyQuaternion(intersect.object.quaternion)
  79997. }
  79998. }else{
  79999. normal = intersect.normal //when showPanos
  80000. } */
  80001. normal = intersect.normal;
  80002. if (normal) {
  80003. var ratio = /* Potree.settings.useDepthTex ? 1 : */0.2;
  80004. this.direction = this.direction.multiplyScalar(1 - ratio);
  80005. this.direction.add(normal.clone().multiplyScalar(ratio));
  80006. }
  80007. //this.direction = normal.clone() //改为瞬间变化,否则刚hover上某个点时看起来不太对
  80008. }
  80009. this.position.copy(location); /* .add(normal.clone().multiplyScalar(.01)); */
  80010. this.updateMatrix(); //lookAt之前要保证得到matrix
  80011. this.lookAt(this.position.clone().add(this.direction));
  80012. this.hoverViewport = viewport; //记录下最近一次hover过的viewport
  80013. this.updateScale(viewport);
  80014. {
  80015. //存储matrix,节省计算
  80016. this.updateMatrix();
  80017. //this.updateMatrixWorld()
  80018. this.matrixMap.clear(); //重新计算
  80019. this.matrixMap.set(viewport, this.matrix.clone());
  80020. //别处会updateMatrixWorld
  80021. }
  80022. this.dispatchEvent({
  80023. type: 'update'
  80024. });
  80025. //为什么navvis在校准数据集时每个viewport里reticule的朝向都刚好垂直于屏幕,似乎限定在了一定范围内,还是在pick时就只pick范围内的点?
  80026. }
  80027. }
  80028. //navvis在地图等地方看reticule是有厚度的
  80029. /* updateMatrixWorld(force){
  80030. console.log('updateMatrixWorld', force)
  80031. super.updateMatrixWorld(force)
  80032. } */
  80033. }
  80034. /**
  80035. *
  80036. * Supersample Anti-Aliasing Render Pass
  80037. *
  80038. * @author bhouston / http://clara.io/
  80039. *
  80040. * This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
  80041. *
  80042. * References: https://en.wikipedia.org/wiki/Supersampling
  80043. *
  80044. */
  80045. //较为原始的一种抗锯齿 (超级采样抗锯齿)
  80046. var SSAARenderPass = function SSAARenderPass(clearColor, clearAlpha) {
  80047. Pass.call(this);
  80048. //this.scene //= scene;
  80049. //this.camera = camera;
  80050. this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
  80051. this.unbiased = true;
  80052. // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.
  80053. this.clearColor = clearColor !== undefined ? clearColor : 0x000000;
  80054. this.clearAlpha = clearAlpha !== undefined ? clearAlpha : 0;
  80055. this.renderUniforms = {
  80056. bgTex: {
  80057. value: null
  80058. },
  80059. outlineTex: {
  80060. value: null
  80061. },
  80062. opacity: {
  80063. value: 1
  80064. }
  80065. };
  80066. this.renderMat = new ShaderMaterial({
  80067. uniforms: this.renderUniforms,
  80068. vertexShader: CopyShader.vertexShader,
  80069. /* fragmentShader: CopyShader.fragmentShader, */
  80070. fragmentShader: " \n uniform sampler2D bgTex; \n uniform sampler2D outlineTex; \n uniform float opacity;\n varying vec2 vUv;\n void main() {\n vec4 color1 = texture2D( bgTex, vUv );\n vec4 color2 = texture2D( outlineTex, vUv ); \n gl_FragColor = opacity * mix(color1, color2, color2.a) ;\n \n \n } \n ",
  80071. premultipliedAlpha: true,
  80072. blending: AdditiveBlending,
  80073. depthTest: false,
  80074. depthWrite: false,
  80075. transparent: true
  80076. });
  80077. this.renderMat2 = new ShaderMaterial({
  80078. uniforms: UniformsUtils.clone(CopyShader.uniforms),
  80079. vertexShader: CopyShader.vertexShader,
  80080. fragmentShader: "uniform float opacity; \n uniform sampler2D tDiffuse; \n varying vec2 vUv;\n\n void main() {\n \n vec4 texel = texture2D( tDiffuse, vUv ); \n \n if(texel.r == 0.0 && texel.g == 0.0 && texel.b == 0.0){\n discard;\n }else{\n gl_FragColor = opacity * texel;\n }\n } \n ",
  80081. depthTest: false,
  80082. depthWrite: false,
  80083. transparent: true
  80084. });
  80085. ////////////////////
  80086. /* this.renderMat.blendSrc = THREE.OneFactor //即将写入缓冲区的颜色。
  80087. this.renderMat.blendDst = THREE.OneFactor //缓冲区已经存在的颜色
  80088. this.renderMat.blendEquation = THREE.AddEquation;
  80089. this.renderMat.blendEquationAlpha = THREE.AddEquation;
  80090. this.renderMat.blendDstAlpha = THREE.SrcAlphaFactor
  80091. this.renderMat.blendSrcAlpha = THREE.SrcAlphaFactor */
  80092. this.camera2 = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
  80093. this.scene2 = new Scene();
  80094. this.quad2 = new Mesh(new PlaneBufferGeometry(2, 2), this.renderMat /* this.copyMaterial */);
  80095. this.quad2.frustumCulled = false; // Avoid getting clipped
  80096. this.scene2.add(this.quad2);
  80097. this.copyPass = new ShaderPass(CopyShader);
  80098. this.copyPass.renderToScreen = true;
  80099. };
  80100. SSAARenderPass.prototype = Object.assign(Object.create(Pass.prototype), {
  80101. constructor: SSAARenderPass,
  80102. dispose: function dispose() {
  80103. if (this.sampleRenderTarget) {
  80104. this.sampleRenderTarget.dispose();
  80105. this.sampleRenderTarget = null;
  80106. }
  80107. },
  80108. setSize: function setSize(width, height) {
  80109. if (this.sampleRenderTarget) this.sampleRenderTarget.setSize(width, height);
  80110. this.childPass && this.childPass.setSize(width, height);
  80111. },
  80112. addPass: function addPass(pass) {
  80113. this.childPass = pass;
  80114. },
  80115. render: function render(scene, camera, viewports, renderer, writeBuffer, readBuffer, maskActive, renderFun) {
  80116. if (this.useCopy) {
  80117. scene = this.copyPass.scene;
  80118. camera = this.copyPass.camera;
  80119. }
  80120. if (!this.sampleRenderTarget) {
  80121. this.sampleRenderTarget = new WebGLRenderTarget(readBuffer.width, readBuffer.height, {
  80122. minFilter: LinearFilter,
  80123. magFilter: LinearFilter,
  80124. format: RGBAFormat
  80125. });
  80126. this.sampleRenderTarget.texture.name = "SSAARenderPass.sample";
  80127. }
  80128. var jitterOffsets = SSAARenderPass.JitterVectors[Math.max(0, Math.min(this.sampleLevel, 5))];
  80129. var autoClear = renderer.autoClear;
  80130. renderer.autoClear = false;
  80131. var oldClearColor = renderer.getClearColor(new Color()).getHex();
  80132. var oldClearAlpha = renderer.getClearAlpha();
  80133. renderer.setClearColor(this.clearColor, this.clearAlpha);
  80134. var baseSampleWeight = 1.0 / jitterOffsets.length;
  80135. var roundingRange = 1 / 32;
  80136. //this.copyUniforms[ "tDiffuse" ].value = this.sampleRenderTarget.texture;
  80137. var oldTarget = renderer.getRenderTarget();
  80138. if (oldTarget) {
  80139. if (oldTarget.scissorTest) {
  80140. var width = oldTarget.scissor.w,
  80141. height = oldTarget.scissor.z;
  80142. } else {
  80143. var width = oldTarget.width,
  80144. height = oldTarget.height;
  80145. }
  80146. } else {
  80147. var width = readBuffer.width,
  80148. height = readBuffer.height;
  80149. }
  80150. // render the scene multiple times, each slightly jitter offset from the last and accumulate the results.
  80151. var opa = 0;
  80152. for (var i = 0; i < jitterOffsets.length; i++) {
  80153. var jitterOffset = jitterOffsets[i];
  80154. if (camera.setViewOffset) {
  80155. camera.setViewOffset(width, height, jitterOffset[0] * 0.0625, jitterOffset[1] * 0.0625,
  80156. // 0.0625 = 1 / 16
  80157. width, height);
  80158. }
  80159. var sampleWeight = baseSampleWeight;
  80160. if (this.unbiased) {
  80161. //更柔和
  80162. var uniformCenteredDistribution = -0.5 + (i + 0.5) / jitterOffsets.length;
  80163. sampleWeight += roundingRange * uniformCenteredDistribution;
  80164. }
  80165. renderer.setRenderTarget(this.sampleRenderTarget);
  80166. renderer.clear();
  80167. if (this.useCopy) {
  80168. this.copyPass.render(scene, camera, null, renderer, writeBuffer, readBuffer);
  80169. } else {
  80170. if (renderFun) {
  80171. renderFun({
  80172. target: this.sampleRenderTarget
  80173. });
  80174. } else {
  80175. renderer.render(scene, camera);
  80176. }
  80177. }
  80178. renderer.setRenderTarget(oldTarget);
  80179. //---------------------
  80180. //获取outline tex
  80181. var hasOutline = this.childPass && this.childPass.render(scene, camera, renderer, writeBuffer, readBuffer, null, renderFun);
  80182. //合成到该材质
  80183. this.renderUniforms["bgTex"].value = this.sampleRenderTarget.texture;
  80184. this.renderUniforms["outlineTex"].value = hasOutline ? readBuffer.texture : null;
  80185. this.renderUniforms["opacity"].value = sampleWeight;
  80186. /* console.log('sampleWeight', sampleWeight)
  80187. opa += sampleWeight */
  80188. if (!this.renderToScreen) {
  80189. renderer.setRenderTarget(writeBuffer);
  80190. }
  80191. if (i === 0) {
  80192. renderer.setClearColor(0x000000, 0); //叠加前颜色必须0
  80193. renderer.clear();
  80194. }
  80195. renderer.render(this.scene2, this.camera2); // , this.renderToScreen ? null : writeBuffer, ( i === 0 )
  80196. if (!this.renderToScreen) {
  80197. renderer.setRenderTarget(oldTarget);
  80198. }
  80199. //if(i==2)break;
  80200. }
  80201. //console.log('sum:',opa)
  80202. if (camera.clearViewOffset) camera.clearViewOffset();
  80203. //renderer.setRenderTarget(readBuffer)
  80204. //renderer.setClearColor( 0x000000, 0 );
  80205. //renderer.clear()
  80206. /* this.quad2.material = this.renderMat2
  80207. this.renderMat2.uniforms.tDiffuse.value = writeBuffer.texture;
  80208. renderer.render( this.scene2, this.camera2);
  80209. this.quad2.material = this.renderMat */
  80210. //renderer.setRenderTarget(oldTarget)
  80211. renderer.autoClear = autoClear;
  80212. renderer.setClearColor(oldClearColor, oldClearAlpha);
  80213. /* 试了好几次,测量线的透明度还是还原不了。 clearAlpha十分影响结果。
  80214. 因为绘制测量线需要背景透明。 或许可以先全部绘制完后,再 copyshader中 抗锯齿?
  80215. 另外会有黑边。
  80216. */
  80217. }
  80218. });
  80219. // These jitter vectors are specified in integers because it is easier.
  80220. // I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)
  80221. // before being used, thus these integers need to be scaled by 1/16.
  80222. //
  80223. // Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
  80224. SSAARenderPass.JitterVectors = [[[0, 0]], [[4, 4], [-4, -4]], [[-2, -6], [6, -2], [-6, 2], [2, 6]], [[1, -3], [-1, 3], [5, 1], [-3, -5], [-5, 5], [-7, -1], [3, 7], [7, -7]], [[1, 1], [-1, -3], [-3, 2], [4, -1], [-5, -2], [2, 5], [5, 3], [3, -5], [-2, 6], [0, -7], [-4, -6], [-6, 4], [-8, 0], [7, -4], [6, 7], [-7, -8]], [[-4, -7], [-7, -5], [-3, -5], [-5, -4], [-1, -4], [-2, -2], [-6, -1], [-4, 0], [-7, 1], [-1, 2], [-6, 3], [-3, 3], [-7, 6], [-3, 6], [-5, 7], [-1, 7], [5, -7], [1, -6], [6, -5], [4, -4], [2, -3], [7, -2], [1, -1], [4, -1], [2, 1], [6, 2], [0, 4], [4, 4], [2, 5], [7, 5], [5, 6], [3, 7]]];
  80225. class MaskPass extends Pass {
  80226. constructor(scene, camera) {
  80227. super();
  80228. this.scene = scene;
  80229. this.camera = camera;
  80230. this.clear = true;
  80231. this.needsSwap = false;
  80232. this.inverse = false;
  80233. }
  80234. render(renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */) {
  80235. var context = renderer.getContext();
  80236. var state = renderer.state;
  80237. // don't update color or depth
  80238. state.buffers.color.setMask(false);
  80239. state.buffers.depth.setMask(false);
  80240. // lock buffers
  80241. state.buffers.color.setLocked(true);
  80242. state.buffers.depth.setLocked(true);
  80243. // set up stencil
  80244. var writeValue, clearValue;
  80245. if (this.inverse) {
  80246. writeValue = 0;
  80247. clearValue = 1;
  80248. } else {
  80249. writeValue = 1;
  80250. clearValue = 0;
  80251. }
  80252. state.buffers.stencil.setTest(true);
  80253. state.buffers.stencil.setOp(context.REPLACE, context.REPLACE, context.REPLACE);
  80254. state.buffers.stencil.setFunc(context.ALWAYS, writeValue, 0xffffffff);
  80255. state.buffers.stencil.setClear(clearValue);
  80256. state.buffers.stencil.setLocked(true);
  80257. // draw into the stencil buffer
  80258. renderer.setRenderTarget(readBuffer);
  80259. if (this.clear) renderer.clear();
  80260. renderer.render(this.scene, this.camera);
  80261. renderer.setRenderTarget(writeBuffer);
  80262. if (this.clear) renderer.clear();
  80263. renderer.render(this.scene, this.camera);
  80264. // unlock color and depth buffer for subsequent rendering
  80265. state.buffers.color.setLocked(false);
  80266. state.buffers.depth.setLocked(false);
  80267. // only render where stencil is set to 1
  80268. state.buffers.stencil.setLocked(false);
  80269. state.buffers.stencil.setFunc(context.EQUAL, 1, 0xffffffff); // draw if == 1
  80270. state.buffers.stencil.setOp(context.KEEP, context.KEEP, context.KEEP);
  80271. state.buffers.stencil.setLocked(true);
  80272. }
  80273. }
  80274. class ClearMaskPass extends Pass {
  80275. constructor() {
  80276. super();
  80277. this.needsSwap = false;
  80278. }
  80279. render(renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */) {
  80280. renderer.state.buffers.stencil.setLocked(false);
  80281. renderer.state.buffers.stencil.setTest(false);
  80282. }
  80283. }
  80284. /**
  80285. * @author alteredq / http://alteredqualia.com/
  80286. */
  80287. var EffectComposer = function EffectComposer(renderer, renderTarget) {
  80288. this.renderer = renderer;
  80289. if (renderTarget === undefined) {
  80290. var parameters = {
  80291. minFilter: LinearFilter,
  80292. magFilter: LinearFilter,
  80293. format: RGBAFormat,
  80294. stencilBuffer: false
  80295. };
  80296. var size = renderer.getDrawingBufferSize(new Vector2());
  80297. renderTarget = new WebGLRenderTarget(size.width, size.height, parameters);
  80298. renderTarget.texture.name = 'EffectComposer.rt1';
  80299. }
  80300. this.renderTarget1 = renderTarget;
  80301. this.renderTarget2 = renderTarget.clone();
  80302. this.renderTarget2.texture.name = 'EffectComposer.rt2';
  80303. this.writeBuffer = this.renderTarget1;
  80304. this.readBuffer = this.renderTarget2;
  80305. this.passes = [];
  80306. // dependencies
  80307. /* if ( THREE.CopyShader === undefined ) {
  80308. console.error( 'THREE.EffectComposer relies on THREE.CopyShader' );
  80309. }
  80310. if ( THREE.ShaderPass === undefined ) {
  80311. console.error( 'THREE.EffectComposer relies on THREE.ShaderPass' );
  80312. } */
  80313. this.copyPass = new ShaderPass(CopyShader);
  80314. viewer.addEventListener('resize', e => {
  80315. //readTarget的话是渲染一整张的,暂时无法一个个viewport渲染所以不用
  80316. this.readTarget || this.setSize(e.viewport.resolution2.x, e.viewport.resolution2.y); //暂时假设composer渲染的viewer的viewports.length == 1
  80317. });
  80318. };
  80319. Object.assign(EffectComposer.prototype, {
  80320. swapBuffers: function swapBuffers() {
  80321. var tmp = this.readBuffer;
  80322. this.readBuffer = this.writeBuffer;
  80323. this.writeBuffer = tmp;
  80324. },
  80325. addPass: function addPass(pass) {
  80326. this.passes.push(pass);
  80327. var size = this.renderer.getDrawingBufferSize(new Vector2());
  80328. pass.setSize(size.width, size.height);
  80329. },
  80330. removePass: function removePass(pass) {
  80331. //add
  80332. var index = this.passes.indexOf(pass);
  80333. index > -1 && this.passes.splice(index, 1);
  80334. },
  80335. insertPass: function insertPass(pass, index) {
  80336. this.passes.splice(index, 0, pass);
  80337. },
  80338. render: function render(scene, camera, viewports, renderFun) {
  80339. var maskActive = false;
  80340. var passes = this.passes.filter(e => e.enabled);
  80341. var pass,
  80342. i,
  80343. il = passes.length;
  80344. var oldTarget = this.renderer.getRenderTarget();
  80345. if (this.readTarget && oldTarget) {
  80346. //add 使用当前renderTarget中的像素
  80347. this.setSize(oldTarget.width, oldTarget.height); //所有viewports一起渲染,整个画面 因暂时没办法一个个copy
  80348. oldTarget.viewport.set(0, 0, oldTarget.width, oldTarget.height);
  80349. oldTarget.scissorTest = false;
  80350. this.copyPass.render(scene, camera, viewports, this.renderer, this.readBuffer, oldTarget);
  80351. }
  80352. for (i = 0; i < il; i++) {
  80353. pass = passes[i];
  80354. //if(i == il-1)pass.renderToScreen = true//
  80355. pass.render(scene, camera, viewports, this.renderer, this.writeBuffer, this.readBuffer, maskActive, renderFun);
  80356. if (pass.needsSwap) {
  80357. if (maskActive) {
  80358. var context = this.renderer.context;
  80359. context.stencilFunc(context.NOTEQUAL, 1, 0xffffffff);
  80360. this.copyPass.render(null, null, viewports, this.renderer, this.writeBuffer, this.readBuffer); // delta
  80361. context.stencilFunc(context.EQUAL, 1, 0xffffffff);
  80362. }
  80363. this.swapBuffers();
  80364. }
  80365. if (MaskPass !== undefined) {
  80366. if (pass instanceof MaskPass) {
  80367. maskActive = true;
  80368. } else if (pass instanceof ClearMaskPass) {
  80369. maskActive = false;
  80370. }
  80371. }
  80372. }
  80373. this.renderer.setRenderTarget(oldTarget);
  80374. //add
  80375. if (!pass.renderToScreen) {
  80376. //最后一个如果没有绘制到屏幕or target上
  80377. this.copyPass.renderToScreen = true;
  80378. this.copyPass.render(null, null, viewports, this.renderer, this.writeBuffer, this.readBuffer);
  80379. }
  80380. },
  80381. reset: function reset(renderTarget) {
  80382. if (renderTarget === undefined) {
  80383. var size = this.renderer.getDrawingBufferSize(new Vector2());
  80384. renderTarget = this.renderTarget1.clone();
  80385. renderTarget.setSize(size.width, size.height);
  80386. }
  80387. this.renderTarget1.dispose();
  80388. this.renderTarget2.dispose();
  80389. this.renderTarget1 = renderTarget;
  80390. this.renderTarget2 = renderTarget.clone();
  80391. this.writeBuffer = this.renderTarget1;
  80392. this.readBuffer = this.renderTarget2;
  80393. },
  80394. setSize: function setSize(width, height, scaleRatio) {
  80395. scaleRatio = scaleRatio || this.scaleRatio || 1;
  80396. //console.log('setSize', width * scaleRatio, height * scaleRatio)
  80397. var maxTexWidth = 4096;
  80398. var w = width * scaleRatio;
  80399. var h = height * scaleRatio;
  80400. if (w > maxTexWidth || h > maxTexWidth) {
  80401. //超出会崩溃
  80402. if (w > h) {
  80403. scaleRatio = maxTexWidth / width;
  80404. } else {
  80405. scaleRatio = maxTexWidth / height;
  80406. }
  80407. }
  80408. w = width * scaleRatio;
  80409. h = height * scaleRatio;
  80410. this.renderTarget1.setSize(w, h);
  80411. this.renderTarget2.setSize(w, h);
  80412. for (var i = 0; i < this.passes.length; i++) {
  80413. this.passes[i].setSize(w, h);
  80414. }
  80415. }
  80416. });
  80417. /**
  80418. * @author alteredq / http://alteredqualia.com/
  80419. */
  80420. class RenderPass extends Pass {
  80421. constructor(overrideMaterial, clearColor, clearAlpha) {
  80422. super();
  80423. /* this.scene = scene;
  80424. this.camera = camera; */
  80425. this.overrideMaterial = overrideMaterial;
  80426. this.clearColor = clearColor;
  80427. this.clearAlpha = clearAlpha !== undefined ? clearAlpha : 0;
  80428. this.clear = true;
  80429. this.clearDepth = false;
  80430. this.needsSwap = false;
  80431. this._oldClearColor = new Color();
  80432. }
  80433. render(scene, camera, viewports, renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */) {
  80434. var oldAutoClear = renderer.autoClear;
  80435. renderer.autoClear = false;
  80436. var oldClearAlpha, oldOverrideMaterial;
  80437. if (this.overrideMaterial !== undefined) {
  80438. oldOverrideMaterial = this.scene.overrideMaterial;
  80439. scene.overrideMaterial = this.overrideMaterial;
  80440. }
  80441. if (this.clearColor) {
  80442. renderer.getClearColor(this._oldClearColor);
  80443. oldClearAlpha = renderer.getClearAlpha();
  80444. renderer.setClearColor(this.clearColor, this.clearAlpha);
  80445. }
  80446. if (this.clearDepth) {
  80447. renderer.clearDepth();
  80448. }
  80449. var oldTarget = renderer.getRenderTarget();
  80450. if (!this.renderToScreen) renderer.setRenderTarget(readBuffer);
  80451. // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
  80452. if (this.clear) renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil);
  80453. renderer.render(scene, camera);
  80454. if (!this.renderToScreen) renderer.setRenderTarget(oldTarget);
  80455. if (this.clearColor) {
  80456. renderer.setClearColor(this._oldClearColor, oldClearAlpha);
  80457. }
  80458. if (this.overrideMaterial !== undefined) {
  80459. scene.overrideMaterial = oldOverrideMaterial;
  80460. }
  80461. renderer.setRenderTarget(oldTarget);
  80462. renderer.autoClear = oldAutoClear;
  80463. }
  80464. }
  80465. /**
  80466. * NVIDIA FXAA by Timothy Lottes
  80467. * https://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
  80468. * - WebGL port by @supereggbert
  80469. * http://www.glge.org/demos/fxaa/
  80470. * Further improved by Daniel Sturk
  80471. */
  80472. var FXAAShader = {
  80473. uniforms: {
  80474. 'tDiffuse': {
  80475. value: null
  80476. },
  80477. 'resolution': {
  80478. value: new Vector2(1 / 1024, 1 / 512)
  80479. }
  80480. },
  80481. vertexShader: /* glsl */"\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}",
  80482. fragmentShader: "\n\tprecision highp float;\n\n\tuniform sampler2D tDiffuse;\n\n\tuniform vec2 resolution;\n\n\tvarying vec2 vUv;\n\n\t// FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)\n\n\t//----------------------------------------------------------------------------------\n\t// File: es3-keplerFXAAassetsshaders/FXAA_DefaultES.frag\n\t// SDK Version: v3.00\n\t// Email: gameworks@nvidia.com\n\t// Site: http://developer.nvidia.com/\n\t//\n\t// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.\n\t//\n\t// Redistribution and use in source and binary forms, with or without\n\t// modification, are permitted provided that the following conditions\n\t// are met:\n\t// * Redistributions of source code must retain the above copyright\n\t// notice, this list of conditions and the following disclaimer.\n\t// * Redistributions in binary form must reproduce the above copyright\n\t// notice, this list of conditions and the following disclaimer in the\n\t// documentation and/or other materials provided with the distribution.\n\t// * Neither the name of NVIDIA CORPORATION nor the names of its\n\t// contributors may be used to endorse or promote products derived\n\t// from this software without specific prior written permission.\n\t//\n\t// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY\n\t// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\t// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n\t// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n\t// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n\t// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n\t// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n\t// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n\t// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n\t// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n\t// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\t//\n\t//----------------------------------------------------------------------------------\n\n\t#ifndef FXAA_DISCARD\n\t\t\t//\n\t\t\t// Only valid for PC OpenGL currently.\n\t\t\t// Probably will not work when FXAA_GREEN_AS_LUMA = 1.\n\t\t\t//\n\t\t\t// 1 = Use discard on pixels which don't need AA.\n\t\t\t// For APIs which enable concurrent TEX+ROP from same surface.\n\t\t\t// 0 = Return unchanged color on pixels which don't need AA.\n\t\t\t//\n\t\t\t#define FXAA_DISCARD 0\n\t#endif\n\n\t/*--------------------------------------------------------------------------*/\n //\u7B2C\u4E09\u4E2A\u53C2\u6570\u52A0\u5165\u540E\u53EA\u80FD\u5728\u7247\u5143\u7740\u8272\u5668\u4E2D\u8C03\u7528\uFF0C\u4E14\u53EA\u5BF9\u91C7\u6837\u5668\u4E3Amipmap\u7C7B\u578B\u7EB9\u7406\u65F6\u6709\u6548\u3002\u4E0D\u660E\u767D\u4F5C\u7528\uFF1F\uFF1F\uFF1F \u4F46\u8B66\u544A\u8BF4\u8303\u56F4\u572816\u4E4B\u5185\n\t#define FxaaTexTop(t, p) texture2D(t, p, -15.0); //-100.0); \n\t#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -15.0); //-100.0)\n\t/*--------------------------------------------------------------------------*/\n\n\t#define NUM_SAMPLES 5\n\n\t// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha\n\tfloat contrast( vec4 a, vec4 b ) {\n\t\t\tvec4 diff = abs( a - b );\n\t\t\treturn max( max( max( diff.r, diff.g ), diff.b ), diff.a );\n\t}\n\n\t/*============================================================================\n\n\t\t\t\t\t\t\t\t\tFXAA3 QUALITY - PC\n\n\t============================================================================*/\n\n\t/*--------------------------------------------------------------------------*/\n\tvec4 FxaaPixelShader(\n\t\t\tvec2 posM,\n\t\t\tsampler2D tex,\n\t\t\tvec2 fxaaQualityRcpFrame,\n\t\t\tfloat fxaaQualityEdgeThreshold,\n\t\t\tfloat fxaaQualityinvEdgeThreshold\n\t) {\n\t\t\tvec4 rgbaM = FxaaTexTop(tex, posM);\n\t\t\tvec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);\n\t\t\tvec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);\n\t\t\tvec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);\n\t\t\tvec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);\n\t\t\t// . S .\n\t\t\t// W M E\n\t\t\t// . N .\n\n\t\t\tbool earlyExit = max( max( max(\n\t\t\t\t\tcontrast( rgbaM, rgbaN ),\n\t\t\t\t\tcontrast( rgbaM, rgbaS ) ),\n\t\t\t\t\tcontrast( rgbaM, rgbaE ) ),\n\t\t\t\t\tcontrast( rgbaM, rgbaW ) )\n\t\t\t\t\t< fxaaQualityEdgeThreshold;\n\t\t\t// . 0 .\n\t\t\t// 0 0 0\n\t\t\t// . 0 .\n\n\t\t\t#if (FXAA_DISCARD == 1)\n\t\t\t\t\tif(earlyExit) FxaaDiscard;\n\t\t\t#else\n\t\t\t\t\tif(earlyExit) return rgbaM;\n\t\t\t#endif\n\n\t\t\tfloat contrastN = contrast( rgbaM, rgbaN );\n\t\t\tfloat contrastS = contrast( rgbaM, rgbaS );\n\t\t\tfloat contrastE = contrast( rgbaM, rgbaE );\n\t\t\tfloat contrastW = contrast( rgbaM, rgbaW );\n\n\t\t\tfloat relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );\n\t\t\trelativeVContrast *= fxaaQualityinvEdgeThreshold;\n\n\t\t\tbool horzSpan = relativeVContrast > 0.;\n\t\t\t// . 1 .\n\t\t\t// 0 0 0\n\t\t\t// . 1 .\n\n\t\t\t// 45 deg edge detection and corners of objects, aka V/H contrast is too similar\n\t\t\tif( abs( relativeVContrast ) < .3 ) {\n\t\t\t\t\t// locate the edge\n\t\t\t\t\tvec2 dirToEdge;\n\t\t\t\t\tdirToEdge.x = contrastE > contrastW ? 1. : -1.;\n\t\t\t\t\tdirToEdge.y = contrastS > contrastN ? 1. : -1.;\n\t\t\t\t\t// . 2 . . 1 .\n\t\t\t\t\t// 1 0 2 ~= 0 0 1\n\t\t\t\t\t// . 1 . . 0 .\n\n\t\t\t\t\t// tap 2 pixels and see which ones are \"outside\" the edge, to\n\t\t\t\t\t// determine if the edge is vertical or horizontal\n\n\t\t\t\t\tvec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);\n\t\t\t\t\tfloat matchAlongH = contrast( rgbaM, rgbaAlongH );\n\t\t\t\t\t// . 1 .\n\t\t\t\t\t// 0 0 1\n\t\t\t\t\t// . 0 H\n\n\t\t\t\t\tvec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);\n\t\t\t\t\tfloat matchAlongV = contrast( rgbaM, rgbaAlongV );\n\t\t\t\t\t// V 1 .\n\t\t\t\t\t// 0 0 1\n\t\t\t\t\t// . 0 .\n\n\t\t\t\t\trelativeVContrast = matchAlongV - matchAlongH;\n\t\t\t\t\trelativeVContrast *= fxaaQualityinvEdgeThreshold;\n\n\t\t\t\t\tif( abs( relativeVContrast ) < .3 ) { // 45 deg edge\n\t\t\t\t\t\t\t// 1 1 .\n\t\t\t\t\t\t\t// 0 0 1\n\t\t\t\t\t\t\t// . 0 1\n\n\t\t\t\t\t\t\t// do a simple blur\n\t\t\t\t\t\t\treturn mix(\n\t\t\t\t\t\t\t\t\trgbaM,\n\t\t\t\t\t\t\t\t\t(rgbaN + rgbaS + rgbaE + rgbaW) * .25,\n\t\t\t\t\t\t\t\t\t.4\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\thorzSpan = relativeVContrast > 0.;\n\t\t\t}\n\n\t\t\tif(!horzSpan) rgbaN = rgbaW;\n\t\t\tif(!horzSpan) rgbaS = rgbaE;\n\t\t\t// . 0 . 1\n\t\t\t// 1 0 1 -> 0\n\t\t\t// . 0 . 1\n\n\t\t\tbool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );\n\t\t\tif(!pairN) rgbaN = rgbaS;\n\n\t\t\tvec2 offNP;\n\t\t\toffNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n\t\t\toffNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n\n\t\t\tbool doneN = false;\n\t\t\tbool doneP = false;\n\n\t\t\tfloat nDist = 0.;\n\t\t\tfloat pDist = 0.;\n\n\t\t\tvec2 posN = posM;\n\t\t\tvec2 posP = posM;\n\n\t\t\tint iterationsUsed = 0;\n\t\t\tint iterationsUsedN = 0;\n\t\t\tint iterationsUsedP = 0;\n\t\t\tfor( int i = 0; i < NUM_SAMPLES; i++ ) {\n\t\t\t\t\titerationsUsed = i;\n\n\t\t\t\t\tfloat increment = float(i + 1);\n\n\t\t\t\t\tif(!doneN) {\n\t\t\t\t\t\t\tnDist += increment;\n\t\t\t\t\t\t\tposN = posM + offNP * nDist;\n\t\t\t\t\t\t\tvec4 rgbaEndN = FxaaTexTop(tex, posN.xy);\n\t\t\t\t\t\t\tdoneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );\n\t\t\t\t\t\t\titerationsUsedN = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!doneP) {\n\t\t\t\t\t\t\tpDist += increment;\n\t\t\t\t\t\t\tposP = posM - offNP * pDist;\n\t\t\t\t\t\t\tvec4 rgbaEndP = FxaaTexTop(tex, posP.xy);\n\t\t\t\t\t\t\tdoneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );\n\t\t\t\t\t\t\titerationsUsedP = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(doneN || doneP) break;\n\t\t\t}\n\n\n\t\t\tif ( !doneP && !doneN ) return rgbaM; // failed to find end of edge\n\n\t\t\tfloat dist = min(\n\t\t\t\t\tdoneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,\n\t\t\t\t\tdoneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.\n\t\t\t);\n\n\t\t\t// hacky way of reduces blurriness of mostly diagonal edges\n\t\t\t// but reduces AA quality\n\t\t\tdist = pow(dist, .5);\n\n\t\t\tdist = 1. - dist;\n\n\t\t\treturn mix(\n\t\t\t\t\trgbaM,\n\t\t\t\t\trgbaN,\n\t\t\t\t\tdist * .5\n\t\t\t);\n\t}\n\n\tvoid main() {\n\t\t\tconst float edgeDetectionQuality = 0.1 ;//.05 ; //\u8D8A\u9AD8\uFF0C\u8D8A\u4FDD\u7559\u7EC6\u8282\uFF1B\u8D8A\u4F4E\uFF0C\u8D8A\u5E73\u6ED1 \u4F46\u6A21\u7CCA \n\t\t\tconst float invEdgeDetectionQuality = 1. / edgeDetectionQuality;\n\n\t\t\tgl_FragColor = FxaaPixelShader(\n\t\t\t\t\tvUv,\n\t\t\t\t\ttDiffuse,\n\t\t\t\t\tresolution,\n\t\t\t\t\tedgeDetectionQuality, // [0,1] contrast needed, otherwise early discard\n\t\t\t\t\tinvEdgeDetectionQuality\n\t\t\t);\n //\u5355\u72EC\u6E32\u67D3\u6D4B\u91CF\u7EBF\u6709\u9ED1\u8FB9\uFF0C\u56E0\u4E3A\u900F\u660E\u533A\u57DF\u7684clearColor\u662F(0,0,0)\uFF0C\u6A21\u7CCA\u5316\u7684\u65F6\u5019\u91C7\u7528\u4E86\u8FD9\u4E9B\u9ED1\u8272\u56E0\u5B50\u6765\u6DF7\u8272\u3002\u56E0\u4E3A\u6D4B\u91CF\u7EBF\u989C\u8272\u53EF\u80FD\u591A\u79CD\uFF0C\u4E5F\u4E0D\u80FD\u76F4\u63A5\u4FEE\u6539clearColor\u4E3A\u5176\u989C\u8272\uFF0C\u4E14\u8FD8\u6709label\u3002\n //\u6545\u800C\u65E0\u6CD5\u5355\u72EC\u6E32\u67D3\u6D4B\u91CF\u7EBF\uFF0C\u800C\u9700\u8981\u5C06\u5E95\u56FE\u4E00\u8D77\u6E32\u67D3\u3002\n }\n\t"
  80483. };
  80484. /**
  80485. * @author spidersharma / http://eduperiment.com/
  80486. */
  80487. var OutlinePass = function OutlinePass(selectedObjects) {
  80488. /* scene = scene;
  80489. camera = camera; */
  80490. this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
  80491. this.visibleEdgeColor = new Color(1, 1, 1);
  80492. this.hiddenEdgeColor = new Color(0.1, 0.04, 0.02);
  80493. this.edgeGlow = 0.0;
  80494. this.usePatternTexture = false;
  80495. //this.edgeThickness = 1.0;
  80496. this.edgeStrength = 50;
  80497. this.downSampleRatio = 1; //2; // 抗锯齿 值越低renderTarget size越大,抗锯齿越强,线条可越细(或许可以把模糊化去掉?)
  80498. this.pulsePeriod = 0;
  80499. this.showHiddenPart = false; //是否判断被遮住的部分,以设置hiddenEdgeColor。一般不需要
  80500. Pass.call(this);
  80501. this.resolution = new Vector2(256, 256);
  80502. var pars = {
  80503. minFilter: LinearFilter,
  80504. magFilter: LinearFilter,
  80505. format: RGBAFormat
  80506. };
  80507. var resx = Math.round(this.resolution.x / this.downSampleRatio);
  80508. var resy = Math.round(this.resolution.y / this.downSampleRatio);
  80509. this.renderTargetMaskBuffer = new WebGLRenderTarget(this.resolution.x, this.resolution.y, pars);
  80510. this.renderTargetMaskBuffer.texture.name = "OutlinePass.mask";
  80511. this.renderTargetMaskBuffer.texture.generateMipmaps = false;
  80512. this.depthMaterial = new MeshDepthMaterial();
  80513. this.depthMaterial.side = DoubleSide;
  80514. this.depthMaterial.depthPacking = RGBADepthPacking;
  80515. this.depthMaterial.blending = NoBlending;
  80516. this.prepareMaskMaterial = this.getPrepareMaskMaterial();
  80517. this.prepareMaskMaterial.side = DoubleSide;
  80518. this.renderTargetDepthBuffer = new WebGLRenderTarget(this.resolution.x, this.resolution.y, pars);
  80519. this.renderTargetDepthBuffer.texture.name = "OutlinePass.depth";
  80520. this.renderTargetDepthBuffer.texture.generateMipmaps = false;
  80521. this.edgeDetectionMaterial = this.getEdgeDetectionMaterial(this.edgeStrength);
  80522. this.renderTargetEdgeBuffer1 = new WebGLRenderTarget(resx, resy, pars);
  80523. this.renderTargetEdgeBuffer1.texture.name = "OutlinePass.edge1";
  80524. this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
  80525. // Overlay material
  80526. this.overlayMaterial = this.getOverlayMaterial();
  80527. // copy material
  80528. this.copyUniforms = UniformsUtils.clone(CopyShader.uniforms);
  80529. this.copyUniforms["opacity"].value = 1.0;
  80530. this.materialCopy = new ShaderMaterial({
  80531. uniforms: this.copyUniforms,
  80532. vertexShader: CopyShader.vertexShader,
  80533. fragmentShader: CopyShader.fragmentShader,
  80534. blending: NoBlending,
  80535. depthTest: false,
  80536. depthWrite: false,
  80537. transparent: true
  80538. });
  80539. this.enabled = true;
  80540. this.needsSwap = false;
  80541. this.oldClearColor = new Color();
  80542. this.oldClearAlpha = 1;
  80543. this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
  80544. this.scene = new Scene();
  80545. this.quad = new Mesh(new PlaneBufferGeometry(2, 2), null);
  80546. this.quad.frustumCulled = false; // Avoid getting clipped
  80547. this.scene.add(this.quad);
  80548. this.textureMatrix = new Matrix4();
  80549. viewer.addEventListener('viewerResize', e => {
  80550. var size = viewer.renderer.getSize(new Vector2());
  80551. this.renderTargetEdgeBuffer1.setSize(size.x, size.y);
  80552. this.renderTargetMaskBuffer.setSize(size.x, size.y);
  80553. this.resolution.set(size.x, size.y);
  80554. });
  80555. };
  80556. OutlinePass.prototype = Object.assign(Object.create(Pass.prototype), {
  80557. constructor: OutlinePass,
  80558. dispose: function dispose() {
  80559. this.renderTargetMaskBuffer.dispose();
  80560. this.renderTargetEdgeBuffer1.dispose();
  80561. this.renderTargetDepthBuffer.dispose();
  80562. },
  80563. replaceDepthToViewZ(camera) {
  80564. var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
  80565. if (type == this.lastCameraType) return;
  80566. this.lastCameraType = type;
  80567. this.prepareMaskMaterial.fragmentShader = this.prepareMaskMaterial.fragmentShader.replace(/DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ');
  80568. this.prepareMaskMaterial.needsUpdate = true;
  80569. },
  80570. setSize: function setSize(width, height) {},
  80571. changeVisibilityOfSelectedObjects: function changeVisibilityOfSelectedObjects(bVisible) {
  80572. function gatherSelectedMeshesCallBack(object) {
  80573. /* if ( object.isMesh ) { */
  80574. if (object.isPointcloud || object.isMesh || object.isLine || object.isSprite) {
  80575. /* if ( bVisible ) {
  80576. object.visible = object.userData.oldVisible;
  80577. delete object.userData.oldVisible;
  80578. } else {
  80579. object.userData.oldVisible = object.visible;
  80580. object.visible = bVisible;
  80581. } */
  80582. Potree.Utils.updateVisible(object, 'overlinePass', bVisible);
  80583. }
  80584. }
  80585. for (var i = 0; i < this.selectedObjects.length; i++) {
  80586. var selectedObject = this.selectedObjects[i];
  80587. selectedObject.traverse(gatherSelectedMeshesCallBack);
  80588. }
  80589. },
  80590. changeVisibilityOfNonSelectedObjects: function changeVisibilityOfNonSelectedObjects(bVisible, scenes) {
  80591. var selectedMeshes = [];
  80592. function gatherSelectedMeshesCallBack(object) {
  80593. //if ( object.isMesh ) selectedMeshes.push( object );
  80594. if (object.isPointcloud || object.isMesh || object.isLine || object.isSprite) {
  80595. selectedMeshes.push(object);
  80596. }
  80597. }
  80598. for (var i = 0; i < this.selectedObjects.length; i++) {
  80599. var selectedObject = this.selectedObjects[i];
  80600. selectedObject.traverse(gatherSelectedMeshesCallBack);
  80601. }
  80602. function VisibilityChangeCallBack(object) {
  80603. if (object.isPointcloud || object.isMesh || object.isLine || object.isSprite) {
  80604. var bFound = false;
  80605. for (var i = 0; i < selectedMeshes.length; i++) {
  80606. var selectedObjectId = selectedMeshes[i].id;
  80607. if (selectedObjectId === object.id) {
  80608. bFound = true;
  80609. break;
  80610. }
  80611. }
  80612. if (!bFound) {
  80613. var visibility = object.visible;
  80614. Potree.Utils.updateVisible(object, 'overlinePass', bVisible); //add
  80615. //但保不齐在设置为false后,渲染时又true了,所以在其他地方update时设置visible 得用updateVisible
  80616. if (!bVisible) {
  80617. object.visible = false;
  80618. } else {
  80619. object.visible = !!object.bVisible;
  80620. }
  80621. object.bVisible = visibility;
  80622. //这两种updateVisible 和 visible 设置都不能去掉, 第一块是为了防止有的visible不是通过updateVisible设置的; 第二块是为了防止渲染时updateVisible又修改了visible为true, 另外渲染时
  80623. return {
  80624. stopContinue: true
  80625. }; //for pointcloud
  80626. }
  80627. }
  80628. }
  80629. scenes.forEach(scene => scene.traverse(VisibilityChangeCallBack));
  80630. },
  80631. updateTextureMatrix: function updateTextureMatrix(camera) {
  80632. this.textureMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
  80633. this.textureMatrix.multiply(camera.projectionMatrix);
  80634. this.textureMatrix.multiply(camera.matrixWorldInverse);
  80635. },
  80636. render: function render(scenes, camera, viewports, renderer, writeBuffer, readBuffer, maskActive, renderFun) {
  80637. if (!(scenes instanceof Array)) scenes = [scenes];
  80638. if (this.selectedObjects.length > 0 && this.edgeStrength > 0) {
  80639. var render2 = function render2(target) {
  80640. var dontRenderRtEDL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  80641. if (renderFun) {
  80642. renderFun({
  80643. target,
  80644. dontRenderRtEDL
  80645. });
  80646. } else {
  80647. renderer.setRenderTarget(target);
  80648. renderer.clear();
  80649. scenes.forEach(scene => renderer.render(scene, camera));
  80650. }
  80651. };
  80652. this.oldClearColor.copy(renderer.getClearColor(new Color()));
  80653. this.oldClearAlpha = renderer.getClearAlpha();
  80654. var oldAutoClear = renderer.autoClear;
  80655. var oldTarget = renderer.getRenderTarget();
  80656. renderer.autoClear = false;
  80657. if (maskActive) renderer.context.disable(renderer.context.STENCIL_TEST);
  80658. renderer.setClearColor(0xffffff, 1);
  80659. var oldBG = viewer.background,
  80660. oldBgOpacity = viewer.backgroundOpacity;
  80661. viewer.background = new Color(1, 1, 1);
  80662. viewer.backgroundOpacity = 1;
  80663. if (this.showHiddenPart) {
  80664. //几乎不会使用
  80665. viewports.forEach(e => {
  80666. e.oldBeforeRender = e.beforeRender;
  80667. e.beforeRender = () => {
  80668. e.oldBeforeRender && e.oldBeforeRender();
  80669. this.replaceDepthToViewZ(e.camera);
  80670. };
  80671. });
  80672. // Make selected objects invisible
  80673. this.changeVisibilityOfSelectedObjects(false);
  80674. scenes.forEach(scene => {
  80675. scene.currentBackground = scene.background;
  80676. scene.background = null;
  80677. // 1. Draw Non Selected objects in the depth buffer
  80678. scene.overrideMaterial = this.depthMaterial;
  80679. });
  80680. render2(this.renderTargetDepthBuffer);
  80681. // Make selected objects visible
  80682. this.changeVisibilityOfSelectedObjects(true);
  80683. viewports.forEach(e => {
  80684. e.beforeRender = () => {
  80685. e.oldBeforeRender && e.oldBeforeRender();
  80686. // Update Texture Matrix for Depth compare
  80687. this.updateTextureMatrix(e.camera);
  80688. this.prepareMaskMaterial.uniforms["cameraNearFar"].value = new Vector2(e.camera.near, e.camera.far);
  80689. };
  80690. });
  80691. } else {
  80692. //不渲染背景
  80693. scenes.forEach(scene => {
  80694. scene.currentBackground = scene.background;
  80695. scene.background = null;
  80696. });
  80697. }
  80698. var colorType,
  80699. colors = new Map(),
  80700. opas = new Map();
  80701. {
  80702. //绘制选中部分
  80703. // Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
  80704. this.changeVisibilityOfNonSelectedObjects(false, scenes);
  80705. scenes.forEach(scene => {
  80706. scene.overrideMaterial = this.prepareMaskMaterial;
  80707. });
  80708. if (this.showHiddenPart) {
  80709. this.prepareMaskMaterial.uniforms["depthTexture"].value = this.renderTargetDepthBuffer.texture;
  80710. this.prepareMaskMaterial.uniforms["textureMatrix"].value = this.textureMatrix;
  80711. }
  80712. //因为点云不受prepareMaskMaterial作用,所以手动将他们变为黑色不透明
  80713. viewer.scene.pointclouds.forEach(e => {
  80714. //先将点云透明度变为1,因为点云透明度莫名其妙会影响其r值//
  80715. colorType = e.material.activeAttributeName;
  80716. e.material.activeAttributeName = 'color';
  80717. colors.set(e, e.material.color);
  80718. e.material.color = '#000000';
  80719. opas.set(e, e.material.opacity);
  80720. e.material.opacity = 1;
  80721. });
  80722. }
  80723. render2(this.renderTargetMaskBuffer);
  80724. {
  80725. //恢复
  80726. viewer.scene.pointclouds.forEach(e => {
  80727. e.material.activeAttributeName = colorType;
  80728. e.material.color = colors.get(e);
  80729. e.material.opacity = opas.get(e);
  80730. });
  80731. if (this.showHiddenPart) {
  80732. viewports.forEach(e => {
  80733. e.beforeRender = e.oldBeforeRender;
  80734. });
  80735. }
  80736. scenes.forEach(scene => {
  80737. scene.overrideMaterial = null;
  80738. scene.background = scene.currentBackground;
  80739. });
  80740. viewer.background = oldBG;
  80741. viewer.backgroundOpacity = oldBgOpacity;
  80742. this.changeVisibilityOfNonSelectedObjects(true, scenes);
  80743. }
  80744. //检测边缘并绘制
  80745. // 3. Apply Edge Detection Pass
  80746. this.quad.material = this.edgeDetectionMaterial;
  80747. this.edgeDetectionMaterial.uniforms["maskTexture"].value = this.renderTargetMaskBuffer.texture; //this.renderTargetMaskDownSampleBuffer.texture;
  80748. this.edgeDetectionMaterial.uniforms["texSize"].value = new Vector2(this.resolution.x, this.resolution.y); //new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
  80749. //this.edgeDetectionMaterial.uniforms[ "texSize" ].value = new THREE.Vector2(this.renderTargetMaskBuffer.width, this.renderTargetMaskBuffer.height)//new THREE.Vector2( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
  80750. this.edgeDetectionMaterial.uniforms["edgeStrength"].value = this.edgeStrength;
  80751. this.edgeDetectionMaterial.uniforms["visibleEdgeColor"].value = this.visibleEdgeColor; //this.tempPulseColor1;
  80752. this.edgeDetectionMaterial.uniforms["hiddenEdgeColor"].value = this.hiddenEdgeColor; //this.tempPulseColor2;
  80753. var buffer;
  80754. if (this.renderToScreen) {
  80755. this.quad.material.transparent = true;
  80756. buffer = null;
  80757. renderer.setClearColor(this.oldClearColor, this.oldClearAlpha);
  80758. render2(null, false); //普通绘制原场景
  80759. //绘制到全屏
  80760. var renderSize = renderer.getSize(new Vector2()); //是client大小
  80761. renderer.setViewport(0, 0, renderSize.x, renderSize.y); //规定视口,影响图形变换(画布的使用范围)
  80762. renderer.setScissorTest(false);
  80763. } else {
  80764. buffer = readBuffer;
  80765. renderer.setClearColor(0x000000, 0);
  80766. renderer.clear();
  80767. }
  80768. renderer.setRenderTarget(buffer);
  80769. renderer.render(this.scene, this.camera); //将边缘覆盖上去
  80770. renderer.setRenderTarget(oldTarget);
  80771. renderer.setClearColor(this.oldClearColor, this.oldClearAlpha);
  80772. renderer.autoClear = oldAutoClear;
  80773. return true;
  80774. }
  80775. },
  80776. getPrepareMaskMaterial: function getPrepareMaskMaterial() {
  80777. if (this.showHiddenPart) {
  80778. return new ShaderMaterial({
  80779. uniforms: {
  80780. "depthTexture": {
  80781. value: null
  80782. },
  80783. "cameraNearFar": {
  80784. value: new Vector2(0.5, 0.5)
  80785. },
  80786. "textureMatrix": {
  80787. value: new Matrix4()
  80788. }
  80789. },
  80790. vertexShader: ['varying vec4 projTexCoord;', 'varying vec4 vPosition;', 'uniform mat4 textureMatrix;', 'void main() {', ' vPosition = modelViewMatrix * vec4( position, 1.0 );', ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', ' projTexCoord = textureMatrix * worldPosition;', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}'].join('\n'),
  80791. fragmentShader: ['#include <packing>', 'varying vec4 vPosition;', 'varying vec4 projTexCoord;', 'uniform sampler2D depthTexture;', 'uniform vec2 cameraNearFar;', 'void main() {', ' float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));', ' float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );', ' float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;',
  80792. //决定是否为hiddenPart
  80793. ' gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);', '}'].join('\n')
  80794. }); //没有绘制部分的颜色是clearColor,255
  80795. } else {
  80796. return new MeshBasicMaterial({
  80797. color: '#000000'
  80798. }); //不检测深度,不判断遮挡
  80799. }
  80800. },
  80801. getEdgeDetectionMaterial: function getEdgeDetectionMaterial(edgeStrength) {
  80802. return new ShaderMaterial({
  80803. uniforms: {
  80804. "edgeStrength": {
  80805. value: edgeStrength
  80806. },
  80807. "maskTexture": {
  80808. value: null
  80809. },
  80810. "texSize": {
  80811. value: new Vector2(10, 10)
  80812. },
  80813. "visibleEdgeColor": {
  80814. value: new Vector3(1.0, 1.0, 1.0)
  80815. },
  80816. "hiddenEdgeColor": {
  80817. value: new Vector3(1.0, 1.0, 1.0)
  80818. }
  80819. },
  80820. vertexShader: "varying vec2 vUv;\n\
  80821. void main() {\n\
  80822. vUv = uv;\n\
  80823. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  80824. }",
  80825. /* fragmentShader:
  80826. "varying vec2 vUv;\
  80827. uniform sampler2D maskTexture;\
  80828. uniform vec2 texSize;\
  80829. uniform vec3 visibleEdgeColor;\
  80830. uniform vec3 hiddenEdgeColor;\
  80831. \
  80832. void main() {\n\
  80833. vec2 invSize = 1.0 / texSize;\
  80834. vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\
  80835. vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\
  80836. vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\
  80837. vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\
  80838. vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\
  80839. float diff1 = (c1.r - c2.r)*0.5;\
  80840. float diff2 = (c3.r - c4.r)*0.5;\
  80841. float d = length( vec2(diff1, diff2) );\
  80842. float a1 = min(c1.g, c2.g);\
  80843. float a2 = min(c3.g, c4.g);\
  80844. float visibilityFactor = min(a1, a2);\
  80845. vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\
  80846. gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\
  80847. }" */
  80848. fragmentShader: "varying vec2 vUv;\n\t\t\t\tuniform sampler2D maskTexture;\n uniform float edgeStrength;\n\t\t\t\tuniform vec2 texSize;\n\t\t\t\tuniform vec3 visibleEdgeColor;\n\t\t\t\tuniform vec3 hiddenEdgeColor;\n\t\t\t\t\n\t\t\t\tvoid main() { \n const float thickness = 1.0;\n vec2 invSize = thickness / texSize;\n\t\t\t\t\tvec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\n\t\t\t\t\tvec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\n\t\t\t\t\tvec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\n\t\t\t\t\tvec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\n\t\t\t\t\tvec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\n\t\t\t\t\tfloat diff1 = (c1.r - c2.r)*0.5; //\u68C0\u6D4B\u8FB9\u7F18\uFF0C\n\t\t\t\t\tfloat diff2 = (c3.r - c4.r)*0.5;\n\t\t\t\t\tfloat d = length( vec2(diff1, diff2) ) * edgeStrength;\n\t\t\t\t\tfloat a1 = min(c1.g, c2.g);\n\t\t\t\t\tfloat a2 = min(c3.g, c4.g);\n\t\t\t\t\tfloat visibilityFactor = min(a1, a2); //\u68C0\u6D4B\u6DF1\u5EA6\u503C\uFF0C\u662F\u5426\u88AB\u906E\u6321\n\t\t\t\t\tvec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\n\t\t\t\t\t//gl_FragColor = vec4(0.0,1.0,0.0,1.0); \n gl_FragColor = vec4(edgeColor, 1.0) * vec4(d); \n\t\t\t\t}"
  80849. });
  80850. //为什么vec4(0.0,1.0,1.0,1.0); 显示出来的是rgb(109,255,255) ? 几乎只有绿色通道会影响红色通道
  80851. },
  80852. getSeperableBlurMaterial: function getSeperableBlurMaterial(maxRadius) {
  80853. return new ShaderMaterial({
  80854. defines: {
  80855. "MAX_RADIUS": maxRadius
  80856. },
  80857. uniforms: {
  80858. "colorTexture": {
  80859. value: null
  80860. },
  80861. "texSize": {
  80862. value: new Vector2(0.5, 0.5)
  80863. },
  80864. "direction": {
  80865. value: new Vector2(0.5, 0.5)
  80866. },
  80867. "kernelRadius": {
  80868. value: 1.0
  80869. }
  80870. },
  80871. vertexShader: "varying vec2 vUv;\n\
  80872. void main() {\n\
  80873. vUv = uv;\n\
  80874. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  80875. }",
  80876. fragmentShader: "#include <common>\
  80877. varying vec2 vUv;\
  80878. uniform sampler2D colorTexture;\
  80879. uniform vec2 texSize;\
  80880. uniform vec2 direction;\
  80881. uniform float kernelRadius;\
  80882. \
  80883. float gaussianPdf(in float x, in float sigma) {\
  80884. return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\
  80885. }\
  80886. void main() {\
  80887. vec2 invSize = 1.0 / texSize;\
  80888. float weightSum = gaussianPdf(0.0, kernelRadius);\
  80889. vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
  80890. vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\
  80891. vec2 uvOffset = delta;\
  80892. for( int i = 1; i <= MAX_RADIUS; i ++ ) {\
  80893. float w = gaussianPdf(uvOffset.x, kernelRadius);\
  80894. vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\
  80895. vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\
  80896. diffuseSum += ((sample1 + sample2) * w);\
  80897. weightSum += (2.0 * w);\
  80898. uvOffset += delta;\
  80899. }\
  80900. gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\
  80901. }"
  80902. });
  80903. },
  80904. getOverlayMaterial: function getOverlayMaterial() {
  80905. //对边缘线进一步处理,已被废弃
  80906. return new ShaderMaterial({
  80907. uniforms: {
  80908. "maskTexture": {
  80909. value: null
  80910. },
  80911. "edgeTexture1": {
  80912. value: null
  80913. },
  80914. "edgeTexture2": {
  80915. value: null
  80916. },
  80917. "patternTexture": {
  80918. value: null
  80919. },
  80920. "edgeStrength": {
  80921. value: 1.0
  80922. },
  80923. "edgeGlow": {
  80924. value: 1.0
  80925. },
  80926. "usePatternTexture": {
  80927. value: 0.0
  80928. }
  80929. },
  80930. vertexShader: "varying vec2 vUv;\n\
  80931. void main() {\n\
  80932. vUv = uv;\n\
  80933. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  80934. }",
  80935. /* fragmentShader:
  80936. "varying vec2 vUv;\
  80937. uniform sampler2D maskTexture;\
  80938. uniform sampler2D edgeTexture1;\
  80939. uniform sampler2D edgeTexture2;\
  80940. uniform sampler2D patternTexture;\
  80941. uniform float edgeStrength;\
  80942. uniform float edgeGlow;\
  80943. uniform bool usePatternTexture;\
  80944. \
  80945. void main() {\
  80946. vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\
  80947. vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\
  80948. vec4 maskColor = texture2D(maskTexture, vUv);\
  80949. vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\
  80950. float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\
  80951. vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\
  80952. vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\ // 删除 * maskColor.r 也就是去掉遮罩,使模型部分也有outline
  80953. if(usePatternTexture)\
  80954. finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\
  80955. gl_FragColor = finalColor;\
  80956. }", */
  80957. fragmentShader: "varying vec2 vUv; \n\t\t\t\tuniform sampler2D edgeTexture1; \n\t\t\t\tuniform float edgeStrength; \n\t\t\t\t \n\t\t\t\tvoid main() { \n\t\t\t\t\tgl_FragColor = edgeStrength * texture2D(edgeTexture1, vUv); \n\t\t\t\t}",
  80958. blending: AdditiveBlending,
  80959. depthTest: false,
  80960. depthWrite: false,
  80961. transparent: true
  80962. });
  80963. }
  80964. });
  80965. OutlinePass.BlurDirectionX = new Vector2(1.0, 0.0);
  80966. OutlinePass.BlurDirectionY = new Vector2(0.0, 1.0);
  80967. /*
  80968. 渲染步骤:(没有showHiddenPart时)
  80969. 仅绘制选中部分,材质为普通的单色材质,颜色是黑色不透明。未绘制部分的clearColor是白色不透明。
  80970. (详见prepareMaskMaterial,输出的r要为0)
  80971. 然后在上面绘制的图中,根据r的差值,得到边缘线。
  80972. 正常绘制场景之后,将上面的边缘线覆盖于其上。
  80973. (如果showHiddenPart,最开始还要先隐藏选中部分,这是为了得到非选中部分的深度值,然后再绘制选中部分时去比较选中和非选中部分之间的深度差异。以判断是否被遮挡。)
  80974. */
  80975. /**
  80976. * @author mschuetz / http://mschuetz.at
  80977. *
  80978. * adapted from THREE.OrbitControls by
  80979. *
  80980. * @author qiao / https://github.com/qiao
  80981. * @author mrdoob / http://mrdoob.com
  80982. * @author alteredq / http://alteredqualia.com/
  80983. * @author WestLangley / http://github.com/WestLangley
  80984. * @author erich666 / http://erichaines.com
  80985. *
  80986. *
  80987. *
  80988. */
  80989. var standartMinRadius = 2;
  80990. window.camRatio = 1850;
  80991. class OrbitControls extends EventDispatcher {
  80992. constructor(viewer, viewport) {
  80993. super();
  80994. this.viewer = viewer;
  80995. this.renderer = viewer.renderer;
  80996. this.scene = null;
  80997. this.sceneControls = new Scene();
  80998. this.rotationSpeed = 3; //旋转速度
  80999. viewport = viewport || viewer.viewports[0];
  81000. this.setCurrentViewport({
  81001. hoverViewport: viewport,
  81002. force: true
  81003. }); //this.currentViewport = viewport
  81004. this.fadeFactor = 20;
  81005. this.yawDelta = 0;
  81006. this.pitchDelta = 0;
  81007. this.panDelta = new Vector2(0, 0);
  81008. this.radiusDelta = 0;
  81009. this.doubleClockZoomEnabled = true;
  81010. this.tweens = [];
  81011. this.dollyStart = new Vector2();
  81012. this.dollyEnd = new Vector2();
  81013. this.minRadius = standartMinRadius;
  81014. this.maxRadius = 300;
  81015. this.keys = {
  81016. FORWARD: ['W'.charCodeAt(0), 38],
  81017. BACKWARD: ['S'.charCodeAt(0), 40],
  81018. LEFT: ['A'.charCodeAt(0), 37],
  81019. RIGHT: ['D'.charCodeAt(0), 39],
  81020. UP: ['Q'.charCodeAt(0)],
  81021. DOWN: ['E'.charCodeAt(0)]
  81022. };
  81023. var drag = e => {
  81024. if (!this.enabled) return;
  81025. var viewport = e.dragViewport;
  81026. if (!viewport /* || viewport.camera.type == "OrthographicCamera" */) return;
  81027. //let camera = viewport.camera
  81028. /* if (e.drag.object !== null) {
  81029. return;
  81030. } */
  81031. var mode;
  81032. if (e.isTouch) {
  81033. if (e.touches.length == 1) {
  81034. mode = 'rotate';
  81035. } else {
  81036. mode = 'scale-pan';
  81037. }
  81038. } else {
  81039. mode = e.buttons === Potree.defines.Buttons.LEFT ? 'rotate' : 'pan';
  81040. }
  81041. if (e.drag.startHandled === undefined) {
  81042. e.drag.startHandled = true;
  81043. this.dispatchEvent({
  81044. type: 'start'
  81045. });
  81046. }
  81047. var ndrag = e.drag.pointerDelta.clone(); //.add(new THREE.Vector2(1,1)).multiplyScalar(0.5)
  81048. ndrag.y *= -1;
  81049. if (mode == 'rotate') {
  81050. this.yawDelta += ndrag.x * this.rotationSpeed;
  81051. this.pitchDelta += ndrag.y * this.rotationSpeed;
  81052. } else if (mode == 'pan') {
  81053. if (!this.dragStarted) this.updateRadius('startPan');
  81054. this.panDelta.x += ndrag.x;
  81055. this.panDelta.y += ndrag.y;
  81056. } else if (mode == 'scale-pan') {
  81057. //add
  81058. this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  81059. var scale = this.dollyEnd.length() / this.dollyStart.length();
  81060. this.dollyStart.copy(this.dollyEnd);
  81061. this.radiusDelta = (1 - scale) * this.currentViewport.view.radius;
  81062. //------------------------
  81063. //平移
  81064. var pointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5); //两个指头的中心点
  81065. var delta = new Vector2().subVectors(pointer, this.lastScalePointer);
  81066. delta.y *= -1;
  81067. this.panDelta.add(delta);
  81068. this.lastScalePointer = pointer.clone();
  81069. //console.log('scale ',scale, this.radiusDelta)
  81070. }
  81071. this.stopTweens();
  81072. this.dragStarted = true;
  81073. };
  81074. var drop = e => {
  81075. if (!this.enabled) return;
  81076. this.dragStarted = false;
  81077. this.dispatchEvent({
  81078. type: 'end'
  81079. });
  81080. };
  81081. var scroll = e => {
  81082. if (!this.enabled) return;
  81083. var resolvedRadius = this.currentViewport.view.radius + this.radiusDelta;
  81084. this.radiusDelta += -e.delta * resolvedRadius * 0.1;
  81085. this.stopTweens();
  81086. this.updateRadius('scroll');
  81087. };
  81088. var dblclick = e => {
  81089. if (!this.enabled) return;
  81090. if (this.doubleClockZoomEnabled) {
  81091. this.zoomToLocation(e.mouse);
  81092. }
  81093. };
  81094. var previousTouch = null;
  81095. var touchStart = e => {
  81096. previousTouch = e;
  81097. };
  81098. var touchEnd = e => {
  81099. previousTouch = e;
  81100. };
  81101. var touchMove = e => {
  81102. if (!this.enabled) return;
  81103. if (e.touches.length === 2 && previousTouch.touches.length === 2) {
  81104. var prev = previousTouch;
  81105. var curr = e;
  81106. var prevDX = prev.touches[0].pageX - prev.touches[1].pageX;
  81107. var prevDY = prev.touches[0].pageY - prev.touches[1].pageY;
  81108. var prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY);
  81109. var currDX = curr.touches[0].pageX - curr.touches[1].pageX;
  81110. var currDY = curr.touches[0].pageY - curr.touches[1].pageY;
  81111. var currDist = Math.sqrt(currDX * currDX + currDY * currDY);
  81112. var delta = currDist / prevDist;
  81113. var resolvedRadius = this.currentViewport.view.radius + this.radiusDelta;
  81114. var newRadius = resolvedRadius / delta;
  81115. this.radiusDelta = newRadius - resolvedRadius;
  81116. this.stopTweens();
  81117. } else if (e.touches.length === 3 && previousTouch.touches.length === 3) {
  81118. var _prev = previousTouch;
  81119. var _curr = e;
  81120. var prevMeanX = (_prev.touches[0].pageX + _prev.touches[1].pageX + _prev.touches[2].pageX) / 3;
  81121. var prevMeanY = (_prev.touches[0].pageY + _prev.touches[1].pageY + _prev.touches[2].pageY) / 3;
  81122. var currMeanX = (_curr.touches[0].pageX + _curr.touches[1].pageX + _curr.touches[2].pageX) / 3;
  81123. var currMeanY = (_curr.touches[0].pageY + _curr.touches[1].pageY + _curr.touches[2].pageY) / 3;
  81124. var _delta = {
  81125. x: (currMeanX - prevMeanX) / this.renderer.domElement.clientWidth,
  81126. y: (currMeanY - prevMeanY) / this.renderer.domElement.clientHeight
  81127. };
  81128. this.panDelta.x += _delta.x;
  81129. this.panDelta.y += _delta.y;
  81130. this.stopTweens();
  81131. }
  81132. previousTouch = e;
  81133. };
  81134. this.addEventListener('touchstart', touchStart);
  81135. this.addEventListener('touchend', touchEnd);
  81136. this.addEventListener('touchmove', touchMove);
  81137. this.viewer.addEventListener('global_drag', drag);
  81138. this.viewer.addEventListener('global_drop', drop);
  81139. this.viewer.addEventListener('global_mousewheel', scroll);
  81140. this.viewer.addEventListener('global_dblclick', dblclick);
  81141. this.viewer.addEventListener('global_touchmove', e => {
  81142. if (e.touches.length > 1) {
  81143. //单指的就触发上一句
  81144. //console.log('global_touchmove' )
  81145. drag(e);
  81146. }
  81147. });
  81148. var prepareScale = e => {
  81149. //触屏的scale
  81150. this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
  81151. this.lastScalePointer = new Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5); //两个指头的中心点
  81152. };
  81153. this.viewer.addEventListener('global_touchstart', e => {
  81154. if (this.enabled && e.touches.length == 2) {
  81155. //只监听开头两个指头
  81156. prepareScale(e);
  81157. }
  81158. });
  81159. /* this.viewer.addEventListener('global_touchend', (e)=>{
  81160. if(!this.enabled)return
  81161. if(e.touches.length==1){//停止scale,开始rotate
  81162. prepareRotate(e)
  81163. //this.pointerDragStart = null
  81164. //console.log('只剩一个', e.pointer.toArray())
  81165. }
  81166. }) */
  81167. this.viewer.addEventListener('focusOnObject', o => {
  81168. if (o.position && o.CamTarget) {
  81169. var distance = o.position.distanceTo(o.CamTarget);
  81170. //if(distance < minRadius) minRadius = distance * 0.5 //融合页面当focus一个很小的物体时,需要将minRadius也调小
  81171. this.minRadius = Math.min(standartMinRadius, distance * 0.5);
  81172. this.maxRadius = Math.max(this.maxRadius, distance);
  81173. //console.log('focusOnObject radius ', viewer.mainViewport.view.radius)
  81174. }
  81175. });
  81176. }
  81177. setScene(scene) {
  81178. this.scene = scene;
  81179. }
  81180. setCurrentViewport() {
  81181. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  81182. //add
  81183. if (!this.enabled && !o.force) return;
  81184. if (o.hoverViewport && this.currentViewport != o.hoverViewport) {
  81185. this.currentViewport = o.hoverViewport;
  81186. }
  81187. }
  81188. setEnable(enabled) {
  81189. this.enabled = enabled;
  81190. }
  81191. stop() {
  81192. this.yawDelta = 0;
  81193. this.pitchDelta = 0;
  81194. this.radiusDelta = 0;
  81195. this.panDelta.set(0, 0);
  81196. }
  81197. zoomToLocation(mouse) {
  81198. var _viewer$modules$Merge;
  81199. var I = viewer.inputHandler.intersect;
  81200. var object;
  81201. if (I) {
  81202. object = I.object || I.pointcloud;
  81203. I = I.location;
  81204. } else {
  81205. //点击空白处(地面)
  81206. var {
  81207. x,
  81208. y
  81209. } = Potree.Utils.getPointerPosAtHeight(0, viewer.inputHandler.pointer);
  81210. I = new Vector3(x, y, 0);
  81211. }
  81212. var dis = this.currentViewport.view.position.distanceTo(I);
  81213. var distance;
  81214. var object_ = object || ((_viewer$modules$Merge = viewer.modules.MergeEditor) === null || _viewer$modules$Merge === void 0 ? void 0 : _viewer$modules$Merge.selected);
  81215. if (object_) {
  81216. distance = this.updateRadiusByModel(object_, dis);
  81217. }
  81218. if (!object) {
  81219. if (!distance || distance < 50) {
  81220. //方便从高空回到地面
  81221. distance = Math.min(dis, 50);
  81222. }
  81223. this.updateRadius('focus');
  81224. }
  81225. viewer.focusOnObject({
  81226. position: I
  81227. }, 'point', null, {
  81228. distance
  81229. });
  81230. }
  81231. updateRadiusByModel(object) {
  81232. var dis = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
  81233. //鼠标到点的距离,如果没有就给个几率最大的距离
  81234. var bound = object.boundingBox.clone().applyMatrix4(object.matrixWorld);
  81235. var size = bound.getSize(new Vector3());
  81236. var len = size.length();
  81237. var distance = MathUtils.clamp(dis, 0.8 * object.scale.x, Math.max(len * 0.1, 3 * object.scale.x));
  81238. this.minRadius = Math.min(distance, standartMinRadius);
  81239. this.maxRadius = dis * 2;
  81240. //console.log('maxRadius hasIntersect', this.maxRadius)
  81241. return distance;
  81242. }
  81243. updateRadius(type) {
  81244. var _viewer$inputHandler$2, _viewer$inputHandler$3;
  81245. if (type == 'startPan') {
  81246. var _viewer$inputHandler$;
  81247. //以drag的point为target, 使drag跟手. (如果scroll地面的时候也能改radius就好了,但是在朝模型scroll时容易误触地板导致radius突然增大)
  81248. var I = (_viewer$inputHandler$ = viewer.inputHandler.intersect) === null || _viewer$inputHandler$ === void 0 ? void 0 : _viewer$inputHandler$.location;
  81249. if (!I) {
  81250. var {
  81251. x,
  81252. y
  81253. } = Potree.Utils.getPointerPosAtHeight(0, viewer.inputHandler.pointer);
  81254. I = new Vector3(x, y, 0); //地面交点(如果没有显示地面网格很可能模型跑到地面之下怎么办,ground不再是0的高度,怎么办。主要是测试时乱放模型。)
  81255. }
  81256. var vec = new Vector3().subVectors(I, this.currentViewport.view.position);
  81257. var dis = vec.projectOnVector(this.currentViewport.view.direction).length(); //要拖拽的点到镜头平面距离
  81258. this.currentViewport.view.radius = dis;
  81259. //console.log('radius',dis)
  81260. }
  81261. var model = ((_viewer$inputHandler$2 = viewer.inputHandler.intersect) === null || _viewer$inputHandler$2 === void 0 ? void 0 : _viewer$inputHandler$2.object) || ((_viewer$inputHandler$3 = viewer.inputHandler.intersect) === null || _viewer$inputHandler$3 === void 0 ? void 0 : _viewer$inputHandler$3.pointcloud);
  81262. if (model) {
  81263. this.updateRadiusByModel(model, viewer.inputHandler.intersect.location.distanceTo(this.currentViewport.view.position));
  81264. } else {
  81265. if (!viewer.bound || viewer.bound.boundSize.x == 0) {
  81266. this.maxRadius = viewer.mainViewport.view.position.length() * 2;
  81267. } else {
  81268. var boundFloor = viewer.bound.boundingBox.clone();
  81269. boundFloor.max.z = boundFloor.min.z;
  81270. var dis2 = boundFloor.distanceToPoint(viewer.mainViewport.view.position); //靠近模型底部时变慢
  81271. this.maxRadius = Math.max(4, dis2 * 5);
  81272. //console.log('maxRadius noIntersect', this.maxRadius)
  81273. }
  81274. }
  81275. }
  81276. /* 增加maxRadius限制是因为2024.12有人提单说在离模型区域bound很远的地方scroll和drag多次之后回来,radius会过大。
  81277. 所以只能稍微加一个影响radius的因素。但是当没有intersect时,效果可能欠佳。
  81278. 没有完美的方法,想象下,在bound外也有物体需要focusPoint, 如path, 此时虽然离bound很远但也需要小radius。
  81279. 而当转向朝bound飞去却很慢,虽然可以根据intersect提高minRadius来加速,但如果是focus一个四周都有模型的target,就会被intersect干扰,无法focus。
  81280. 现在存在的现象就是容易出现radius过小,游不到终点的情况,所以我让双击可以focus地面,通过这个办法攀到终点。另外drag时修改了radius,使跟手。但若不显示地面和地图,就很奇怪。
  81281. *没办法直接更改radius,而是通过minRadius和maxRadius, 是因为情况太多了,直接更改不能满足所有情况,还会造成突变。
  81282. *minRadius一般不超过standardMinRadius
  81283. */
  81284. stopTweens() {
  81285. this.tweens.forEach(e => e.stop());
  81286. this.tweens = [];
  81287. }
  81288. update(delta) {
  81289. if (!this.enabled) return;
  81290. var view = this.currentViewport.view; //this.currentViewport.view;
  81291. var camera = this.currentViewport.camera;
  81292. {
  81293. // accelerate while input is given
  81294. var ih = this.viewer.inputHandler;
  81295. var moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  81296. var moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  81297. var moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  81298. var moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  81299. var moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  81300. var moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  81301. var moveSpeed = this.currentViewport.getMoveSpeed() / 20;
  81302. var px = 0,
  81303. py = 0,
  81304. pz = 0;
  81305. if (moveForward) {
  81306. py = 1 * moveSpeed;
  81307. } else if (moveBackward) {
  81308. py = -1 * moveSpeed;
  81309. }
  81310. if (moveLeft) {
  81311. px = -1 * moveSpeed;
  81312. } else if (moveRight) {
  81313. px = 1 * moveSpeed;
  81314. }
  81315. if (moveUp) {
  81316. pz = 1 * moveSpeed;
  81317. } else if (moveDown) {
  81318. pz = -1 * moveSpeed;
  81319. }
  81320. (px != 0 || py != 0 || pz != 0) && view.translate(px, py, pz, true);
  81321. }
  81322. {
  81323. // apply rotation
  81324. var progression = Math.min(1, this.fadeFactor * delta);
  81325. var yaw = view.yaw;
  81326. var pitch = view.pitch;
  81327. var pivot = view.getPivot();
  81328. yaw -= progression * this.yawDelta;
  81329. pitch -= progression * this.pitchDelta;
  81330. view.yaw = yaw;
  81331. view.pitch = pitch;
  81332. var V = this.currentViewport.view.direction.multiplyScalar(-view.radius);
  81333. var position = new Vector3().addVectors(pivot, V);
  81334. view.position.copy(position);
  81335. }
  81336. if (camera.type != 'OrthographicCamera') {
  81337. // apply pan 平移
  81338. var panDistance = view.radius * Math.tan(MathUtils.degToRad(camera.fov / 2)); //参照4dkk 只要radius设置正确就完全跟手(见updateRadius)
  81339. //计算了下确实是这么算的。 平移pivot。
  81340. var _px = -this.panDelta.x * panDistance * camera.aspect;
  81341. var _py = this.panDelta.y * panDistance;
  81342. view.pan(_px, _py);
  81343. }
  81344. {
  81345. // apply zoom
  81346. var _progression = 1; //Math.min(1, this.fadeFactor * delta);
  81347. // let radius = view.radius + progression * this.radiusDelta * view.radius * 0.1;
  81348. var radius = view.radius + _progression * this.radiusDelta;
  81349. var _V = view.direction.multiplyScalar(-radius);
  81350. var _position = new Vector3().addVectors(view.getPivot(), _V);
  81351. radius = Math.min(radius, this.maxRadius);
  81352. if (this.constantlyForward) {
  81353. // 到达中心点后还能继续向前移动,也就是能推进中心点
  81354. radius = Math.max(radius, this.minRadius);
  81355. }
  81356. view.radius = radius;
  81357. view.position.copy(_position);
  81358. }
  81359. {
  81360. var speed = view.radius;
  81361. this.viewer.setMoveSpeed && this.viewer.setMoveSpeed(speed);
  81362. }
  81363. {
  81364. // decelerate over time
  81365. /* let progression = Math.min(1, this.fadeFactor * delta);
  81366. let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  81367. this.yawDelta *= attenuation;
  81368. this.pitchDelta *= attenuation;
  81369. this.panDelta.multiplyScalar(attenuation);
  81370. // this.radiusDelta *= attenuation;
  81371. this.radiusDelta -= progression * this.radiusDelta; */
  81372. //取消衰减,直接stop
  81373. this.stop();
  81374. }
  81375. }
  81376. }
  81377. ;
  81378. // Adapted from three.js VRButton
  81379. class VRButton {
  81380. constructor() {
  81381. this.onStartListeners = [];
  81382. this.onEndListeners = [];
  81383. this.element = null;
  81384. }
  81385. onStart(callback) {
  81386. this.onStartListeners.push(callback);
  81387. }
  81388. onEnd(callback) {
  81389. this.onEndListeners.push(callback);
  81390. }
  81391. static async createButton(renderer, options) {
  81392. if (options) {
  81393. console.error('THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.');
  81394. }
  81395. var button = new VRButton();
  81396. var element = document.createElement('button');
  81397. button.element = element;
  81398. function setEnter() {
  81399. button.element.innerHTML = "\n\t\t\t\t<div style=\"font-size: 0.5em;\">ENTER</div>\n\t\t\t\t<div style=\"font-weight: bold;\">VR</div>\n\t\t\t";
  81400. }
  81401. function setExit() {
  81402. button.element.innerHTML = "\n\t\t\t\t<div style=\"font-size: 0.5em;\">EXIT</div>\n\t\t\t\t<div style=\"font-weight: bold;\">VR</div>\n\t\t\t";
  81403. }
  81404. function showEnterVR( /*device*/
  81405. ) {
  81406. var currentSession = null;
  81407. function onSessionStarted(session) {
  81408. session.addEventListener('end', onSessionEnded);
  81409. for (var listener of button.onStartListeners) {
  81410. listener();
  81411. }
  81412. renderer.xr.setSession(session);
  81413. setExit();
  81414. currentSession = session;
  81415. }
  81416. function onSessionEnded( /*event*/
  81417. ) {
  81418. currentSession.removeEventListener('end', onSessionEnded);
  81419. for (var listener of button.onEndListeners) {
  81420. listener();
  81421. }
  81422. setEnter();
  81423. currentSession = null;
  81424. }
  81425. //
  81426. button.element.style.display = '';
  81427. button.element.style.cursor = 'pointer';
  81428. setEnter();
  81429. button.element.onmouseenter = function () {
  81430. button.element.style.opacity = '1.0';
  81431. };
  81432. button.element.onmouseleave = function () {
  81433. button.element.style.opacity = '0.7';
  81434. };
  81435. button.element.onclick = function () {
  81436. if (currentSession === null) {
  81437. // WebXR's requestReferenceSpace only works if the corresponding feature
  81438. // was requested at session creation time. For simplicity, just ask for
  81439. // the interesting ones as optional features, but be aware that the
  81440. // requestReferenceSpace call will fail if it turns out to be unavailable.
  81441. // ('local' is always available for immersive sessions and doesn't need to
  81442. // be requested separately.)
  81443. var sessionInit = {
  81444. optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking']
  81445. };
  81446. navigator.xr.requestSession('immersive-vr', sessionInit).then(onSessionStarted);
  81447. } else {
  81448. currentSession.end();
  81449. }
  81450. };
  81451. }
  81452. function stylizeElement(element) {
  81453. element.style.position = 'absolute';
  81454. element.style.bottom = '20px';
  81455. element.style.padding = '12px 6px';
  81456. element.style.border = '1px solid #fff';
  81457. element.style.borderRadius = '4px';
  81458. element.style.background = 'rgba(0,0,0,0.1)';
  81459. element.style.color = '#fff';
  81460. element.style.font = 'normal 13px sans-serif';
  81461. element.style.textAlign = 'center';
  81462. element.style.opacity = '0.7';
  81463. element.style.outline = 'none';
  81464. element.style.zIndex = '999';
  81465. }
  81466. if ('xr' in navigator) {
  81467. button.element.id = 'VRButton';
  81468. button.element.style.display = 'none';
  81469. stylizeElement(button.element);
  81470. var supported = await navigator.xr.isSessionSupported('immersive-vr');
  81471. if (supported) {
  81472. showEnterVR();
  81473. return button;
  81474. } else {
  81475. return null;
  81476. }
  81477. } else {
  81478. if (window.isSecureContext === false) {
  81479. console.log("WEBXR NEEDS HTTPS");
  81480. } else {
  81481. console.log("WEBXR not available");
  81482. }
  81483. return null;
  81484. }
  81485. }
  81486. }
  81487. !function (e, a) {
  81488. "object" == typeof exports && "object" == typeof module ? module.exports = a() : "function" == typeof define && define.amd ? define([], a) : "object" == typeof exports ? exports.DxfParser = a() : e.DxfParser = a();
  81489. }("undefined" != typeof self ? self : undefined, function () {
  81490. return function (e) {
  81491. var a = {};
  81492. function t(r) {
  81493. if (a[r]) return a[r].exports;
  81494. var n = a[r] = {
  81495. i: r,
  81496. l: !1,
  81497. exports: {}
  81498. };
  81499. return e[r].call(n.exports, n, n.exports, t), n.l = !0, n.exports;
  81500. }
  81501. return t.m = e, t.c = a, t.d = function (e, a, r) {
  81502. t.o(e, a) || Object.defineProperty(e, a, {
  81503. enumerable: !0,
  81504. get: r
  81505. });
  81506. }, t.r = function (e) {
  81507. "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
  81508. value: "Module"
  81509. }), Object.defineProperty(e, "__esModule", {
  81510. value: !0
  81511. });
  81512. }, t.t = function (e, a) {
  81513. if (1 & a && (e = t(e)), 8 & a) return e;
  81514. if (4 & a && "object" == typeof e && e && e.__esModule) return e;
  81515. var r = Object.create(null);
  81516. if (t.r(r), Object.defineProperty(r, "default", {
  81517. enumerable: !0,
  81518. value: e
  81519. }), 2 & a && "string" != typeof e) for (var n in e) t.d(r, n, function (a) {
  81520. return e[a];
  81521. }.bind(null, n));
  81522. return r;
  81523. }, t.n = function (e) {
  81524. var a = e && e.__esModule ? function () {
  81525. return e.default;
  81526. } : function () {
  81527. return e;
  81528. };
  81529. return t.d(a, "a", a), a;
  81530. }, t.o = function (e, a) {
  81531. return Object.prototype.hasOwnProperty.call(e, a);
  81532. }, t.p = "", t(t.s = 1);
  81533. }([function (e, a, t) {
  81534. var r, n;
  81535. !function (o, c) {
  81536. "use strict";
  81537. void 0 === (n = "function" == typeof (r = function r() {
  81538. var e = function e() {},
  81539. a = "undefined",
  81540. t = ["trace", "debug", "info", "warn", "error"];
  81541. function r(e, a) {
  81542. var t = e[a];
  81543. if ("function" == typeof t.bind) return t.bind(e);
  81544. try {
  81545. return Function.prototype.bind.call(t, e);
  81546. } catch (a) {
  81547. return function () {
  81548. return Function.prototype.apply.apply(t, [e, arguments]);
  81549. };
  81550. }
  81551. }
  81552. function n(a, r) {
  81553. for (var n = 0; n < t.length; n++) {
  81554. var o = t[n];
  81555. this[o] = n < a ? e : this.methodFactory(o, a, r);
  81556. }
  81557. this.log = this.debug;
  81558. }
  81559. function o(t, o, c) {
  81560. return function (t) {
  81561. "debug" === t && (t = "log");
  81562. return typeof console !== a && (void 0 !== console[t] ? r(console, t) : void 0 !== console.log ? r(console, "log") : e);
  81563. }(t) || function (e, t, r) {
  81564. return function () {
  81565. typeof console !== a && (n.call(this, t, r), this[e].apply(this, arguments));
  81566. };
  81567. }.apply(this, arguments);
  81568. }
  81569. function c(e, r, c) {
  81570. var i,
  81571. u = this,
  81572. s = "loglevel";
  81573. function l() {
  81574. var e;
  81575. if (typeof window !== a) {
  81576. try {
  81577. e = window.localStorage[s];
  81578. } catch (e) {}
  81579. if (typeof e === a) try {
  81580. var t = window.document.cookie,
  81581. r = t.indexOf(encodeURIComponent(s) + "=");
  81582. -1 !== r && (e = /^([^;]+)/.exec(t.slice(r))[1]);
  81583. } catch (e) {}
  81584. return void 0 === u.levels[e] && (e = void 0), e;
  81585. }
  81586. }
  81587. e && (s += ":" + e), u.name = e, u.levels = {
  81588. TRACE: 0,
  81589. DEBUG: 1,
  81590. INFO: 2,
  81591. WARN: 3,
  81592. ERROR: 4,
  81593. SILENT: 5
  81594. }, u.methodFactory = c || o, u.getLevel = function () {
  81595. return i;
  81596. }, u.setLevel = function (r, o) {
  81597. if ("string" == typeof r && void 0 !== u.levels[r.toUpperCase()] && (r = u.levels[r.toUpperCase()]), !("number" == typeof r && r >= 0 && r <= u.levels.SILENT)) throw "log.setLevel() called with invalid level: " + r;
  81598. if (i = r, !1 !== o && function (e) {
  81599. var r = (t[e] || "silent").toUpperCase();
  81600. if (typeof window === a) return;
  81601. try {
  81602. return void (window.localStorage[s] = r);
  81603. } catch (e) {}
  81604. try {
  81605. window.document.cookie = encodeURIComponent(s) + "=" + r + ";";
  81606. } catch (e) {}
  81607. }(r), n.call(u, r, e), typeof console === a && r < u.levels.SILENT) return "No console available for logging";
  81608. }, u.setDefaultLevel = function (e) {
  81609. l() || u.setLevel(e, !1);
  81610. }, u.enableAll = function (e) {
  81611. u.setLevel(u.levels.TRACE, e);
  81612. }, u.disableAll = function (e) {
  81613. u.setLevel(u.levels.SILENT, e);
  81614. };
  81615. var v = l();
  81616. null == v && (v = null == r ? "WARN" : r), u.setLevel(v, !1);
  81617. }
  81618. var i = new c(),
  81619. u = {};
  81620. i.getLogger = function (e) {
  81621. if ("string" != typeof e || "" === e) throw new TypeError("You must supply a name when creating a logger.");
  81622. var a = u[e];
  81623. return a || (a = u[e] = new c(e, i.getLevel(), i.methodFactory)), a;
  81624. };
  81625. var s = typeof window !== a ? window.log : void 0;
  81626. return i.noConflict = function () {
  81627. return typeof window !== a && window.log === i && (window.log = s), i;
  81628. }, i.getLoggers = function () {
  81629. return u;
  81630. }, i;
  81631. }) ? r.call(a, t, a, e) : r) || (e.exports = n);
  81632. }();
  81633. }, function (e, a, t) {
  81634. "use strict";
  81635. function r(e) {
  81636. this._pointer = 0, this._data = e, this._eof = !1;
  81637. }
  81638. function n(e, a) {
  81639. return e <= 9 ? a : e >= 10 && e <= 59 ? parseFloat(a) : e >= 60 && e <= 99 ? parseInt(a) : e >= 100 && e <= 109 ? a : e >= 110 && e <= 149 ? parseFloat(a) : e >= 160 && e <= 179 ? parseInt(a) : e >= 210 && e <= 239 ? parseFloat(a) : e >= 270 && e <= 289 ? parseInt(a) : e >= 290 && e <= 299 ? function (e) {
  81640. if ("0" === e) return !1;
  81641. if ("1" === e) return !0;
  81642. throw TypeError("String '" + e + "' cannot be cast to Boolean type");
  81643. }(a) : e >= 300 && e <= 369 ? a : e >= 370 && e <= 389 ? parseInt(a) : e >= 390 && e <= 399 ? a : e >= 400 && e <= 409 ? parseInt(a) : e >= 410 && e <= 419 ? a : e >= 420 && e <= 429 ? parseInt(a) : e >= 430 && e <= 439 ? a : e >= 440 && e <= 459 ? parseInt(a) : e >= 460 && e <= 469 ? parseFloat(a) : e >= 470 && e <= 481 ? a : 999 === e ? a : e >= 1e3 && e <= 1009 ? a : e >= 1010 && e <= 1059 ? parseFloat(a) : e >= 1060 && e <= 1071 ? parseInt(a) : (console.log("WARNING: Group code does not have a defined type: %j", {
  81644. code: e,
  81645. value: a
  81646. }), a);
  81647. }
  81648. t.r(a), r.prototype.next = function () {
  81649. var e;
  81650. if (!this.hasNext()) throw this._eof ? new Error("Cannot call 'next' after EOF group has been read") : new Error("Unexpected end of input: EOF group not read before end of file. Ended on code " + this._data[this._pointer]);
  81651. return e = {
  81652. code: parseInt(this._data[this._pointer])
  81653. }, this._pointer++, e.value = n(e.code, this._data[this._pointer].trim()), this._pointer++, 0 === e.code && "EOF" === e.value && (this._eof = !0), this.lastReadGroup = e, e;
  81654. }, r.prototype.peek = function () {
  81655. if (!this.hasNext()) throw this._eof ? new Error("Cannot call 'next' after EOF group has been read") : new Error("Unexpected end of input: EOF group not read before end of file. Ended on code " + this._data[this._pointer]);
  81656. var e = {
  81657. code: parseInt(this._data[this._pointer])
  81658. };
  81659. return e.value = n(e.code, this._data[this._pointer + 1].trim()), e;
  81660. }, r.prototype.rewind = function (e) {
  81661. e = e || 1, this._pointer = this._pointer - 2 * e;
  81662. }, r.prototype.hasNext = function () {
  81663. return !this._eof && !(this._pointer > this._data.length - 2);
  81664. }, r.prototype.isEOF = function () {
  81665. return this._eof;
  81666. };
  81667. var o = [0, 16711680, 16776960, 65280, 65535, 255, 16711935, 16777215, 8421504, 12632256, 16711680, 16744319, 13369344, 13395558, 10027008, 10046540, 8323072, 8339263, 4980736, 4990502, 16727808, 16752511, 13382400, 13401958, 10036736, 10051404, 8331008, 8343359, 4985600, 4992806, 16744192, 16760703, 13395456, 13408614, 10046464, 10056268, 8339200, 8347455, 4990464, 4995366, 16760576, 16768895, 13408512, 13415014, 10056192, 10061132, 8347392, 8351551, 4995328, 4997670, 16776960, 16777087, 13421568, 13421670, 10000384, 10000460, 8355584, 8355647, 5000192, 5000230, 12582656, 14679935, 10079232, 11717734, 7510016, 8755276, 6258432, 7307071, 3755008, 4344870, 8388352, 12582783, 6736896, 10079334, 5019648, 7510092, 4161280, 6258495, 2509824, 3755046, 4194048, 10485631, 3394560, 8375398, 2529280, 6264908, 2064128, 5209919, 1264640, 3099686, 65280, 8388479, 52224, 6736998, 38912, 5019724, 32512, 4161343, 19456, 2509862, 65343, 8388511, 52275, 6737023, 38950, 5019743, 32543, 4161359, 19475, 2509871, 65407, 8388543, 52326, 6737049, 38988, 5019762, 32575, 4161375, 19494, 2509881, 65471, 8388575, 52377, 6737074, 39026, 5019781, 32607, 4161391, 19513, 2509890, 65535, 8388607, 52428, 6737100, 39064, 5019800, 32639, 4161407, 19532, 2509900, 49151, 8380415, 39372, 6730444, 29336, 5014936, 24447, 4157311, 14668, 2507340, 32767, 8372223, 26316, 6724044, 19608, 5010072, 16255, 4153215, 9804, 2505036, 16383, 8364031, 13260, 6717388, 9880, 5005208, 8063, 4149119, 4940, 2502476, 255, 8355839, 204, 6710988, 152, 5000344, 127, 4145023, 76, 2500172, 4129023, 10452991, 3342540, 8349388, 2490520, 6245528, 2031743, 5193599, 1245260, 3089996, 8323327, 12550143, 6684876, 10053324, 4980888, 7490712, 4128895, 6242175, 2490444, 3745356, 12517631, 14647295, 10027212, 11691724, 7471256, 8735896, 6226047, 7290751, 3735628, 4335180, 16711935, 16744447, 13369548, 13395660, 9961624, 9981080, 8323199, 8339327, 4980812, 4990540, 16711871, 16744415, 13369497, 13395634, 9961586, 9981061, 8323167, 8339311, 4980793, 4990530, 16711807, 16744383, 13369446, 13395609, 9961548, 9981042, 8323135, 8339295, 4980774, 4990521, 16711743, 16744351, 13369395, 13395583, 9961510, 9981023, 8323103, 8339279, 4980755, 4990511, 3355443, 5987163, 8684676, 11382189, 14079702, 16777215];
  81668. function c(e) {
  81669. var a = {};
  81670. e.rewind();
  81671. var t = e.next(),
  81672. r = t.code;
  81673. if (a.x = t.value, r += 10, (t = e.next()).code != r) throw new Error("Expected code for point value to be " + r + " but got " + t.code + ".");
  81674. return a.y = t.value, r += 10, (t = e.next()).code != r ? (e.rewind(), a) : (a.z = t.value, a);
  81675. }
  81676. function i(e, a) {
  81677. switch (a.code) {
  81678. case 0:
  81679. e.type = a.value;
  81680. break;
  81681. case 5:
  81682. e.handle = a.value;
  81683. /* if(e.handle == "2FDDB"){
  81684. console.log(1)
  81685. } */
  81686. break;
  81687. case 6:
  81688. e.lineType = a.value;
  81689. break;
  81690. case 8:
  81691. e.layer = a.value;
  81692. break;
  81693. case 48:
  81694. e.lineTypeScale = a.value;
  81695. break;
  81696. case 60:
  81697. e.visible = 0 === a.value;
  81698. break;
  81699. case 62:
  81700. e.colorIndex = a.value, e.color = (t = Math.abs(a.value), o[t]);
  81701. break;
  81702. case 67:
  81703. e.inPaperSpace = 0 !== a.value;
  81704. break;
  81705. case 100:
  81706. break;
  81707. case 330:
  81708. e.ownerHandle = a.value;
  81709. break;
  81710. case 347:
  81711. e.materialObjectHandle = a.value;
  81712. break;
  81713. case 370:
  81714. e.lineweight = a.value;
  81715. break;
  81716. case 420:
  81717. e.color = a.value;
  81718. break;
  81719. case 1e3:
  81720. e.extendedData = e.extendedData || {}, e.extendedData.customStrings = e.extendedData.customStrings || [], e.extendedData.customStrings.push(a.value);
  81721. break;
  81722. case 1001:
  81723. e.extendedData = e.extendedData || {}, e.extendedData.applicationName = a.value;
  81724. break;
  81725. default:
  81726. return !1;
  81727. }
  81728. var t;
  81729. return !0;
  81730. }
  81731. function u() {}
  81732. function s(e, a) {
  81733. var t,
  81734. r = [],
  81735. n = !1,
  81736. o = !1;
  81737. for (t = 0; t <= 4; t++) {
  81738. for (var c = {}; "EOF" !== a && 0 !== a.code && !o;) {
  81739. switch (a.code) {
  81740. case 10:
  81741. case 11:
  81742. case 12:
  81743. case 13:
  81744. if (n) {
  81745. o = !0;
  81746. continue;
  81747. }
  81748. c.x = a.value, n = !0;
  81749. break;
  81750. case 20:
  81751. case 21:
  81752. case 22:
  81753. case 23:
  81754. c.y = a.value;
  81755. break;
  81756. case 30:
  81757. case 31:
  81758. case 32:
  81759. case 33:
  81760. c.z = a.value;
  81761. break;
  81762. default:
  81763. return r;
  81764. }
  81765. a = e.next();
  81766. }
  81767. r.push(c), n = !1, o = !1;
  81768. }
  81769. return e.rewind(), r;
  81770. }
  81771. function l() {}
  81772. function v() {}
  81773. function d() {}
  81774. function b() {}
  81775. function p() {}
  81776. function f() {}
  81777. function k() {}
  81778. function y() {}
  81779. function x(e, a) {
  81780. if (!e || e <= 0) throw Error("n must be greater than 0 verticies");
  81781. var t,
  81782. r = [],
  81783. n = !1,
  81784. o = !1,
  81785. c = a.lastReadGroup;
  81786. for (t = 0; t < e; t++) {
  81787. for (var i = {}; "EOF" !== c && 0 !== c.code && !o;) {
  81788. switch (c.code) {
  81789. case 10:
  81790. if (n) {
  81791. o = !0;
  81792. continue;
  81793. }
  81794. i.x = c.value, n = !0;
  81795. break;
  81796. case 20:
  81797. i.y = c.value;
  81798. break;
  81799. case 30:
  81800. i.z = c.value;
  81801. break;
  81802. case 40:
  81803. i.startWidth = c.value;
  81804. break;
  81805. case 41:
  81806. i.endWidth = c.value;
  81807. break;
  81808. case 42:
  81809. 0 != c.value && (i.bulge = c.value);
  81810. break;
  81811. default:
  81812. return n && r.push(i), r;
  81813. }
  81814. c = a.next();
  81815. }
  81816. r.push(i), n = !1, o = !1;
  81817. }
  81818. return a.rewind(), r;
  81819. }
  81820. function h() {}
  81821. function g() {}
  81822. function E() {}
  81823. function w() {}
  81824. function m(e, a) {
  81825. var t = {
  81826. type: a.value
  81827. };
  81828. for (a = e.next(); "EOF" != a && 0 != a.code;) i(t, a), a = e.next();
  81829. return t;
  81830. }
  81831. function P() {}
  81832. function F() {}
  81833. function O() {}
  81834. u.ForEntityName = "3DFACE", u.prototype.parseEntity = function (e, a) {
  81835. var t = {
  81836. type: a.value,
  81837. vertices: []
  81838. };
  81839. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  81840. switch (a.code) {
  81841. case 70:
  81842. t.shape = 1 == (1 & a.value), t.hasContinuousLinetypePattern = 128 == (128 & a.value);
  81843. break;
  81844. case 10:
  81845. t.vertices = s(e, a), a = e.lastReadGroup;
  81846. break;
  81847. default:
  81848. i(t, a);
  81849. }
  81850. a = e.next();
  81851. }
  81852. return t;
  81853. }, l.ForEntityName = "ARC", l.prototype.parseEntity = function (e, a) {
  81854. var t;
  81855. for (t = {
  81856. type: a.value
  81857. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  81858. switch (a.code) {
  81859. case 10:
  81860. t.center = c(e);
  81861. break;
  81862. case 40:
  81863. t.radius = a.value;
  81864. break;
  81865. case 50:
  81866. t.startAngle = Math.PI / 180 * a.value;
  81867. break;
  81868. case 51:
  81869. t.endAngle = Math.PI / 180 * a.value, t.angleLength = t.endAngle - t.startAngle;
  81870. break;
  81871. default:
  81872. i(t, a);
  81873. }
  81874. a = e.next();
  81875. }
  81876. return t;
  81877. }, v.ForEntityName = "ATTDEF", v.prototype.parseEntity = function (e, a) {
  81878. var t = {
  81879. type: a.value,
  81880. scale: 1,
  81881. textStyle: "STANDARD"
  81882. };
  81883. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  81884. switch (a.code) {
  81885. case 1:
  81886. t.text = a.value;
  81887. break;
  81888. case 2:
  81889. t.tag = a.value;
  81890. break;
  81891. case 3:
  81892. t.prompt = a.value;
  81893. break;
  81894. case 7:
  81895. t.textStyle = a.value;
  81896. break;
  81897. case 10:
  81898. t.startPoint = c(e);
  81899. break;
  81900. case 11:
  81901. t.endPoint = c(e);
  81902. break;
  81903. case 39:
  81904. t.thickness = a.value;
  81905. break;
  81906. case 40:
  81907. t.textHeight = a.value;
  81908. break;
  81909. case 41:
  81910. t.scale = a.value;
  81911. break;
  81912. case 50:
  81913. t.rotation = a.value;
  81914. break;
  81915. case 51:
  81916. t.obliqueAngle = a.value;
  81917. break;
  81918. case 70:
  81919. t.invisible = !!(1 & a.value), t.constant = !!(2 & a.value), t.verificationRequired = !!(4 & a.value), t.preset = !!(8 & a.value);
  81920. break;
  81921. case 71:
  81922. t.backwards = !!(2 & a.value), t.mirrored = !!(4 & a.value);
  81923. break;
  81924. case 72:
  81925. t.horizontalJustification = a.value;
  81926. break;
  81927. case 73:
  81928. t.fieldLength = a.value;
  81929. break;
  81930. case 74:
  81931. t.verticalJustification = a.value;
  81932. break;
  81933. case 100:
  81934. break;
  81935. case 210:
  81936. t.extrusionDirectionX = a.value;
  81937. break;
  81938. case 220:
  81939. t.extrusionDirectionY = a.value;
  81940. break;
  81941. case 230:
  81942. t.extrusionDirectionZ = a.value;
  81943. break;
  81944. default:
  81945. i(t, a);
  81946. }
  81947. a = e.next();
  81948. }
  81949. return t;
  81950. }, d.ForEntityName = "CIRCLE", d.prototype.parseEntity = function (e, a) {
  81951. var t, r;
  81952. for (t = {
  81953. type: a.value
  81954. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  81955. switch (a.code) {
  81956. case 10:
  81957. t.center = c(e);
  81958. break;
  81959. case 40:
  81960. t.radius = a.value;
  81961. break;
  81962. case 50:
  81963. t.startAngle = Math.PI / 180 * a.value;
  81964. break;
  81965. case 51:
  81966. (r = Math.PI / 180 * a.value) < t.startAngle ? t.angleLength = r + 2 * Math.PI - t.startAngle : t.angleLength = r - t.startAngle, t.endAngle = r;
  81967. break;
  81968. default:
  81969. i(t, a);
  81970. }
  81971. a = e.next();
  81972. }
  81973. return t;
  81974. }, b.ForEntityName = "DIMENSION", b.prototype.parseEntity = function (e, a) {
  81975. var t;
  81976. for (t = {
  81977. type: a.value
  81978. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  81979. switch (a.code) {
  81980. case 2:
  81981. t.block = a.value;
  81982. break;
  81983. case 10:
  81984. t.anchorPoint = c(e);
  81985. break;
  81986. case 11:
  81987. t.middleOfText = c(e);
  81988. break;
  81989. case 12:
  81990. t.insertionPoint = c(e);
  81991. break;
  81992. case 13:
  81993. t.linearOrAngularPoint1 = c(e);
  81994. break;
  81995. case 14:
  81996. t.linearOrAngularPoint2 = c(e);
  81997. break;
  81998. case 15:
  81999. t.diameterOrRadiusPoint = c(e);
  82000. break;
  82001. case 16:
  82002. t.arcPoint = c(e);
  82003. break;
  82004. case 70:
  82005. t.dimensionType = a.value;
  82006. break;
  82007. case 71:
  82008. t.attachmentPoint = a.value;
  82009. break;
  82010. case 42:
  82011. t.actualMeasurement = a.value;
  82012. break;
  82013. case 1:
  82014. t.text = a.value;
  82015. break;
  82016. case 50:
  82017. t.angle = a.value;
  82018. break;
  82019. default:
  82020. i(t, a);
  82021. }
  82022. a = e.next();
  82023. }
  82024. return t;
  82025. }, p.ForEntityName = "ELLIPSE", p.prototype.parseEntity = function (e, a) {
  82026. var t;
  82027. for (t = {
  82028. type: a.value
  82029. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82030. switch (a.code) {
  82031. case 10:
  82032. t.center = c(e);
  82033. break;
  82034. case 11:
  82035. t.majorAxisEndPoint = c(e);
  82036. break;
  82037. case 40:
  82038. t.axisRatio = a.value;
  82039. break;
  82040. case 41:
  82041. t.startAngle = a.value;
  82042. break;
  82043. case 42:
  82044. t.endAngle = a.value;
  82045. break;
  82046. case 2:
  82047. t.name = a.value;
  82048. break;
  82049. default:
  82050. i(t, a);
  82051. }
  82052. a = e.next();
  82053. }
  82054. return t;
  82055. }, f.ForEntityName = "INSERT", f.prototype.parseEntity = function (e, a) {
  82056. var t;
  82057. for (t = {
  82058. type: a.value
  82059. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82060. switch (a.code) {
  82061. case 2:
  82062. t.name = a.value;
  82063. break;
  82064. case 41:
  82065. t.xScale = a.value;
  82066. break;
  82067. case 42:
  82068. t.yScale = a.value;
  82069. break;
  82070. case 43:
  82071. t.zScale = a.value;
  82072. break;
  82073. case 10:
  82074. t.position = c(e);
  82075. break;
  82076. case 50:
  82077. t.rotation = a.value;
  82078. break;
  82079. case 70:
  82080. t.columnCount = a.value;
  82081. break;
  82082. case 71:
  82083. t.rowCount = a.value;
  82084. break;
  82085. case 44:
  82086. t.columnSpacing = a.value;
  82087. break;
  82088. case 45:
  82089. t.rowSpacing = a.value;
  82090. break;
  82091. case 210:
  82092. t.extrusionDirection = c(e);
  82093. break;
  82094. default:
  82095. i(t, a);
  82096. }
  82097. a = e.next();
  82098. }
  82099. return t;
  82100. }, k.ForEntityName = "LINE", k.prototype.parseEntity = function (e, a) {
  82101. var t = {
  82102. type: a.value,
  82103. vertices: []
  82104. };
  82105. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82106. switch (a.code) {
  82107. case 10:
  82108. t.vertices.unshift(c(e));
  82109. break;
  82110. case 11:
  82111. t.vertices.push(c(e));
  82112. break;
  82113. case 210:
  82114. t.extrusionDirection = c(e);
  82115. break;
  82116. case 100:
  82117. break;
  82118. default:
  82119. i(t, a);
  82120. }
  82121. a = e.next();
  82122. }
  82123. return t;
  82124. }, y.ForEntityName = "LWPOLYLINE", y.prototype.parseEntity = function (e, a) {
  82125. var t = {
  82126. type: a.value,
  82127. vertices: []
  82128. },
  82129. r = 0;
  82130. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82131. switch (a.code) {
  82132. case 38:
  82133. t.elevation = a.value;
  82134. break;
  82135. case 39:
  82136. t.depth = a.value;
  82137. break;
  82138. case 70:
  82139. t.shape = 1 == (1 & a.value), t.hasContinuousLinetypePattern = 128 == (128 & a.value);
  82140. break;
  82141. case 90:
  82142. r = a.value;
  82143. break;
  82144. case 10:
  82145. //t.vertices = x(r, e);
  82146. //改,因有的文件有点问题,可能版本原因
  82147. t.vertices.push(...x(r, e)); //有的文件同一个entity需要多次执行到这里,所以不能直接覆盖,要push
  82148. t.vertices = t.vertices.filter(e => e.x != void 0); //而且会出现空的vertix:{},所以排除下
  82149. break;
  82150. case 43:
  82151. 0 !== a.value && (t.width = a.value);
  82152. break;
  82153. case 210:
  82154. t.extrusionDirectionX = a.value;
  82155. break;
  82156. case 220:
  82157. t.extrusionDirectionY = a.value;
  82158. break;
  82159. case 230:
  82160. t.extrusionDirectionZ = a.value;
  82161. break;
  82162. default:
  82163. i(t, a);
  82164. }
  82165. a = e.next();
  82166. }
  82167. return t;
  82168. }, h.ForEntityName = "MTEXT", h.prototype.parseEntity = function (e, a) {
  82169. var t = {
  82170. type: a.value
  82171. };
  82172. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82173. switch (a.code) {
  82174. case 3:
  82175. case 1:
  82176. t.text ? t.text += a.value : t.text = a.value;
  82177. break;
  82178. case 10:
  82179. t.position = c(e);
  82180. break;
  82181. case 40:
  82182. t.height = a.value;
  82183. break;
  82184. case 41:
  82185. t.width = a.value;
  82186. break;
  82187. case 50:
  82188. t.rotation = a.value;
  82189. break;
  82190. case 71:
  82191. t.attachmentPoint = a.value;
  82192. break;
  82193. case 72:
  82194. t.drawingDirection = a.value;
  82195. break;
  82196. default:
  82197. i(t, a);
  82198. }
  82199. a = e.next();
  82200. }
  82201. return t;
  82202. }, g.ForEntityName = "POINT", g.prototype.parseEntity = function (e, a) {
  82203. var t;
  82204. for (t = {
  82205. type: a.value
  82206. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82207. switch (a.code) {
  82208. case 10:
  82209. t.position = c(e);
  82210. break;
  82211. case 39:
  82212. t.thickness = a.value;
  82213. break;
  82214. case 210:
  82215. t.extrusionDirection = c(e);
  82216. break;
  82217. case 100:
  82218. break;
  82219. default:
  82220. i(t, a);
  82221. }
  82222. a = e.next();
  82223. }
  82224. return t;
  82225. }, E.ForEntityName = "VERTEX", E.prototype.parseEntity = function (e, a) {
  82226. var t = {
  82227. type: a.value
  82228. };
  82229. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82230. switch (a.code) {
  82231. case 10:
  82232. t.x = a.value;
  82233. break;
  82234. case 20:
  82235. t.y = a.value;
  82236. break;
  82237. case 30:
  82238. t.z = a.value;
  82239. break;
  82240. case 40:
  82241. case 41:
  82242. case 42:
  82243. 0 != a.value && (t.bulge = a.value);
  82244. break;
  82245. case 70:
  82246. t.curveFittingVertex = 0 != (1 & a.value), t.curveFitTangent = 0 != (2 & a.value), t.splineVertex = 0 != (8 & a.value), t.splineControlPoint = 0 != (16 & a.value), t.threeDPolylineVertex = 0 != (32 & a.value), t.threeDPolylineMesh = 0 != (64 & a.value), t.polyfaceMeshVertex = 0 != (128 & a.value);
  82247. break;
  82248. case 50:
  82249. case 71:
  82250. t.faceA = a.value;
  82251. break;
  82252. case 72:
  82253. t.faceB = a.value;
  82254. break;
  82255. case 73:
  82256. t.faceC = a.value;
  82257. break;
  82258. case 74:
  82259. t.faceD = a.value;
  82260. break;
  82261. default:
  82262. i(t, a);
  82263. }
  82264. a = e.next();
  82265. }
  82266. return t;
  82267. }, w.ForEntityName = "POLYLINE", w.prototype.parseEntity = function (e, a) {
  82268. var t = {
  82269. type: a.value,
  82270. vertices: []
  82271. };
  82272. for (a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82273. switch (a.code) {
  82274. case 10:
  82275. case 20:
  82276. case 30:
  82277. case 39:
  82278. t.thickness = a.value;
  82279. break;
  82280. case 40:
  82281. case 41:
  82282. break;
  82283. case 70:
  82284. t.shape = 0 != (1 & a.value), t.includesCurveFitVertices = 0 != (2 & a.value), t.includesSplineFitVertices = 0 != (4 & a.value), t.is3dPolyline = 0 != (8 & a.value), t.is3dPolygonMesh = 0 != (16 & a.value), t.is3dPolygonMeshClosed = 0 != (32 & a.value), t.isPolyfaceMesh = 0 != (64 & a.value), t.hasContinuousLinetypePattern = 0 != (128 & a.value);
  82285. break;
  82286. case 71:
  82287. case 72:
  82288. case 73:
  82289. case 74:
  82290. case 75:
  82291. break;
  82292. case 210:
  82293. t.extrusionDirection = c(e);
  82294. break;
  82295. default:
  82296. i(t, a);
  82297. }
  82298. a = e.next();
  82299. }
  82300. return t.vertices = function (e, a) {
  82301. var t = new E(),
  82302. r = [];
  82303. for (; !e.isEOF();) if (0 === a.code) if ("VERTEX" === a.value) r.push(t.parseEntity(e, a)), a = e.lastReadGroup;else if ("SEQEND" === a.value) {
  82304. m(e, a);
  82305. break;
  82306. }
  82307. return r;
  82308. }(e, a), t;
  82309. }, P.ForEntityName = "SOLID", P.prototype.parseEntity = function (e, a) {
  82310. var t;
  82311. for ((t = {
  82312. type: a.value
  82313. }).points = [], a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82314. switch (a.code) {
  82315. case 10:
  82316. t.points[0] = c(e);
  82317. break;
  82318. case 11:
  82319. t.points[1] = c(e);
  82320. break;
  82321. case 12:
  82322. t.points[2] = c(e);
  82323. break;
  82324. case 13:
  82325. t.points[3] = c(e);
  82326. break;
  82327. case 210:
  82328. t.extrusionDirection = c(e);
  82329. break;
  82330. default:
  82331. i(t, a);
  82332. }
  82333. a = e.next();
  82334. }
  82335. return t;
  82336. }, F.ForEntityName = "SPLINE", F.prototype.parseEntity = function (e, a) {
  82337. var t;
  82338. for (t = {
  82339. type: a.value
  82340. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82341. switch (a.code) {
  82342. case 10:
  82343. t.controlPoints || (t.controlPoints = []), t.controlPoints.push(c(e));
  82344. break;
  82345. case 11:
  82346. t.fitPoints || (t.fitPoints = []), t.fitPoints.push(c(e));
  82347. break;
  82348. case 12:
  82349. t.startTangent = c(e);
  82350. break;
  82351. case 13:
  82352. t.endTangent = c(e);
  82353. break;
  82354. case 40:
  82355. t.knotValues || (t.knotValues = []), t.knotValues.push(a.value);
  82356. break;
  82357. case 70:
  82358. 0 != (1 & a.value) && (t.closed = !0), 0 != (2 & a.value) && (t.periodic = !0), 0 != (4 & a.value) && (t.rational = !0), 0 != (8 & a.value) && (t.planar = !0), 0 != (16 & a.value) && (t.planar = !0, t.linear = !0);
  82359. break;
  82360. case 71:
  82361. t.degreeOfSplineCurve = a.value;
  82362. break;
  82363. case 72:
  82364. t.numberOfKnots = a.value;
  82365. break;
  82366. case 73:
  82367. t.numberOfControlPoints = a.value;
  82368. break;
  82369. case 74:
  82370. t.numberOfFitPoints = a.value;
  82371. break;
  82372. case 210:
  82373. t.normalVector = c(e);
  82374. break;
  82375. default:
  82376. i(t, a);
  82377. }
  82378. a = e.next();
  82379. }
  82380. return t;
  82381. }, O.ForEntityName = "TEXT", O.prototype.parseEntity = function (e, a) {
  82382. var t;
  82383. for (t = {
  82384. type: a.value
  82385. }, a = e.next(); "EOF" !== a && 0 !== a.code;) {
  82386. switch (a.code) {
  82387. case 10:
  82388. t.startPoint = c(e);
  82389. break;
  82390. case 11:
  82391. t.endPoint = c(e);
  82392. break;
  82393. case 40:
  82394. t.textHeight = a.value;
  82395. break;
  82396. case 41:
  82397. t.xScale = a.value;
  82398. break;
  82399. case 50:
  82400. t.rotation = a.value;
  82401. break;
  82402. case 1:
  82403. t.text = a.value;
  82404. break;
  82405. case 72:
  82406. t.halign = a.value;
  82407. break;
  82408. case 73:
  82409. t.valign = a.value;
  82410. break;
  82411. default:
  82412. i(t, a);
  82413. }
  82414. a = e.next();
  82415. }
  82416. return t;
  82417. };
  82418. var N = t(0);
  82419. function T() {
  82420. var e;
  82421. this._entityHandlers = {}, (e = this).registerEntityHandler(u), e.registerEntityHandler(l), e.registerEntityHandler(v), e.registerEntityHandler(d), e.registerEntityHandler(b), e.registerEntityHandler(p), e.registerEntityHandler(f), e.registerEntityHandler(k), e.registerEntityHandler(y), e.registerEntityHandler(h), e.registerEntityHandler(g), e.registerEntityHandler(w), e.registerEntityHandler(P), e.registerEntityHandler(F), e.registerEntityHandler(O);
  82422. }
  82423. function S(e) {
  82424. N.debug("unhandled group " + L(e));
  82425. }
  82426. function L(e) {
  82427. return e.code + ":" + e.value;
  82428. }
  82429. N.setLevel("error"), T.prototype.parse = function (e, a) {
  82430. throw new Error("read() not implemented. Use readSync()");
  82431. }, T.prototype.registerEntityHandler = function (e) {
  82432. var a = new e();
  82433. this._entityHandlers[e.ForEntityName] = a;
  82434. }, T.prototype.parseSync = function (e) {
  82435. return "string" == typeof e ? this._parse(e) : (console.error("Cannot read dxf source of type `" + typeof e), null);
  82436. }, T.prototype.parseStream = function (e, a) {
  82437. var t = "",
  82438. r = this;
  82439. e.on("data", function (e) {
  82440. t += e;
  82441. }), e.on("end", function () {
  82442. try {
  82443. var e = r._parse(t);
  82444. } catch (e) {
  82445. return a(e);
  82446. }
  82447. a(null, e);
  82448. }), e.on("error", function (e) {
  82449. a(e);
  82450. });
  82451. }, T.prototype._parse = function (e) {
  82452. var a,
  82453. t,
  82454. n = {},
  82455. c = 0,
  82456. i = e.split(/\r\n|\r|\n/g);
  82457. if (!(a = new r(i)).hasNext()) throw Error("Empty file");
  82458. var u = this,
  82459. s = function s(e, a) {
  82460. return t.code === e && t.value === a;
  82461. },
  82462. l = function l() {
  82463. var e = null,
  82464. r = null,
  82465. n = {};
  82466. for (t = a.next();;) {
  82467. if (s(0, "ENDSEC")) {
  82468. e && (n[e] = r);
  82469. break;
  82470. }
  82471. 9 === t.code ? (e && (n[e] = r), e = t.value) : 10 === t.code ? r = {
  82472. x: t.value
  82473. } : 20 === t.code ? r.y = t.value : 30 === t.code ? r.z = t.value : r = t.value, t = a.next();
  82474. }
  82475. return t = a.next(), n;
  82476. },
  82477. v = function v() {
  82478. var e,
  82479. r = {};
  82480. for (t = a.next(); "EOF" !== t.value && !s(0, "ENDSEC");) s(0, "BLOCK") ? (N.debug("block {"), e = d(), N.debug("}"), x(e), e.name ? r[e.name] = e : N.error('block with handle "' + e.handle + '" is missing a name.')) : (S(t), t = a.next());
  82481. return r;
  82482. },
  82483. d = function d() {
  82484. var e = {};
  82485. for (t = a.next(); "EOF" !== t.value;) {
  82486. switch (t.code) {
  82487. case 1:
  82488. e.xrefPath = t.value, t = a.next();
  82489. break;
  82490. case 2:
  82491. e.name = t.value, t = a.next();
  82492. break;
  82493. case 3:
  82494. e.name2 = t.value, t = a.next();
  82495. break;
  82496. case 5:
  82497. e.handle = t.value, t = a.next();
  82498. break;
  82499. case 8:
  82500. e.layer = t.value, t = a.next();
  82501. break;
  82502. case 10:
  82503. e.position = y(), t = a.next();
  82504. break;
  82505. case 67:
  82506. e.paperSpace = !(!t.value || 1 != t.value), t = a.next();
  82507. break;
  82508. case 70:
  82509. 0 != t.value && (e.type = t.value), t = a.next();
  82510. break;
  82511. case 100:
  82512. t = a.next();
  82513. break;
  82514. case 330:
  82515. e.ownerHandle = t.value, t = a.next();
  82516. break;
  82517. case 0:
  82518. if ("ENDBLK" == t.value) break;
  82519. e.entities = k(!0);
  82520. break;
  82521. default:
  82522. S(t), t = a.next();
  82523. }
  82524. if (s(0, "ENDBLK")) {
  82525. t = a.next();
  82526. break;
  82527. }
  82528. }
  82529. return e;
  82530. },
  82531. b = function b() {
  82532. var e = {};
  82533. for (t = a.next(); "EOF" !== t.value && !s(0, "ENDSEC");) {
  82534. s(0, "TABLE") ? (t = a.next(), f[t.value] ? (N.debug(t.value + " Table {"), e[f[t.value].tableName] = p(), N.debug("}")) : N.debug("Unhandled Table " + t.value)) : t = a.next();
  82535. }
  82536. return t = a.next(), e;
  82537. };
  82538. var p = function p() {
  82539. var e,
  82540. r = f[t.value],
  82541. n = {},
  82542. o = 0;
  82543. for (t = a.next(); !s(0, "ENDTAB");) switch (t.code) {
  82544. case 5:
  82545. n.handle = t.value, t = a.next();
  82546. break;
  82547. case 330:
  82548. n.ownerHandle = t.value, t = a.next();
  82549. break;
  82550. case 100:
  82551. "AcDbSymbolTable" === t.value ? t = a.next() : (S(t), t = a.next());
  82552. break;
  82553. case 70:
  82554. o = t.value, t = a.next();
  82555. break;
  82556. case 0:
  82557. t.value === r.dxfSymbolName ? n[r.tableRecordsProperty] = r.parseTableRecords() : (S(t), t = a.next());
  82558. break;
  82559. default:
  82560. S(t), t = a.next();
  82561. }
  82562. var c = n[r.tableRecordsProperty];
  82563. return c && (c.constructor === Array ? e = c.length : "object" == typeof c && (e = Object.keys(c).length), o !== e && N.warn("Parsed " + e + " " + r.dxfSymbolName + "'s but expected " + o)), t = a.next(), n;
  82564. },
  82565. f = {
  82566. VPORT: {
  82567. tableRecordsProperty: "viewPorts",
  82568. tableName: "viewPort",
  82569. dxfSymbolName: "VPORT",
  82570. parseTableRecords: function parseTableRecords() {
  82571. var e = [],
  82572. r = {};
  82573. for (N.debug("ViewPort {"), t = a.next(); !s(0, "ENDTAB");) switch (t.code) {
  82574. case 2:
  82575. r.name = t.value, t = a.next();
  82576. break;
  82577. case 10:
  82578. r.lowerLeftCorner = y(), t = a.next();
  82579. break;
  82580. case 11:
  82581. r.upperRightCorner = y(), t = a.next();
  82582. break;
  82583. case 12:
  82584. r.center = y(), t = a.next();
  82585. break;
  82586. case 13:
  82587. r.snapBasePoint = y(), t = a.next();
  82588. break;
  82589. case 14:
  82590. r.snapSpacing = y(), t = a.next();
  82591. break;
  82592. case 15:
  82593. r.gridSpacing = y(), t = a.next();
  82594. break;
  82595. case 16:
  82596. r.viewDirectionFromTarget = y(), t = a.next();
  82597. break;
  82598. case 17:
  82599. r.viewTarget = y(), t = a.next();
  82600. break;
  82601. case 42:
  82602. r.lensLength = t.value, t = a.next();
  82603. break;
  82604. case 43:
  82605. r.frontClippingPlane = t.value, t = a.next();
  82606. break;
  82607. case 44:
  82608. r.backClippingPlane = t.value, t = a.next();
  82609. break;
  82610. case 45:
  82611. r.viewHeight = t.value, t = a.next();
  82612. break;
  82613. case 50:
  82614. r.snapRotationAngle = t.value, t = a.next();
  82615. break;
  82616. case 51:
  82617. r.viewTwistAngle = t.value, t = a.next();
  82618. break;
  82619. case 79:
  82620. r.orthographicType = t.value, t = a.next();
  82621. break;
  82622. case 110:
  82623. r.ucsOrigin = y(), t = a.next();
  82624. break;
  82625. case 111:
  82626. r.ucsXAxis = y(), t = a.next();
  82627. break;
  82628. case 112:
  82629. r.ucsYAxis = y(), t = a.next();
  82630. break;
  82631. case 110:
  82632. r.ucsOrigin = y(), t = a.next();
  82633. break;
  82634. case 281:
  82635. r.renderMode = t.value, t = a.next();
  82636. break;
  82637. case 281:
  82638. r.defaultLightingType = t.value, t = a.next();
  82639. break;
  82640. case 292:
  82641. r.defaultLightingOn = t.value, t = a.next();
  82642. break;
  82643. case 330:
  82644. r.ownerHandle = t.value, t = a.next();
  82645. break;
  82646. case 63:
  82647. case 421:
  82648. case 431:
  82649. r.ambientColor = t.value, t = a.next();
  82650. break;
  82651. case 0:
  82652. "VPORT" === t.value && (N.debug("}"), e.push(r), N.debug("ViewPort {"), r = {}, t = a.next());
  82653. break;
  82654. default:
  82655. S(t), t = a.next();
  82656. }
  82657. return N.debug("}"), e.push(r), e;
  82658. }
  82659. },
  82660. LTYPE: {
  82661. tableRecordsProperty: "lineTypes",
  82662. tableName: "lineType",
  82663. dxfSymbolName: "LTYPE",
  82664. parseTableRecords: function parseTableRecords() {
  82665. var e,
  82666. r,
  82667. n = {},
  82668. o = {};
  82669. for (N.debug("LType {"), t = a.next(); !s(0, "ENDTAB");) switch (t.code) {
  82670. case 2:
  82671. o.name = t.value, e = t.value, t = a.next();
  82672. break;
  82673. case 3:
  82674. o.description = t.value, t = a.next();
  82675. break;
  82676. case 73:
  82677. (r = t.value) > 0 && (o.pattern = []), t = a.next();
  82678. break;
  82679. case 40:
  82680. o.patternLength = t.value, t = a.next();
  82681. break;
  82682. case 49:
  82683. o.pattern.push(t.value), t = a.next();
  82684. break;
  82685. case 0:
  82686. N.debug("}"), r > 0 && r !== o.pattern.length && N.warn("lengths do not match on LTYPE pattern"), n[e] = o, o = {}, N.debug("LType {"), t = a.next();
  82687. break;
  82688. default:
  82689. t = a.next();
  82690. }
  82691. return N.debug("}"), n[e] = o, n;
  82692. }
  82693. },
  82694. LAYER: {
  82695. tableRecordsProperty: "layers",
  82696. tableName: "layer",
  82697. dxfSymbolName: "LAYER",
  82698. parseTableRecords: function parseTableRecords() {
  82699. var e,
  82700. r,
  82701. n = {},
  82702. c = {};
  82703. for (N.debug("Layer {"), t = a.next(); !s(0, "ENDTAB");) switch (t.code) {
  82704. case 2:
  82705. c.name = t.value, e = t.value, t = a.next();
  82706. break;
  82707. case 62:
  82708. c.visible = t.value >= 0, c.colorIndex = Math.abs(t.value), c.color = (r = c.colorIndex, o[r]), t = a.next();
  82709. break;
  82710. case 70:
  82711. c.frozen = 0 != (1 & t.value) || 0 != (2 & t.value), t = a.next();
  82712. break;
  82713. case 0:
  82714. "LAYER" === t.value && (N.debug("}"), n[e] = c, N.debug("Layer {"), c = {}, e = void 0, t = a.next());
  82715. break;
  82716. default:
  82717. S(t), t = a.next();
  82718. }
  82719. return N.debug("}"), n[e] = c, n;
  82720. }
  82721. }
  82722. },
  82723. k = function k(e) {
  82724. var r = [],
  82725. n = e ? "ENDBLK" : "ENDSEC";
  82726. for (e || (t = a.next());;) if (0 === t.code) {
  82727. if (t.value === n) break;
  82728. var o,
  82729. c = u._entityHandlers[t.value];
  82730. if (null == c) {
  82731. N.warn("Unhandled entity " + t.value), t = a.next();
  82732. continue;
  82733. }
  82734. N.debug(t.value + " {"), o = c.parseEntity(a, t), t = a.lastReadGroup, N.debug("}"), x(o), r.push(o);
  82735. } else t = a.next();
  82736. return "ENDSEC" == n && (t = a.next()), r;
  82737. },
  82738. y = function y() {
  82739. var e = {},
  82740. r = t.code;
  82741. if (e.x = t.value, r += 10, (t = a.next()).code != r) throw new Error("Expected code for point value to be " + r + " but got " + t.code + ".");
  82742. return e.y = t.value, r += 10, (t = a.next()).code != r ? (a.rewind(), e) : (e.z = t.value, e);
  82743. },
  82744. x = function x(e) {
  82745. if (!e) throw new TypeError("entity cannot be undefined or null");
  82746. e.handle || (e.handle = c++);
  82747. };
  82748. return function () {
  82749. for (t = a.next(); !a.isEOF();) if (0 === t.code && "SECTION" === t.value) {
  82750. if (2 !== (t = a.next()).code) {
  82751. console.error("Unexpected code %s after 0:SECTION", L(t)), t = a.next();
  82752. continue;
  82753. }
  82754. "HEADER" === t.value ? (N.debug("> HEADER"), n.header = l(), N.debug("<")) : "BLOCKS" === t.value ? (N.debug("> BLOCKS"), n.blocks = v(), N.debug("<")) : "ENTITIES" === t.value ? (N.debug("> ENTITIES"), n.entities = k(!1), N.debug("<")) : "TABLES" === t.value ? (N.debug("> TABLES"), n.tables = b(), N.debug("<")) : "EOF" === t.value ? N.debug("EOF") : N.warn("Skipping section '%s'", t.value);
  82755. } else t = a.next();
  82756. }(), n;
  82757. };
  82758. a.default = T;
  82759. }]).default;
  82760. });
  82761. class DxfLoader extends EventDispatcher {
  82762. constructor() {
  82763. super();
  82764. this.parser = new Potree.DxfParser();
  82765. }
  82766. load(url, done) {
  82767. var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  82768. Potree.loadFile(url, {
  82769. returnText: true
  82770. }, data => {
  82771. var dxfJson = this.parser.parseSync(data);
  82772. console.log(dxfJson);
  82773. var model = this.createModel(dxfJson, options);
  82774. done(model);
  82775. });
  82776. }
  82777. createModel(data) {
  82778. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  82779. var root = new Object3D();
  82780. var i, entity, obj, min_x, min_y, min_z, max_x, max_y, max_z;
  82781. /* var dims = {
  82782. min: { x: false, y: false, z: false},
  82783. max: { x: false, y: false, z: false}
  82784. }; */
  82785. //let bound = THREE.Box3
  82786. for (i = 0; i < data.entities.length; i++) {
  82787. entity = data.entities[i];
  82788. obj = drawEntity(entity, data, options.unsupportTypes);
  82789. if (obj) {
  82790. var bbox = new Box3().setFromObject(obj);
  82791. /* if (bbox.min.x && ((dims.min.x === false) || (dims.min.x > bbox.min.x))) dims.min.x = bbox.min.x;
  82792. if (bbox.min.y && ((dims.min.y === false) || (dims.min.y > bbox.min.y))) dims.min.y = bbox.min.y;
  82793. if (bbox.min.z && ((dims.min.z === false) || (dims.min.z > bbox.min.z))) dims.min.z = bbox.min.z;
  82794. if (bbox.max.x && ((dims.max.x === false) || (dims.max.x < bbox.max.x))) dims.max.x = bbox.max.x;
  82795. if (bbox.max.y && ((dims.max.y === false) || (dims.max.y < bbox.max.y))) dims.max.y = bbox.max.y;
  82796. if (bbox.max.z && ((dims.max.z === false) || (dims.max.z < bbox.max.z))) dims.max.z = bbox.max.z; */
  82797. root.add(obj);
  82798. }
  82799. obj = null;
  82800. }
  82801. return root;
  82802. }
  82803. }
  82804. function drawEntity(entity, data, unsupportTypes, group) {
  82805. var mesh;
  82806. if (unsupportTypes && unsupportTypes.includes(entity.type)) {
  82807. console.warn('����һ��dxf������Ƶ�type��', entity.type);
  82808. return; //add �����Ƹ���
  82809. }
  82810. if (entity.type === 'CIRCLE' || entity.type === 'ARC') {
  82811. mesh = drawArc(entity, data, unsupportTypes, group);
  82812. } else if (entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
  82813. mesh = drawLine(entity, data, unsupportTypes, group);
  82814. } else if (entity.type === 'TEXT') {
  82815. //"MTEXT" text: "{\fKaiTi|b0|i0|c134|p49;�������̨}"
  82816. mesh = drawText(entity, data, unsupportTypes, group);
  82817. } else if (entity.type === 'SOLID') {
  82818. mesh = drawSolid(entity, data);
  82819. } else if (entity.type === 'POINT') {
  82820. mesh = drawPoint(entity, data);
  82821. } else if (entity.type === 'INSERT') {
  82822. //Ƕ������group
  82823. mesh = drawBlock(entity, data, unsupportTypes, group);
  82824. } else if (entity.type === 'SPLINE') {
  82825. mesh = drawSpline(entity, data);
  82826. } else if (entity.type === 'MTEXT') {
  82827. mesh = drawMtext(entity, data, unsupportTypes, group);
  82828. } else if (entity.type === 'ELLIPSE') {
  82829. mesh = drawEllipse(entity, data, unsupportTypes, group);
  82830. } else if (entity.type === 'DIMENSION') {
  82831. var dimTypeEnum = entity.dimensionType & 7;
  82832. if (dimTypeEnum === 0) {
  82833. mesh = drawDimension(entity, data);
  82834. } else {
  82835. console.log("Unsupported Dimension type: " + dimTypeEnum);
  82836. }
  82837. } else {
  82838. console.log("Unsupported Entity Type: " + entity.type);
  82839. }
  82840. if (entity.type === 'LWPOLYLINE' || entity.type === 'LINE' || entity.type === 'POLYLINE') {
  82841. mesh = drawLine(entity, data);
  82842. }
  82843. /* if(entity.type === 'INSERT') {
  82844. mesh = drawBlock(entity, data); //group
  82845. } */
  82846. /*
  82847. �Ŷ���arc
  82848. �ƺ�ǽ�ڶ��Dz���insert���ͣ���������
  82849. */
  82850. mesh && (mesh.dxfInfo = entity); //add
  82851. return mesh;
  82852. }
  82853. function drawEllipse(entity, data) {
  82854. var color = getColor$2(entity, data);
  82855. var xrad = Math.sqrt(Math.pow(entity.majorAxisEndPoint.x, 2) + Math.pow(entity.majorAxisEndPoint.y, 2));
  82856. var yrad = xrad * entity.axisRatio;
  82857. var rotation = Math.atan2(entity.majorAxisEndPoint.y, entity.majorAxisEndPoint.x);
  82858. var curve = new EllipseCurve(entity.center.x, entity.center.y, xrad, yrad, entity.startAngle, entity.endAngle, false,
  82859. // Always counterclockwise
  82860. rotation);
  82861. var points = curve.getPoints(50);
  82862. var geometry = new BufferGeometry().setFromPoints(points);
  82863. var material = new LineBasicMaterial({
  82864. linewidth: 1,
  82865. color: color
  82866. });
  82867. // Create the final object to add to the scene
  82868. var ellipse = new Line(geometry, material);
  82869. return ellipse;
  82870. }
  82871. function drawMtext(entity, data) {
  82872. var color = getColor$2(entity, data);
  82873. //if (!font) { return console.log('font parameter not set. Ignoring text entity.')}
  82874. var geometry = new TextGeometry(entity.text, {
  82875. //font: font,
  82876. size: entity.height * (4 / 5),
  82877. height: 1
  82878. });
  82879. var material = new MeshBasicMaterial({
  82880. color: color
  82881. });
  82882. var text = new Mesh(geometry, material);
  82883. // Measure what we rendered.
  82884. var measure = new Box3();
  82885. measure.setFromObject(text);
  82886. var textWidth = measure.max.x - measure.min.x;
  82887. // If the text ends up being wider than the box, it's supposed
  82888. // to be multiline. Doing that in threeJS is overkill.
  82889. if (textWidth > entity.width) {
  82890. console.log("Can't render this multipline MTEXT entity, sorry.", entity);
  82891. return undefined;
  82892. }
  82893. text.position.z = 0;
  82894. switch (entity.attachmentPoint) {
  82895. case 1:
  82896. // Top Left
  82897. text.position.x = entity.position.x;
  82898. text.position.y = entity.position.y - entity.height;
  82899. break;
  82900. case 2:
  82901. // Top Center
  82902. text.position.x = entity.position.x - textWidth / 2;
  82903. text.position.y = entity.position.y - entity.height;
  82904. break;
  82905. case 3:
  82906. // Top Right
  82907. text.position.x = entity.position.x - textWidth;
  82908. text.position.y = entity.position.y - entity.height;
  82909. break;
  82910. case 4:
  82911. // Middle Left
  82912. text.position.x = entity.position.x;
  82913. text.position.y = entity.position.y - entity.height / 2;
  82914. break;
  82915. case 5:
  82916. // Middle Center
  82917. text.position.x = entity.position.x - textWidth / 2;
  82918. text.position.y = entity.position.y - entity.height / 2;
  82919. break;
  82920. case 6:
  82921. // Middle Right
  82922. text.position.x = entity.position.x - textWidth;
  82923. text.position.y = entity.position.y - entity.height / 2;
  82924. break;
  82925. case 7:
  82926. // Bottom Left
  82927. text.position.x = entity.position.x;
  82928. text.position.y = entity.position.y;
  82929. break;
  82930. case 8:
  82931. // Bottom Center
  82932. text.position.x = entity.position.x - textWidth / 2;
  82933. text.position.y = entity.position.y;
  82934. break;
  82935. case 9:
  82936. // Bottom Right
  82937. text.position.x = entity.position.x - textWidth;
  82938. text.position.y = entity.position.y;
  82939. break;
  82940. default:
  82941. return undefined;
  82942. }
  82943. ;
  82944. return text;
  82945. }
  82946. function drawSpline(entity, data) {
  82947. var color = getColor$2(entity, data);
  82948. var points = entity.controlPoints.map(function (vec) {
  82949. return new Vector2(vec.x, vec.y);
  82950. });
  82951. var interpolatedPoints = [];
  82952. var curve;
  82953. if (entity.degreeOfSplineCurve === 2 || entity.degreeOfSplineCurve === 3) {
  82954. for (var i = 0; i + 2 < points.length; i = i + 2) {
  82955. if (entity.degreeOfSplineCurve === 2) {
  82956. curve = new QuadraticBezierCurve(points[i], points[i + 1], points[i + 2]);
  82957. } else {
  82958. curve = new QuadraticBezierCurve3(points[i], points[i + 1], points[i + 2]);
  82959. }
  82960. interpolatedPoints.push.apply(interpolatedPoints, curve.getPoints(50));
  82961. }
  82962. } else {
  82963. curve = new SplineCurve(points);
  82964. interpolatedPoints = curve.getPoints(100);
  82965. }
  82966. var geometry = new BufferGeometry().setFromPoints(interpolatedPoints);
  82967. var material = new LineBasicMaterial({
  82968. linewidth: 1,
  82969. color: color
  82970. });
  82971. var splineObject = new Line(geometry, material);
  82972. return splineObject;
  82973. }
  82974. function drawLine(entity, data) {
  82975. var geometry = new Geometry(),
  82976. color = getColor$2(entity, data),
  82977. material,
  82978. lineType,
  82979. vertex,
  82980. startPoint,
  82981. endPoint,
  82982. bulgeGeometry,
  82983. bulge,
  82984. i,
  82985. line;
  82986. if (!entity.vertices) return console.log('entity missing vertices.');
  82987. // create geometry
  82988. for (i = 0; i < entity.vertices.length; i++) {
  82989. if (entity.vertices[i].bulge) {
  82990. bulge = entity.vertices[i].bulge;
  82991. startPoint = entity.vertices[i];
  82992. endPoint = i + 1 < entity.vertices.length ? entity.vertices[i + 1] : geometry.vertices[0];
  82993. bulgeGeometry = new THREEx.BulgeGeometry(startPoint, endPoint, bulge);
  82994. geometry.vertices.push.apply(geometry.vertices, bulgeGeometry.vertices);
  82995. } else {
  82996. vertex = entity.vertices[i];
  82997. geometry.vertices.push(new Vector3(vertex.x, vertex.y, 0));
  82998. }
  82999. }
  83000. if (entity.shape) geometry.vertices.push(geometry.vertices[0]);
  83001. // set material
  83002. if (entity.lineType) {
  83003. lineType = data.tables.lineType.lineTypes[entity.lineType];
  83004. }
  83005. if (lineType && lineType.pattern && lineType.pattern.length !== 0) {
  83006. material = new LineDashedMaterial({
  83007. color: color,
  83008. gapSize: 4,
  83009. dashSize: 4
  83010. });
  83011. } else {
  83012. material = new LineBasicMaterial({
  83013. linewidth: 1,
  83014. color: color
  83015. });
  83016. }
  83017. // if(lineType && lineType.pattern && lineType.pattern.length !== 0) {
  83018. // geometry.computeLineDistances();
  83019. // // Ugly hack to add diffuse to this. Maybe copy the uniforms object so we
  83020. // // don't add diffuse to a material.
  83021. // lineType.material.uniforms.diffuse = { type: 'c', value: new THREE.Color(color) };
  83022. // material = new THREE.ShaderMaterial({
  83023. // uniforms: lineType.material.uniforms,
  83024. // vertexShader: lineType.material.vertexShader,
  83025. // fragmentShader: lineType.material.fragmentShader
  83026. // });
  83027. // }else {
  83028. // material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
  83029. // }
  83030. line = new Line(geometry, material);
  83031. return line;
  83032. }
  83033. function drawArc(entity, data) {
  83034. var startAngle, endAngle;
  83035. if (entity.type === 'CIRCLE') {
  83036. startAngle = entity.startAngle || 0;
  83037. endAngle = startAngle + 2 * Math.PI;
  83038. } else {
  83039. startAngle = entity.startAngle;
  83040. endAngle = entity.endAngle;
  83041. }
  83042. var curve = new ArcCurve(0, 0, entity.radius, startAngle, endAngle);
  83043. var points = curve.getPoints(32);
  83044. var geometry = new BufferGeometry().setFromPoints(points);
  83045. var material = new LineBasicMaterial({
  83046. color: getColor$2(entity, data)
  83047. });
  83048. var arc = new Line(geometry, material);
  83049. arc.position.x = entity.center.x;
  83050. arc.position.y = entity.center.y;
  83051. arc.position.z = entity.center.z;
  83052. return arc;
  83053. }
  83054. function drawSolid(entity, data) {
  83055. var material,
  83056. mesh,
  83057. verts,
  83058. geometry = new Geometry();
  83059. verts = geometry.vertices;
  83060. verts.push(new Vector3(entity.points[0].x, entity.points[0].y, entity.points[0].z));
  83061. verts.push(new Vector3(entity.points[1].x, entity.points[1].y, entity.points[1].z));
  83062. verts.push(new Vector3(entity.points[2].x, entity.points[2].y, entity.points[2].z));
  83063. verts.push(new Vector3(entity.points[3].x, entity.points[3].y, entity.points[3].z));
  83064. // Calculate which direction the points are facing (clockwise or counter-clockwise)
  83065. var vector1 = new Vector3();
  83066. var vector2 = new Vector3();
  83067. vector1.subVectors(verts[1], verts[0]);
  83068. vector2.subVectors(verts[2], verts[0]);
  83069. vector1.cross(vector2);
  83070. // If z < 0 then we must draw these in reverse order
  83071. if (vector1.z < 0) {
  83072. geometry.faces.push(new Face3(2, 1, 0));
  83073. geometry.faces.push(new Face3(2, 3, 1));
  83074. } else {
  83075. geometry.faces.push(new Face3(0, 1, 2));
  83076. geometry.faces.push(new Face3(1, 3, 2));
  83077. }
  83078. material = new MeshBasicMaterial({
  83079. color: getColor$2(entity, data)
  83080. });
  83081. return new Mesh(geometry, material);
  83082. }
  83083. function drawText(entity, data) {
  83084. var geometry, material, text;
  83085. //����Ҫfont���ܻ�������
  83086. /* if(!font)
  83087. return console.warn('Text is not supported without a Three.js font loaded with THREE.FontLoader! Load a font of your choice and pass this into the constructor. See the sample for this repository or Three.js examples at http://threejs.org/examples/?q=text#webgl_geometry_text for more details.');
  83088. */
  83089. geometry = new TextGeometry(entity.text, {
  83090. /* font: font, */height: 0,
  83091. size: entity.textHeight || 12
  83092. });
  83093. if (entity.rotation) {
  83094. var zRotation = entity.rotation * Math.PI / 180;
  83095. geometry.rotateZ(zRotation);
  83096. }
  83097. material = new MeshBasicMaterial({
  83098. color: getColor$2(entity, data)
  83099. });
  83100. text = new Mesh(geometry, material);
  83101. text.position.x = entity.startPoint.x;
  83102. text.position.y = entity.startPoint.y;
  83103. text.position.z = entity.startPoint.z;
  83104. return text;
  83105. }
  83106. function drawPoint(entity, data) {
  83107. var geometry, material, point;
  83108. geometry = new Geometry();
  83109. geometry.vertices.push(new Vector3(entity.position.x, entity.position.y, entity.position.z));
  83110. // TODO: could be more efficient. PointCloud per layer?
  83111. var numPoints = 1;
  83112. var color = getColor$2(entity, data);
  83113. var colors = new Float32Array(numPoints * 3);
  83114. colors[0] = color.r;
  83115. colors[1] = color.g;
  83116. colors[2] = color.b;
  83117. geometry.colors = colors;
  83118. geometry.computeBoundingBox();
  83119. material = new PointsMaterial({
  83120. size: 0.05,
  83121. vertexColors: VertexColors
  83122. });
  83123. point = new Points(geometry, material);
  83124. //scene.add(point);
  83125. return point;
  83126. }
  83127. function drawDimension(entity, data, unsupportTypes, parentGroup) {
  83128. return drawBlock(entity, data, unsupportTypes, parentGroup, true);
  83129. //��
  83130. /* var block = data.blocks[entity.block];
  83131. if (!block || !block.entities) return null;
  83132. var group = new THREE.Object3D();
  83133. // if(entity.anchorPoint) {
  83134. // group.position.x = entity.anchorPoint.x;
  83135. // group.position.y = entity.anchorPoint.y;
  83136. // group.position.z = entity.anchorPoint.z;
  83137. // }
  83138. for(var i = 0; i < block.entities.length; i++) {
  83139. var childEntity = drawEntity(block.entities[i], data, group);
  83140. if(childEntity && !group.children.includes(childEntity)) group.add(childEntity);
  83141. }
  83142. return group; */
  83143. }
  83144. function drawBlock(entity, data, unsupportTypes, parentGroup, isDimension) {
  83145. var block = data.blocks[entity.name];
  83146. if (!block.entities) return null;
  83147. var group = new Object3D();
  83148. parentGroup && parentGroup.add(group); //��ǰ���� Ϊ�˻��matrixWorld
  83149. if (!isDimension) {
  83150. if (entity.position) {
  83151. group.position.x = entity.position.x;
  83152. group.position.y = entity.position.y;
  83153. group.position.z = entity.position.z;
  83154. }
  83155. if (entity.xScale) {
  83156. group.scale.x = entity.xScale;
  83157. }
  83158. if (entity.yScale) {
  83159. group.scale.y = entity.yScale;
  83160. }
  83161. if (entity.rotation) {
  83162. group.rotation.z = entity.rotation * Math.PI / 180;
  83163. }
  83164. //add: ���������еĻ������������Զ add zScale
  83165. var flag;
  83166. if (entity.zScale != void 0 && entity.extrusionDirection) {
  83167. //see (005.dxf�� others/01.dxf) extrusionDirection ={x:0,y:0,z:-1}
  83168. group.position.x *= Math.sign(entity.zScale);
  83169. group.scale.x *= Math.sign(entity.zScale);
  83170. group.rotation.z *= Math.sign(entity.zScale);
  83171. flag = 1;
  83172. //�����������extrusionDirection
  83173. }
  83174. } else {
  83175. /* if(entity.anchorPoint) {
  83176. group.position.x = entity.anchorPoint.x;
  83177. group.position.y = entity.anchorPoint.y;
  83178. group.position.z = entity.anchorPoint.z;
  83179. } */
  83180. }
  83181. //add:
  83182. group.updateMatrixWorld();
  83183. var visiEntities = block.entities.filter(e => e.visible !== false);
  83184. //console.log("block�Ŀɼ�children����"+block.entities.length)
  83185. for (var i = 0; i < visiEntities.length; i++) {
  83186. var childEntity = drawEntity(visiEntities[i], data, unsupportTypes, group);
  83187. if (childEntity && !group.children.includes(childEntity)) group.add(childEntity);
  83188. }
  83189. return group;
  83190. }
  83191. function getColor$2(entity, data) {
  83192. var color = 0x000000; //default
  83193. if (entity.color) color = entity.color;else if (data.tables && data.tables.layer && data.tables.layer.layers[entity.layer]) color = data.tables.layer.layers[entity.layer].color;
  83194. if (color == null || color === 0xffffff) {
  83195. color = 0x000000;
  83196. }
  83197. return color;
  83198. }
  83199. function createLineTypeShaders(data) {
  83200. var ltype, type;
  83201. if (!data.tables || !data.tables.lineType) return;
  83202. var ltypes = data.tables.lineType.lineTypes;
  83203. for (type in ltypes) {
  83204. ltype = ltypes[type];
  83205. if (!ltype.pattern) continue;
  83206. ltype.material = createDashedLineShader(ltype.pattern);
  83207. }
  83208. }
  83209. function createDashedLineShader(pattern) {
  83210. var i,
  83211. dashedLineShader = {},
  83212. totalLength = 0.0;
  83213. for (i = 0; i < pattern.length; i++) {
  83214. totalLength += Math.abs(pattern[i]);
  83215. }
  83216. dashedLineShader.uniforms = UniformsUtils.merge([UniformsLib['common'], UniformsLib['fog'], {
  83217. 'pattern': {
  83218. type: 'fv1',
  83219. value: pattern
  83220. },
  83221. 'patternLength': {
  83222. type: 'f',
  83223. value: totalLength
  83224. }
  83225. }]);
  83226. dashedLineShader.vertexShader = ['attribute float lineDistance;', 'varying float vLineDistance;', ShaderChunk['color_pars_vertex'], 'void main() {', ShaderChunk['color_vertex'], 'vLineDistance = lineDistance;', 'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}'].join('\n');
  83227. dashedLineShader.fragmentShader = ['uniform vec3 diffuse;', 'uniform float opacity;', 'uniform float pattern[' + pattern.length + '];', 'uniform float patternLength;', 'varying float vLineDistance;', ShaderChunk['color_pars_fragment'], ShaderChunk['fog_pars_fragment'], 'void main() {', 'float pos = mod(vLineDistance, patternLength);', 'for ( int i = 0; i < ' + pattern.length + '; i++ ) {', 'pos = pos - abs(pattern[i]);', 'if( pos < 0.0 ) {', 'if( pattern[i] > 0.0 ) {', 'gl_FragColor = vec4(1.0, 0.0, 0.0, opacity );', 'break;', '}', 'discard;', '}', '}', ShaderChunk['color_fragment'], ShaderChunk['fog_fragment'], '}'].join('\n');
  83228. return dashedLineShader;
  83229. }
  83230. function findExtents(scene) {
  83231. for (var child of scene.children) {
  83232. var minX, maxX, minY, maxY;
  83233. if (child.position) {
  83234. minX = Math.min(child.position.x, minX);
  83235. minY = Math.min(child.position.y, minY);
  83236. maxX = Math.max(child.position.x, maxX);
  83237. maxY = Math.max(child.position.y, maxY);
  83238. }
  83239. }
  83240. return {
  83241. min: {
  83242. x: minX,
  83243. y: minY
  83244. },
  83245. max: {
  83246. x: maxX,
  83247. y: maxY
  83248. }
  83249. };
  83250. }
  83251. // Three.js extension functions. Webpack doesn't seem to like it if we modify the THREE object directly.
  83252. var THREEx = {
  83253. Math: {}
  83254. };
  83255. /**
  83256. * Returns the angle in radians of the vector (p1,p2). In other words, imagine
  83257. * putting the base of the vector at coordinates (0,0) and finding the angle
  83258. * from vector (1,0) to (p1,p2).
  83259. * @param {Object} p1 start point of the vector
  83260. * @param {Object} p2 end point of the vector
  83261. * @return {Number} the angle
  83262. */
  83263. THREEx.Math.angle2 = function (p1, p2) {
  83264. var v1 = new Vector2(p1.x, p1.y);
  83265. var v2 = new Vector2(p2.x, p2.y);
  83266. v2.sub(v1); // sets v2 to be our chord
  83267. v2.normalize();
  83268. if (v2.y < 0) return -Math.acos(v2.x);
  83269. return Math.acos(v2.x);
  83270. };
  83271. THREEx.Math.polar = function (point, distance, angle) {
  83272. var result = {};
  83273. result.x = point.x + distance * Math.cos(angle);
  83274. result.y = point.y + distance * Math.sin(angle);
  83275. return result;
  83276. };
  83277. /**
  83278. * Calculates points for a curve between two points
  83279. * @param startPoint - the starting point of the curve
  83280. * @param endPoint - the ending point of the curve
  83281. * @param bulge - a value indicating how much to curve
  83282. * @param segments - number of segments between the two given points
  83283. */
  83284. THREEx.BulgeGeometry = function (startPoint, endPoint, bulge, segments) {
  83285. var vertex, i, center, p0, p1, angle, radius, startAngle, thetaAngle;
  83286. Geometry.call(this);
  83287. this.startPoint = p0 = startPoint ? new Vector2(startPoint.x, startPoint.y) : new Vector2(0, 0);
  83288. this.endPoint = p1 = endPoint ? new Vector2(endPoint.x, endPoint.y) : new Vector2(1, 0);
  83289. this.bulge = bulge = bulge || 1;
  83290. angle = 4 * Math.atan(bulge);
  83291. radius = p0.distanceTo(p1) / 2 / Math.sin(angle / 2);
  83292. center = THREEx.Math.polar(startPoint, radius, THREEx.Math.angle2(p0, p1) + (Math.PI / 2 - angle / 2));
  83293. this.segments = segments = segments || Math.max(Math.abs(Math.ceil(angle / (Math.PI / 18))), 6); // By default want a segment roughly every 10 degrees
  83294. startAngle = THREEx.Math.angle2(center, p0);
  83295. thetaAngle = angle / segments;
  83296. this.vertices.push(new Vector3(p0.x, p0.y, 0));
  83297. for (i = 1; i <= segments - 1; i++) {
  83298. vertex = THREEx.Math.polar(center, Math.abs(radius), startAngle + thetaAngle * i);
  83299. this.vertices.push(new Vector3(vertex.x, vertex.y, 0));
  83300. }
  83301. };
  83302. THREEx.BulgeGeometry.prototype = Object.create(Geometry.prototype);
  83303. /* -----note--------------
  83304. */
  83305. var _q = new Quaternion();
  83306. var _targetPos = new Vector3();
  83307. var _targetVec = new Vector3();
  83308. var _effectorPos = new Vector3();
  83309. var _effectorVec = new Vector3();
  83310. var _linkPos = new Vector3();
  83311. var _invLinkQ = new Quaternion();
  83312. var _linkScale = new Vector3();
  83313. var _axis$1 = new Vector3();
  83314. var _vector$e = new Vector3();
  83315. var _matrix$2 = new Matrix4();
  83316. /**
  83317. * CCD Algorithm
  83318. * - https://web.archive.org/web/20221206080850/https://sites.google.com/site/auraliusproject/ccd-algorithm
  83319. *
  83320. * // ik parameter example
  83321. * //
  83322. * // target, effector, index in links are bone index in skeleton.bones.
  83323. * // the bones relation should be
  83324. * // <-- parent child -->
  83325. * // links[ n ], links[ n - 1 ], ..., links[ 0 ], effector
  83326. * iks = [ {
  83327. * target: 1,
  83328. * effector: 2,
  83329. * links: [ { index: 5, limitation: new Vector3( 1, 0, 0 ) }, { index: 4, enabled: false }, { index : 3 } ],
  83330. * iteration: 10,
  83331. * minAngle: 0.0,
  83332. * maxAngle: 1.0,
  83333. * } ];
  83334. */
  83335. class CCDIKSolver {
  83336. /**
  83337. * @param {THREE.SkinnedMesh} mesh
  83338. * @param {Array<Object>} iks
  83339. */
  83340. constructor(mesh) {
  83341. var iks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  83342. this.mesh = mesh;
  83343. this.iks = iks;
  83344. this._valid();
  83345. }
  83346. /**
  83347. * Update all IK bones.
  83348. *
  83349. * @return {CCDIKSolver}
  83350. */
  83351. update() {
  83352. var iks = this.iks;
  83353. for (var i = 0, il = iks.length; i < il; i++) {
  83354. this.updateOne(iks[i]);
  83355. }
  83356. return this;
  83357. }
  83358. /**
  83359. * Update one IK bone
  83360. *
  83361. * @param {Object} ik parameter
  83362. * @return {CCDIKSolver}
  83363. */
  83364. updateOne(ik) {
  83365. var bones = this.mesh.skeleton.bones;
  83366. // for reference overhead reduction in loop
  83367. var math = Math;
  83368. var effector = bones[ik.effector];
  83369. var target = bones[ik.target];
  83370. // don't use getWorldPosition() here for the performance
  83371. // because it calls updateMatrixWorld( true ) inside.
  83372. _targetPos.setFromMatrixPosition(target.matrixWorld);
  83373. var links = ik.links;
  83374. var iteration = ik.iteration !== undefined ? ik.iteration : 1;
  83375. for (var i = 0; i < iteration; i++) {
  83376. var rotated = false;
  83377. for (var j = 0, jl = links.length; j < jl; j++) {
  83378. var link = bones[links[j].index];
  83379. // skip this link and following links
  83380. if (links[j].enabled === false) break;
  83381. var limitation = links[j].limitation;
  83382. var rotationMin = links[j].rotationMin;
  83383. var rotationMax = links[j].rotationMax;
  83384. // don't use getWorldPosition/Quaternion() here for the performance
  83385. // because they call updateMatrixWorld( true ) inside.
  83386. link.matrixWorld.decompose(_linkPos, _invLinkQ, _linkScale);
  83387. _invLinkQ.invert();
  83388. _effectorPos.setFromMatrixPosition(effector.matrixWorld);
  83389. // work in link world
  83390. _effectorVec.subVectors(_effectorPos, _linkPos);
  83391. _effectorVec.applyQuaternion(_invLinkQ);
  83392. _effectorVec.normalize();
  83393. _targetVec.subVectors(_targetPos, _linkPos);
  83394. _targetVec.applyQuaternion(_invLinkQ);
  83395. _targetVec.normalize();
  83396. var angle = _targetVec.dot(_effectorVec);
  83397. if (angle > 1.0) {
  83398. angle = 1.0;
  83399. } else if (angle < -1.0) {
  83400. angle = -1.0;
  83401. }
  83402. angle = math.acos(angle);
  83403. // skip if changing angle is too small to prevent vibration of bone
  83404. if (angle < 1e-5) continue;
  83405. if (ik.minAngle !== undefined && angle < ik.minAngle) {
  83406. angle = ik.minAngle;
  83407. }
  83408. if (ik.maxAngle !== undefined && angle > ik.maxAngle) {
  83409. angle = ik.maxAngle;
  83410. }
  83411. _axis$1.crossVectors(_effectorVec, _targetVec);
  83412. _axis$1.normalize();
  83413. _q.setFromAxisAngle(_axis$1, angle);
  83414. link.quaternion.multiply(_q);
  83415. // TODO: re-consider the limitation specification
  83416. if (limitation !== undefined) {
  83417. var c = link.quaternion.w;
  83418. if (c > 1.0) c = 1.0;
  83419. var c2 = math.sqrt(1 - c * c);
  83420. link.quaternion.set(limitation.x * c2, limitation.y * c2, limitation.z * c2, c);
  83421. }
  83422. if (rotationMin !== undefined) {
  83423. link.rotation.setFromVector3(_vector$e.setFromEuler(link.rotation).max(rotationMin));
  83424. }
  83425. if (rotationMax !== undefined) {
  83426. link.rotation.setFromVector3(_vector$e.setFromEuler(link.rotation).min(rotationMax));
  83427. }
  83428. link.updateMatrixWorld(true);
  83429. rotated = true;
  83430. }
  83431. if (!rotated) break;
  83432. }
  83433. return this;
  83434. }
  83435. /**
  83436. * Creates Helper
  83437. *
  83438. * @param {number} sphereSize
  83439. * @return {CCDIKHelper}
  83440. */
  83441. createHelper(sphereSize) {
  83442. return new CCDIKHelper(this.mesh, this.iks, sphereSize);
  83443. }
  83444. // private methods
  83445. _valid() {
  83446. var iks = this.iks;
  83447. var bones = this.mesh.skeleton.bones;
  83448. for (var i = 0, il = iks.length; i < il; i++) {
  83449. var ik = iks[i];
  83450. var effector = bones[ik.effector];
  83451. var links = ik.links;
  83452. var link0 = void 0,
  83453. link1 = void 0;
  83454. link0 = effector;
  83455. for (var j = 0, jl = links.length; j < jl; j++) {
  83456. link1 = bones[links[j].index];
  83457. if (link0.parent !== link1) {
  83458. console.warn('THREE.CCDIKSolver: bone ' + link0.name + ' is not the child of bone ' + link1.name);
  83459. }
  83460. link0 = link1;
  83461. }
  83462. }
  83463. }
  83464. }
  83465. function getPosition(bone, matrixWorldInv) {
  83466. return _vector$e.setFromMatrixPosition(bone.matrixWorld).applyMatrix4(matrixWorldInv);
  83467. }
  83468. function setPositionOfBoneToAttributeArray(array, index, bone, matrixWorldInv) {
  83469. var v = getPosition(bone, matrixWorldInv);
  83470. array[index * 3 + 0] = v.x;
  83471. array[index * 3 + 1] = v.y;
  83472. array[index * 3 + 2] = v.z;
  83473. }
  83474. /**
  83475. * Visualize IK bones
  83476. */
  83477. class CCDIKHelper extends Object3D {
  83478. /**
  83479. * @param {SkinnedMesh} mesh
  83480. * @param {Array<Object>} [iks=[]]
  83481. * @param {number} [sphereSize=0.25]
  83482. */
  83483. constructor(mesh) {
  83484. var iks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  83485. var sphereSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.25;
  83486. super();
  83487. this.root = mesh;
  83488. this.iks = iks;
  83489. this.matrix.copy(mesh.matrixWorld);
  83490. this.matrixAutoUpdate = false;
  83491. this.sphereGeometry = new SphereGeometry(sphereSize, 16, 8);
  83492. this.targetSphereMaterial = new MeshBasicMaterial({
  83493. color: new Color(0xff8888),
  83494. depthTest: false,
  83495. depthWrite: false,
  83496. transparent: true
  83497. });
  83498. this.effectorSphereMaterial = new MeshBasicMaterial({
  83499. color: new Color(0x88ff88),
  83500. depthTest: false,
  83501. depthWrite: false,
  83502. transparent: true
  83503. });
  83504. this.linkSphereMaterial = new MeshBasicMaterial({
  83505. color: new Color(0x8888ff),
  83506. depthTest: false,
  83507. depthWrite: false,
  83508. transparent: true
  83509. });
  83510. this.lineMaterial = new LineBasicMaterial({
  83511. color: new Color(0xff0000),
  83512. depthTest: false,
  83513. depthWrite: false,
  83514. transparent: true
  83515. });
  83516. this._init();
  83517. }
  83518. /**
  83519. * Updates IK bones visualization.
  83520. *
  83521. * @param {Boolean} force
  83522. */
  83523. updateMatrixWorld(force) {
  83524. var mesh = this.root;
  83525. if (this.visible) {
  83526. var offset = 0;
  83527. var iks = this.iks;
  83528. var bones = mesh.skeleton.bones;
  83529. _matrix$2.copy(mesh.matrixWorld).invert();
  83530. for (var i = 0, il = iks.length; i < il; i++) {
  83531. var ik = iks[i];
  83532. var targetBone = bones[ik.target];
  83533. var effectorBone = bones[ik.effector];
  83534. var targetMesh = this.children[offset++];
  83535. var effectorMesh = this.children[offset++];
  83536. targetMesh.position.copy(getPosition(targetBone, _matrix$2));
  83537. effectorMesh.position.copy(getPosition(effectorBone, _matrix$2));
  83538. for (var j = 0, jl = ik.links.length; j < jl; j++) {
  83539. var link = ik.links[j];
  83540. var linkBone = bones[link.index];
  83541. var linkMesh = this.children[offset++];
  83542. linkMesh.position.copy(getPosition(linkBone, _matrix$2));
  83543. }
  83544. var line = this.children[offset++];
  83545. var array = line.geometry.attributes.position.array;
  83546. setPositionOfBoneToAttributeArray(array, 0, targetBone, _matrix$2);
  83547. setPositionOfBoneToAttributeArray(array, 1, effectorBone, _matrix$2);
  83548. for (var _j = 0, _jl = ik.links.length; _j < _jl; _j++) {
  83549. var _link = ik.links[_j];
  83550. var _linkBone = bones[_link.index];
  83551. setPositionOfBoneToAttributeArray(array, _j + 2, _linkBone, _matrix$2);
  83552. }
  83553. line.geometry.attributes.position.needsUpdate = true;
  83554. }
  83555. }
  83556. this.matrix.copy(mesh.matrixWorld);
  83557. super.updateMatrixWorld(force);
  83558. }
  83559. /**
  83560. * Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app.
  83561. */
  83562. dispose() {
  83563. this.sphereGeometry.dispose();
  83564. this.targetSphereMaterial.dispose();
  83565. this.effectorSphereMaterial.dispose();
  83566. this.linkSphereMaterial.dispose();
  83567. this.lineMaterial.dispose();
  83568. var children = this.children;
  83569. for (var i = 0; i < children.length; i++) {
  83570. var child = children[i];
  83571. if (child.isLine) child.geometry.dispose();
  83572. }
  83573. }
  83574. // private method
  83575. _init() {
  83576. var scope = this;
  83577. var iks = this.iks;
  83578. function createLineGeometry(ik) {
  83579. var geometry = new BufferGeometry();
  83580. var vertices = new Float32Array((2 + ik.links.length) * 3);
  83581. geometry.setAttribute('position', new BufferAttribute(vertices, 3));
  83582. return geometry;
  83583. }
  83584. function createTargetMesh() {
  83585. return new Mesh(scope.sphereGeometry, scope.targetSphereMaterial);
  83586. }
  83587. function createEffectorMesh() {
  83588. return new Mesh(scope.sphereGeometry, scope.effectorSphereMaterial);
  83589. }
  83590. function createLinkMesh() {
  83591. return new Mesh(scope.sphereGeometry, scope.linkSphereMaterial);
  83592. }
  83593. function createLine(ik) {
  83594. return new Line(createLineGeometry(ik), scope.lineMaterial);
  83595. }
  83596. for (var i = 0, il = iks.length; i < il; i++) {
  83597. var ik = iks[i];
  83598. this.add(createTargetMesh());
  83599. this.add(createEffectorMesh());
  83600. for (var j = 0, jl = ik.links.length; j < jl; j++) {
  83601. this.add(createLinkMesh());
  83602. }
  83603. this.add(createLine(ik));
  83604. }
  83605. }
  83606. }
  83607. //import * as GaussianSplats3D from "../../../libs/gaussian/gaussian-splats-3d.module.js";
  83608. var loaders = {};
  83609. var mapArea;
  83610. var shelterHistory = [];
  83611. Potree.isIframeChild = window.parent != window; //子页面
  83612. /* if(Potree.isIframeChild){
  83613. let rootWin = Common.getRootWindow()
  83614. rootWin && rootWin.viewer.dispatchEvent({type:'createIframe', window}) //给祖先页面发送信息,得不到可能跨域了或无viewer
  83615. } */
  83616. /* window.addEventListener('focus',()=>{
  83617. console.log('focus',window.winIndex)
  83618. })
  83619. window.addEventListener('blur',()=>{
  83620. console.log('blur',window.winIndex)
  83621. }) */
  83622. Cache.enabled = true; //这样不会重复网络请求相同的图(如热点换图)。
  83623. class Viewer extends ViewerBase {
  83624. constructor(domElement, mapArea_) {
  83625. var _this$modules$SiteMod;
  83626. var args = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  83627. super(domElement, $.extend(args, {
  83628. name: 'mainViewer',
  83629. antialias: true,
  83630. preserveDrawingBuffer: true
  83631. }));
  83632. //注:viewer因为要分屏,尤其是四屏,preserveDrawingBuffer需要为true, 否则无法局部clear
  83633. window.viewer = this;
  83634. mapArea = mapArea_;
  83635. this.setLoaders();
  83636. this.tempRange = {
  83637. ir: {
  83638. min: Infinity,
  83639. max: -Infinity
  83640. },
  83641. //红外
  83642. temp: {
  83643. min: Infinity,
  83644. max: -Infinity
  83645. } //火灾
  83646. };
  83647. /* if(Potree.settings.number == 'SS-t-g45LdhXGdYv'){
  83648. this.tempRange.temp = {min:473.1, max:1273.1}
  83649. } */
  83650. if (this.renderer.capabilities.isWebGL2) {
  83651. Potree.settings.isWebgl2 = true; //是否启用webgl2
  83652. }
  83653. if (Potree.settings.editType == "pano" || Potree.settings.editType == "merge") {
  83654. this.modules = {
  83655. Alignment,
  83656. SiteModel,
  83657. volumeComputer: new VolumeComputer() //暂时
  83658. };
  83659. if (Potree.settings.editType == "pano") {
  83660. this.modules.PanoEditor = PanoEditor$1;
  83661. } else if (Potree.settings.editType == "merge") {
  83662. this.modules.MergeEditor = MergeEditor;
  83663. this.modules.CamAniEditor = CamAniEditor;
  83664. this.modules.AnimationEditor = new AnimationEditor();
  83665. Potree.settings.useDepthTex = Potree.settings.mergeType2;
  83666. }
  83667. } else {
  83668. this.modules = {
  83669. Clip,
  83670. Alignment,
  83671. SiteModel,
  83672. RouteGuider: new RouteGuider(),
  83673. clipping: new Clipping(),
  83674. ParticleEditor,
  83675. CamAniEditor,
  83676. volumeComputer: new VolumeComputer(),
  83677. MergeEditor
  83678. };
  83679. }
  83680. {
  83681. Potree.timeCollect = {
  83682. //median预置一个中等值,以防止cpu过低的设备首次卡顿
  83683. //depthSampler : {minCount:400, median: 1}, //旧的 实时从图片中获取色值的用时,但是现在直接从data中取
  83684. depthSamChangeImg: {
  83685. minCount: 200,
  83686. median: 25
  83687. },
  83688. //换图的用时。 需要一开始就start
  83689. sortByScore: {
  83690. minCount: Infinity
  83691. }
  83692. //loop :{minCount:Infinity }
  83693. };
  83694. for (var i in Potree.timeCollect) {
  83695. Potree.timeCollect[i].measures = [];
  83696. Potree.timeCollect[i].sum = 0;
  83697. }
  83698. setTimeout(() => {
  83699. for (var _i in Potree.timeCollect) {
  83700. Potree.timeCollect[_i].start = true;
  83701. }
  83702. /* setTimeout(()=>{
  83703. console.log('timeCollect', Potree.timeCollect.depthSampler.median, Potree.timeCollect.depthSampler.ave, Potree.timeCollect.depthSampler.measures.length)
  83704. },10000) */
  83705. }, 2000);
  83706. {
  83707. this.fpsCollect = {};
  83708. var init = name => {
  83709. this.fpsCollect[name] = [];
  83710. this.fpsCollect[name].durSum = 0;
  83711. };
  83712. init('short');
  83713. init('long');
  83714. init('rendered');
  83715. init('renderedLong');
  83716. init('camChanged');
  83717. init('camChangedLong');
  83718. Potree.fps = 40; //随便写一个
  83719. Potree.fps2 = 40; //随便写一个
  83720. Potree.fpsRendered = 35; //随便写一个
  83721. Potree.fpsRendered2 = 35; //随便写一个
  83722. Potree.fpsCamChanged = 30; //随便写一个
  83723. Potree.fpsCamChanged2 = 30; //随便写一个
  83724. //this.pageHiddenCollect = []
  83725. }
  83726. /* setTimeout(()=>{
  83727. console.log('depthSamChangeImg',Potree.timeCollect.depthSamChangeImg.median, 'sortByScore',Potree.timeCollect.sortByScore.median)
  83728. console.log('fps',Potree.fps, Potree.fps2,Potree.fpsRendered )
  83729. },25000) */
  83730. }
  83731. this.memoryModelCountInfo = {
  83732. tilePosCount: 0,
  83733. tileTexArea: 0,
  83734. otherPosCount: 0,
  83735. otherTexArea: 0
  83736. };
  83737. this.navigateMode = 'free'; // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点,
  83738. this.isEdit = true;
  83739. this.waitQueue = [];
  83740. this.unitConvert = new UoMService();
  83741. this.visible = true;
  83742. this.fpVisiDatasets = [];
  83743. this.atDatasets = [];
  83744. this.objs = new Object3D(), this.objs.name = 'objs';
  83745. this.objs.addEventListener('isVisible', () => {
  83746. this.setAllTilesets(model => model.visiChangeCallback());
  83747. });
  83748. this.testMaxNodeCount = 0;
  83749. this.tiles3dVisiVCount = 0;
  83750. //this.lastPos = new THREE.Vector3(Infinity,Infinity,Infinity)
  83751. //-------------
  83752. var supportExtFragDepth = !!Potree.Features.EXT_DEPTH.isSupported(this.renderer.getContext()); //iphoneX居然不支持
  83753. //这意味着边缘增强和测量线遮挡失效
  83754. if (!supportExtFragDepth) console.error('ExtFragDepth unsupported! 边缘增强和测量线遮挡失效');
  83755. this.guiLoaded = false;
  83756. this.guiLoadTasks = [];
  83757. this.onVrListeners = [];
  83758. this.messages = [];
  83759. this.elMessages = $("\n\t\t<div id=\"message_listing\" \n\t\t\tstyle=\"position: absolute; z-index: 1000; left: 10px; bottom: 10px\">\n\t\t</div>");
  83760. $(domElement).append(this.elMessages);
  83761. this.fakeMeasure = {};
  83762. setTimeout(() => {
  83763. if (!Potree.settings.isWebgl2 && !Potree.browser.urlHasValue('webgl1')) {
  83764. console.warn('不支持webgl2');
  83765. }
  83766. }, 3000);
  83767. try {
  83768. if (!Potree.settings.isOfficial) {
  83769. // generate missing dom hierarchy
  83770. if ($(domElement).find('#potree_map').length === 0) {
  83771. var potreeMap = $("\n <div id=\"potree_map\" class=\"mapBox\" style=\"position: absolute; left: 50px; top: 50px; width: 400px; height: 400px; display: none\">\n <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;\">\n </div>\n <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>\n </div>\n ");
  83772. $(domElement).append(potreeMap);
  83773. }
  83774. if ($(domElement).find('#potree_description').length === 0) {
  83775. var potreeDescription = $("<div id=\"potree_description\" class=\"potree_info_text\"></div>");
  83776. $(domElement).append(potreeDescription);
  83777. }
  83778. if ($(domElement).find('#potree_annotations').length === 0) {
  83779. var potreeAnnotationContainer = $("\n <div id=\"potree_annotation_container\" \n style=\"position: absolute; z-index: 100000; width: 100%; height: 100%; pointer-events: none;\"></div>");
  83780. $(domElement).append(potreeAnnotationContainer);
  83781. }
  83782. if ($(domElement).find('#potree_quick_buttons').length === 0) {
  83783. var _potreeMap = $("\n <div id=\"potree_quick_buttons\" class=\"quick_buttons_container\" style=\"\">\n </div>\n ");
  83784. $(domElement).append(_potreeMap);
  83785. }
  83786. //add
  83787. {
  83788. $(domElement).append($("<div id='potree_labels'></div>"));
  83789. if (!mapArea && Potree.settings.editType != 'merge' /* || Potree.settings.showObjectsOnMap */) {
  83790. mapArea = $("<div id='mapGaode'></div>");
  83791. $(domElement).append(mapArea);
  83792. mapArea = mapArea[0];
  83793. }
  83794. }
  83795. /* let domRoot = this.renderer.domElement.parentElement;
  83796. let elAttach = $("<input type='button' value='test'></input>");
  83797. elAttach.css({
  83798. position : "absolute",
  83799. right : '10%',
  83800. bottom: '20px',
  83801. zIndex: "10000",
  83802. fontSize:'1em', color:"black",
  83803. background:'rgba(255,255,255,0.8)',
  83804. })
  83805. let state = false
  83806. elAttach.on("click", () => {
  83807. window.buttonFunction && window.buttonFunction()
  83808. });
  83809. domRoot.appendChild(elAttach[0]); */
  83810. }
  83811. this.tiles3dMemoryUsage = 0;
  83812. this.pointCloudLoadedCallback = args.onPointCloudLoaded || function () {};
  83813. // if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
  83814. // defaultSettings.navigation = "Orbit";
  83815. // }
  83816. this.server = null;
  83817. this.fov = 60;
  83818. this.isFlipYZ = false;
  83819. this.useDEMCollisions = false;
  83820. this.generateDEM = false;
  83821. this.minNodeSize = 30; //允许加载的node的最小可见像素宽度。越大越省性能
  83822. this.edlStrength = 1.0;
  83823. this.edlRadius = 1.4;
  83824. this.edlOpacity = 1.0;
  83825. this.useEDL = false;
  83826. this.description = "";
  83827. this.setClassifications(ClassificationScheme['user']);
  83828. this.moveSpeed = 1;
  83829. this.lengthUnit = LengthUnits.METER;
  83830. this.lengthUnitDisplay = LengthUnits.METER;
  83831. this.showBoundingBox = false;
  83832. this.showAnnotations = true;
  83833. this.freeze = false;
  83834. this.elevationGradientRepeat = ElevationGradientRepeat.CLAMP;
  83835. this.filterReturnNumberRange = [0, 7];
  83836. this.filterNumberOfReturnsRange = [0, 7];
  83837. this.filterGPSTimeRange = [-Infinity, Infinity];
  83838. this.filterPointSourceIDRange = [0, 65535];
  83839. this.potreeRenderer = null;
  83840. this.edlRenderer = null;
  83841. this.pRenderer = null;
  83842. this.scene = null;
  83843. this.sceneVR = null;
  83844. this.overlay = null;
  83845. this.overlayCamera = null;
  83846. this.inputHandler = null;
  83847. this.controls = null;
  83848. this.clippingTool = null;
  83849. this.transformationTool = null;
  83850. this.navigationCube = null;
  83851. this.compass = null;
  83852. this.skybox = null;
  83853. this.clock = new Clock();
  83854. this.background = null;
  83855. this.buffers = new Map();
  83856. if (args.noDragAndDrop) {} else {
  83857. this.initDragAndDrop();
  83858. }
  83859. if (Potree.settings.isTest) {
  83860. this.stats = new _Stats();
  83861. this.stats.showPanel(2); // 0: fps, 1: ms, 2: mb, 3+: custom
  83862. document.body.appendChild(this.stats.dom);
  83863. }
  83864. {
  83865. this.overlay = new Scene();
  83866. this.overlayCamera = new OrthographicCamera(0, 1, 1, 0, -1000, 1000);
  83867. }
  83868. this.pRenderer = new Renderer$1(this.renderer);
  83869. {
  83870. var near = 2.5;
  83871. var far = 10.0;
  83872. var fov = 90;
  83873. this.shadowTestCam = new PerspectiveCamera(90, 1, near, far);
  83874. this.shadowTestCam.position.set(3.50, -2.80, 8.561);
  83875. this.shadowTestCam.lookAt(new Vector3(0, 0, 4.87));
  83876. }
  83877. var scene = new ExtendScene(this.renderer);
  83878. {
  83879. // create VR scene
  83880. this.sceneVR = new Scene();
  83881. // let texture = new THREE.TextureLoader().load(`${Potree.resourcePath}/images/vr_controller_help.jpg`);
  83882. // let plane = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
  83883. // let infoMaterial = new THREE.MeshBasicMaterial({map: texture});
  83884. // let infoNode = new THREE.Mesh(plane, infoMaterial);
  83885. // infoNode.position.set(-0.5, 1, 0);
  83886. // infoNode.scale.set(0.4, 0.3, 1);
  83887. // infoNode.lookAt(0, 1, 0)
  83888. // this.sceneVR.add(infoNode);
  83889. // window.infoNode = infoNode;
  83890. }
  83891. this.setScene(scene);
  83892. //add: for 截图时抗锯齿
  83893. {
  83894. /* this.composer = new EffectComposer( this.renderer );
  83895. this.ssaaRenderPass = new SSAARenderPass(0x000000, 0);
  83896. this.composer.addPass( this.ssaaRenderPass );
  83897. */
  83898. //this.ssaaRenderPass.useCopy = true
  83899. //this.ssaaRenderPass.renderToScreen = true;
  83900. //this.ssaaRenderPass.needsSwap = false
  83901. //见 https://threejs.org/examples/?q=AA#webgl_postprocessing_fxaa 效果和SSAA差不多,都对透明不太友好。
  83902. /* let outlinePass = this.outlinePass = new OutlinePass( );
  83903. this.ssaaRenderPass.addPass(outlinePass)
  83904. */
  83905. //ssaa有透明度、发黑的问题所以不用了
  83906. //--------------------------
  83907. this.composer = new EffectComposer(this.renderer);
  83908. this.composer.scaleRatio = 4; //将底图和测量线绘制在一张高倍贴图上,for测量线不模糊
  83909. this.composer.readTarget = true; //把底图和测量线一起fxaa
  83910. /* const renderPass = new RenderPass();
  83911. //renderPass.clearColor = new THREE.Color( 0,0,0 );
  83912. //renderPass.clearAlpha = 0;
  83913. renderPass.clear = !this.composer.readTarget
  83914. this.composer.addPass( renderPass );
  83915. */
  83916. //for 融合页面
  83917. var outlinePass = this.outlinePass = new OutlinePass();
  83918. outlinePass.renderToScreen = true; //这样更流畅,不用ssaa了,缺点是outline有锯齿
  83919. outlinePass.enabled = false;
  83920. this.composer.addPass(outlinePass);
  83921. outlinePass.edgeStrength = 4;
  83922. outlinePass.edgeGlow = 0;
  83923. outlinePass.visibleEdgeColor = new Color("#09a1b3");
  83924. /* this.fxaaPass = new ShaderPass( FXAAShader );
  83925. this.fxaaPass.readTarget = true //add
  83926. this.fxaaPass.setSize = function(width, height){
  83927. this.material.uniforms[ 'resolution' ].value.x = 1 / ( width ) ;
  83928. this.material.uniforms[ 'resolution' ].value.y = 1 / ( height ) ;
  83929. }
  83930. this.fxaaPass.renderToScreen = true;
  83931. this.composer.addPass( this.fxaaPass ); */
  83932. //抗锯齿截图 效果时而好时而不好,文字比较模糊
  83933. //这两个暂时不能一起用。目前刚好不需要一起用
  83934. /* this.images360.fastTranMaskPass = new FastTranPass( this.renderer )
  83935. this.composer.addPass(this.images360.fastTranMaskPass)//add */
  83936. }
  83937. {
  83938. this.mainViewport = new Viewport(this.scene.view, this.scene.cameraP, {
  83939. left: 0,
  83940. bottom: 0,
  83941. width: 1,
  83942. height: 1,
  83943. name: 'MainView'
  83944. });
  83945. this.viewports = [this.mainViewport];
  83946. Potree.settings.showCompass && this.addCompass();
  83947. //this.axis = new AxisViewer(this.mainViewport, this.renderArea )
  83948. this.magnifier = new Magnifier(this);
  83949. this.reticule = new Reticule(this);
  83950. this.scene.scene.add(this.magnifier);
  83951. this.scene.scene.add(this.reticule);
  83952. if (Potree.settings.editType != "pano" && Potree.settings.editType != 'merge' /* || Potree.settings.showObjectsOnMap */ && !args.noMap) {
  83953. this.mapViewer = new MapViewer(mapArea /* $('#mapGaode')[0] */);
  83954. }
  83955. if (Potree.settings.showMap3d) {
  83956. //test
  83957. this.map3d = new MapLayer(this, this.mainViewport, true);
  83958. this.scene.scene.add(this.map3d.sceneGroup);
  83959. this.map3d.disabled = true;
  83960. this.map3d.addEventListener('loadDone', () => {
  83961. this.dispatchEvent('content_changed');
  83962. });
  83963. this.map3d.addEventListener('tileLoaded', () => {
  83964. Potree.Common.intervalTool.isWaiting('mapUpdateTile', () => {
  83965. this.dispatchEvent('content_changed'); //渲染 尤其vpn访问google网速慢需要
  83966. }, 1000);
  83967. });
  83968. this.map3d.sceneGroup.position.z = -0.1;
  83969. this.addEventListener('setLonlat', e => {
  83970. this.map3d.disabled = false;
  83971. Potree.settings.cameraFar = 80000000;
  83972. }, {
  83973. once: true
  83974. });
  83975. }
  83976. this.inputHandler = new InputHandler(this, this.scene.scene);
  83977. this.inputHandler.containsMouse = true; //初始化,使键盘事件在mainViewer有效
  83978. this.inputHandler.registerInteractiveScene(this.scene.overlayScene);
  83979. //this.inputHandler.setScene(this.scene);
  83980. //this.inputHandler.addInputListener(this);//add
  83981. this.clippingTool = new ClippingTool(this);
  83982. this.transformationTool = new TransformationTool(this);
  83983. this.navigationCube = new NavigationCube(this);
  83984. this.navigationCube.visible = false;
  83985. this.createControls();
  83986. this.clippingTool.setScene(this.scene);
  83987. var onPointcloudAdded = e => {
  83988. if (this.scene.pointclouds.length === 1) {
  83989. var speed = e.pointcloud.boundingBox.getSize(new Vector3()).length();
  83990. speed = speed / 2000;
  83991. this.setMoveSpeed(speed);
  83992. }
  83993. };
  83994. var onVolumeRemoved = e => {
  83995. this.inputHandler.deselect(e.volume);
  83996. };
  83997. this.addEventListener('scene_changed', e => {
  83998. this.inputHandler.setScene(e.scene);
  83999. this.clippingTool.setScene(this.scene);
  84000. if (!e.scene.hasEventListener("pointcloud_added", onPointcloudAdded)) {
  84001. e.scene.addEventListener("pointcloud_added", onPointcloudAdded);
  84002. }
  84003. if (!e.scene.hasEventListener("volume_removed", onPointcloudAdded)) {
  84004. e.scene.addEventListener("volume_removed", onVolumeRemoved);
  84005. }
  84006. });
  84007. this.scene.addEventListener("volume_removed", onVolumeRemoved);
  84008. this.scene.addEventListener('pointcloud_added', onPointcloudAdded);
  84009. }
  84010. {
  84011. // set defaults
  84012. this.setFOV(60);
  84013. this.setEDLEnabled(false);
  84014. this.setEDLRadius(3);
  84015. this.setEDLStrength(0.01);
  84016. this.setEDLOpacity(1.0);
  84017. this.setPointBudget(1 * 1000 * 1000);
  84018. this.setShowBoundingBox(false);
  84019. this.setFreeze(false);
  84020. this.setControls(this.fpControls /* orbitControls */);
  84021. this.setBackground(new Color(Potree.config.background), 1 /* 'gradient' */);
  84022. this.scaleFactor = 1;
  84023. this.loadSettingsFromURL();
  84024. }
  84025. // start rendering!
  84026. //if(args.useDefaultRenderLoop === undefined || args.useDefaultRenderLoop === true){
  84027. //requestAnimationFrame(this.loop.bind(this));
  84028. //}
  84029. this.renderer.setAnimationLoop(this.loop.bind(this));
  84030. this.loadGUI = this.loadGUI.bind(this);
  84031. this.annotationTool = new AnnotationTool(this);
  84032. this.measuringTool = new MeasuringTool(this);
  84033. //this.profileTool = new ProfileTool(this);
  84034. this.volumeTool = new VolumeTool(this);
  84035. this.tagTool = new TagTool(this);
  84036. //-----------
  84037. CursorDeal.init(this, this.mapViewer ? [this, this.mapViewer] : [this]); //ADD
  84038. if (Potree.settings.editType == "pano") {
  84039. this.modules.PanoEditor.init();
  84040. this.modules.SiteModel.init(); //add
  84041. } else if (Potree.settings.editType == "merge") {
  84042. this.modules.MergeEditor.init();
  84043. } else {
  84044. this.modules.SiteModel.init();
  84045. this.modules.ParticleEditor.init();
  84046. }
  84047. this.modules.Alignment.init();
  84048. this.images360 = new Images360(this);
  84049. this.scene.scene.add(this.objs);
  84050. //add test
  84051. /* const environment = new RoomEnvironment();
  84052. const pmremGenerator = new THREE.PMREMGenerator( this.renderer );
  84053. this.scene.scene.environment = pmremGenerator.fromScene( environment ).texture;
  84054. */
  84055. //-----------
  84056. this.modules.volumeComputer && this.modules.volumeComputer.init();
  84057. } catch (e) {
  84058. this.onCrash(e);
  84059. }
  84060. //-----------------------add----------------------------------------------------
  84061. /* {
  84062. let ratio
  84063. this.addEventListener('resize',(e)=>{
  84064. if(ratio != e.deviceRatio){ //因为devicePixelRatio会影响到点云大小,所以改变时计算下点云大小
  84065. viewer.scene.pointclouds.forEach(p => {
  84066. p.changePointSize()
  84067. })
  84068. }
  84069. ratio = e.deviceRatio
  84070. })
  84071. } */
  84072. {
  84073. var pointDensity = '';
  84074. Object.defineProperty(Potree.settings, "pointDensity", {
  84075. get: function get() {
  84076. return pointDensity;
  84077. },
  84078. set: density => {
  84079. if (density) {
  84080. var config = Potree.config.pointDensity[density];
  84081. var pointBudget = config.pointBudget;
  84082. if (density == 'magnifier') {
  84083. //尽可能不变pointBudget,否则点云可能会闪烁,因点云被释放又加载,如SS-t-7DUfWAUZ3V
  84084. pointBudget = Math.max(Potree.pointBudget, Potree.config.pointDensity['magnifier'].pointBudget);
  84085. } else if (this.magnifier.visible) {
  84086. //放大镜打开时要保证最低点云数量(全景模式没点)
  84087. pointBudget = Math.max(pointBudget, Potree.config.pointDensity['magnifier'].pointBudget);
  84088. }
  84089. viewer.setMinNodeSize(config.minNodeSize || Potree.config.minNodeSize);
  84090. viewer.setPointBudget(pointBudget);
  84091. pointDensity = density;
  84092. this.setPointLevels();
  84093. this.dispatchEvent('pointDensityChanged');
  84094. }
  84095. }
  84096. });
  84097. var UserPointDensity = '';
  84098. Object.defineProperty(Potree.settings, "UserPointDensity", {
  84099. get: function get() {
  84100. return UserPointDensity;
  84101. },
  84102. set: density => {
  84103. if (UserPointDensity != density) {
  84104. if (Potree.settings.displayMode == 'showPointCloud' && this.viewports.length != 4) {
  84105. //漫游模式和四屏时都有自己的pointDensity
  84106. Potree.settings.pointDensity = density;
  84107. }
  84108. UserPointDensity = density;
  84109. this.dispatchEvent('UserPointDensityChanged');
  84110. }
  84111. }
  84112. });
  84113. }
  84114. {
  84115. var cameraFar = Potree.settings.cameraFar;
  84116. Object.defineProperty(Potree.settings, "cameraFar", {
  84117. get: function get() {
  84118. return cameraFar;
  84119. },
  84120. set: far => {
  84121. if (far != cameraFar) {
  84122. if (Potree.settings.displayMode != 'showPanos' && !this.fixCamFar) {
  84123. this.mainViewport.camera.far = far;
  84124. this.mainViewport.camera.updateProjectionMatrix();
  84125. }
  84126. cameraFar = far;
  84127. }
  84128. }
  84129. });
  84130. }
  84131. /* this.reticule.addEventListener('update',(e)=>{
  84132. this.needRender = true
  84133. if(this.mapViewer && this.mapViewer.attachedToViewer)this.mapViewer.needRender = true //分屏时mapViewer也有reticule
  84134. }) */
  84135. this.reticule.addEventListener('update', e => {
  84136. this.reticule.hoverViewport && (this.reticule.hoverViewport.needRender = true);
  84137. this.lazyRenderViewports();
  84138. if (this.mapViewer && this.mapViewer.attachedToViewer && (this.mapViewer.viewports[0].needRender || this.needRender)) this.mapViewer.needRender = true; //分屏时mapViewer也有reticule
  84139. });
  84140. this.addEventListener('pointcloud_changed', e => {
  84141. if (this.screenshoting) {
  84142. this.viewports.filter(e => !e.noPointcloud).forEach(e => e.needRender = true);
  84143. } else this.lazyRenderViewports();
  84144. });
  84145. if (!Potree.settings.pathSmooth && Potree.settings.editType == 'merge') {
  84146. viewer.addEventListener('camera_changed', e => {
  84147. if (e.viewport == viewer.mainViewport && e.changeInfo.positionChanged) {
  84148. Common$1.intervalTool.isWaiting('updatePathArrows', () => {
  84149. Potree.Path.updateArrows();
  84150. }, 1000);
  84151. }
  84152. });
  84153. }
  84154. this.addEventListener('allLoaded', () => {
  84155. this.allLoaded = true;
  84156. setTimeout(this.testPointcloudsMaxLevel.bind(this), 1000); //延迟一丢丢,等画面出现
  84157. //Potree.settings.renderAllViewports = browser.maybeQilin() && this.renderer.capabilities.maxCubemapSize <= 2048 && //麒麟chromium若获取过webgl2只渲染一个viewport的话其他的会变黑
  84158. this.scene.pointclouds.forEach(pointcloud => {
  84159. pointcloud.addEventListener('isVisible', e => {
  84160. //是否显示该点的mesh(不显示也能走)
  84161. //console.log('pointcloud isVisible', this.id, e.visible)
  84162. if (e.reason != 'displayMode' && e.reason != 'overlinePass') {
  84163. this.updateModelBound('visibleChanged');
  84164. }
  84165. this.dispatchEvent('pointcloud_changed');
  84166. });
  84167. pointcloud.material.addEventListener('material_property_changed', () => {
  84168. this.dispatchEvent('pointcloud_changed');
  84169. });
  84170. });
  84171. window.addEventListener('unfocusPage', e => {
  84172. console.log('unfocusPage', document.title);
  84173. this.setDisplay(false);
  84174. });
  84175. window.addEventListener('focusPage', e => {
  84176. console.log('focusPage', document.title);
  84177. this.setDisplay(true);
  84178. });
  84179. this.createHackMesh();
  84180. }, {
  84181. once: true
  84182. });
  84183. if (Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge' || Potree.settings.mergeType2) {
  84184. var updated, zoomLevel;
  84185. var update = e => {
  84186. if (e.type == 'updateModelBound' || e.viewport == this.mainViewport && (e.changeInfo.positionChanged || zoomLevel != this.images360.zoomLevel)) {
  84187. zoomLevel = this.images360.zoomLevel; //对updateMarkerVisibles有影响
  84188. //e.changeInfo.positionChanged && shelterHistory.clear() //清空
  84189. (e.type == 'updateModelBound' || e.changeInfo.positionChanged) && this.updateDatasetAt(); //更新所在数据集
  84190. if (Potree.settings.ifShowMarker) {
  84191. Common$1.intervalTool.isWaiting('updateMarkerVisibles', () => {
  84192. if (!this.mainViewport.view.isFlying()) {
  84193. this.updateMarkerVisibles();
  84194. }
  84195. }, 500);
  84196. }
  84197. }
  84198. };
  84199. this.addEventListener('camera_changed', update);
  84200. this.addEventListener('updateModelBound', update);
  84201. this.addEventListener('showMarkerChanged', () => {
  84202. this.updatePanosVisibles(this.modules.SiteModel.currentFloor);
  84203. this.updateMarkerVisibles();
  84204. });
  84205. /* if(!Potree.Features.EXT_DEPTH.isSupported()){
  84206. this.images360.addEventListener('endChangeMode',(e)=>{
  84207. if(e.mode == 'showPanos'){
  84208. this.updateMarkerVisibles()
  84209. }
  84210. }) */
  84211. this.images360.addEventListener('getNeighbourAuto', e => {
  84212. if ( /* Potree.settings.displayMode == 'showPanos' && */e.panos.includes(this.images360.currentPano)) {
  84213. Common$1.intervalTool.isWaiting('updateMarkerVisibles', () => {
  84214. this.updateMarkerVisibles();
  84215. }, 500);
  84216. }
  84217. });
  84218. /* } */
  84219. }
  84220. if (Potree.settings.editType == 'merge') {
  84221. var updatePlayInSight = () => {
  84222. Common$1.intervalTool.isWaiting('updatePlayInSight', () => {
  84223. Overlay.updatePlayInSight();
  84224. }, 500);
  84225. };
  84226. this.addEventListener('camera_changed', updatePlayInSight);
  84227. }
  84228. (_this$modules$SiteMod = this.modules.SiteModel) === null || _this$modules$SiteMod === void 0 || _this$modules$SiteMod.bus.addEventListener('FloorChange', e => {
  84229. if (Potree.settings.editType == 'pano') {
  84230. if (this.modules.PanoEditor.entered) return; //点位编辑时楼层按钮高亮的是显示的楼层,而不是所在楼层
  84231. this.modules.PanoEditor.dispatchEvent({
  84232. type: 'changeFloor',
  84233. floor: e.currentFloor
  84234. });
  84235. } else {
  84236. this.updateFpVisiDatasets();
  84237. this.updatePanosVisibles(e.currentFloor); //问:编辑空间模型时,需不需要改为显示当前选择的楼层。因为若所在楼层和选中的不一致,修改选中楼层的轮廓却改不了marker显示很奇怪,尤其刚好在一个建筑内时。
  84238. }
  84239. });
  84240. if (Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge') {
  84241. var _this$mapViewer;
  84242. this.mapViewer && this.addEventListener('switchFloorplanSelect', e => {
  84243. //进入平面图设置后 切换选中的数据集
  84244. this.selectedFloorplan = e.pointcloud; //绝对显示
  84245. this.updateFpVisiDatasets();
  84246. var pointclouds;
  84247. if (e.pointcloud) {
  84248. pointclouds = [e.pointcloud];
  84249. } else if (this.fpVisiDatasets.length) {
  84250. pointclouds = this.fpVisiDatasets;
  84251. }
  84252. pointclouds && this.mapViewer.fitToDatasets(pointclouds);
  84253. });
  84254. (_this$mapViewer = this.mapViewer) === null || _this$mapViewer === void 0 || _this$mapViewer.mapLayer.addEventListener('floorplanLoaded', () => {
  84255. this.updateCadVisibles(this.fpVisiDatasets, true); //加载完成后重新更新下
  84256. });
  84257. /* this.modules.Clip.bus.addEventListener('updateSelectedDatasets',()=>{
  84258. this.updateFpVisiDatasets()
  84259. }) */
  84260. var count = 0;
  84261. viewer.addEventListener('pointcloud_changed', e => {
  84262. if (count > 5 && !Potree.settings.showHotIr && !Potree.settings.showHotTemp) return;
  84263. Common$1.intervalTool.isWaiting('gatherTempRange', e => {
  84264. var _Potree$visibleNodes;
  84265. if (this.gatherTempRange() && (_Potree$visibleNodes = Potree.visibleNodes) !== null && _Potree$visibleNodes !== void 0 && _Potree$visibleNodes.length) count++; //成功获取
  84266. }, MathUtils.clamp(200, count * 200, 1200));
  84267. });
  84268. }
  84269. {
  84270. var interval;
  84271. document.addEventListener('visibilitychange', e => {
  84272. var v = !document.hidden;
  84273. //console.warn('visibilitychange', v )
  84274. this.dispatchEvent({
  84275. type: 'pageVisible',
  84276. v
  84277. });
  84278. //this.pageHiddenCollect.push({time:performance.now, visible:v})
  84279. if (!v) {
  84280. var marks = performance.getEntriesByName("loop-start");
  84281. marks.length && (marks[marks.length - 1].pageHidden = true);
  84282. }
  84283. if (this.screenshoting && !v) {
  84284. //截图过程中离开页面需要照常loop。但是尽量别离开页面,效果只能达到90%
  84285. interval = setInterval(() => {
  84286. //console.log('force loop', Date.now())
  84287. if (this.screenshoting) {
  84288. //截图完成时如果还没回来就不loop
  84289. this.loop(Date.now());
  84290. }
  84291. }, 50); //实际>1000, 浏览器会放慢定时器,放慢多少不确定
  84292. } else if (v && interval) {
  84293. clearInterval(interval);
  84294. }
  84295. });
  84296. }
  84297. /* if(!Potree.isIframeChild){
  84298. window.winIndex = 0;
  84299. let index = 1;
  84300. this.addEventListener('createIframe',(e)=>{//创建了子页面
  84301. let child = e.window;
  84302. child.winIndex = index ++;
  84303. })
  84304. //不知道删除iframe时是否那些模型还在内存里,需要释放吗? 如果要需要加一个事件
  84305. } */
  84306. /* {
  84307. let setInteract = ()=>{
  84308. this.interacted = true //标记这一帧用户有操作屏幕
  84309. }
  84310. this.addEventListener('global_mousedown', setInteract)
  84311. this.addEventListener('global_touchmove', setInteract)
  84312. this.addEventListener('global_mousewheel', setInteract)
  84313. }
  84314. {//针对数据集偏离中心很远后产生的精度损失而抖动
  84315. this.addEventListener('camera_changed', e => {
  84316. if(e.viewport == this.mainViewport && (e.changeInfo.positionChanged)){
  84317. if(Potree.settings.editType != 'merge' && Potree.settings.editType != 'pano'){
  84318. if(!this.mainViewport.view.isFlying() ){
  84319. let pos = this.mainViewport.view.position.clone() // this.mainViewport.camera.getWorldPosition(new THREE.Vector3)
  84320. if(pos.lengthSq() > 25000000){
  84321. Common.intervalTool.isWaiting('moveWorldCenter', ()=>{
  84322. pos = this.mainViewport.view.position.clone()
  84323. this.mainViewport.view.translateWorld(-pos.x, -pos.y, -pos.z)
  84324. this.scene.scene.position.sub(pos)
  84325. console.log('变位置', pos)
  84326. this.scene.pointclouds.forEach(cloud=>{
  84327. Alignment.setMatrix(cloud)
  84328. })
  84329. },500)
  84330. }
  84331. }
  84332. }
  84333. }
  84334. })
  84335. }*/
  84336. }
  84337. addCompass() {
  84338. if (this.compass) return;
  84339. this.compass = new Compass(Potree.settings.compassDom, this.mainViewport);
  84340. if (!Potree.settings.editType) {
  84341. //激光场景
  84342. this.floorCompass = new FloorCompass(this);
  84343. }
  84344. }
  84345. lazyRenderViewports(updateCount) {
  84346. //本来要写this.needRender = true的, 但在分四个屏时防止太卡而排队render
  84347. var viewports = this.viewports;
  84348. if (viewports.length == 1 || this.needRender) {
  84349. return this.needRender = true;
  84350. }
  84351. var maxWaitTime = 200;
  84352. var now = Date.now();
  84353. var maxRenderCount = 1;
  84354. viewports.forEach(e => {
  84355. if (now - e.lastRenderTime > maxWaitTime) {
  84356. e.needRender = true;
  84357. }
  84358. });
  84359. var renderCount = viewports.filter(e => e.needRender).length;
  84360. //console.log('renderCount', renderCount)
  84361. var list = viewports.filter(e => !e.needRender).sort((a, b) => a.lastRenderTime - b.lastRenderTime); //没有准备render的,按上次渲染时间排序,作为候补
  84362. if (renderCount < maxRenderCount) {
  84363. //还有名额,补齐
  84364. list.slice(0, maxRenderCount - renderCount).forEach(e => {
  84365. e.needRender = true;
  84366. });
  84367. } else if (list[0] && now - list[0].lastRenderTime > maxWaitTime) {
  84368. //名额不足时,考虑候补队列第一个是否超时,超时的话也渲染
  84369. list[0].needRender = true;
  84370. }
  84371. }
  84372. getObjectPointCount(object) {
  84373. var posCount = 0,
  84374. texArea = 0;
  84375. object.traverse(function (mesh) {
  84376. var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  84377. //let visi = o.visible === false ? false : mesh.visible //mesh.realVisible() //如果祖先不可见,此mesh一定不可见
  84378. if (mesh.geometry) {
  84379. if (mesh.geometry instanceof BufferGeometry) {
  84380. posCount += mesh.geometry.attributes.position.count;
  84381. } else {
  84382. posCount += mesh.geometry.vertices.length;
  84383. }
  84384. //visi && (visiPosCount += mesh.geometry.attributes.position.count)
  84385. }
  84386. /* if(mesh.material && !mesh.material.map){
  84387. console.log('!mesh.material.map ?')
  84388. } */
  84389. if (mesh.material) {
  84390. var mats = mesh.material instanceof Array ? mesh.material : [mesh.material];
  84391. mats.forEach(mat => {
  84392. var map = mat.map;
  84393. if (map) {
  84394. if (!map.image) {
  84395. console.error('!mat.map.image ??', mat.map.uuid); //obj可能会
  84396. return;
  84397. }
  84398. texArea += map.image.width * map.image.height;
  84399. //visi && (visiTexArea += a)
  84400. }
  84401. });
  84402. }
  84403. //return {visible:visi}
  84404. });
  84405. return {
  84406. posCount,
  84407. texArea
  84408. };
  84409. }
  84410. ifPointBlockedByIntersect(point, panoId, soon) {
  84411. //点是否被遮挡
  84412. var ifShelter;
  84413. var now = Date.now();
  84414. var extraPanoId = panoId != void 0;
  84415. if (!this.shelterCount) return;
  84416. var history = shelterHistory.find(e => e.point.equals(point));
  84417. var cameraPos = this.mainViewport.view.position.clone();
  84418. if (panoId == void 0) {
  84419. if (this.images360.isAtPano(0.05)) {
  84420. panoId = this.images360.currentPano.id;
  84421. }
  84422. }
  84423. if (history) {
  84424. if (panoId != void 0) {
  84425. ifShelter = history.panos[panoId];
  84426. } else {
  84427. if (history.notAtPano.cameraPos && history.notAtPano.cameraPos.equals(cameraPos)) {
  84428. ifShelter = history.notAtPano.ifShelter;
  84429. }
  84430. }
  84431. var index = shelterHistory.indexOf(history); //先取出,稍后放回
  84432. shelterHistory.splice(index, 1);
  84433. } else {
  84434. //新增
  84435. history = {
  84436. point,
  84437. panos: {},
  84438. notAtPano: {}
  84439. };
  84440. var minCount = 100;
  84441. if (shelterHistory.length > minCount) {
  84442. //去除最早的
  84443. var old;
  84444. while (old = shelterHistory[0], now - old.lastTime > 1000) {
  84445. //因为不知热点个数,所以需要加上时间限制,超过时间才能删。
  84446. if (old == history || shelterHistory.length == minCount) break;
  84447. shelterHistory.splice(0, 1);
  84448. //console.log('delete')
  84449. }
  84450. }
  84451. }
  84452. if (ifShelter == void 0) {
  84453. delete history.waitCompute;
  84454. if (this.mainViewport.view.isFlying()) {
  84455. return useLastResult();
  84456. }
  84457. if (panoId != void 0) {
  84458. var pano = this.images360.getPano(panoId);
  84459. if ((soon || this.shelterCount.byTex < this.shelterCount.maxByTex) && pano.depthTex) {
  84460. ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({
  84461. point,
  84462. margin: Potree.config.shelterMargin,
  84463. useDepthTex: true,
  84464. pano,
  84465. viewport: this.mainViewport
  84466. });
  84467. history.panos[panoId] = ifShelter;
  84468. this.shelterCount.byTex++;
  84469. //console.log('computeByTex direct', panoId, point, ifShelter)
  84470. } else {
  84471. //soon的无tex不敢写……
  84472. //console.log('延迟tex',panoId, point )
  84473. history.waitCompute = {
  84474. panoId,
  84475. forceGet: extraPanoId
  84476. };
  84477. return useLastResult();
  84478. }
  84479. } else {
  84480. if ( /* history.ifShelter == void 0 || */this.shelterCount.byCloud < this.shelterCount.maxByCloud) {
  84481. //弊端:第一个总是直接计算,后面的都是延后。但无法改进,因是一个个传进来的,无法预测。
  84482. ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({
  84483. point,
  84484. margin: Potree.config.shelterMargin,
  84485. pickWindowSize: 3
  84486. });
  84487. history.notAtPano = {
  84488. cameraPos,
  84489. ifShelter
  84490. };
  84491. this.shelterCount.byCloud++;
  84492. //console.log('computeByCloud direct', point.toArray())
  84493. } else {
  84494. //console.log('延迟cloud' )
  84495. history.waitCompute = {
  84496. cameraPos
  84497. };
  84498. return useLastResult();
  84499. }
  84500. }
  84501. }
  84502. history.ifShelter = ifShelter;
  84503. history.lastTime = now;
  84504. shelterHistory.push(history); //最新使用的保持在最后一个,使队列按照从旧到新排列
  84505. function useLastResult() {
  84506. //暂时先用上一次的值
  84507. shelterHistory.push(history);
  84508. history.lastTime = now;
  84509. return history.ifShelter;
  84510. }
  84511. return ifShelter;
  84512. }
  84513. computeShelter() {
  84514. //先算用深度图的,然后再点云;
  84515. //let depthTiming = Potree.timeCollect.depthSampler.median
  84516. var byTex = 0,
  84517. byCloud = 0;
  84518. var len = shelterHistory.length;
  84519. var waitCloud = [];
  84520. var maxTexCount = Common$1.getBestCount('shelterMaxDepthSample', 1, 50, 1, 13 /* ,true */);
  84521. for (var i = len - 1; i >= 0; i--) {
  84522. var history = shelterHistory[i];
  84523. if (history.waitCompute) {
  84524. var panoId = history.waitCompute.panoId;
  84525. if (panoId != void 0) {
  84526. var _this$images360$curre;
  84527. if (!history.waitCompute.forceGet && (panoId != ((_this$images360$curre = this.images360.currentPano) === null || _this$images360$curre === void 0 ? void 0 : _this$images360$curre.id) || !this.images360.isAtPano(0.1))) {
  84528. delete history.waitCompute; //取消计算
  84529. } else {
  84530. var pano = this.images360.getPano(panoId);
  84531. if (pano.depthTex) {
  84532. if (byTex >= maxTexCount) break;
  84533. byTex++;
  84534. var ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({
  84535. point: history.point,
  84536. pano,
  84537. margin: Potree.config.shelterMargin,
  84538. useDepthTex: true,
  84539. viewport: this.mainViewport
  84540. });
  84541. history.panos[panoId] = ifShelter;
  84542. history.ifShelter = ifShelter;
  84543. delete history.waitCompute;
  84544. //console.log('补1', history.point.toArray())
  84545. } else {
  84546. if (pano.pointcloud.hasDepthTex) {
  84547. //先等待加载完深度图
  84548. } else {
  84549. waitCloud.push(history);
  84550. }
  84551. }
  84552. }
  84553. } else {
  84554. waitCloud.push(history);
  84555. }
  84556. }
  84557. }
  84558. var maxCloudCount;
  84559. if (byTex < maxTexCount && waitCloud.length) {
  84560. maxCloudCount = this.lastFrameChanged ? Common$1.getBestCount('shelterMaxCloud', 0, 2, 4, 8 /* ,true */) : 5;
  84561. var waitCloud2 = [];
  84562. if (maxCloudCount) {
  84563. for (var _i2 = 0; _i2 < waitCloud.length; _i2++) {
  84564. var _history = waitCloud[_i2];
  84565. if (_history.waitCompute.cameraPos) {
  84566. if (!viewer.mainViewport.view.position.equals(_history.waitCompute.cameraPos)) {
  84567. delete _history.waitCompute;
  84568. //console.log('delete history.waitCompute', history)
  84569. continue; //取消计算
  84570. } else {
  84571. waitCloud2.push(_history);
  84572. }
  84573. } else {
  84574. waitCloud2.push(_history);
  84575. }
  84576. }
  84577. var list = waitCloud2.map(e => e.point);
  84578. var result = Common$1.batchHandling.getSlice('shelterByCloud', list, {
  84579. maxUseCount: maxCloudCount,
  84580. useEquals: true,
  84581. stopWhenAllUsed: true
  84582. }); //iphonex稳定后大概在7-10。
  84583. //list.length>0 && console.log('list',list, maxCloudCount)
  84584. result.list.forEach(e => {
  84585. var _this$images360$curre2;
  84586. var history = waitCloud2.find(a => a.point.equals(e));
  84587. var panoId = history.waitCompute.panoId;
  84588. var cameraPos = panoId != void 0 && panoId != ((_this$images360$curre2 = this.images360.currentPano) === null || _this$images360$curre2 === void 0 ? void 0 : _this$images360$curre2.id) && this.images360.getPano(panoId).position; //如果非当前点,需要改相机位置
  84589. var ifShelter = !!viewer.inputHandler.ifBlockedByIntersect({
  84590. point: history.point,
  84591. cameraPos,
  84592. margin: Potree.config.shelterMargin,
  84593. pickWindowSize: 3,
  84594. viewport: this.mainViewport
  84595. });
  84596. if (history.waitCompute.cameraPos) {
  84597. history.notAtPano = {
  84598. cameraPos: history.waitCompute.cameraPos,
  84599. ifShelter
  84600. };
  84601. } else {
  84602. history.panos[panoId] = ifShelter;
  84603. }
  84604. history.ifShelter = ifShelter;
  84605. byCloud++;
  84606. //console.log('补2', history.point.toArray())
  84607. delete history.waitCompute;
  84608. });
  84609. }
  84610. }
  84611. if (byTex || byCloud) {
  84612. //console.log('shelterComputed',byTex,byCloud, maxTexCount, maxCloudCount)
  84613. Common$1.intervalTool.isWaiting('shelterComputed', () => {
  84614. //console.log('shelterComputed update')
  84615. this.dispatchEvent('shelterComputed');
  84616. }, 340);
  84617. }
  84618. }
  84619. updateDatasetAt(force) {
  84620. //更新所在数据集
  84621. var fun = () => {
  84622. var currPos = viewer.mainViewport.view.position;
  84623. //if(force || !currPos.equals(this.lastPos)){
  84624. //this.lastPos.copy(currPos)
  84625. var at = this.scene.pointclouds.filter(e => (e.visible || e.unvisibleReasons && e.unvisibleReasons.length == 1 && e.unvisibleReasons[0].reason == 'displayMode') && e.ifContainsPoint(currPos));
  84626. if (Common$1.getDifferenceSet(at, this.atDatasets).length) {
  84627. //console.log('atDatasets', at)
  84628. this.atDatasets = at;
  84629. if (Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge') {
  84630. this.updateFpVisiDatasets();
  84631. if (!viewer.modules.SiteModel.currentFloor) {
  84632. this.updatePanosVisibles(); //所在数据集的点位显示
  84633. }
  84634. }
  84635. this.dispatchEvent({
  84636. type: 'pointcloudAtChange',
  84637. pointclouds: at
  84638. });
  84639. }
  84640. force = false;
  84641. };
  84642. //}
  84643. if (force) fun();else Common$1.intervalTool.isWaiting('atWhichDataset', fun, 300);
  84644. }
  84645. updatePanosVisibles(currentFloor) {
  84646. //显示当前楼层的所有panos
  84647. if (!Potree.settings.ifShowMarker) return;
  84648. var inEntity = currentFloor;
  84649. //console.error('updatePanosVisibles', currentFloor)
  84650. var SiteModel = this.modules.SiteModel;
  84651. viewer.images360.panos.forEach(pano => {
  84652. var visible = inEntity ? inEntity.panos.includes(pano) : this.atDatasets.some(e => e.panos.includes(pano));
  84653. /* if(!visible && inEntity && SiteModel.noEditBefore && !SiteModel.entities.some(e=>e.panos.includes(pano))){
  84654. //没编辑过的空间模型很有错的可能,如果pano不在任何楼里就显示2025.3 for https://laser.4dkankan.com/?lang=zh&m=SG-y2wVWYmrM7u#/
  84655. visible = true
  84656. } */
  84657. Potree.Utils.updateVisible(pano, 'buildingChange', visible, 2);
  84658. });
  84659. this.dispatchEvent('content_changed');
  84660. } //注:非official的没有获取sitemodel的信息所以不执行楼层判断,marker显示不对是正常的
  84661. /* 2023.11.24 针对部分场景的楼层很矮,很容易就到楼层外了,且不能修改楼高。如SG-t-9NdCpxrUPLL#/,采取如下措施:
  84662. 1 如果不在任何一楼层,但在某个数据集中,就显示该数据集所有的marker
  84663. 2 如果当前楼层无,则显示上一次的currentFloor的marker
  84664. (目前先使用方案1)
  84665. */
  84666. updateMarkerVisibles() {
  84667. //限制显示的marker个数,因镜头内marker多的时候可能会卡
  84668. if (!Potree.settings.ifShowMarker) return;
  84669. var minRadius = 8 * this.images360.zoomLevel,
  84670. //当视线垂直于marker时的最小可见距离,此范围内可见的pano绝对可见
  84671. maxRadius = 50 * this.images360.zoomLevel,
  84672. //当视线垂直于marker时的最大可见距离,此范围外绝对不可见
  84673. hopeCount = browser.isMobile() ? 8 : 15; //期望达到的真实可见的marker数
  84674. var sheltered = pano => {
  84675. if ( /* Potree.settings.displayMode == 'showPanos' && !Potree.Features.EXT_DEPTH.isSupported() && */this.images360.isAtPano() && !this.mainViewport.view.isFlying()) {
  84676. return !this.images360.isNeighbour(this.images360.currentPano, pano, {
  84677. dontCompute: true
  84678. }); //起初因不支持EXT_DEPTH时无法用depthTex遮住marker, 后为了减少绘制,都判断
  84679. }
  84680. };
  84681. var panoMap = new Map(); //先记录想要设置为可见的
  84682. var set = () => {
  84683. //最后确定设置
  84684. var count = 0;
  84685. viewer.images360.panos.forEach(pano => {
  84686. var v = panoMap.get(pano).visible;
  84687. v && count++;
  84688. Potree.Utils.updateVisible(pano.marker, 'limitMarkerShow', v);
  84689. });
  84690. //console.log('updateMarkerVisibles marker显示个数', count)
  84691. this.dispatchEvent('content_changed');
  84692. };
  84693. var isWithinDis = (pano, maxDis) => {
  84694. //是否marker到相机的距离 没有超出可视距离。可视距离考虑上倾斜角,倾斜越大可视距离越短
  84695. var camPos = viewer.mainViewport.camera.position;
  84696. var o = panoMap.get(pano);
  84697. o.dis = o.dis || camPos.distanceTo(pano.marker.position);
  84698. o.sin = o.sin || Math.sqrt(Math.abs(camPos.z - pano.marker.position.z) / o.dis); //和地面夹角的sin。 按公式是不加Math.sqrt的,但是这样大马路上在贴近地面时算出的个数非常少,所以增大点……
  84699. return o.dis < maxDis * o.sin;
  84700. };
  84701. viewer.images360.panos.forEach(pano => {
  84702. //minRadius内的记录为可见
  84703. var o = {};
  84704. panoMap.set(pano, o);
  84705. if (pano.visible && !sheltered(pano) && isWithinDis(pano, minRadius)) {
  84706. o.visible = true;
  84707. }
  84708. });
  84709. //不超过hopeCount的话,可以直接确定设置
  84710. if (viewer.images360.panos.filter(pano => panoMap.get(pano).visible).length >= hopeCount) return set();
  84711. //距离超过maxRadius就绝对不可见
  84712. var insideOutCirle = viewer.images360.panos.filter(pano => pano.visible && !sheltered(pano) && isWithinDis(pano, maxRadius));
  84713. if (insideOutCirle.length <= hopeCount) {
  84714. insideOutCirle.forEach(pano => panoMap.get(pano).visible = true);
  84715. return set();
  84716. }
  84717. //数量超过hopeCount时,根据距离排序
  84718. insideOutCirle.sort((a, b) => {
  84719. return panoMap.get(a).dis - panoMap.get(b).dis;
  84720. });
  84721. var slice = insideOutCirle.slice(0, hopeCount);
  84722. slice.forEach(pano => panoMap.get(pano).visible = true);
  84723. set();
  84724. }
  84725. updateFpVisiDatasets() {
  84726. if (!this.mapViewer) return;
  84727. var Clip = this.modules.Clip;
  84728. var SiteModel = this.modules.SiteModel;
  84729. var Alignment = this.modules.Alignment;
  84730. var currentFloor = SiteModel.currentFloor;
  84731. /* if(Clip.editing){//下载页面已经改为和普通时一样,根据位置判断
  84732. this.updateCadVisibles(Clip.selectedDatasets)
  84733. }else */
  84734. if (this.selectedFloorplan) {
  84735. //平面图设置中 或 地理设置
  84736. var pointclouds = [this.selectedFloorplan];
  84737. this.updateCadVisibles(pointclouds);
  84738. } else if (SiteModel.editing || Alignment.editing) {
  84739. //只显示勾选的,也就是显示的点云的
  84740. var _pointclouds = this.scene.pointclouds.filter(p => Potree.Utils.getObjVisiByReason(p, 'datasetSelection'));
  84741. this.updateCadVisibles(_pointclouds);
  84742. //this.updatePanosVisibles(currentFloor/* , pointclouds */)
  84743. } else {
  84744. var _pointclouds2 = currentFloor ? this.findPointcloudsAtFloor(currentFloor) : [];
  84745. if (_pointclouds2.length == 0) {
  84746. if (this.focusDatasets) {
  84747. _pointclouds2 = this.focusDatasets;
  84748. }
  84749. }
  84750. if (_pointclouds2.length == 0) {
  84751. //如果当前不在任何楼层或楼层中无数据集,就用当前所在数据集
  84752. _pointclouds2 = this.atDatasets;
  84753. }
  84754. this.updateCadVisibles(_pointclouds2);
  84755. //this.updatePanosVisibles(currentFloor/* , pointclouds */)
  84756. }
  84757. }
  84758. /* findPointcloudsAtFloor(entity){//找当前楼层需要显示哪些数据集。
  84759. //数据集的belongToEntity 在这个entity内(否则会出现点击数据集飞过去平面图却不显示)。or 如果数据集有漫游点的话,需要包含>20%的漫游点。 (防止重叠体积很大但其实一个漫游点都不包含)
  84760. //重叠体积>50% 或 包含>50%的漫游点
  84761. const ratio1 = 0.2, ratio2 = 0.5, ratio3 = 0.95
  84762. var lowScores = []
  84763. var pointclouds = viewer.scene.pointclouds.filter(e=>{
  84764. let score = 0
  84765. if(e.belongToEntity && (e.belongToEntity == entity || e.belongToEntity.buildParent == entity)){//条件1 若该数据集挂载到该楼层 或 该数据集挂载到的房间属于该楼层(这样能显示该层所有房间)
  84766. return true
  84767. }
  84768. if(e.panos.length){//条件2
  84769. var insidePanos = e.panos.filter(a=>entity.ifContainsPoint(a.position));
  84770. let panoCountRatio = insidePanos.length / e.panos.length
  84771. if(panoCountRatio > ratio2)return true
  84772. score += panoCountRatio
  84773. }
  84774. //条件3
  84775. let volume = entity.intersectPointcloudVolume(e);
  84776. let volumeRatio = volume / entity.getVolume(true) //注:hole加入计算
  84777. if(volumeRatio > ratio3){ //ratio3要高一些,因为点云bounding可能很大,包含很多无点云的空间。即使整个数据集包含entity都不一定看起来在数据集中。(千万要防止两层楼都显示了)
  84778. return true
  84779. }else{
  84780. score += volumeRatio
  84781. }
  84782. lowScores.push({score, pointcloud:e})
  84783. })
  84784. if(pointclouds.length == 0){//从低分项挑一个出来。
  84785. lowScores.sort((a,b)=>{return a.score - b.score})
  84786. if(lowScores[0].score > 0.4){
  84787. pointclouds = [lowScores[0].pointcloud]
  84788. }
  84789. }
  84790. return pointclouds
  84791. } */
  84792. findPointcloudsAtFloor(entity) {
  84793. //找当前楼层需要显示哪些数据集。
  84794. //数据集的belongToEntity 在这个entity内(否则会出现点击数据集飞过去平面图却不显示)。or 如果数据集有漫游点的话,需要包含>20%的漫游点。 (防止重叠体积很大但其实一个漫游点都不包含)
  84795. //重叠体积>50% 或 包含>50%的漫游点
  84796. var ratio1 = 0.2,
  84797. ratio2 = 0.5,
  84798. ratio3 = 0.95;
  84799. var lowScores = [];
  84800. var pointclouds = viewer.scene.pointclouds.filter(e => {
  84801. var score = 0;
  84802. if (e.belongToEntity && (e.belongToEntity == entity || e.belongToEntity.buildParent == entity)) {
  84803. //条件1 若该数据集挂载到该楼层 或 该数据集挂载到的房间属于该楼层(这样能显示该层所有房间)
  84804. return true;
  84805. }
  84806. if (e.panos.length) {
  84807. //条件2
  84808. var insidePanos = e.panos.filter(a => entity.ifContainsPoint(a.position));
  84809. var panoCountRatio = insidePanos.length / e.panos.length;
  84810. if (panoCountRatio > ratio2) return true;
  84811. score += panoCountRatio * 2;
  84812. }
  84813. //条件3
  84814. var coverHeightRatio = entity.coverPointcloudHeight(e, true); //重叠高度占楼层高度的比率。
  84815. if (coverHeightRatio < 0.2) return;
  84816. var {
  84817. toEntity,
  84818. toPointcloud
  84819. } = entity.intersectPointcloudArea(e, true); //重叠面积占比
  84820. var coverAreaRatio = Math.max(toEntity, toPointcloud); //占数据集俯视面积的比率 和 占楼层的面积比率,挑一个大的。 (有的数据集被划分多个楼层,所以每层都应该显示该数据集的图。还有的数据集比较大,可能包含多个建筑,则看占楼层面积)
  84821. if (coverAreaRatio < 0.2) return;
  84822. score += coverAreaRatio * coverHeightRatio;
  84823. lowScores.push({
  84824. score,
  84825. pointcloud: e
  84826. });
  84827. });
  84828. /* if(pointclouds.length == 0){//从低分项挑一个出来。
  84829. lowScores.sort((a,b)=>{return a.score - b.score})
  84830. if(lowScores[0].score > 0.4){
  84831. pointclouds = [lowScores[0].pointcloud]
  84832. }
  84833. } */
  84834. lowScores.forEach(e => {
  84835. //一个楼层里可以包含许多个数据集 调试SG-t-ds27ym7xzjJ
  84836. if (e.score > 0.5) {
  84837. pointclouds.push(e.pointcloud);
  84838. }
  84839. });
  84840. return pointclouds;
  84841. }
  84842. updateCadVisibles(visiClouds, force) {
  84843. //console.log('visiClouds',visiClouds)
  84844. var oldVisi = this.fpVisiDatasets;
  84845. var visiClouds = this.fpVisiDatasets = visiClouds;
  84846. if (!force) {
  84847. var difference = Common$1.getDifferenceSet(oldVisi, visiClouds);
  84848. if (difference.length == 0) return;
  84849. }
  84850. //console.log('visiClouds',visiClouds.map(e=>e.name))
  84851. viewer.scene.pointclouds.forEach(pointcloud => {
  84852. var floorplan = viewer.mapViewer.mapLayer.getFloorplan(pointcloud.dataset_id);
  84853. var visi = visiClouds.includes(pointcloud);
  84854. if (floorplan) {
  84855. Potree.Utils.updateVisible(floorplan.objectGroup, 'buildingChange', visi);
  84856. } /* else if(!visi){
  84857. let changeVisi = (e)=>{
  84858. Potree.Utils.updateVisible(e.floorplan.objectGroup, 'buildingChange', this.fpVisiDatasets.includes(pointcloud))
  84859. viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded', changeVisi)
  84860. console.log('updateCadVisibles加载后更改显示',e)
  84861. }
  84862. viewer.mapViewer.mapLayer.addEventListener('floorplanLoaded', changeVisi)
  84863. } */
  84864. //已经添加了全局的 floorplanLoaded后会updateCadVisibles,这段就删了
  84865. });
  84866. viewer.mapViewer.mapLayer.needUpdate = true; //可能需要更新加载的level程度
  84867. viewer.mapViewer.needRender = true; //若上句不触发加载也要立即重新绘制
  84868. }
  84869. //促使点云加载出最高级别
  84870. testPointcloudsMaxLevel() {
  84871. var _this = this;
  84872. //所有点云都无需testMaxNodeLevel 就停止
  84873. var camera_changed,
  84874. count = 0;
  84875. var _test = function test() {
  84876. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  84877. camera_changed = true;
  84878. var camera = e.camera || _this.scene.getActiveCamera();
  84879. Common$1.intervalTool.isWaiting('testPointcloudsMaxLevel', () => {
  84880. if (!camera_changed && count > 50 || Potree.settings.displayMode == 'showPanos' || _this.pauseTestMaxLevel) return; //只有当camera_changed后才继续循环, 除了最开始几次需要连续加载下
  84881. camera_changed = false;
  84882. count++;
  84883. //console.log('testPointcloudsMaxLevel中', camera.type /* count */)
  84884. var oldCount = _this.testMaxNodeCount;
  84885. var success = true;
  84886. viewer.scene.pointclouds.forEach(e => {
  84887. var wait = e.testMaxNodeLevel(camera);
  84888. if (wait) {
  84889. success = false;
  84890. }
  84891. });
  84892. /* if(oldCount<=Potree.config.testNodeCount1 && this.testMaxNodeCount>Potree.config.testNodeCount1 ){//差不多等当前所在数据集nodeMaxLevel加载出来
  84893. viewer.scene.pointclouds.forEach(e=>{e.changePointSize()}) //重新更新一下大小。因之前用的是nodeMaxLevelPredict (防止刚开始因nodeMaxLevel没涨完,导致过大的点云突然出现
  84894. } */
  84895. if (!success) return true; //没有全部加载完,继续循环
  84896. else {
  84897. _this.removeEventListener('camera_changed', _test);
  84898. console.log('testPointcloudsMaxLevel结束');
  84899. }
  84900. }, count < 10 ? 250 : 500);
  84901. };
  84902. this.addEventListener('camera_changed', _test);
  84903. _test();
  84904. /* 检验:
  84905. viewer.scene.pointclouds.sort((a,b)=>a.nodeMaxLevelPredict.min - b.nodeMaxLevelPredict.min).forEach(e=>console.log(e.nodeMaxLevel, e.nodeMaxLevelPredict.min))
  84906. */
  84907. }
  84908. setPointLevels() {
  84909. this.scene.pointclouds.forEach(e => {
  84910. e.setPointLevel();
  84911. });
  84912. }
  84913. onCrash(error) {
  84914. console.error(error);
  84915. $(this.renderArea).empty();
  84916. if ($(this.renderArea).find('#potree_failpage').length === 0) {
  84917. var elFailPage = $("\n\t\t\t<div id=\"#potree_failpage\" class=\"potree_failpage\"> \n\t\t\t\t\n\t\t\t\t<h1>Potree Encountered An Error </h1>\n\n\t\t\t\t<p>\n\t\t\t\tThis may happen if your browser or graphics card is not supported.\n\t\t\t\t<br>\n\t\t\t\tWe recommend to use \n\t\t\t\t<a href=\"https://www.google.com/chrome/browser\" target=\"_blank\" style=\"color:initial\">Chrome</a>\n\t\t\t\tor \n\t\t\t\t<a href=\"https://www.mozilla.org/\" target=\"_blank\">Firefox</a>.\n\t\t\t\t</p>\n\n\t\t\t\t<p>\n\t\t\t\tPlease also visit <a href=\"http://webglreport.com/\" target=\"_blank\">webglreport.com</a> and \n\t\t\t\tcheck whether your system supports WebGL.\n\t\t\t\t</p>\n\t\t\t\t<p>\n\t\t\t\tIf you are already using one of the recommended browsers and WebGL is enabled, \n\t\t\t\tconsider filing an issue report at <a href=\"https://github.com/potree/potree/issues\" target=\"_blank\">github</a>,<br>\n\t\t\t\tincluding your operating system, graphics card, browser and browser version, as well as the \n\t\t\t\terror message below.<br>\n\t\t\t\tPlease do not report errors on unsupported browsers.\n\t\t\t\t</p>\n\n\t\t\t\t<pre id=\"potree_error_console\" style=\"width: 100%; height: 100%\"></pre>\n\t\t\t\t\n\t\t\t</div>");
  84918. var elErrorMessage = elFailPage.find('#potree_error_console');
  84919. elErrorMessage.html(error.stack);
  84920. $(this.renderArea).append(elFailPage);
  84921. }
  84922. throw error;
  84923. }
  84924. // ------------------------------------------------------------------------------------
  84925. // Viewer API
  84926. // ------------------------------------------------------------------------------------
  84927. setScene(scene) {
  84928. if (scene === this.scene) {
  84929. return;
  84930. }
  84931. var oldScene = this.scene;
  84932. this.scene = scene;
  84933. this.dispatchEvent({
  84934. type: 'scene_changed',
  84935. oldScene: oldScene,
  84936. scene: scene
  84937. });
  84938. {
  84939. // Annotations
  84940. $('.annotation').detach();
  84941. // for(let annotation of this.scene.annotations){
  84942. // this.renderArea.appendChild(annotation.domElement[0]);
  84943. // }
  84944. this.scene.annotations.traverse(annotation => {
  84945. this.renderArea.appendChild(annotation.domElement[0]);
  84946. });
  84947. if (!this.onAnnotationAdded) {
  84948. this.onAnnotationAdded = e => {
  84949. // console.log("annotation added: " + e.annotation.title);
  84950. e.annotation.traverse(node => {
  84951. $("#potree_annotation_container").append(node.domElement);
  84952. //this.renderArea.appendChild(node.domElement[0]);
  84953. node.scene = this.scene;
  84954. });
  84955. };
  84956. }
  84957. if (oldScene) {
  84958. oldScene.annotations.removeEventListener('annotation_added', this.onAnnotationAdded);
  84959. }
  84960. this.scene.annotations.addEventListener('annotation_added', this.onAnnotationAdded);
  84961. }
  84962. }
  84963. setControls(controls /* , setSpeed */) {
  84964. if (controls !== this.controls) {
  84965. if (this.controls) {
  84966. this.controls.setEnable(false);
  84967. //this.inputHandler.removeInputListener(this.controls);
  84968. this.controls.moveSpeed = this.moveSpeed; //记录 (因为orbit的radius很大,转为firstPerson时要缩小)
  84969. }
  84970. this.controls = controls;
  84971. controls.moveSpeed && this.setMoveSpeed(controls.moveSpeed); //add
  84972. this.controls.setEnable(true);
  84973. //this.inputHandler.addInputListener(this.controls);
  84974. }
  84975. }
  84976. getControls() {
  84977. if (this.renderer.xr.isPresenting) {
  84978. return this.vrControls;
  84979. } else {
  84980. return this.controls;
  84981. }
  84982. }
  84983. getMinNodeSize() {
  84984. return this.minNodeSize;
  84985. }
  84986. setMinNodeSize(value) {
  84987. if (this.minNodeSize !== value) {
  84988. this.minNodeSize = value;
  84989. this.dispatchEvent({
  84990. 'type': 'minnodesize_changed',
  84991. 'viewer': this
  84992. });
  84993. }
  84994. }
  84995. getBackground() {
  84996. return this.background;
  84997. }
  84998. setBackground(bg, src) {
  84999. /* if (this.background === bg ) {
  85000. return;
  85001. } */
  85002. if (bg === "skybox") {
  85003. if (!src) src = Potree.resourcePath + '/textures/skybox/xingkong.jpg';
  85004. this.skybox = Utils.loadSkybox(src, this.skybox, () => {
  85005. this.background = bg;
  85006. });
  85007. } else {
  85008. this.background = bg;
  85009. }
  85010. this.backgroundOpacity = 1; //add
  85011. this.dispatchEvent({
  85012. 'type': 'background_changed',
  85013. 'viewer': this
  85014. });
  85015. }
  85016. setDescription(value) {
  85017. this.description = value;
  85018. $('#potree_description').html(value);
  85019. //$('#potree_description').text(value);
  85020. }
  85021. getDescription() {
  85022. return this.description;
  85023. }
  85024. setShowBoundingBox(value) {
  85025. if (this.showBoundingBox !== value) {
  85026. this.showBoundingBox = value;
  85027. this.dispatchEvent({
  85028. 'type': 'show_boundingbox_changed',
  85029. 'viewer': this
  85030. });
  85031. }
  85032. }
  85033. getShowBoundingBox() {
  85034. return this.showBoundingBox;
  85035. }
  85036. setMoveSpeed(value) {
  85037. if (this.getMoveSpeed() !== value) {
  85038. this.mainViewport.setMoveSpeed(value);
  85039. this.dispatchEvent({
  85040. 'type': 'move_speed_changed',
  85041. 'viewer': this,
  85042. 'speed': value
  85043. });
  85044. }
  85045. }
  85046. getMoveSpeed() {
  85047. return this.mainViewport.moveSpeed;
  85048. }
  85049. setWeightClassification(w) {
  85050. for (var i = 0; i < this.scene.pointclouds.length; i++) {
  85051. this.scene.pointclouds[i].material.weightClassification = w;
  85052. this.dispatchEvent({
  85053. 'type': 'attribute_weights_changed' + i,
  85054. 'viewer': this
  85055. });
  85056. }
  85057. }
  85058. setFreeze(value) {
  85059. value = Boolean(value);
  85060. if (this.freeze !== value) {
  85061. this.freeze = value;
  85062. this.dispatchEvent({
  85063. 'type': 'freeze_changed',
  85064. 'viewer': this
  85065. });
  85066. }
  85067. }
  85068. getFreeze() {
  85069. return this.freeze;
  85070. }
  85071. setElevationGradientRepeat(value) {
  85072. if (this.elevationGradientRepeat !== value) {
  85073. this.elevationGradientRepeat = value;
  85074. this.dispatchEvent({
  85075. type: "elevation_gradient_repeat_changed",
  85076. viewer: this
  85077. });
  85078. }
  85079. }
  85080. setPointBudget(value) {
  85081. //pointBudget: 每次刷新显示点数量的最大值。 缓存中的点数量也跟此有关,但大于这个数值。
  85082. if (Potree.pointBudget !== value && value) {
  85083. Potree.pointBudget = parseInt(value);
  85084. this.dispatchEvent({
  85085. 'type': 'point_budget_changed',
  85086. 'viewer': this
  85087. });
  85088. }
  85089. }
  85090. getPointBudget() {
  85091. return Potree.pointBudget;
  85092. }
  85093. setShowAnnotations(value) {
  85094. if (this.showAnnotations !== value) {
  85095. this.showAnnotations = value;
  85096. this.dispatchEvent({
  85097. 'type': 'show_annotations_changed',
  85098. 'viewer': this
  85099. });
  85100. }
  85101. }
  85102. getShowAnnotations() {
  85103. return this.showAnnotations;
  85104. }
  85105. setDEMCollisionsEnabled(value) {
  85106. if (this.useDEMCollisions !== value) {
  85107. this.useDEMCollisions = value;
  85108. this.dispatchEvent({
  85109. 'type': 'use_demcollisions_changed',
  85110. 'viewer': this
  85111. });
  85112. }
  85113. ;
  85114. }
  85115. getDEMCollisionsEnabled() {
  85116. return this.useDEMCollisions;
  85117. }
  85118. setEDLEnabled(value) {
  85119. value = Boolean(value) && Features.SHADER_EDL.isSupported();
  85120. if (this.useEDL !== value) {
  85121. this.useEDL = value;
  85122. this.dispatchEvent({
  85123. 'type': 'use_edl_changed',
  85124. 'viewer': this
  85125. });
  85126. this.dispatchEvent('pointcloud_changed');
  85127. }
  85128. }
  85129. getEDLEnabled() {
  85130. return this.useEDL;
  85131. }
  85132. setEDLRadius(value) {
  85133. if (this.edlRadius !== value) {
  85134. this.edlRadius = value;
  85135. this.dispatchEvent({
  85136. 'type': 'edl_radius_changed',
  85137. 'viewer': this
  85138. });
  85139. this.dispatchEvent('pointcloud_changed');
  85140. }
  85141. }
  85142. getEDLRadius() {
  85143. return this.edlRadius;
  85144. }
  85145. setEDLStrength(value) {
  85146. if (this.edlStrength !== value) {
  85147. this.edlStrength = value;
  85148. this.dispatchEvent({
  85149. 'type': 'edl_strength_changed',
  85150. 'viewer': this
  85151. });
  85152. this.dispatchEvent('pointcloud_changed');
  85153. }
  85154. }
  85155. getEDLStrength() {
  85156. return this.edlStrength;
  85157. }
  85158. setEDLOpacity(value) {
  85159. if (this.edlOpacity !== value) {
  85160. this.edlOpacity = value;
  85161. this.dispatchEvent({
  85162. 'type': 'edl_opacity_changed',
  85163. 'viewer': this
  85164. });
  85165. this.dispatchEvent('pointcloud_changed');
  85166. }
  85167. }
  85168. getEDLOpacity() {
  85169. return this.edlOpacity;
  85170. }
  85171. setFOV(value) {
  85172. if (this.fov !== value) {
  85173. var oldFov = this.fov;
  85174. this.fov = value;
  85175. this.scene.cameraP.fov = this.fov; //add
  85176. this.scene.cameraP.updateProjectionMatrix(); //add
  85177. this.dispatchEvent({
  85178. 'type': 'fov_changed',
  85179. 'viewer': this,
  85180. oldFov,
  85181. fov: this.fov
  85182. });
  85183. }
  85184. }
  85185. getFOV() {
  85186. return this.fov;
  85187. }
  85188. disableAnnotations() {
  85189. this.scene.annotations.traverse(annotation => {
  85190. annotation.domElement.css('pointer-events', 'none');
  85191. // return annotation.visible;
  85192. });
  85193. }
  85194. enableAnnotations() {
  85195. this.scene.annotations.traverse(annotation => {
  85196. annotation.domElement.css('pointer-events', 'auto');
  85197. // return annotation.visible;
  85198. });
  85199. }
  85200. setClassifications(classifications) {
  85201. for (var i in classifications) {
  85202. var color = classifications[i].color;
  85203. if (typeof color == 'string') {
  85204. color = new Color(color);
  85205. color = [color.r, color.g, color.b, 1];
  85206. classifications[i].color = color;
  85207. }
  85208. }
  85209. this.classifications = classifications;
  85210. this.dispatchEvent({
  85211. 'type': 'classifications_changed',
  85212. 'viewer': this
  85213. });
  85214. }
  85215. setClassificationVisibility(key, value) {
  85216. if (!this.classifications[key]) {
  85217. this.classifications[key] = {
  85218. visible: value,
  85219. name: 'no name'
  85220. };
  85221. this.dispatchEvent({
  85222. 'type': 'classification_visibility_changed',
  85223. 'viewer': this
  85224. });
  85225. } else if (this.classifications[key].visible !== value) {
  85226. this.classifications[key].visible = value;
  85227. this.dispatchEvent({
  85228. 'type': 'classification_visibility_changed',
  85229. 'viewer': this
  85230. });
  85231. }
  85232. }
  85233. toggleAllClassificationsVisibility() {
  85234. var numVisible = 0;
  85235. var numItems = 0;
  85236. for (var key of Object.keys(this.classifications)) {
  85237. if (this.classifications[key].visible) {
  85238. numVisible++;
  85239. }
  85240. numItems++;
  85241. }
  85242. var visible = true;
  85243. if (numVisible === numItems) {
  85244. visible = false;
  85245. }
  85246. var somethingChanged = false;
  85247. for (var _key of Object.keys(this.classifications)) {
  85248. if (this.classifications[_key].visible !== visible) {
  85249. this.classifications[_key].visible = visible;
  85250. somethingChanged = true;
  85251. }
  85252. }
  85253. if (somethingChanged) {
  85254. this.dispatchEvent({
  85255. 'type': 'classification_visibility_changed',
  85256. 'viewer': this
  85257. });
  85258. }
  85259. }
  85260. setFilterReturnNumberRange(from, to) {
  85261. this.filterReturnNumberRange = [from, to];
  85262. this.dispatchEvent({
  85263. 'type': 'filter_return_number_range_changed',
  85264. 'viewer': this
  85265. });
  85266. }
  85267. setFilterNumberOfReturnsRange(from, to) {
  85268. this.filterNumberOfReturnsRange = [from, to];
  85269. this.dispatchEvent({
  85270. 'type': 'filter_number_of_returns_range_changed',
  85271. 'viewer': this
  85272. });
  85273. }
  85274. setFilterGPSTimeRange(from, to) {
  85275. this.filterGPSTimeRange = [from, to];
  85276. this.dispatchEvent({
  85277. 'type': 'filter_gps_time_range_changed',
  85278. 'viewer': this
  85279. });
  85280. }
  85281. setFilterPointSourceIDRange(from, to) {
  85282. this.filterPointSourceIDRange = [from, to];
  85283. this.dispatchEvent({
  85284. 'type': 'filter_point_source_id_range_changed',
  85285. 'viewer': this
  85286. });
  85287. }
  85288. setLengthUnit(value) {
  85289. switch (value) {
  85290. case 'm':
  85291. this.lengthUnit = LengthUnits.METER;
  85292. this.lengthUnitDisplay = LengthUnits.METER;
  85293. break;
  85294. case 'ft':
  85295. this.lengthUnit = LengthUnits.FEET;
  85296. this.lengthUnitDisplay = LengthUnits.FEET;
  85297. break;
  85298. case 'in':
  85299. this.lengthUnit = LengthUnits.INCH;
  85300. this.lengthUnitDisplay = LengthUnits.INCH;
  85301. break;
  85302. }
  85303. this.dispatchEvent({
  85304. 'type': 'length_unit_changed',
  85305. 'viewer': this,
  85306. value: value
  85307. });
  85308. }
  85309. setLengthUnitAndDisplayUnit(lengthUnitValue, lengthUnitDisplayValue) {
  85310. switch (lengthUnitValue) {
  85311. case 'm':
  85312. this.lengthUnit = LengthUnits.METER;
  85313. break;
  85314. case 'ft':
  85315. this.lengthUnit = LengthUnits.FEET;
  85316. break;
  85317. case 'in':
  85318. this.lengthUnit = LengthUnits.INCH;
  85319. break;
  85320. }
  85321. switch (lengthUnitDisplayValue) {
  85322. case 'm':
  85323. this.lengthUnitDisplay = LengthUnits.METER;
  85324. break;
  85325. case 'ft':
  85326. this.lengthUnitDisplay = LengthUnits.FEET;
  85327. break;
  85328. case 'in':
  85329. this.lengthUnitDisplay = LengthUnits.INCH;
  85330. break;
  85331. }
  85332. this.dispatchEvent({
  85333. 'type': 'length_unit_changed',
  85334. 'viewer': this,
  85335. value: lengthUnitValue
  85336. });
  85337. }
  85338. zoomTo(node, factor) {
  85339. var animationDuration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  85340. var view = this.mainViewport.view;
  85341. var camera = this.scene.cameraP.clone();
  85342. camera.rotation.copy(this.scene.cameraP.rotation);
  85343. camera.rotation.order = "ZXY";
  85344. camera.rotation.x = Math.PI / 2 + view.pitch;
  85345. camera.rotation.z = view.yaw;
  85346. camera.updateMatrix();
  85347. camera.updateMatrixWorld();
  85348. camera.zoomTo(node, factor);
  85349. var bs;
  85350. if (node.boundingSphere) {
  85351. bs = node.boundingSphere;
  85352. } else if (node.geometry && node.geometry.boundingSphere) {
  85353. bs = node.geometry.boundingSphere;
  85354. } else {
  85355. bs = node.boundingBox.getBoundingSphere(new Sphere());
  85356. }
  85357. bs = bs.clone().applyMatrix4(node.matrixWorld);
  85358. var startPosition = view.position.clone();
  85359. var endPosition = camera.position.clone();
  85360. var startTarget = view.getPivot();
  85361. var endTarget = bs.center;
  85362. var startRadius = view.radius;
  85363. var endRadius = endPosition.distanceTo(endTarget);
  85364. var easing = TWEEN.Easing.Quartic.Out;
  85365. {
  85366. // animate camera position
  85367. var pos = startPosition.clone();
  85368. var tween = new TWEEN.Tween(pos).to(endPosition, animationDuration);
  85369. tween.easing(easing);
  85370. tween.onUpdate(() => {
  85371. view.position.copy(pos);
  85372. });
  85373. tween.start();
  85374. }
  85375. {
  85376. // animate camera target
  85377. var target = startTarget.clone();
  85378. var _tween = new TWEEN.Tween(target).to(endTarget, animationDuration);
  85379. _tween.easing(easing);
  85380. _tween.onUpdate(() => {
  85381. view.lookAt(target);
  85382. });
  85383. _tween.onComplete(() => {
  85384. view.lookAt(target);
  85385. this.dispatchEvent({
  85386. type: 'focusing_finished',
  85387. target: this
  85388. });
  85389. });
  85390. this.dispatchEvent({
  85391. type: 'focusing_started',
  85392. target: this
  85393. });
  85394. _tween.start();
  85395. }
  85396. }
  85397. moveToGpsTimeVicinity(time) {
  85398. var result = Potree.Utils.findClosestGpsTime(time, viewer);
  85399. var box = result.node.pointcloud.deepestNodeAt(result.position).getBoundingBox();
  85400. var diameter = box.min.distanceTo(box.max);
  85401. var camera = this.scene.getActiveCamera();
  85402. var offset = camera.getWorldDirection(new Vector3()).multiplyScalar(diameter);
  85403. var newCamPos = result.position.clone().sub(offset);
  85404. this.scene.view.position.copy(newCamPos);
  85405. this.scene.view.lookAt(result.position);
  85406. }
  85407. showAbout() {
  85408. $(function () {
  85409. $('#about-panel').dialog();
  85410. });
  85411. }
  85412. getGpsTimeExtent() {
  85413. var range = [Infinity, -Infinity];
  85414. for (var pointcloud of this.scene.pointclouds) {
  85415. var attributes = pointcloud.pcoGeometry.pointAttributes.attributes;
  85416. var aGpsTime = attributes.find(a => a.name === "gps-time");
  85417. if (aGpsTime) {
  85418. range[0] = Math.min(range[0], aGpsTime.range[0]);
  85419. range[1] = Math.max(range[1], aGpsTime.range[1]);
  85420. }
  85421. }
  85422. return range;
  85423. }
  85424. fitToScreen() {
  85425. var factor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
  85426. var animationDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  85427. var box = this.getBoundingBox(this.scene.pointclouds);
  85428. var node = new Object3D();
  85429. node.boundingBox = box;
  85430. this.zoomTo(node, factor, animationDuration);
  85431. this.controls.stop();
  85432. }
  85433. toggleNavigationCube() {
  85434. this.navigationCube.visible = !this.navigationCube.visible;
  85435. /* this.viewports.push({
  85436. name:'navigationCube',
  85437. left:0, bottom:0, width:0.2,
  85438. }) */
  85439. }
  85440. /* setView(pos, view) {
  85441. if(!pos) return;
  85442. switch(pos) {
  85443. case "F":
  85444. this.setFrontView(view);
  85445. break;
  85446. case "B":
  85447. this.setBackView(view);
  85448. break;
  85449. case "L":
  85450. this.setLeftView(view);
  85451. break;
  85452. case "R":
  85453. this.setRightView(view);
  85454. break;
  85455. case "U":
  85456. this.setTopView(view);
  85457. break;
  85458. case "D":
  85459. this.setBottomView(view);
  85460. break;
  85461. }
  85462. } */
  85463. setTopView(view) {
  85464. view = view || this.scene.view;
  85465. view.setCubeView("top");
  85466. this.fitToScreen();
  85467. }
  85468. setBottomView() {
  85469. this.scene.view.yaw = -Math.PI;
  85470. this.scene.view.pitch = Math.PI / 2;
  85471. this.fitToScreen();
  85472. }
  85473. setFrontView(view) {
  85474. view = view || this.scene.view;
  85475. view.yaw = 0;
  85476. view.pitch = 0;
  85477. this.fitToScreen();
  85478. }
  85479. setBackView(view) {
  85480. view = view || this.scene.view;
  85481. view.yaw = Math.PI;
  85482. view.pitch = 0;
  85483. this.fitToScreen();
  85484. }
  85485. setLeftView() {
  85486. this.scene.view.yaw = -Math.PI / 2;
  85487. this.scene.view.pitch = 0;
  85488. this.fitToScreen();
  85489. }
  85490. setRightView() {
  85491. this.scene.view.yaw = Math.PI / 2;
  85492. this.scene.view.pitch = 0;
  85493. this.fitToScreen();
  85494. }
  85495. flipYZ() {
  85496. this.isFlipYZ = !this.isFlipYZ;
  85497. // TODO flipyz
  85498. console.log('TODO');
  85499. }
  85500. setCameraMode(mode) {
  85501. this.scene.cameraMode = mode;
  85502. viewer.mainViewport.camera = mode == CameraMode.PERSPECTIVE ? this.scene.cameraP : this.scene.cameraO; //改
  85503. for (var pointcloud of this.scene.pointclouds) {
  85504. pointcloud.material.useOrthographicCamera = mode == CameraMode.ORTHOGRAPHIC;
  85505. }
  85506. }
  85507. getProjection() {
  85508. var pointcloud = this.scene.pointclouds[0];
  85509. if (pointcloud) {
  85510. return pointcloud.projection;
  85511. } else {
  85512. return null;
  85513. }
  85514. }
  85515. async loadProject(url, done) {
  85516. var response = await fetch(url);
  85517. if (response.ok) {
  85518. var text = await response.text();
  85519. var json = JSON5.parse(text);
  85520. // const json = JSON.parse(text);
  85521. if (json.type === "Potree") {
  85522. Potree.loadProject(viewer, json, done);
  85523. }
  85524. } else {
  85525. console.warn("未能加载:" + url);
  85526. }
  85527. }
  85528. saveProject() {
  85529. return Potree.saveProject(this);
  85530. }
  85531. loadSettingsFromURL() {
  85532. if (Utils.getParameterByName("pointSize")) {
  85533. this.setPointSize(parseFloat(Utils.getParameterByName("pointSize")));
  85534. }
  85535. if (Utils.getParameterByName("FOV")) {
  85536. this.setFOV(parseFloat(Utils.getParameterByName("FOV")));
  85537. }
  85538. if (Utils.getParameterByName("opacity")) {
  85539. this.setOpacity(parseFloat(Utils.getParameterByName("opacity")));
  85540. }
  85541. if (Utils.getParameterByName("edlEnabled")) {
  85542. var enabled = Utils.getParameterByName("edlEnabled") === "true";
  85543. this.setEDLEnabled(enabled);
  85544. }
  85545. if (Utils.getParameterByName('edlRadius')) {
  85546. this.setEDLRadius(parseFloat(Utils.getParameterByName('edlRadius')));
  85547. }
  85548. if (Utils.getParameterByName('edlStrength')) {
  85549. this.setEDLStrength(parseFloat(Utils.getParameterByName('edlStrength')));
  85550. }
  85551. if (Utils.getParameterByName('pointBudget')) {
  85552. this.setPointBudget(parseFloat(Utils.getParameterByName('pointBudget')));
  85553. }
  85554. if (Utils.getParameterByName('showBoundingBox')) {
  85555. var _enabled = Utils.getParameterByName('showBoundingBox') === 'true';
  85556. if (_enabled) {
  85557. this.setShowBoundingBox(true);
  85558. } else {
  85559. this.setShowBoundingBox(false);
  85560. }
  85561. }
  85562. if (Utils.getParameterByName('material')) {
  85563. var material = Utils.getParameterByName('material');
  85564. this.setMaterial(material);
  85565. }
  85566. if (Utils.getParameterByName('pointSizing')) {
  85567. var sizing = Utils.getParameterByName('pointSizing');
  85568. this.setPointSizing(sizing);
  85569. }
  85570. if (Utils.getParameterByName('quality')) {
  85571. var quality = Utils.getParameterByName('quality');
  85572. this.setQuality(quality);
  85573. }
  85574. if (Utils.getParameterByName('position')) {
  85575. var value = Utils.getParameterByName('position');
  85576. value = value.replace('[', '').replace(']', '');
  85577. var tokens = value.split(';');
  85578. var x = parseFloat(tokens[0]);
  85579. var y = parseFloat(tokens[1]);
  85580. var z = parseFloat(tokens[2]);
  85581. this.scene.view.position.set(x, y, z);
  85582. }
  85583. if (Utils.getParameterByName('target')) {
  85584. var _value = Utils.getParameterByName('target');
  85585. _value = _value.replace('[', '').replace(']', '');
  85586. var _tokens = _value.split(';');
  85587. var _x = parseFloat(_tokens[0]);
  85588. var _y = parseFloat(_tokens[1]);
  85589. var _z = parseFloat(_tokens[2]);
  85590. this.scene.view.lookAt(new Vector3(_x, _y, _z));
  85591. }
  85592. if (Utils.getParameterByName('background')) {
  85593. var _value2 = Utils.getParameterByName('background');
  85594. this.setBackground(_value2);
  85595. }
  85596. // if(Utils.getParameterByName("elevationRange")){
  85597. // let value = Utils.getParameterByName("elevationRange");
  85598. // value = value.replace("[", "").replace("]", "");
  85599. // let tokens = value.split(";");
  85600. // let x = parseFloat(tokens[0]);
  85601. // let y = parseFloat(tokens[1]);
  85602. //
  85603. // this.setElevationRange(x, y);
  85604. // //this.scene.view.target.set(x, y, z);
  85605. // }
  85606. }
  85607. // ------------------------------------------------------------------------------------
  85608. // Viewer Internals
  85609. // ------------------------------------------------------------------------------------
  85610. createControls() {
  85611. {
  85612. // create FIRST PERSON CONTROLS
  85613. this.fpControls = new FirstPersonControls(this, this.mainViewport);
  85614. this.fpControls.enabled = false;
  85615. this.fpControls.addEventListener('start', this.disableAnnotations.bind(this));
  85616. this.fpControls.addEventListener('end', this.enableAnnotations.bind(this));
  85617. /* this.addEventListener("loadPointCloudDone", ()=>{
  85618. let boundPlane = new THREE.Box3()
  85619. boundPlane.expandByPoint(this.bound.boundingBox.min.clone())//最低高度为bound的最低
  85620. boundPlane.expandByPoint(this.bound.boundingBox.max.clone().setZ(this.bound.center.z))//最高高度为bound的中心高度
  85621. FirstPersonControls.boundPlane = boundPlane
  85622. FirstPersonControls.standardSpeed = THREE.Math.clamp( Math.sqrt(this.bound.boundSize.length() )/ 100 , 0.02,0.5); //在这个boundPlane中的速度
  85623. }) */
  85624. }
  85625. // { // create GEO CONTROLS
  85626. // this.geoControls = new GeoControls(this.scene.camera, this.renderer.domElement);
  85627. // this.geoControls.enabled = false;
  85628. // this.geoControls.addEventListener("start", this.disableAnnotations.bind(this));
  85629. // this.geoControls.addEventListener("end", this.enableAnnotations.bind(this));
  85630. // this.geoControls.addEventListener("move_speed_changed", (event) => {
  85631. // this.setMoveSpeed(this.geoControls.moveSpeed);
  85632. // });
  85633. // }
  85634. {
  85635. // create ORBIT CONTROLS
  85636. this.orbitControls = new OrbitControls(this);
  85637. this.orbitControls.enabled = false;
  85638. this.orbitControls.addEventListener('start', this.disableAnnotations.bind(this));
  85639. this.orbitControls.addEventListener('end', this.enableAnnotations.bind(this));
  85640. }
  85641. /* { // create EARTH CONTROLS
  85642. this.earthControls = new EarthControls(this);
  85643. this.earthControls.enabled = false;
  85644. this.earthControls.addEventListener('start', this.disableAnnotations.bind(this));
  85645. this.earthControls.addEventListener('end', this.enableAnnotations.bind(this));
  85646. }
  85647. { // create DEVICE ORIENTATION CONTROLS
  85648. this.deviceControls = new DeviceOrientationControls(this);
  85649. this.deviceControls.enabled = false;
  85650. this.deviceControls.addEventListener('start', this.disableAnnotations.bind(this));
  85651. this.deviceControls.addEventListener('end', this.enableAnnotations.bind(this));
  85652. } */
  85653. /* { // create VR CONTROLS
  85654. this.vrControls = new VRControls(this);
  85655. this.vrControls.enabled = false;
  85656. this.vrControls.addEventListener('start', this.disableAnnotations.bind(this));
  85657. this.vrControls.addEventListener('end', this.enableAnnotations.bind(this));
  85658. } */
  85659. }
  85660. toggleSidebar() {
  85661. var renderArea = $('#potree_render_area');
  85662. var isVisible = renderArea.css('left') !== '0px';
  85663. if (isVisible) {
  85664. renderArea.css('left', '0px');
  85665. } else {
  85666. renderArea.css('left', '300px');
  85667. }
  85668. }
  85669. toggleMap() {
  85670. // let map = $('#potree_map');
  85671. // map.toggle(100);
  85672. if (this.mapView) {
  85673. this.mapView.toggle();
  85674. }
  85675. }
  85676. onGUILoaded(callback) {
  85677. if (this.guiLoaded) {
  85678. callback();
  85679. } else {
  85680. this.guiLoadTasks.push(callback);
  85681. }
  85682. }
  85683. promiseGuiLoaded() {
  85684. return new Promise(resolve => {
  85685. if (this.guiLoaded) {
  85686. resolve();
  85687. } else {
  85688. this.guiLoadTasks.push(resolve);
  85689. }
  85690. });
  85691. }
  85692. loadGUI(callback) {
  85693. if (callback) {
  85694. this.onGUILoaded(callback);
  85695. }
  85696. var viewer = this;
  85697. var sidebarContainer = $('#potree_sidebar_container');
  85698. sidebarContainer.load(new URL(Potree.scriptPath + '/' + (Potree.settings.sidebar || 'sidebar1.html')).href, () => {
  85699. sidebarContainer.css('width', '300px');
  85700. sidebarContainer.css('height', '100%');
  85701. var imgMenuToggle = document.createElement('img');
  85702. imgMenuToggle.src = new URL(Potree.resourcePath + '/icons/menu_button.svg').href;
  85703. imgMenuToggle.onclick = this.toggleSidebar;
  85704. imgMenuToggle.classList.add('potree_menu_toggle');
  85705. var imgMapToggle = document.createElement('img');
  85706. imgMapToggle.src = new URL(Potree.resourcePath + '/icons/map_icon.png').href;
  85707. imgMapToggle.style.display = 'none';
  85708. imgMapToggle.onclick = e => {
  85709. this.toggleMap();
  85710. };
  85711. imgMapToggle.id = 'potree_map_toggle';
  85712. var elButtons = $("#potree_quick_buttons").get(0);
  85713. elButtons.append(imgMenuToggle);
  85714. elButtons.append(imgMapToggle);
  85715. VRButton.createButton(this.renderer).then(vrButton => {
  85716. if (vrButton == null) {
  85717. console.log("VR not supported or active.");
  85718. return;
  85719. }
  85720. this.renderer.xr.enabled = true;
  85721. var element = vrButton.element;
  85722. element.style.position = "";
  85723. element.style.bottom = "";
  85724. element.style.left = "";
  85725. element.style.margin = "4px";
  85726. element.style.fontSize = "100%";
  85727. element.style.width = "2.5em";
  85728. element.style.height = "2.5em";
  85729. element.style.padding = "0";
  85730. element.style.textShadow = "black 2px 2px 2px";
  85731. element.style.display = "block";
  85732. elButtons.append(element);
  85733. vrButton.onStart(() => {
  85734. this.dispatchEvent({
  85735. type: "vr_start"
  85736. });
  85737. });
  85738. vrButton.onEnd(() => {
  85739. this.dispatchEvent({
  85740. type: "vr_end"
  85741. });
  85742. });
  85743. });
  85744. /* this.mapView = new MapView(this);
  85745. this.mapView.init(); */
  85746. i18n.init({
  85747. lng: 'en',
  85748. resGetPath: Potree.resourcePath + '/lang/__lng__/__ns__.json',
  85749. preload: ['en', 'fr', 'de', 'jp', 'se', 'es', 'zh'],
  85750. getAsync: true,
  85751. debug: false
  85752. }, function (t) {
  85753. // Start translation once everything is loaded
  85754. $('body').i18n();
  85755. });
  85756. $(() => {
  85757. //initSidebar(this);
  85758. var sidebar = new Sidebar(this);
  85759. sidebar.init();
  85760. this.sidebar = sidebar;
  85761. //if (callback) {
  85762. // $(callback);
  85763. //}
  85764. var elProfile = $('<div>').load(new URL(Potree.scriptPath + '/profile.html').href, () => {
  85765. $(document.body).append(elProfile.children());
  85766. this.profileWindow = new ProfileWindow(this);
  85767. this.profileWindowController = new ProfileWindowController(this);
  85768. $('#profile_window').draggable({
  85769. handle: $('#profile_titlebar'),
  85770. containment: $(document.body)
  85771. });
  85772. $('#profile_window').resizable({
  85773. containment: $(document.body),
  85774. handles: 'n, e, s, w'
  85775. });
  85776. $(() => {
  85777. this.guiLoaded = true;
  85778. for (var task of this.guiLoadTasks) {
  85779. task();
  85780. }
  85781. });
  85782. });
  85783. });
  85784. });
  85785. return this.promiseGuiLoaded();
  85786. }
  85787. setLanguage(lang) {
  85788. i18n.setLng(lang);
  85789. $('body').i18n();
  85790. }
  85791. setServer(server) {
  85792. this.server = server;
  85793. }
  85794. initDragAndDrop() {
  85795. function allowDrag(e) {
  85796. e.dataTransfer.dropEffect = 'copy';
  85797. e.preventDefault();
  85798. }
  85799. var dropHandler = async event => {
  85800. console.log(event);
  85801. event.preventDefault();
  85802. for (var item of event.dataTransfer.items) {
  85803. console.log(item);
  85804. if (item.kind !== "file") {
  85805. continue;
  85806. }
  85807. var file = item.getAsFile();
  85808. var isJson = file.name.toLowerCase().endsWith(".json");
  85809. var isGeoPackage = file.name.toLowerCase().endsWith(".gpkg");
  85810. if (isJson) {
  85811. try {
  85812. var text = await file.text();
  85813. var json = JSON.parse(text);
  85814. if (json.type === "Potree") {
  85815. Potree.loadProject(viewer, json);
  85816. }
  85817. } catch (e) {
  85818. console.error("failed to parse the dropped file as JSON");
  85819. console.error(e);
  85820. }
  85821. } else if (isGeoPackage) {
  85822. var hasPointcloud = viewer.scene.pointclouds.length > 0;
  85823. if (!hasPointcloud) {
  85824. var msg = "At least one point cloud is needed that specifies the ";
  85825. msg += "coordinate reference system before loading vector data.";
  85826. console.error(msg);
  85827. } else {
  85828. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  85829. proj4.defs("pointcloud", this.getProjection());
  85830. var transform = proj4("WGS84", "pointcloud");
  85831. var buffer = await file.arrayBuffer();
  85832. var params = {
  85833. transform: transform,
  85834. source: file.name
  85835. };
  85836. var geo = await Potree.GeoPackageLoader.loadBuffer(buffer, params);
  85837. viewer.scene.addGeopackage(geo);
  85838. }
  85839. }
  85840. }
  85841. };
  85842. $("body")[0].addEventListener("dragenter", allowDrag);
  85843. $("body")[0].addEventListener("dragover", allowDrag);
  85844. $("body")[0].addEventListener("drop", dropHandler);
  85845. }
  85846. updateAnnotations() {
  85847. if (!this.visibleAnnotations) {
  85848. this.visibleAnnotations = new Set();
  85849. }
  85850. this.scene.annotations.updateBounds();
  85851. this.scene.cameraP.updateMatrixWorld();
  85852. this.scene.cameraO.updateMatrixWorld();
  85853. var distances = [];
  85854. var renderAreaSize = this.renderer.getSize(new Vector2());
  85855. var viewer = this;
  85856. var visibleNow = [];
  85857. this.scene.annotations.traverse(annotation => {
  85858. if (annotation === this.scene.annotations) {
  85859. return true;
  85860. }
  85861. if (!annotation.visible) {
  85862. return false;
  85863. }
  85864. annotation.scene = this.scene;
  85865. var element = annotation.domElement;
  85866. var position = annotation.position.clone();
  85867. position.add(annotation.offset);
  85868. if (!position) {
  85869. position = annotation.boundingBox.getCenter(new Vector3());
  85870. }
  85871. var distance = viewer.scene.cameraP.position.distanceTo(position);
  85872. var radius = annotation.boundingBox.getBoundingSphere(new Sphere()).radius;
  85873. var screenPos = new Vector3();
  85874. var screenSize = 0;
  85875. {
  85876. // SCREEN POS
  85877. screenPos.copy(position).project(this.scene.getActiveCamera());
  85878. screenPos.x = renderAreaSize.x * (screenPos.x + 1) / 2;
  85879. screenPos.y = renderAreaSize.y * (1 - (screenPos.y + 1) / 2);
  85880. // SCREEN SIZE
  85881. if (viewer.scene.cameraMode == CameraMode.PERSPECTIVE) {
  85882. var fov = Math.PI * viewer.scene.cameraP.fov / 180;
  85883. var slope = Math.tan(fov / 2.0);
  85884. var projFactor = 0.5 * renderAreaSize.y / (slope * distance);
  85885. screenSize = radius * projFactor;
  85886. } else {
  85887. screenSize = Utils.projectedRadiusOrtho(radius, viewer.scene.cameraO.projectionMatrix, renderAreaSize.x, renderAreaSize.y);
  85888. }
  85889. }
  85890. element.css("left", screenPos.x + "px");
  85891. element.css("top", screenPos.y + "px");
  85892. //element.css("display", "block");
  85893. var zIndex = 10000000 - distance * (10000000 / this.scene.cameraP.far);
  85894. if (annotation.descriptionVisible) {
  85895. zIndex += 10000000;
  85896. }
  85897. element.css("z-index", parseInt(zIndex));
  85898. if (annotation.children.length > 0) {
  85899. var expand = screenSize > annotation.collapseThreshold || annotation.boundingBox.containsPoint(this.scene.getActiveCamera().position);
  85900. annotation.expand = expand;
  85901. if (!expand) {
  85902. //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
  85903. var inFrustum = screenPos.z >= -1 && screenPos.z <= 1;
  85904. if (inFrustum) {
  85905. visibleNow.push(annotation);
  85906. }
  85907. }
  85908. return expand;
  85909. } else {
  85910. //annotation.display = (screenPos.z >= -1 && screenPos.z <= 1);
  85911. var _inFrustum = screenPos.z >= -1 && screenPos.z <= 1;
  85912. if (_inFrustum) {
  85913. visibleNow.push(annotation);
  85914. }
  85915. }
  85916. });
  85917. var notVisibleAnymore = new Set(this.visibleAnnotations);
  85918. for (var annotation of visibleNow) {
  85919. annotation.display = true;
  85920. notVisibleAnymore.delete(annotation);
  85921. }
  85922. this.visibleAnnotations = visibleNow;
  85923. for (var _annotation of notVisibleAnymore) {
  85924. _annotation.display = false;
  85925. }
  85926. }
  85927. updateMaterialDefaults(pointcloud) {
  85928. // PROBLEM STATEMENT:
  85929. // * [min, max] of intensity, source id, etc. are computed as point clouds are loaded
  85930. // * the point cloud material won't know the range it should use until some data is loaded
  85931. // * users can modify the range at runtime, but sensible default ranges should be
  85932. // applied even if no GUI is present
  85933. // * display ranges shouldn't suddenly change even if the actual range changes over time.
  85934. // e.g. the root node has intensity range [1, 478]. One of the descendants increases range to
  85935. // [0, 2047]. We should not automatically change to the new range because that would result
  85936. // in sudden and drastic changes of brightness. We should adjust the min/max of the sidebar slider.
  85937. var material = pointcloud.material;
  85938. var attIntensity = pointcloud.getAttribute("intensity");
  85939. if (attIntensity != null && material.intensityRange[0] === Infinity) {
  85940. material.intensityRange = [...attIntensity.range];
  85941. }
  85942. // const attIntensity = pointcloud.getAttribute("intensity");
  85943. // if(attIntensity && material.intensityRange[0] === Infinity){
  85944. // material.intensityRange = [...attIntensity.range];
  85945. // }
  85946. // let attributes = pointcloud.getAttributes();
  85947. // for(let attribute of attributes.attributes){
  85948. // if(attribute.range){
  85949. // let range = [...attribute.range];
  85950. // material.computedRange.set(attribute.name, range);
  85951. // //material.setRange(attribute.name, range);
  85952. // }
  85953. // }
  85954. }
  85955. update(delta, timestamp) {
  85956. var _this$map3d, _this$map3d2;
  85957. viewer.addTimeMark('update', 'start');
  85958. TWEEN.update(timestamp);
  85959. transitions.update(delta); //写在开头,因为这时候最为固定,计时准确
  85960. this.dispatchEvent({
  85961. type: 'update_start',
  85962. delta: delta,
  85963. timestamp: timestamp
  85964. });
  85965. this.updateScreenSize(); //判断是否改变canvas大小
  85966. var scene = this.scene;
  85967. var camera = scene.getActiveCamera();
  85968. var visiblePointClouds = this.scene.pointclouds.filter(pc => pc.visible);
  85969. Potree.pointLoadLimit = Potree.pointBudget * 2;
  85970. /* const lTarget = camera.position.clone().add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(1000));
  85971. this.scene.directionalLight.position.copy(camera.position);
  85972. this.scene.directionalLight.lookAt(lTarget); */
  85973. for (var pointcloud of visiblePointClouds) {
  85974. pointcloud.showBoundingBox = this.showBoundingBox;
  85975. pointcloud.generateDEM = this.generateDEM;
  85976. pointcloud.minimumNodePixelSize = this.minNodeSize;
  85977. var material = pointcloud.material;
  85978. material.uniforms.uFilterReturnNumberRange.value = this.filterReturnNumberRange;
  85979. material.uniforms.uFilterNumberOfReturnsRange.value = this.filterNumberOfReturnsRange;
  85980. material.uniforms.uFilterGPSTimeClipRange.value = this.filterGPSTimeRange;
  85981. material.uniforms.uFilterPointSourceIDClipRange.value = this.filterPointSourceIDRange;
  85982. //material.classificationName = this.classificationName
  85983. //material.classification = this.classifications;
  85984. //material.recomputeClassification();
  85985. this.updateMaterialDefaults(pointcloud);
  85986. }
  85987. {
  85988. if (this.showBoundingBox) {
  85989. var bbRoot = this.scene.scene.getObjectByName("potree_bounding_box_root");
  85990. if (!bbRoot) {
  85991. var node = new Object3D();
  85992. node.name = "potree_bounding_box_root";
  85993. this.scene.scene.add(node);
  85994. bbRoot = node;
  85995. }
  85996. var visibleBoxes = [];
  85997. for (var _pointcloud of this.scene.pointclouds) {
  85998. for (var _node of _pointcloud.visibleNodes.filter(vn => vn.boundingBoxNode !== undefined)) {
  85999. var box = _node.boundingBoxNode;
  86000. visibleBoxes.push(box);
  86001. }
  86002. }
  86003. bbRoot.children = visibleBoxes;
  86004. }
  86005. }
  86006. if (this.boundNeedUpdate) this.updateModelBound(); //add
  86007. this.scene.cameraP.fov = this.fov;
  86008. var controls = this.getControls();
  86009. if (controls === this.deviceControls) {
  86010. this.controls.setScene(scene);
  86011. this.controls.update(delta);
  86012. this.scene.cameraP.position.copy(scene.view.position);
  86013. this.scene.cameraO.position.copy(scene.view.position);
  86014. } else if (controls !== null) {
  86015. controls.setScene(scene);
  86016. controls.update(delta);
  86017. //更新camera
  86018. this.viewports.forEach(viewport => {
  86019. if (!viewport.active) return;
  86020. viewport.view.applyToCamera(viewport.camera);
  86021. });
  86022. }
  86023. this.lastFrameChanged = this.cameraChanged(); //判断camera画面是否改变
  86024. {
  86025. // update clip boxes
  86026. var boxes = [];
  86027. // volumes with clipping enabled
  86028. boxes.push(...this.scene.volumes.filter(v => v.clip && v instanceof BoxVolume$1));
  86029. // profile segments
  86030. for (var profile of this.scene.profiles) {
  86031. boxes.push(...profile.boxes);
  86032. }
  86033. // Needed for .getInverse(), pre-empt a determinant of 0, see #815 / #816
  86034. var degenerate = box => box.matrixWorld.determinant() !== 0 && box.clip;
  86035. var clipBoxes = boxes.filter(degenerate).map(box => {
  86036. box.updateMatrixWorld();
  86037. var boxInverse = box.matrixWorld.clone().invert();
  86038. //let boxPosition = box.getWorldPosition(new THREE.Vector3());
  86039. return {
  86040. box: box,
  86041. inverse: boxInverse /* , position: boxPosition */
  86042. };
  86043. });
  86044. //改
  86045. var bigClipInBox = clipBoxes.find(e => e.box.clipTask == ClipTask.SHOW_INSIDE_Big && !e.box.highlight); //裁剪下载 when this.modules.Clip.editing
  86046. var clipBoxes_in = clipBoxes.filter(e => e.box.clipTask == ClipTask.SHOW_INSIDE && !e.box.highlight);
  86047. var clipBoxes_out = clipBoxes.filter(e => e.box.clipTask == ClipTask.SHOW_OUTSIDE && !e.box.highlight);
  86048. var highlightBoxes = clipBoxes.filter(e => e.box.highlight);
  86049. //let prismPolygons = this.modules.volumeComputer && this.modules.volumeComputer.entered ? viewer.scene.measurements.filter(e=>(e.measureType == 'MulDistance Ring') && !e.isNew) : []
  86050. var prismPolygons = this.modules.volumeComputer ? this.modules.volumeComputer.prisms.filter(e => !e.isNew && e.visible && !e.dontHighlight && (e.baseModel || !e.modelHaventLoad)) : [];
  86051. // set clip volumes in material
  86052. for (var _pointcloud2 of visiblePointClouds) {
  86053. _pointcloud2.material.setClipBoxes(bigClipInBox, clipBoxes_in, clipBoxes_out, highlightBoxes, prismPolygons);
  86054. }
  86055. }
  86056. {
  86057. for (var _pointcloud3 of visiblePointClouds) {
  86058. _pointcloud3.material.elevationGradientRepeat = this.elevationGradientRepeat;
  86059. }
  86060. }
  86061. {
  86062. // update navigation cube
  86063. this.navigationCube.update(camera.rotation);
  86064. }
  86065. this.updateAnnotations();
  86066. if (this.mapView) {
  86067. this.mapView.update(delta);
  86068. if (this.mapView.sceneProjection) {
  86069. $("#potree_map_toggle").css("display", "block");
  86070. }
  86071. }
  86072. this.transformationTool.update();
  86073. if (Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge') {
  86074. this.modules.ParticleEditor.update(delta);
  86075. }
  86076. this.mapViewer && this.mapViewer.update(delta); //地图更新
  86077. (this.lastFrameChanged || ((_this$map3d = this.map3d) === null || _this$map3d === void 0 ? void 0 : _this$map3d.needUpdate)) && ((_this$map3d2 = this.map3d) === null || _this$map3d2 === void 0 ? void 0 : _this$map3d2.update(delta)); //地图更新
  86078. this.dispatchEvent({
  86079. type: 'update',
  86080. delta: delta,
  86081. timestamp: timestamp
  86082. }); //在有sidebar时耗高cpu,占本update函数80%
  86083. viewer.addTimeMark('update', 'end');
  86084. //add ------
  86085. this.reticule.updateVisible();
  86086. }
  86087. updateViewPointcloud(camera, areaSize, isViewport) {
  86088. var result = Potree.updatePointClouds(this.scene.pointclouds, camera, areaSize);
  86089. //if(isViewport)return
  86090. var tStart = performance.now();
  86091. var campos = camera.position;
  86092. var closestImage = Infinity;
  86093. for (var images of this.scene.orientedImages) {
  86094. for (var image of images.images) {
  86095. var distance = image.mesh.position.distanceTo(campos);
  86096. closestImage = Math.min(closestImage, distance);
  86097. }
  86098. }
  86099. //const tEnd = performance.now();
  86100. //改:不根据点云修改视野near far
  86101. var near = camera.near,
  86102. far = camera.far;
  86103. if (!camera.limitFar && result.lowestSpacing !== Infinity) {
  86104. //let near = result.lowestSpacing * 10.0;
  86105. var _far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
  86106. _far = Math.max(_far * 1.5, 10000);
  86107. //near = Math.min(100.0, Math.max(0.01, near));
  86108. //near = Math.min(near, closestImage);
  86109. _far = Math.max(_far, near + 10000);
  86110. /* if(near === Infinity){
  86111. near = 0.1;
  86112. } */
  86113. //camera.near = near; //为了其他物体的显示,不修改near
  86114. camera.far = _far;
  86115. }
  86116. /* if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
  86117. camera.near = -camera.far;
  86118. } */
  86119. if ( /* near != camera.near || */far != camera.far) {
  86120. camera.updateProjectionMatrix();
  86121. }
  86122. //注:pointcloud.visibleNodes会随着near far自动更新
  86123. }
  86124. getPRenderer() {
  86125. if (this.useHQ) {
  86126. if (!this.hqRenderer) {
  86127. this.hqRenderer = new HQSplatRenderer(this);
  86128. }
  86129. this.hqRenderer.useEDL = this.useEDL;
  86130. return this.hqRenderer;
  86131. } else {
  86132. /* if (this.useEDL && Features.SHADER_EDL.isSupported()) {
  86133. if (!this.edlRenderer) {
  86134. this.edlRenderer = new EDLRenderer(this);
  86135. }
  86136. return this.edlRenderer;
  86137. } else {
  86138. if (!this.potreeRenderer) {
  86139. this.potreeRenderer = new PotreeRenderer(this);
  86140. }
  86141. return this.potreeRenderer;
  86142. } */
  86143. if (!this.edlRenderer) {
  86144. this.edlRenderer = new EDLRenderer(this);
  86145. }
  86146. return this.edlRenderer;
  86147. }
  86148. }
  86149. renderVR() {
  86150. //渲染部分没改完
  86151. var renderer = this.renderer;
  86152. renderer.setClearColor(0x550000, 0);
  86153. renderer.clear();
  86154. var xr = renderer.xr;
  86155. var dbg = new PerspectiveCamera();
  86156. var xrCameras = xr.getCamera(dbg);
  86157. if (xrCameras.cameras.length !== 2) {
  86158. return;
  86159. }
  86160. var makeCam = this.vrControls.getCamera.bind(this.vrControls);
  86161. {
  86162. // clear framebuffer
  86163. if (viewer.background === "skybox") {
  86164. renderer.setClearColor(0xff0000, 1);
  86165. } else if (viewer.background === "gradient") {
  86166. renderer.setClearColor(0x112233, 1);
  86167. } else if (viewer.background === "black") {
  86168. renderer.setClearColor(0x000000, 1);
  86169. } else if (viewer.background === "white") {
  86170. renderer.setClearColor(0xFFFFFF, 1);
  86171. } else {
  86172. renderer.setClearColor(0x000000, 0);
  86173. }
  86174. renderer.clear();
  86175. }
  86176. // render background
  86177. if (this.background === "skybox") {
  86178. var {
  86179. skybox
  86180. } = this;
  86181. var _cam = makeCam();
  86182. skybox.camera.rotation.copy(_cam.rotation);
  86183. skybox.camera.fov = _cam.fov;
  86184. skybox.camera.aspect = _cam.aspect;
  86185. // let dbg = new THREE.Object3D();
  86186. var _dbg = skybox.parent;
  86187. // dbg.up.set(0, 0, 1);
  86188. _dbg.rotation.x = Math.PI / 2;
  86189. // skybox.camera.parent = dbg;
  86190. // dbg.children.push(skybox.camera);
  86191. _dbg.updateMatrix();
  86192. _dbg.updateMatrixWorld();
  86193. skybox.camera.updateMatrix();
  86194. skybox.camera.updateMatrixWorld();
  86195. skybox.camera.updateProjectionMatrix();
  86196. renderer.render(skybox.scene, skybox.camera);
  86197. // renderer.render(skybox.scene, cam);
  86198. } else if (this.background === "gradient") {
  86199. // renderer.render(this.scene.sceneBG, this.scene.cameraBG);
  86200. }
  86201. this.renderer.xr.getSession().updateRenderState({
  86202. depthNear: 0.1,
  86203. depthFar: 10000
  86204. });
  86205. var cam = null;
  86206. var view = null;
  86207. {
  86208. // render world scene
  86209. cam = makeCam();
  86210. cam.position.z -= 0.8 * cam.scale.x;
  86211. cam.parent = null;
  86212. // cam.near = 0.05;
  86213. cam.near = viewer.scene.getActiveCamera().near;
  86214. cam.far = viewer.scene.getActiveCamera().far;
  86215. cam.updateMatrix();
  86216. cam.updateMatrixWorld();
  86217. this.scene.scene.updateMatrix();
  86218. this.scene.scene.updateMatrixWorld();
  86219. this.scene.scene.matrixAutoUpdate = false;
  86220. var camWorld = cam.matrixWorld.clone();
  86221. view = camWorld.clone().invert();
  86222. this.scene.scene.matrix.copy(view);
  86223. this.scene.scene.matrixWorld.copy(view);
  86224. cam.matrix.identity();
  86225. cam.matrixWorld.identity();
  86226. cam.matrixWorldInverse.identity();
  86227. renderer.render(this.scene.scene, cam);
  86228. this.scene.scene.matrixWorld.identity();
  86229. }
  86230. for (var pointcloud of this.scene.pointclouds) {
  86231. var viewport = xrCameras.cameras[0].viewport;
  86232. pointcloud.material.useEDL = false;
  86233. pointcloud.screenHeight = viewport.height;
  86234. pointcloud.screenWidth = viewport.width;
  86235. // automatically switch to paraboloids because they cause far less flickering in VR,
  86236. // when point sizes are larger than around 2 pixels
  86237. // if(Features.SHADER_INTERPOLATION.isSupported()){
  86238. // pointcloud.material.shape = Potree.PointShape.PARABOLOID;
  86239. // }
  86240. }
  86241. // render point clouds
  86242. for (var xrCamera of xrCameras.cameras) {
  86243. var v = xrCamera.viewport;
  86244. renderer.setViewport(v.x, v.y, v.width, v.height);
  86245. // xrCamera.fov = 90;
  86246. {
  86247. // estimate VR fov
  86248. var proj = xrCamera.projectionMatrix;
  86249. var inv = proj.clone().invert();
  86250. var p1 = new Vector4(0, 1, -1, 1).applyMatrix4(inv);
  86251. var rad = p1.y;
  86252. var fov = 180 * (rad / Math.PI);
  86253. xrCamera.fov = fov;
  86254. }
  86255. for (var _pointcloud4 of this.scene.pointclouds) {
  86256. var {
  86257. material
  86258. } = _pointcloud4;
  86259. material.useEDL = false;
  86260. }
  86261. var vrWorld = view.clone().invert();
  86262. vrWorld.multiply(xrCamera.matrixWorld);
  86263. var vrView = vrWorld.clone().invert();
  86264. this.pRenderer.render(this.scene.scenePointCloud, xrCamera, null, {
  86265. viewOverride: vrView
  86266. });
  86267. }
  86268. {
  86269. // render VR scene
  86270. var _cam2 = makeCam();
  86271. _cam2.parent = null;
  86272. renderer.render(this.sceneVR, _cam2);
  86273. }
  86274. renderer.resetState();
  86275. }
  86276. clear() {
  86277. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  86278. var background = params.background || this.background;
  86279. var backgroundOpacity = params.backgroundOpacity == void 0 ? this.backgroundOpacity : params.backgroundOpacity; //如果想完全透明,只需要backgroundOpacity为0
  86280. var renderer = this.renderer;
  86281. //let gl = renderer.getContext()
  86282. if (background instanceof Color) {
  86283. //add
  86284. renderer.setClearColor(background, backgroundOpacity);
  86285. } else if (background === "skybox") {
  86286. renderer.setClearColor(0x000000, backgroundOpacity);
  86287. } else if (background === 'gradient') {
  86288. renderer.setClearColor(0x000000, backgroundOpacity);
  86289. } else if (background === 'black') {
  86290. renderer.setClearColor(0x000000, 1);
  86291. } else if (background === 'white') {
  86292. renderer.setClearColor(0xFFFFFF, 1);
  86293. } else {
  86294. renderer.setClearColor(background, backgroundOpacity);
  86295. }
  86296. params.target || renderer.clear();
  86297. }
  86298. getBuffer(viewport) {
  86299. //根据不同viewport返回rtEDL的texture
  86300. var buffer = this.buffers.get(viewport);
  86301. if (!buffer) {
  86302. buffer = new WebGLRenderTarget(viewport.resolution.x, viewport.resolution.y, {
  86303. minFilter: NearestFilter,
  86304. magFilter: NearestFilter,
  86305. format: RGBAFormat,
  86306. type: FloatType
  86307. });
  86308. this.buffers.set(viewport, rtEDL);
  86309. }
  86310. return buffer;
  86311. }
  86312. async renderDefault() {
  86313. var params_ = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  86314. if (!this.visible) return;
  86315. var pRenderer = this.getPRenderer();
  86316. var viewports = params_.viewports || this.viewports;
  86317. var renderer = params_.renderer || this.renderer;
  86318. viewer.addTimeMark('renderDefault', 'start');
  86319. //console.log('render', viewports.map(e=>e.name).join(','))
  86320. var renderSize;
  86321. if (params_.target) {
  86322. renderSize = new Vector2(params_.target.width, params_.target.height); //是画布大小
  86323. //可能需要viewer.setSize
  86324. } else {
  86325. renderSize = renderer.getSize(new Vector2()); //是client大小
  86326. }
  86327. ///let needsResize = viewports.length > 1 || params_.resize //去掉原因:因为不需要渲染的viewport不在此中所以无法判断几个viewport
  86328. for (var i = 0; i < viewports.length; i++) {
  86329. var viewport = viewports[i];
  86330. var params = $.extend({}, params_);
  86331. params.viewport = viewport;
  86332. //if(!params.target){
  86333. params.camera = params.camera || viewport.camera;
  86334. params.extraEnableLayers = viewport.extraEnableLayers;
  86335. params.cameraLayers = viewport.cameraLayers;
  86336. //}
  86337. params.useModelOnRT = Potree.settings.intersectOnObjs && pRenderer.canUseRTPoint() && pRenderer.getIfRtEDL_(params) && !pRenderer.getIfuseEdl(params); //模型是否绘制在rtEDL上且能直接绘制到屏幕(感觉容易错)
  86338. var left, bottom, width, height;
  86339. {
  86340. left = Math.ceil(renderSize.x * viewport.left);
  86341. bottom = Math.ceil(renderSize.y * viewport.bottom);
  86342. if (params_.target) {
  86343. //有target时最好viewport是专门建出来的
  86344. width = renderSize.x * viewport.width; //target的大小可能和viewport不同,比如截图,这时会更改viewport大小
  86345. height = renderSize.y * viewport.height;
  86346. } else {
  86347. width = viewport.resolution.x; // 用的是client的width和height
  86348. height = viewport.resolution.y;
  86349. }
  86350. if (width == 0 || height == 0) continue; //return
  86351. width = Math.ceil(width); //使用ceil,当原本有小数时,会重叠一个像素,无所谓
  86352. height = Math.ceil(height);
  86353. var scissorTest = viewport.width < 1 || viewport.height < 1;
  86354. if (params_.target) {
  86355. params_.target.viewport.set(left, bottom, width, height);
  86356. scissorTest && params_.target.scissor.set(left, bottom, width, height);
  86357. params_.target.scissorTest = scissorTest;
  86358. renderer.setRenderTarget(params_.target);
  86359. } else {
  86360. /* if(viewports.length == 1 && left == 0 && bottom == 0){
  86361. left = 1 , width-=1 //这种情况下渲染也会有问题,只有鼠标的地方刷新 估计是pick那影响的
  86362. } */
  86363. /* if(scissorTest && left == 0 && bottom == 0){
  86364. left = 1 , width-=1
  86365. } */
  86366. if (viewport.forViewOffset) {
  86367. //分块渲染,渲染时的camera还是原来的,但加载点云时的camera是分块中的
  86368. viewport.forViewOffset.camera.setViewOffset(renderSize.x, renderSize.y, left, renderSize.y - bottom - height, width, height);
  86369. renderer.setViewport(0, 0, renderSize.x, renderSize.y);
  86370. viewport.resolution.copy(viewport.forViewOffset.originViewport.resolution);
  86371. viewport.resolution2.copy(viewport.forViewOffset.originViewport.resolution2); //后续渲染都当做原先的viewport
  86372. } else {
  86373. renderer.setViewport(left, bottom, width, height); //规定视口,影响图形变换(画布的使用范围)
  86374. }
  86375. //scissorTest && console.log('setScissor', left, bottom, width, height)
  86376. scissorTest && renderer.setScissor(left, bottom, width, height); //规定渲染范围
  86377. renderer.setScissorTest(scissorTest); //开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
  86378. }
  86379. }
  86380. //if(needsResize){
  86381. this.ifEmitResize({
  86382. viewport
  86383. });
  86384. //}
  86385. viewer.dispatchEvent({
  86386. type: "render.begin",
  86387. viewer: viewer,
  86388. viewport,
  86389. params
  86390. });
  86391. viewport.beforeRender && viewport.beforeRender();
  86392. if (viewport.render) {
  86393. if (!viewport.render($.extend({}, params, {
  86394. renderer,
  86395. clear: params.clear || this.clear.bind(this),
  86396. resize: null,
  86397. renderBG: this.renderBG.bind(this),
  86398. force: true //viewer content_change时map也直接渲染吧 //!viewport.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
  86399. }))) continue; //return
  86400. } else {
  86401. this.clear(params);
  86402. pRenderer.clearTargets(params);
  86403. this.renderBG(viewport);
  86404. if (this.splatMesh) {
  86405. Potree.Utils.setCameraLayers(params.camera, ['model']);
  86406. this.renderer.render(this.splatMesh, params.camera);
  86407. }
  86408. if (Potree.settings.notAdditiveBlending) {
  86409. params.renderBeforeCloud = true;
  86410. this.renderOverlay1(params); //先渲染不透明的model。
  86411. }
  86412. }
  86413. if (!viewport.noPointcloud) {
  86414. if (params_.needWaitLoadPoint) {
  86415. await this.waitPointLoad(null, params_.maxTimeForPointLoad, viewport); //resolution得用split前整个的viewport的
  86416. } else {
  86417. this.updateViewPointcloud(params.camera, viewport.resolution, true);
  86418. }
  86419. pRenderer.render(params); //渲染点云 skybox。
  86420. }
  86421. if (Potree.settings.notAdditiveBlending) {
  86422. // 融合页面才用到
  86423. params.renderBeforeCloud = false;
  86424. this.renderOverlay1(params);
  86425. this.renderOverlay2(params);
  86426. } else {
  86427. this.renderOverlay(params);
  86428. }
  86429. viewport.afterRender && viewport.afterRender();
  86430. this.dispatchEvent({
  86431. type: "render.end",
  86432. viewer: this,
  86433. viewport
  86434. });
  86435. viewport.needRender = false;
  86436. viewport.lastRenderTime = Date.now();
  86437. }
  86438. /* if(params_.screenshot){ //抗锯齿
  86439. this.composer.render();
  86440. } */
  86441. this.renderer.setRenderTarget(null);
  86442. viewer.scene.pointclouds[0] && this.addFakeMeasure('visibleNodes', viewer.scene.pointclouds[0].visibleNodes.length); //
  86443. this.addFakeMeasure('numVisiblePoints', Potree.numVisiblePoints / 100000); //十万 numVisiblePoints和帧率成反比(若每一帧都render的话),和render用时成正比 (y=kn+b)。但visibleNodes个数也影响,多的话也更卡。visibleNodes和numVisiblePoints不成正比,少的visibleNodes可能numVisiblePoints多
  86444. viewer.addTimeMark('renderDefault', 'end');
  86445. }
  86446. renderBG(viewport) {
  86447. var background = viewport.background || viewer.background;
  86448. var backgroundOpacity = viewport.backgroundOpacity == void 0 ? viewer.backgroundOpacity : viewport.backgroundOpacity; //如果想完全透明,只需要backgroundOpacity为0
  86449. if (backgroundOpacity != 0) {
  86450. //绘制背景. 为了防止相机移动后天空不动有点死板,做一定的动态
  86451. if (background === "skybox") {
  86452. //限制相机到原点的距离。
  86453. var skyCamera = viewport.camera.type == "OrthographicCamera" ? viewer.skybox.cameraOrtho : viewer.skybox.camera;
  86454. var safeRatio = 0.02;
  86455. var safeWidth = Potree.config.skyboxBgWidth * safeRatio / 2; //相机只能在这个范围内移动
  86456. if (!viewport.skyboxFixPos) {
  86457. //允许不在全景图中心,允许位移造成一定程度畸变
  86458. var dir = new Vector3().subVectors(viewport.camera.position, viewer.bound.center);
  86459. var length = dir.length();
  86460. var moveMax = 100;
  86461. var aimRadius = easing.easeOutQuart(Math.min(length, moveMax), 0, safeWidth, moveMax); //(x, startY, wholeY, maxX) 当自变量为0-moveMax时,相机位移量为0-safeWidth
  86462. dir.multiplyScalar(aimRadius / length);
  86463. skyCamera.position.copy(dir);
  86464. } else {
  86465. skyCamera.position.set(0, 0, 0);
  86466. }
  86467. skyCamera.rotation.copy(viewport.camera.rotation);
  86468. skyCamera.aspect = viewport.camera.aspect;
  86469. if (viewport.camera.type == "OrthographicCamera") {
  86470. //调节zoom
  86471. skyCamera.left = viewport.camera.left;
  86472. skyCamera.right = viewport.camera.right;
  86473. skyCamera.top = viewport.camera.top;
  86474. skyCamera.bottom = viewport.camera.bottom;
  86475. var a = Potree.config.skyboxBgWidth / 2 - safeWidth;
  86476. var minY = Math.max(skyCamera.right / a, skyCamera.top / a, viewport.skyboxMinZoom || 0); //能够使skybox铺满画布的最小zoom. 提示:越远zoom越小
  86477. var maxY = Math.max(20, minY); //自定义一个 不会超过的最大实际zoom
  86478. //viewport.camera.zoom自变量的变化范围:
  86479. var minX = 1;
  86480. var maxX = 80;
  86481. var x = MathUtils.clamp(viewport.camera.zoom - minX, minX, maxX);
  86482. skyCamera.zoom = easing.easeOutCubic(x - minX, minY, maxY - minY, maxX - minX); //自变量范围从0开始,所以减去minX
  86483. //pos的范围先不管了 其实aimRadius是有误的,但效果还行
  86484. } else {
  86485. skyCamera.fov = viewport.camera.fov;
  86486. skyCamera.zoom = 1;
  86487. }
  86488. viewport.skyboxRenderFun && viewport.skyboxRenderFun();
  86489. skyCamera.updateProjectionMatrix();
  86490. skyCamera.updateMatrixWorld();
  86491. viewer.renderer.render(viewer.skybox.scene, skyCamera);
  86492. } else if (background === 'gradient') {
  86493. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  86494. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  86495. } else if (background === 'overlayColor') {
  86496. //在不clear的前提下加一层背景色
  86497. viewer.scene.bg2.material.color.copy(viewport.backgroundColor);
  86498. viewer.scene.bg2.material.opacity = viewport.backgroundOpacity;
  86499. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
  86500. viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  86501. }
  86502. }
  86503. if (this.map3d && viewport == this.mainViewport) {
  86504. Potree.Utils.setCameraLayers(viewport.camera, ['map']);
  86505. viewer.renderer.render(this.scene.scene, viewport.camera);
  86506. }
  86507. //全景图的部分和点云有点相关就不移动到这了。但是如果是showPanos模式,就不要渲染背景了。
  86508. }
  86509. /*
  86510. 关于透明度:
  86511. 由于点云和mesh是分开渲染的,且材质很不一样,所以透明和blend有冲突
  86512. 1 如果点云的blend是AdditiveBlending,也就是普通的叠加模式。
  86513. 则半透明点云的depthTest和depthWrite都为false
  86514. 这时候mesh要后渲染,且depthWrite不能为false(除非depthTest也为false),否则将被点云遮住。
  86515. 2 如果点云的blend是普通型
  86516. 则半透明点云的depthTest和depthWrite都为true。(为何depthWrite不能像mesh一样为false, 否则点云自身透明会错乱,可能因为太多points了)
  86517. 这时候若mesh全部先渲染,则 透过depthWrite为false的半透明mesh看不透明点云,mesh会完全被点云遮住。但是透明的物体就是depthWrite要为false,否则也会完全遮住点云
  86518. 即使是后渲染半透明的mesh,若透过点云看mesh,mesh会完全被点云遮住(为什么之前遇到过 透过点云看mesh,点云会显示不出)
  86519. 最终选择是先渲染不透明的mesh,然后点云,然后透明的mesh。虽然点云对mesh透明会失效。
  86520. */
  86521. renderOverlay(params) {
  86522. viewer.addTimeMark('renderOverlay', 'start');
  86523. this.renderOverlay1(params);
  86524. this.renderOverlay2(params);
  86525. viewer.addTimeMark('renderOverlay', 'end');
  86526. }
  86527. renderOverlay1(params) {
  86528. //渲染主要的mesh
  86529. var camera = params.camera ? params.camera : this.scene.getActiveCamera();
  86530. var renderer = params.renderer || this.renderer;
  86531. this.reticule.updateAtViewports(params.viewport);
  86532. renderer.setRenderTarget(params.target || null);
  86533. //为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖
  86534. var cameraLayers;
  86535. if (params.cameraLayers) cameraLayers = params.cameraLayers;else {
  86536. if (params.viewport.name == "mapViewport") cameraLayers = ['bothMapAndScene', 'light'];else {
  86537. cameraLayers = ['sceneObjects', 'light', 'bothMapAndScene', 'monitor', 'dontIntersect'];
  86538. if (!params.useModelOnRT) {
  86539. cameraLayers.push('model');
  86540. }
  86541. }
  86542. }
  86543. if (cameraLayers.length) {
  86544. Potree.Utils.setCameraLayers(camera, cameraLayers, params.extraEnableLayers); //透明贴图层 skybox 、reticule marker 不能遮住测量线
  86545. if ('renderBeforeCloud' in params) {
  86546. this.scene.scene.traverse(object => {
  86547. if (params.useModelOnRT && viewer.objs.children.includes(object)) return {
  86548. stopContinue: true
  86549. }; //already drawn on rt
  86550. if (object.material) {
  86551. var transparent = object.material.opacity < 1 || object.material.mapTransparent || !object.material.depthTest || !object.material.depthWrite; //不写入深度的往往最后来比较
  86552. Potree.Utils.updateVisible(object, 'renderOpa', params.renderBeforeCloud != transparent);
  86553. //点云之前渲染的话隐藏半透明的, 点云之后渲染的话隐藏不透明的。 depthTest==false的也最后渲染。 mapTransparent是手动加的,代表确定该贴图含有透明部分,即使opacity为1
  86554. }
  86555. }); //ground的材质中opacity为1,所以被当做不透明了
  86556. }
  86557. viewer.dispatchEvent({
  86558. type: "render.begin2",
  86559. name: 'scene',
  86560. viewport: params.viewport,
  86561. viewer: this
  86562. });
  86563. renderer.render(this.scene.scene, camera);
  86564. if ('renderBeforeCloud' in params) {
  86565. this.scene.scene.traverse(object => {
  86566. if (params.useModelOnRT && viewer.objs.children.includes(object)) return {
  86567. stopContinue: true
  86568. }; //already drawn on rt
  86569. if (object.material) {
  86570. Potree.Utils.updateVisible(object, 'renderOpa', true); //恢复
  86571. }
  86572. });
  86573. }
  86574. }
  86575. this.dispatchEvent({
  86576. type: "render.pass.scene",
  86577. viewer: viewer
  86578. });
  86579. }
  86580. renderOverlay2(params) {
  86581. //渲染剩余部分
  86582. var renderer = params.renderer || this.renderer;
  86583. var camera = params.camera ? params.camera : this.scene.getActiveCamera();
  86584. //清除深度 !!!!
  86585. renderer.clearDepth();
  86586. if (!params.magnifier) {
  86587. //测量线
  86588. this.dispatchEvent({
  86589. type: "render.pass.perspective_overlay",
  86590. camera,
  86591. screenshot: params.screenshot,
  86592. viewport: params.viewport,
  86593. renderer
  86594. });
  86595. if (!params.screenshot && params.viewport.name != "mapViewport") {
  86596. Potree.Utils.setCameraLayers(camera, ['magnifier']); //magnifier 遮住测量线
  86597. renderer.render(this.scene.scene, camera);
  86598. }
  86599. }
  86600. if (params.viewport.name != "mapViewport") {
  86601. Potree.Utils.setCameraLayers(camera, ['volume', 'transformationTool']);
  86602. //viewer.dispatchEvent({type: "render.begin2" , name:'clip&trans',viewport:params.viewport })
  86603. renderer.render(this.clippingTool.sceneVolume, camera); //official 可以删
  86604. renderer.render(this.transformationTool.scene, camera);
  86605. }
  86606. }
  86607. setLimitFar(state) {
  86608. //切换是否limitFar
  86609. viewer.mainViewport.camera.limitFar = !!state;
  86610. if (state) {
  86611. viewer.mainViewport.camera.near = 0.02;
  86612. viewer.mainViewport.camera.far = Potree.settings.displayMode == 'showPanos' ? viewer.farWhenShowPano : Potree.settings.cameraFar;
  86613. viewer.mainViewport.camera.updateProjectionMatrix();
  86614. }
  86615. }
  86616. setClipState(state) {
  86617. //有时候需要暂时关闭下clip
  86618. state = !!state;
  86619. if (this.clipUnabled == !state) return;
  86620. this.scene.volumes.filter(v => /* v.clip && */v instanceof Potree.BoxVolume).map(volume => {
  86621. volume.clip = state;
  86622. Potree.Utils.updateVisible(volume, 'setClipState', state);
  86623. });
  86624. this.clipUnabled = !state;
  86625. }
  86626. /* 大规模WebGL应用引发浏览器崩溃的几种情况及解决办法
  86627. https://blog.csdn.net/weixin_30378311/article/details/94846947 */
  86628. async render() {
  86629. var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  86630. //add params
  86631. viewer.addTimeMark('render', 'start');
  86632. var vrActive = this.renderer.xr.isPresenting;
  86633. var {
  86634. SiteModel,
  86635. PanoEditor
  86636. } = viewer.modules;
  86637. if (this.screenshoting && !params.screenshot) return; //正在截图
  86638. var s = SiteModel.editing && SiteModel.selected && (SiteModel.selected.buildType == 'room' || SiteModel.selected.buildType == 'floor'); //空间模型的房间选中材质是需要depth的,这时候需要绘制两次点云
  86639. Potree.settings.pointEnableRT = /* !this.screenshoting && */this.scene.measurements.filter(e => e.visible).length > 0 || s || (PanoEditor === null || PanoEditor === void 0 ? void 0 : PanoEditor.entered) || this.tags.children.some(e => e.visible);
  86640. //2024.12为什么截图时不遮挡?
  86641. if (vrActive) {
  86642. this.renderVR();
  86643. } else {
  86644. var specialRender = !!params.viewports;
  86645. var viewports = params.viewports || this.viewports;
  86646. if (!this.needRender && !Potree.settings.renderAllViewports) {
  86647. viewports = viewports.filter(v => v.needRender); //可以渲染的条件是viewer或viewport的needRender为true
  86648. }
  86649. viewports = viewports.filter(v => v.active);
  86650. if (viewports.length > 0) {
  86651. params.viewports = viewports;
  86652. if (this.outlinePass.selectedObjects.length && this.outlinePass.edgeStrength > 0 && !params.screenshot
  86653. // || this.images360.fastTranMaskPass.enabled
  86654. ) {
  86655. var scenes = this.inputHandler.interactiveScenes.concat(this.scene.scene).concat(viewer.scene.scenePointCloud);
  86656. this.composer.render(scenes, null, this.viewports, this.renderDefault.bind(this));
  86657. } else {
  86658. await this.renderDefault(params);
  86659. }
  86660. {
  86661. var marks = performance.getEntriesByName("loop-start");
  86662. marks.length && (marks[marks.length - 1].rendered = true);
  86663. }
  86664. }
  86665. if (!specialRender) this.needRender = false;
  86666. }
  86667. viewer.addTimeMark('render', 'end');
  86668. }
  86669. startScreenshot() {
  86670. var info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  86671. var width = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 800;
  86672. var height = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 400;
  86673. var compressRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
  86674. //add
  86675. //let deferred = info.deferred || $.Deferred();
  86676. var getImageDeferred = info.getImageDeferred || $.Deferred();
  86677. var finishDeferred = info.finishDeferred || $.Deferred();
  86678. var viewerMaster = info.map ? this.mapViewer : this; //截图主体
  86679. var useMap = info.map || info.type == 'measure' || info.type.includes('prism2d');
  86680. if (Potree.settings.displayMode == 'showPanos' && viewer.mainViewport.view.isFlying('pos')) {
  86681. //如果在飞,飞完再截图
  86682. info.getImageDeferred = getImageDeferred, info.finishDeferred = finishDeferred;
  86683. var f = () => {
  86684. this.startScreenshot(info, width, height, compressRatio);
  86685. };
  86686. viewer.mainViewport.view.addEventListener('flyingDone', f, {
  86687. once: true
  86688. });
  86689. return {
  86690. getImagePromise: getImageDeferred.promise(),
  86691. finishPromise: finishDeferred.promise()
  86692. };
  86693. }
  86694. var startTime = Date.now();
  86695. //抗锯齿待加 1 post处理 2截图大张再抗锯齿缩小
  86696. this.pauseTestMaxLevel = true;
  86697. this.screenshoting = true;
  86698. console.log('startScreenshot: ' + startTime);
  86699. var updateCamera = () => {
  86700. viewports.forEach(e => {
  86701. e.view.applyToCamera(e.camera); //因为fly时只更新了view所以要强制更新下camera
  86702. this.dispatchEvent({
  86703. //update map and sprite, mapChanged
  86704. type: "camera_changed",
  86705. camera: e.camera,
  86706. viewport: e,
  86707. changeInfo: {
  86708. positionChanged: true,
  86709. changed: true
  86710. }
  86711. });
  86712. });
  86713. };
  86714. var screenshot = async () => {
  86715. var pose;
  86716. useMap && (viewer.mapViewer.needRender = true);
  86717. info.beforeScreenshot && info.beforeScreenshot();
  86718. var render = async () => {
  86719. this.needRender = true;
  86720. viewports.forEach(e => e.active = true);
  86721. if (info.useRenderTarget) {
  86722. //离屏渲染 有抗锯齿问题、在手机上速度慢 主视图一样会变内容,还是不用这个了
  86723. var {
  86724. dataUrl
  86725. } = viewerMaster.makeScreenshot(new Vector2(width, height), null, compressRatio);
  86726. } else {
  86727. //直接渲染 会改变canvas大小
  86728. var canvas = viewerMaster.renderer.domElement;
  86729. //canvas.width = width, canvas.height = height //不需要改canvas大小, 只需要 this.renderer.setSize(width, height ); 前面updateScreenSize已经执行
  86730. await viewerMaster.render({
  86731. screenshot: true,
  86732. width,
  86733. height,
  86734. resize: true,
  86735. needWaitLoadPoint: !!info.splitRenderInfo,
  86736. maxTimeForPointLoad: info.maxTimeForPointLoad
  86737. }); //需要resize
  86738. /* if(info.type.includes('prism2d')){//o.map要为true
  86739. viewer.dispatchEvent({type:'resize', viewport:viewer.mapViewer.viewports[0]}) //借用viewer通知lineMaterial resize
  86740. viewerMaster.renderOverlay()
  86741. } */
  86742. var dataUrl = canvas.toDataURL(compressRatio < 1 ? 'image/jpeg' : 'image/png', compressRatio);
  86743. }
  86744. return dataUrl;
  86745. };
  86746. var dataUrl;
  86747. if (info.splitRenderInfo) {
  86748. //为了防崩溃,分区域批次渲染
  86749. var {
  86750. wc,
  86751. hc
  86752. } = info.splitRenderInfo;
  86753. var camera = viewer.mainViewport.camera;
  86754. var dataUrls = [];
  86755. var width_ = Math.ceil(1 / wc * width),
  86756. height_ = Math.ceil(1 / hc * height); //可能加起来比原图大,没事到时候边界会重合
  86757. viewer.updateScreenSize({
  86758. forceUpdateSize: true,
  86759. width: width_,
  86760. height: height_,
  86761. forTarget: info.useRenderTarget
  86762. }); //更新viewports相机透视 使focusOnObject在此窗口大小下
  86763. for (var i = 0; i < wc; i++) {
  86764. var col = [];
  86765. for (var j = 0; j < hc; j++) {
  86766. var left = Math.ceil((-wc / 2 + 0.5 + i) * width_),
  86767. top = Math.ceil((-hc / 2 + 0.5 + j) * height_);
  86768. camera.setViewOffset(width_, height_, left, top, width_, height_); //顺序从上到下从左到右
  86769. var _dataUrl = await render();
  86770. //Common.downloadFile(dataUrl, 'screenshot'+ i+':'+j+'.png')
  86771. col.push({
  86772. dataUrl: _dataUrl,
  86773. width: width_,
  86774. height: height_
  86775. });
  86776. }
  86777. dataUrls.push(col);
  86778. }
  86779. camera.clearViewOffset();
  86780. dataUrl = await Utils.combineImgs(dataUrls, compressRatio, width, height);
  86781. } else {
  86782. dataUrl = await render();
  86783. }
  86784. if (info.splitRenderInfo) {
  86785. viewer.viewports = [viewer.mainViewport];
  86786. }
  86787. if (!Potree.settings.isOfficial) {
  86788. Common$1.downloadFile(dataUrl, 'screenshot.png');
  86789. }
  86790. var finish = () => {
  86791. oldStates.viewports.forEach(old => {
  86792. //恢复相机
  86793. var viewport = viewports.find(v => v.name == old.name);
  86794. viewport.left = old.left;
  86795. viewport.bottom = old.bottom;
  86796. viewport.width = old.width;
  86797. viewport.height = old.height;
  86798. viewport.view.copy(old.view);
  86799. //viewport.view.applyToCamera(viewport.camera);
  86800. if (viewport.camera.isOrthographicCamera) {
  86801. viewport.camera.zoom = viewport.view.zoom;
  86802. }
  86803. });
  86804. viewerMaster.updateScreenSize({
  86805. forceUpdateSize: true
  86806. }); //更新像素
  86807. /* oldStates.viewports.forEach(old=>{//恢复相机
  86808. var viewport = [mapViewport, mainViewport].find(v=>v.name == old.name);
  86809. this.dispatchEvent({ //update map
  86810. type: "camera_changed",
  86811. camera: viewport.camera,
  86812. viewport : viewport
  86813. })
  86814. }) */
  86815. updateCamera();
  86816. finishDeferred.resolve({
  86817. dataUrl,
  86818. pose
  86819. });
  86820. info.map || setTimeout(() => {
  86821. if (!this.screenshoting) {
  86822. //Potree.settings.pointNoLimit = false
  86823. Potree.settings.pointDensity = 'high';
  86824. //console.warn('恢复pointDensity')
  86825. /* if(viewer.scene.pointclouds[0].material.oldSize_ ){
  86826. viewer.scene.pointclouds[0].material.size = viewer.scene.pointclouds[0].material.oldSize_
  86827. viewer.scene.pointclouds[0].material.oldSize_ = null
  86828. } */
  86829. }
  86830. }, 500); //延迟:避免连续多次截图时释放点云
  86831. this.screenshoting = false;
  86832. console.log('screenshot done: ' + startTime, 'costTime', Date.now() - startTime + 'ms');
  86833. };
  86834. {
  86835. //恢复:
  86836. this.backgroundOpacity = oldStates.bgOpacity;
  86837. this.background = oldStates.background;
  86838. this.pauseTestMaxLevel = false;
  86839. oldStates.displayMode && (Potree.settings.displayMode = oldStates.displayMode);
  86840. if (info.type == 'measure' || info.type.includes('prism2d')) {
  86841. this.modules.SiteModel.pauseUpdateEntity = false;
  86842. this.focusDatasets = null;
  86843. this.scene.measurements.forEach(e => Potree.Utils.updateVisible(e, 'screenshot', true));
  86844. info.type == 'measure' && info.measurement.setSelected(false, 'screenshot');
  86845. }
  86846. if (info.type.includes('prism2d')) {
  86847. //viewer.mapViewer.transparentBG = false;
  86848. (info.prisms || [info.prism]).forEach(prism => {
  86849. prism.changeStyleForScreenshot(false);
  86850. if (info.type == 'prism2d-single') {
  86851. prism.baseModel && (Potree.Utils.updateVisible(prism.baseModel, 'screenshot', false, 3, 'cancel'), Potree.Utils.setObjectLayers(prism.baseModel, 'model'));
  86852. prism.setEditState(false);
  86853. }
  86854. });
  86855. }
  86856. this.images360.panos.forEach(pano => {
  86857. Potree.Utils.updateVisible(pano, 'screenshot', true);
  86858. });
  86859. Potree.Utils.updateVisible(this.reticule, 'screenshot', true);
  86860. if (useMap) {
  86861. Potree.Utils.updateVisible(this.mapViewer.cursor, 'screenshot', true);
  86862. if (oldStates.attachedToViewer != this.mapViewer.attachedToViewer) {
  86863. this.mapViewer.attachToMainViewer(!!oldStates.attachedToViewer);
  86864. }
  86865. if (oldStates.attachedToViewer && this.mapViewer.splitDir != oldStates.oldSplitDir) {
  86866. this.mapViewer.changeSplitScreenDir(oldStates.oldSplitDir);
  86867. }
  86868. mapViewport.noPointcloud = oldStates.noPointcloud;
  86869. Potree.Utils.updateVisible(viewer.mapViewer.mapLayer.sceneGroup, 'screenshot-prism', true);
  86870. }
  86871. var recover = () => {
  86872. if (Potree.settings.displayMode == 'showPanos') {
  86873. viewer.images360.flyToPano({
  86874. pano: oldStates.pano,
  86875. duration: 0,
  86876. callback: () => {
  86877. finish();
  86878. }
  86879. });
  86880. } else {
  86881. finish();
  86882. }
  86883. };
  86884. if (info.ifGetPose) {
  86885. Potree.sdk.scene.getPose().done(pose_ => {
  86886. pose = pose_;
  86887. getImageDeferred.resolve({
  86888. dataUrl,
  86889. pose
  86890. });
  86891. recover();
  86892. });
  86893. } else {
  86894. recover();
  86895. }
  86896. }
  86897. }; // screenshot end
  86898. var mapViewport;
  86899. var mainViewport = this.mainViewport;
  86900. var viewports = [],
  86901. oldStates = {
  86902. viewports: [],
  86903. pano: Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : null,
  86904. bgOpacity: this.backgroundOpacity,
  86905. background: this.background
  86906. };
  86907. if (!info.type.includes('prism2d')) {
  86908. viewports.push(mainViewport);
  86909. mainViewport.camera.isOrthographicCamera && (mainViewport.view.zoom = mainViewport.camera.zoom);
  86910. oldStates.viewports.push(mainViewport.clone());
  86911. }
  86912. if (useMap) {
  86913. mapViewport = this.mapViewer.viewports[0];
  86914. mapViewport.view.zoom = mapViewport.camera.zoom;
  86915. viewports.push(mapViewport);
  86916. oldStates.viewports.push(mapViewport.clone());
  86917. oldStates.attachedToViewer = this.mapViewer.attachedToViewer;
  86918. oldStates.noPointcloud = mapViewport.noPointcloud;
  86919. oldStates.displayMode = Potree.settings.displayMode;
  86920. Potree.Utils.updateVisible(this.mapViewer.cursor, 'screenshot', false); //令mapCursor不可见
  86921. }
  86922. viewports.forEach(e => e.active = false); //暂停渲染
  86923. if (info.hideMarkers) {
  86924. this.images360.panos.forEach(pano => {
  86925. //令漫游点不可见
  86926. Potree.Utils.updateVisible(pano, 'screenshot', false);
  86927. });
  86928. }
  86929. Potree.Utils.updateVisible(this.reticule, 'screenshot', false); //令reticule不可见
  86930. if (info.bgOpacity != void 0) {
  86931. this.backgroundOpacity = info.bgOpacity;
  86932. }
  86933. if (info.background != void 0) {
  86934. this.background = info.background;
  86935. }
  86936. Potree.settings.pointDensity = info.pointDensity || 'screenshot';
  86937. var focusDatasets = measurements => {
  86938. this.focusDatasets = [];
  86939. measurements.forEach(measure => {
  86940. measure.points_datasets.forEach(e => {
  86941. var p = viewer.scene.pointclouds.find(a => a.dataset_id == e);
  86942. if (p && !this.focusDatasets.includes(p)) {
  86943. this.focusDatasets.push(p);
  86944. }
  86945. });
  86946. });
  86947. this.updateFpVisiDatasets();
  86948. };
  86949. if (info.type == 'measure') {
  86950. //要截图双屏
  86951. this.scene.measurements.forEach(e => Potree.Utils.updateVisible(e, 'screenshot', e == info.measurement));
  86952. info.measurement.setSelected(true, 'screenshot');
  86953. //因为分屏后位置才最终确定,才能确定是否显示出floorplan所以先分屏
  86954. if (Potree.settings.floorplanEnable) {
  86955. oldStates.oldSplitDir = this.mapViewer.splitDir;
  86956. this.mapViewer.attachToMainViewer(true, 'measure', 0.5, {
  86957. dir: 'leftRight'
  86958. });
  86959. }
  86960. viewer.updateScreenSize({
  86961. forceUpdateSize: true,
  86962. width,
  86963. height,
  86964. forTarget: info.useRenderTarget
  86965. }); //更新viewports相机透视 使focusOnObject在此窗口大小下
  86966. var begin = () => {
  86967. useMap = this.mapViewer.attachedToViewer;
  86968. updateCamera();
  86969. if (useMap) {
  86970. var waitMap = () => {
  86971. console.log('waitMap: ' + startTime, Date.now(), this.mapViewer.mapLayer.loadingInProgress);
  86972. this.mapViewer.waitLoadDone(screenshot.bind(this)); //等待地图所有加载完
  86973. };
  86974. this.waitPointLoad(waitMap, info.maxTimeForPointLoad);
  86975. } else {
  86976. this.waitPointLoad(screenshot, info.maxTimeForPointLoad);
  86977. }
  86978. };
  86979. var {
  86980. promise
  86981. } = this.focusOnObject(info.measurement, 'measure', 0, {
  86982. basePanoSize: 1024,
  86983. gotoBestView: true
  86984. //minMapWidth: THREE.Math.clamp(Math.min(viewer.bound.boundSize.x, viewer.bound.boundSize.y) / (20/* this.mapViewer.mapLayer.maps.find(e=>e.name == 'map').disabled ? 6 : 3*/), 2, 25) //有地图的话为了显示出名字需要更大范围
  86985. }); //注意:不同角度截图 得到三维的会不一样,因为focusOnObject是根据方向的
  86986. promise.done(() => {
  86987. //console.log('promise.done')
  86988. //根据当前位置更新floorplan显示
  86989. //console.log('view Pos ', this.mainViewport.view.position.toArray())
  86990. this.updateDatasetAt(true);
  86991. this.modules.SiteModel.updateEntityAt(true, {
  86992. measure: info.measurement
  86993. }); //更新测量线所在楼层,展示俯视图
  86994. if (!this.modules.SiteModel.inEntity) {
  86995. focusDatasets([info.measurement]);
  86996. }
  86997. this.modules.SiteModel.pauseUpdateEntity = true;
  86998. //console.log('currentFloor', this.modules.SiteModel.currentFloor, 'currentDataset', this.atDatasets )
  86999. var floorplanShowed = this.mapViewer.mapLayer.maps.some(e => e.name.includes('floorplan') && e.objectGroup.visible); //如果没有floorplan展示就不分屏(如果focus时飞出数据集从而不展示怎么办。尤其是俯瞰比较长的线时容易这样,或许要根据其所在数据集强制显示)
  87000. if (!floorplanShowed && this.mapViewer.attachedToViewer) {
  87001. this.mapViewer.attachToMainViewer(false); //取消分屏
  87002. viewer.updateScreenSize({
  87003. forceUpdateSize: true,
  87004. width,
  87005. height,
  87006. forTarget: info.useRenderTarget
  87007. }); //更新viewports相机透视
  87008. var {
  87009. promise: _promise
  87010. } = this.focusOnObject(info.measurement, 'measure', 0, {
  87011. basePanoSize: 1024,
  87012. gotoBestView: true
  87013. }); //因画面比例更改,重新focus
  87014. _promise.done(() => {
  87015. begin();
  87016. });
  87017. } else {
  87018. begin();
  87019. }
  87020. });
  87021. } else if (info.type.includes('prism2d')) {
  87022. var points = [],
  87023. prisms = info.type == 'prism2d-all' ? info.prisms : [info.prism];
  87024. this.mapViewer.attachToMainViewer(true, 'screenshot', 1, {/* dir:'leftRight' */});
  87025. viewer.updateScreenSize({
  87026. forceUpdateSize: true,
  87027. width,
  87028. height,
  87029. forTarget: info.useRenderTarget
  87030. }); //更新viewports相机透视 使focusOnObject在此窗口大小下
  87031. prisms.forEach(prism => {
  87032. var prismPoints = prism.points.slice();
  87033. if (prism.baseModel) {
  87034. var currentBound = prism.baseModel.currentBound || prism.baseModel.boundingBox.clone().applyMatrix4(prism.baseModel.matrixWorld);
  87035. prismPoints = prismPoints.map(e => e.clone().setZ(Math.max(e.z, currentBound.max.z)));
  87036. }
  87037. points.push(...prismPoints);
  87038. prism.setSelected(false);
  87039. prism.changeStyleForScreenshot(true, {
  87040. hideLabel: info.type != 'prism2d-all',
  87041. showName: info.type == 'prism2d-all'
  87042. });
  87043. if (info.type == 'prism2d-single') {
  87044. prism.baseModel && (Potree.Utils.updateVisible(prism.baseModel, 'screenshot', true, 3, 'add'), Potree.Utils.setObjectLayers(prism.baseModel, 'bothMapAndScene'));
  87045. prism.setEditState(true);
  87046. }
  87047. });
  87048. this.scene.measurements.forEach(e => Potree.Utils.updateVisible(e, 'screenshot', prisms.includes(e)));
  87049. this.backgroundOpacity = 0;
  87050. var {
  87051. promise: _promise2
  87052. } = this.focusOnObject({
  87053. points
  87054. }, 'prisms2d', 0, {
  87055. minMapWidth: 0.5,
  87056. onlyMap: true,
  87057. focusBoundCenter: true,
  87058. boundExpandRatio: 1.4
  87059. });
  87060. _promise2.done(() => {
  87061. updateCamera();
  87062. if (info.type == 'prism2d-all') {
  87063. //全部 带平面图
  87064. focusDatasets(prisms); //更新平面图 可能有漏洞,当不在任何一个数据集内的话?
  87065. this.mapViewer.waitLoadDone(screenshot.bind(this)); //等待地图所有加载完
  87066. } else {
  87067. //single
  87068. mapViewport.noPointcloud = false; //显示点云,而非平面图
  87069. Potree.settings.displayMode = 'showPointCloud';
  87070. Potree.Utils.updateVisible(viewer.mapViewer.mapLayer.sceneGroup, 'screenshot-prism', false);
  87071. this.waitPointLoad(screenshot, 5000);
  87072. }
  87073. });
  87074. } else {
  87075. //default
  87076. var done = () => {
  87077. updateCamera();
  87078. if (info.splitRenderInfo) {
  87079. screenshot();
  87080. } else {
  87081. this.waitPointLoad(screenshot, info.maxTimeForPointLoad);
  87082. }
  87083. };
  87084. viewer.updateScreenSize({
  87085. forceUpdateSize: true,
  87086. width,
  87087. height,
  87088. forTarget: info.useRenderTarget
  87089. }); //更新viewports相机透视 使focusOnObject在此窗口大小下
  87090. if (info.focusObjectInfo) {
  87091. var {
  87092. promise: _promise3
  87093. } = this.focusOnObject(...info.focusObjectInfo);
  87094. _promise3.done(() => {
  87095. done();
  87096. });
  87097. } else {
  87098. done();
  87099. }
  87100. }
  87101. /*
  87102. 测量线的截图因为要调用分屏的,会改变画面
  87103. 但是普通截图的话,不会改变画面
  87104. */
  87105. return {
  87106. getImagePromise: getImageDeferred.promise(),
  87107. finishPromise: finishDeferred.promise()
  87108. };
  87109. }
  87110. async waitPointLoad(done, maxTimeForPointLoad) {
  87111. var viewport = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : viewer.mainViewport;
  87112. var resolution = arguments.length > 3 ? arguments[3] : undefined;
  87113. return new Promise((resolve, reject) => {
  87114. var finish;
  87115. var dealDone = () => {
  87116. viewer.removeEventListener('update', update);
  87117. viewer.removeEventListener('overPointBudget', decreaseLevel);
  87118. finish || done && done();
  87119. finish = true;
  87120. resolve();
  87121. };
  87122. var decreaseLevel = e => {
  87123. //降点云level 但基本降完也不会再加载低等级的点云了,所以是否直接不降?即使质量不平均
  87124. if (e.restQueueSize < 10) return; //差不多完成了
  87125. var pointclouds = viewer.scene.pointclouds.filter(e => e.visibleNodes.length);
  87126. console.log('准备decreaseLevel, numVisiblePoints', e.numVisiblePoints, '最小numVisiblePoints占比', 1 / pointclouds.length);
  87127. pointclouds.forEach(pointcloud => {
  87128. var percent = pointcloud.numVisiblePoints / e.numVisiblePoints;
  87129. //console.log('numVisiblePoints占总比', pointcloud.dataset_id, percent )
  87130. if (percent < 1 / pointclouds.length) return;
  87131. var old = pointcloud.maxLevel;
  87132. var levels = pointcloud.visibleNodes.map(e => e.getLevel());
  87133. var actMaxLevel = Math.max.apply(null, levels); //实际加载到的最高的node level
  87134. pointcloud.maxLevel = actMaxLevel - 1;
  87135. console.warn(pointcloud.dataset_id, 'decreaseLevel,新maxLevel', actMaxLevel - 1, '原maxlevel', old);
  87136. });
  87137. };
  87138. /* if(Potree.settings.displayMode == 'showPointCloud'){
  87139. viewer.updateScreenSize({forceUpdateSize:true, width, height, forTarget:info.useRenderTarget})//需要先setSize才能加载范围内的点云
  87140. } */
  87141. //updateCamera()
  87142. //viewer.addEventListener('overPointBudget',decreaseLevel)
  87143. var update = () => {
  87144. //前提:已经禁止渲染,仅加载点云
  87145. var camera = viewport.forViewOffset ? viewport.forViewOffset.camera : viewport.camera;
  87146. Potree.updatePointClouds(viewer.scene.pointclouds, camera, resolution || viewport.resolution);
  87147. };
  87148. viewer.addEventListener('update', update);
  87149. update();
  87150. var maxTime = maxTimeForPointLoad || 2000;
  87151. document.hidden && (maxTime *= 6); //离开页面后会变成1秒1帧
  87152. setTimeout(() => {
  87153. if (Potree.pointsLoading && Potree.settings.displayMode == 'showPointCloud') {
  87154. //如果还在加载
  87155. viewer.addEventListener('pointsLoaded', () => {
  87156. //点云加载完时(不一定准确)
  87157. if (!finish) console.log('加载完毕', ' numVisiblePoints', Potree.numVisiblePoints);
  87158. dealDone();
  87159. }, {
  87160. once: true
  87161. });
  87162. var overTime = () => {
  87163. //超时不候(其实之后等待地图还会再加载几秒)
  87164. if (document.hidden) {
  87165. return setTimeout(overTime, maxTime);
  87166. }
  87167. if (!finish) console.warn('超时, numVisiblePoints', Potree.numVisiblePoints);
  87168. dealDone();
  87169. };
  87170. setTimeout(overTime, maxTime);
  87171. } else {
  87172. console.log('已经加载完,无需再加载点云 numVisiblePoints', Potree.numVisiblePoints);
  87173. dealDone();
  87174. }
  87175. }, 200); //先加载一段时间
  87176. });
  87177. }
  87178. focusOnObject(object, type, duration) {
  87179. var o = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  87180. //飞向热点、测量线等 。
  87181. //console.log('focusOnObject: ', object, type)
  87182. var deferred = o.deferred || $.Deferred();
  87183. var target = new Vector3(),
  87184. //相机focus的位置
  87185. position = new Vector3(),
  87186. //相机最终位置
  87187. dis; //相机距离目标
  87188. duration = duration == void 0 ? 1200 : duration;
  87189. var camera = o.endCamera || viewer.scene.getActiveCamera();
  87190. var cameraPos = camera.position.clone();
  87191. var boundSize;
  87192. if (o.dontChangeCamDir && (o.endYaw == void 0 || o.endPitch == void 0)) {
  87193. //在俯视时仅靠dir来算不准
  87194. o.endYaw = viewer.mainViewport.view.yaw;
  87195. o.endPitch = viewer.mainViewport.view.pitch;
  87196. }
  87197. var moveMap = done => {
  87198. if (this.mapViewer && !o.dontMoveMap) {
  87199. //console.log('mapFocusOn: '+target.toArray())
  87200. var minMapWidth = o.minMapWidth || 2; //截图的时候要显示的地图范围较大,为了显示出地区名字
  87201. var minBound = new Vector2(minMapWidth, minMapWidth); //针对垂直线,在地图上只有一个点
  87202. //原始的bound
  87203. var boundOri;
  87204. if (object.points) {
  87205. boundOri = new Box3();
  87206. object.points.forEach(e => {
  87207. boundOri.expandByPoint(e);
  87208. });
  87209. } else {
  87210. boundOri = object.boundingBox;
  87211. }
  87212. if (o.focusBoundCenter) {
  87213. boundOri.getCenter(target);
  87214. target.z += 1;
  87215. }
  87216. var boundSizeOri = boundOri.getSize(new Vector3());
  87217. var expand = o.boundExpandRatio || math.linearClamp(Math.max(boundSizeOri.x, boundSizeOri.y), [0.5, 30], [2.5, 1.2]); //为了能同时看清测量线和地图,当测量线较短时,扩大margin,防止地图过度放大
  87218. var boundSizeMap = boundSizeOri.clone();
  87219. boundSizeMap.x *= expand, boundSizeMap.y *= expand;
  87220. boundSizeMap.x = Math.max(minBound.x, boundSizeMap.x);
  87221. boundSizeMap.y = Math.max(minBound.y, boundSizeMap.y);
  87222. this.mapViewer.moveTo(target.clone(), boundSizeMap, duration, o.margin, null, done);
  87223. }
  87224. };
  87225. if (o.onlyMap) {
  87226. moveMap(() => {
  87227. deferred.resolve();
  87228. });
  87229. return {
  87230. promise: deferred.promise()
  87231. };
  87232. }
  87233. var getPosWithFullBound = (points, boundingBox, target, cameraPos) => {
  87234. //使boundingBox差不多占满屏幕时的相机到target的距离
  87235. // points 和 boundingBox 至少有一个
  87236. var scale;
  87237. if (o.dontChangeCamDir) {
  87238. var inv = camera.matrixWorldInverse;
  87239. } else {
  87240. var cameraTemp = camera.clone();
  87241. var view = viewer.mainViewport.view.clone();
  87242. view.position.copy(cameraPos);
  87243. view.lookAt(target);
  87244. if (o.endPitch != void 0) {
  87245. view.pitch = o.endPitch;
  87246. view.yaw = o.endYaw;
  87247. }
  87248. view.applyToCamera(cameraTemp);
  87249. //对镜头的bound
  87250. var inv = cameraTemp.matrixWorldInverse;
  87251. }
  87252. var bound = new Box3();
  87253. if (points) {
  87254. //使用points得到的bound更小 //如果points和boundingbox的差别较大,尤其使target和points中心不一致,那么points不一定会刚好在boundingbox内
  87255. points.forEach(e => {
  87256. var p = e.clone().applyMatrix4(inv);
  87257. bound.expandByPoint(p);
  87258. });
  87259. scale = 1.2;
  87260. } else {
  87261. bound = boundingBox.applyMatrix4(inv);
  87262. scale = 1; //0.9;
  87263. }
  87264. boundSize = bound.getSize(new Vector3());
  87265. if (o.boundScale) {
  87266. scale = o.boundScale;
  87267. }
  87268. {
  87269. boundSize.x *= scale; //稍微放大一些,不然会靠到屏幕边缘
  87270. boundSize.y *= scale;
  87271. var min = o.minBound || 1;
  87272. boundSize.x = Math.max(min, boundSize.x);
  87273. boundSize.y = Math.max(min, boundSize.y);
  87274. }
  87275. if (camera.type == 'OrthographicCamera') {
  87276. dis = boundSize.length() / 2;
  87277. } else {
  87278. var aspect = boundSize.x / boundSize.y;
  87279. if (camera.aspect > aspect) {
  87280. //视野更宽则用bound的纵向来决定
  87281. dis = boundSize.y / 2 / Math.tan(MathUtils.degToRad(camera.fov / 2)) + boundSize.z / 2;
  87282. } else {
  87283. var hfov = cameraLight.getHFOVForCamera(camera, true);
  87284. dis = boundSize.x / 2 / Math.tan(hfov / 2) + boundSize.z / 2;
  87285. }
  87286. dis += camera.near;
  87287. }
  87288. dis = Math.max(0.1, dis);
  87289. o.maxDis && (dis = Math.min(o.maxDis, dis));
  87290. //三个顶点以上的由于measure的中心不等于bound的中心,所以点会超出bound外。 且由于视椎近大远小,即使是两个点的,bound居中后线看上去仍旧不居中.
  87291. //获得相机最佳位置
  87292. var dir;
  87293. if (o.dontChangeCamDir) {
  87294. dir = viewer.mainViewport.view.direction.negate();
  87295. } else {
  87296. dir = new Vector3().subVectors(cameraPos, target).normalize();
  87297. }
  87298. if (o.dontLookUp && dir.z < 0) {
  87299. dir.negate();
  87300. }
  87301. position.copy(target).add(dir.multiplyScalar(dis));
  87302. if (false) {
  87303. //打开以检查box
  87304. if (!this.boundBox) {
  87305. //调试
  87306. this.boundBox = new Mesh(new BoxGeometry(1, 1, 1, 1));
  87307. this.boundBox.material.wireframe = true;
  87308. this.boundBox.up.set(0, 0, 1);
  87309. Potree.Utils.setObjectLayers(this.boundBox, 'sceneObjects');
  87310. this.scene.scene.add(this.boundBox);
  87311. }
  87312. this.boundBox.position.copy(target);
  87313. this.boundBox.scale.copy(boundSize);
  87314. this.boundBox.lookAt(position);
  87315. }
  87316. return position;
  87317. };
  87318. if (this.images360.flying) {
  87319. var f = () => {
  87320. this.focusOnObject(object, type, duration, $.extend(o, {
  87321. deferred
  87322. }));
  87323. this.images360.removeEventListener('cameraMoveDone', f);
  87324. };
  87325. this.images360.addEventListener('cameraMoveDone', f);
  87326. return {
  87327. promise: deferred.promise()
  87328. };
  87329. }
  87330. if (type == 'measure') {
  87331. if (object.points.length == 0) {
  87332. return {
  87333. promise: deferred.resolve()
  87334. };
  87335. }
  87336. target.copy(object.getCenter());
  87337. //试试改变位置(方向),直视测量线。能避免倾斜角度造成的非常不居中、以及看不到面的情况
  87338. if (o.gotoBestView) {
  87339. //直接沿着法线方向看
  87340. if (object.points.length > 2) {
  87341. var facePlane = object.getFacePlane(target);
  87342. var normal = facePlane.normal.clone();
  87343. if (normal.dot(this.mainViewport.view.direction) > 0) {
  87344. normal.negate(); //顺着视线
  87345. }
  87346. //normal.z = Math.max(0.2, normal.z)//尽量不要仰视
  87347. cameraPos.copy(target).add(normal);
  87348. } else {
  87349. var lineDir = new Vector3().subVectors(object.points[0], object.points[1]).normalize();
  87350. var _facePlane = new Plane().setFromNormalAndCoplanarPoint(lineDir, target);
  87351. //if(cameraPos.z < target.z + 1)cameraPos.z = target.z + 1//尽量不要仰视
  87352. var dir = new Vector3().subVectors(cameraPos, target).normalize();
  87353. dir.z = Math.max(dir.z, 0.4);
  87354. cameraPos.copy(target).add(dir); //尽量不要仰视
  87355. var _dis = cameraPos.distanceTo(target);
  87356. dir = lineDir.clone().multiplyScalar(_dis);
  87357. var line = new Line3().set(cameraPos.clone().add(dir), cameraPos.clone().add(dir.negate())); //过相机位置作到面的垂线
  87358. _facePlane.intersectLine(line, cameraPos); //得垂足,作为新的相机位置。就能在测量线中间看测量线
  87359. }
  87360. } else {
  87361. if (object.points.length > 2) {
  87362. var _facePlane2 = object.getFacePlane(target);
  87363. var _normal = _facePlane2.normal.clone();
  87364. var angle = this.mainViewport.view.direction.angleTo(_normal);
  87365. var minDiff = MathUtils.degToRad(30);
  87366. //console.log('angle',angle)
  87367. if (angle > minDiff && angle < Math.PI - minDiff) {
  87368. //当几乎正对时就不执行
  87369. if (angle < Math.PI / 2) {
  87370. //在背面
  87371. _normal.negate();
  87372. }
  87373. var _dir = new Vector3().subVectors(camera.position, target).normalize();
  87374. var newDir = new Vector3().addVectors(_dir, _normal); //两个角度的中间
  87375. //console.log('newDir',newDir)
  87376. cameraPos.copy(target.clone().add(newDir));
  87377. }
  87378. } else if (object.points.length == 2) {
  87379. //线段
  87380. var _lineDir = new Vector3().subVectors(object.points[0], object.points[1]).normalize();
  87381. var _angle = this.mainViewport.view.direction.angleTo(_lineDir);
  87382. var maxDiff = Math.PI * 0.25; // 45度
  87383. if (_angle < maxDiff || _angle > Math.PI - maxDiff) {
  87384. //当几乎正对时就不执行
  87385. if (_angle > Math.PI / 2) {
  87386. //令dir和lineDir成钝角
  87387. _lineDir.negate();
  87388. }
  87389. var _dir2 = new Vector3().subVectors(camera.position, target).normalize();
  87390. var mid = new Vector3().addVectors(_lineDir, _dir2).normalize(); //中间法向量(如果刚好dir和lineDir反向,那得到的为零向量,就不移动了,但一般不会酱紫吧)
  87391. var _newDir = new Vector3().addVectors(_dir2, mid);
  87392. cameraPos.copy(target.clone().add(_newDir));
  87393. }
  87394. } else {
  87395. console.error('measure 没有facePlane points点数还不为2?');
  87396. }
  87397. }
  87398. //截图时直接飞到最佳视角,也就是平视它所在面。其余时候为了避免镜头旋转过大就算了。
  87399. position = getPosWithFullBound(object.points, null, target, cameraPos);
  87400. moveMap();
  87401. if (Potree.settings.displayMode == 'showPointCloud') {
  87402. //点云
  87403. var minDis = 0.3;
  87404. if (0) {
  87405. //如果没有被选中,会被遮挡。 2023.11.15 最好展示全局(尤其截图时),虽然被遮挡,但focus的过程是选中状态全显示的,可以看出所在范围。
  87406. var checkIntersect = () => {
  87407. var intersect = this.inputHandler.ifBlockedByIntersect({
  87408. point: position,
  87409. cameraPos: target
  87410. }); // 不一定准确
  87411. if (intersect) {
  87412. var blockCount = 0,
  87413. unblockCount = 0,
  87414. visi;
  87415. for (var i = 0; i < object.points.length; i++) {
  87416. //如果顶点超过一半不可见,就要更改位置
  87417. var p = object.points[i];
  87418. var blocked = this.inputHandler.ifBlockedByIntersect({
  87419. point: p,
  87420. margin: 0.3,
  87421. cameraPos: position,
  87422. pickWindowSize: 4
  87423. });
  87424. if (blocked) {
  87425. blockCount++;
  87426. if (blockCount / object.points.length >= 0.5) {
  87427. visi = false;
  87428. break;
  87429. }
  87430. } else {
  87431. unblockCount++;
  87432. if (unblockCount / object.points.length > 0.5) {
  87433. visi = true;
  87434. break;
  87435. }
  87436. }
  87437. }
  87438. if (visi == void 0) {
  87439. visi = unblockCount / object.points.length > 0.5;
  87440. }
  87441. var shrink = () => {
  87442. var dir = new Vector3().subVectors(position, target).normalize().multiplyScalar(intersect.distance);
  87443. position.copy(target).add(dir);
  87444. console.log('checkIntersect newPos', position.clone());
  87445. };
  87446. if (!visi) {
  87447. //更改位置距离target如果小于最小距离,需要反向。 否则直接缩短距离。
  87448. if (intersect.distance < minDis) {
  87449. console.log('检测到intersect 反向', intersect.distance);
  87450. var position1 = position.clone();
  87451. var _dir3 = new Vector3().subVectors(position, target);
  87452. position.copy(target).sub(_dir3);
  87453. var intersect2 = this.inputHandler.ifBlockedByIntersect({
  87454. point: position,
  87455. cameraPos: target
  87456. }); // 不一定准确
  87457. if (intersect2) {
  87458. if (intersect2.distance < intersect.distance) {
  87459. position.copy(position1); //恢复
  87460. }
  87461. shrink();
  87462. }
  87463. } else {
  87464. shrink();
  87465. }
  87466. }
  87467. }
  87468. };
  87469. checkIntersect();
  87470. //多折线没有areaPlane 有时候会看向空白区域 - -
  87471. }
  87472. } else if (Potree.settings.displayMode == 'showPanos') {
  87473. var _object$measureType;
  87474. //全景 (比较难校准)
  87475. var target2, _dir4;
  87476. if ((_object$measureType = object.measureType) !== null && _object$measureType !== void 0 && _object$measureType.includes('MulDistance')) {
  87477. //因为该线不闭合,可能看向target的方向会没有线,所以换一个target
  87478. target2 = object.points[Math.round(object.points.length / 2)]; //直接看向中间点
  87479. _dir4 = new Vector3().subVectors(target2, position).normalize();
  87480. }
  87481. var pano = viewer.images360.fitPanoTowardPoint({
  87482. /*point : target, //不使用目标点来判断是因为缺少measure角度的信息。比如虽然可以靠近线的中心,但是线朝向屏幕,那几乎就是一个点了。
  87483. //bestDistance : dis * 0.5, //乘以小数是为了尽量靠近
  87484. boundSphere: boundOri.getBoundingSphere(new THREE.Sphere), */
  87485. target,
  87486. dir: _dir4,
  87487. point: position,
  87488. bestDistance: 0,
  87489. checkIntersect: o.checkIntersect,
  87490. gotoBestView: o.gotoBestView
  87491. });
  87492. var result = {
  87493. promise: deferred.promise()
  87494. };
  87495. if (pano && pano.msg) {
  87496. pano = pano.pano;
  87497. result.msg = pano.msg;
  87498. }
  87499. if (pano) {
  87500. viewer.images360.flyToPano({
  87501. pano,
  87502. target: target2 || target,
  87503. duration,
  87504. deferred,
  87505. dontMoveMap: true,
  87506. basePanoSize: o.basePanoSize
  87507. }); //dontMoveMap不要移动map,否则flytopano会自动在map中focus到漫游点的位置,而非测量线了
  87508. if (viewer.images360.currentPano == pano) {
  87509. var dis1 = viewer.images360.currentPano.position.distanceTo(target);
  87510. var dis2 = position.distanceTo(target);
  87511. //console.log('dis1 / dis2',dis1 / dis2, 'dis1-dis2', dis1-dis2)
  87512. return {
  87513. msg: dis1 / dis2 > 1.5 && dis1 - dis2 > 10 ? 'tooFar' : 'posNoChange',
  87514. promise: deferred.promise()
  87515. };
  87516. }
  87517. }
  87518. return result;
  87519. /* if(viewer.images360.currentPano == pano){
  87520. let dis1 = viewer.images360.currentPano.position.distanceTo(target)
  87521. let dis2 = position.distanceTo(target)
  87522. //console.log('dis1 / dis2',dis1 / dis2, 'dis1-dis2', dis1-dis2)
  87523. return {msg: (dis1 / dis2 > 1.5 && dis1-dis2>10)? 'tooFar' : 'posNoChange', promise : deferred.promise() }
  87524. }else{
  87525. return {promise : deferred.promise()}
  87526. } */
  87527. //出现过到达位置后测量线标签闪烁的情况
  87528. // 测量线截图 全景 最好能放大. 但要确保该位置放大后图片加载完有点困难
  87529. }
  87530. } else if (type == 'tag' || type == 'point') {
  87531. //dimension = 1
  87532. target.copy(object.position);
  87533. var bestDistance = o.distance || 3;
  87534. if (!o.dontMoveMap && this.mapViewer) {
  87535. //console.log('mapFocusOn: '+target.toArray())
  87536. this.mapViewer.moveTo(target.clone(), null, duration);
  87537. }
  87538. if (Potree.settings.displayMode == 'showPointCloud' && !o.requestShowPano) {
  87539. if (o.dontChangePos) {
  87540. position.copy(cameraPos);
  87541. } else {
  87542. if (o.maxDis) {
  87543. var disNow = cameraPos.distanceTo(target);
  87544. dis = MathUtils.clamp(disNow, 1, o.maxDis);
  87545. } else {
  87546. dis = bestDistance;
  87547. }
  87548. var dir_ = o.direction ? o.direction.clone().negate() : this.mainViewport.view.direction.negate(); // */new THREE.Vector3().subVectors(camera.position, target).normalize()
  87549. if (o.dontLookUp && dir_.z < 0) dir_.z *= -1;
  87550. position.copy(target).add(dir_.multiplyScalar(dis));
  87551. }
  87552. if (o.sameFloor) {
  87553. //需要在同一楼层
  87554. var atFloor = this.modules.SiteModel.pointInWhichEntity(target, 'floor');
  87555. if (atFloor) {
  87556. var camFloor = this.modules.SiteModel.pointInWhichEntity(position, 'floor');
  87557. if (camFloor != atFloor) {
  87558. var raycaster = new Raycaster();
  87559. var origin = target;
  87560. var _dir5 = new Vector3().subVectors(position, target).normalize();
  87561. raycaster.set(origin, _dir5);
  87562. var intersect = Potree.Utils.getIntersect(null, [atFloor.box], null, raycaster);
  87563. if (intersect) {
  87564. var _dis2 = MathUtils.clamp(intersect.distance - 0.2, camera.near, intersect.distance);
  87565. position.addVectors(origin, _dir5.multiplyScalar(_dis2));
  87566. console.log('移动到楼层');
  87567. } else {
  87568. console.error('?no intersect?');
  87569. }
  87570. }
  87571. }
  87572. }
  87573. if (o.checkIntersect) {
  87574. //识别被点云遮住的话
  87575. var _intersect; //反向查找从target到相机的第一个intersect
  87576. _intersect = this.inputHandler.ifBlockedByIntersect({
  87577. point: position,
  87578. margin: 0,
  87579. cameraPos: target
  87580. } /* {point:target, margin: 0.2, cameraPos:position} */);
  87581. if (_intersect) {
  87582. position.copy(_intersect.location);
  87583. console.log('移近');
  87584. }
  87585. }
  87586. } else {
  87587. var _pano = viewer.images360.fitPanoTowardPoint({
  87588. point: target,
  87589. dir: this.mainViewport.view.direction,
  87590. //尽量不改相机方向,避免镜头晃动
  87591. checkIntersect: o.checkIntersect,
  87592. sameFloor: o.sameFloor,
  87593. bestDistance,
  87594. maxDis: o.maxDis //越近越好,但不要太近,bestDistance左右差不多
  87595. });
  87596. var _result = {
  87597. promise: deferred.promise()
  87598. };
  87599. if (_pano && _pano.msg) {
  87600. _pano = _pano.pano;
  87601. _result.msg = _pano.msg;
  87602. }
  87603. _pano && viewer.images360.flyToPano({
  87604. pano: _pano,
  87605. target,
  87606. duration,
  87607. deferred,
  87608. dontMoveMap: true,
  87609. basePanoSize: o.basePanoSize
  87610. });
  87611. return _result;
  87612. }
  87613. } else if (object.boundingBox && type == 'boundingBox') {
  87614. //使屏幕刚好看全boundingBox
  87615. //object.boundingBox.min.clamp(new THREE.Vector3(-1e4, -1e4, -1e4), new THREE.Vector3(1e4, 1e4, 1e4))//防止过大,ces崩溃
  87616. //object.boundingBox.max.clamp(new THREE.Vector3(-1e4, -1e4, -1e4), new THREE.Vector3(1e4, 1e4, 1e4))//防止过大,ces崩溃
  87617. target = object.boundingBox.getCenter(new Vector3());
  87618. if (o.dir) {
  87619. //指定方向
  87620. cameraPos.copy(target).sub(o.dir);
  87621. }
  87622. position = getPosWithFullBound(object.points, object.boundingBox.clone(), target, cameraPos);
  87623. if (Potree.settings.displayMode == 'showPanos') {
  87624. //全景 (比较难校准)
  87625. var _pano2 = viewer.images360.fitPanoTowardPoint({
  87626. point: position,
  87627. bestDistance: 0
  87628. });
  87629. var _result2 = {
  87630. promise: deferred.promise()
  87631. };
  87632. if (_pano2 && _pano2.msg) {
  87633. _pano2 = _pano2.pano;
  87634. _result2.msg = _pano2.msg;
  87635. }
  87636. _pano2 && viewer.images360.flyToPano({
  87637. pano: _pano2,
  87638. target,
  87639. duration,
  87640. deferred,
  87641. dontMoveMap: true,
  87642. basePanoSize: o.basePanoSize
  87643. }); //dontMoveMap不要移动map,否则flytopano会自动在map中focus到漫游点的位置,而非测量线了
  87644. if (!_pano2) {
  87645. console.error('no pano');
  87646. }
  87647. return _result2;
  87648. //出现过到达位置后测量线标签闪烁的情况
  87649. } else {
  87650. /* if(o.dontChangeCamDir){
  87651. target = null
  87652. } */
  87653. moveMap();
  87654. }
  87655. }
  87656. if (o.startCamera && o.endCamera) {
  87657. viewer.mainViewport.view.tranCamera(this.mainViewport, {
  87658. endPosition: position,
  87659. target,
  87660. boundSize,
  87661. callback: () => {
  87662. //console.log('focusOnObjectSuccess: '+object.name, type)
  87663. deferred.resolve();
  87664. },
  87665. startCamera: o.startCamera,
  87666. endCamera: o.endCamera,
  87667. midCamera: this.scene.cameraBasic,
  87668. endYaw: o.endYaw,
  87669. endPitch: o.endPitch
  87670. }, duration);
  87671. } else if (camera.type == "OrthographicCamera") {
  87672. viewer.mainViewport.view.moveOrthoCamera(this.mainViewport, {
  87673. endPosition: position,
  87674. target,
  87675. boundSize,
  87676. endYaw: o.endYaw,
  87677. endPitch: o.endPitch,
  87678. callback: () => {
  87679. //console.log('focusOnObjectSuccess: '+object.name, type)
  87680. deferred.resolve();
  87681. }
  87682. }, duration);
  87683. } else {
  87684. viewer.mainViewport.view.setView({
  87685. position,
  87686. target,
  87687. duration,
  87688. endYaw: o.endYaw,
  87689. endPitch: o.endPitch,
  87690. callback: () => {
  87691. //console.log('focusOnObjectSuccess: '+object.name, type)
  87692. deferred.resolve();
  87693. }
  87694. });
  87695. }
  87696. this.dispatchEvent({
  87697. type: 'focusOnObject',
  87698. CamTarget: target,
  87699. position
  87700. }); //给controls发送信息
  87701. return {
  87702. promise: deferred.promise()
  87703. };
  87704. }
  87705. flyToDataset() {
  87706. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  87707. var pointcloud;
  87708. if (o instanceof Object3D) pointcloud = o;else if (o.pointcloud) pointcloud = o.pointcloud;else pointcloud = this.scene.pointclouds.find(p => p.dataset_id == o.id);
  87709. var duration = o.duration == void 0 ? 1000 : o.duration;
  87710. if (o.focusOnPoint || !pointcloud.panosBound) {
  87711. //focus点云上一点,避免center区域刚好没有点
  87712. if (pointcloud.root.geometryNode) {
  87713. var posArr = pointcloud.root.geometryNode.geometry.attributes.position.array;
  87714. var count = pointcloud.root.geometryNode.geometry.attributes.position.count;
  87715. var index = Math.ceil(count / 2); //随便取一个点
  87716. var point = new Vector3(posArr[index * 3 + 0], posArr[index * 3 + 1], posArr[index * 3 + 2]);
  87717. //point.applyMatrix4(pointcloud.root.pointcloud.matrixWorld)
  87718. point.applyMatrix4(pointcloud.root.sceneNode.matrixWorld);
  87719. viewer.focusOnObject({
  87720. position: point
  87721. }, 'point', duration, {
  87722. dontChangeCamDir: true,
  87723. distance: 15
  87724. });
  87725. o.dontMoveMap || viewer.mapViewer.fitToPointcloud(pointcloud, duration);
  87726. console.log('flyToDataset focusOnPoint done');
  87727. return;
  87728. }
  87729. }
  87730. var center = pointcloud.bound.getCenter(new Vector3());
  87731. var position;
  87732. var getPano = () => {
  87733. //获取离中心最近的pano
  87734. var request = [];
  87735. var rank = [Images360.scoreFunctions.distanceSquared({
  87736. position: center
  87737. })];
  87738. var r = Common$1.sortByScore(pointcloud.panos, request, rank);
  87739. if (r.length) {
  87740. return r[0].item;
  87741. }
  87742. };
  87743. if (Potree.settings.displayMode == 'showPanos') {
  87744. var pano = getPano();
  87745. if (pano) {
  87746. if (pano == this.images360.currentPano) return 'posNoChange';
  87747. this.images360.flyToPano({
  87748. pano
  87749. });
  87750. } else return false;
  87751. } else {
  87752. var target;
  87753. position = center;
  87754. if (pointcloud.panosBound) {
  87755. var panosCenter = pointcloud.panosBound.center; //pano集中的地方,也就是真正有点云的地方
  87756. position = panosCenter.clone();
  87757. /* let ratio = 0.2
  87758. position.z = center.z * ratio + panosCenter.z * (1-ratio) //因为panos一般比较低,为了不让相机朝下时看不到点云,加一丢丢中心高度
  87759. */
  87760. var _pano3 = getPano();
  87761. if (_pano3) {
  87762. target = _pano3.position; //针对像隧道一样的场景, 中心点还是panosCenter都在没有点云的地方,所以还是看向其中一个漫游点好。
  87763. position.z = target.z; //水平, 避免朝上或朝下
  87764. }
  87765. }
  87766. if (this.modules.Clip.editing) {
  87767. position.z = center.z; //剪裁时在中心高度,因为以点云为重点
  87768. this.modules.Clip.bus.dispatchEvent({
  87769. type: 'flyToPos',
  87770. position,
  87771. duration
  87772. });
  87773. } else {
  87774. if (math.closeTo(position, this.images360.position)) return 'posNoChange';
  87775. viewer.mainViewport.view.setView({
  87776. position,
  87777. target,
  87778. duration
  87779. });
  87780. }
  87781. o.dontMoveMap || viewer.mapViewer.fitToPointcloud(pointcloud, duration);
  87782. }
  87783. return true;
  87784. }
  87785. findClosestDatasetOnMap(position) {
  87786. //寻找当前平面图上离某点最近的数据集
  87787. var pointclouds = viewer.scene.pointclouds.filter(e => e.visible);
  87788. var addScore = viewer.bound.boundSize.length();
  87789. var r = Potree.Common.sortByScore(pointclouds, [], [e => {
  87790. //pos2d和bound2d距离排序
  87791. var pos3d = position.clone().setZ(e.panosBound ? e.panosBound.center.z : (e.bound.min.z + e.bound.max.z) / 2);
  87792. return -(e.panosBound ? e.panosBound.bounding : e.bound).distanceToPoint(pos3d);
  87793. }, e => {
  87794. //最有可能的是地图上显示的平面图
  87795. return e in viewer.fpVisiDatasets ? addScore : 0;
  87796. }]);
  87797. return r[0] && r[0].item;
  87798. }
  87799. addTimeMark(name, type) {
  87800. var record = Potree.timeCollect[name];
  87801. var needRecord = record && record.start && record.measures.length < record.minCount;
  87802. if (needRecord || Potree.measureTimings) {
  87803. performance.mark(name + "-" + type);
  87804. if (type == 'end') {
  87805. var measure = performance.measure(name, name + "-start", name + "-end");
  87806. if (needRecord) {
  87807. if (!measure) {
  87808. //有出现过手机的depthSamChangeImg得不到measure,可能是因为时间太长在resolveTimings被清除了? iphone8 plus ios14.1 型号MQ8F2CH/A
  87809. return; //console.log('未能得到performance.measure',name)
  87810. }
  87811. record.latestDuration = measure.duration;
  87812. record.measures.push(measure.duration);
  87813. record.sum += measure.duration;
  87814. record.ave = record.sum / record.measures.length;
  87815. record.measures.sort((a, b) => a - b);
  87816. record.median = record.measures[parseInt(record.measures.length / 2)];
  87817. }
  87818. }
  87819. }
  87820. }
  87821. addFakeMeasure(name, duration) {
  87822. //把一些count当做duration来统计
  87823. if (!Potree.measureTimings) return;
  87824. if (!this.fakeMeasure[name]) {
  87825. this.fakeMeasure[name] = [];
  87826. }
  87827. var object = {
  87828. name,
  87829. duration
  87830. };
  87831. this.fakeMeasure[name].push(object);
  87832. }
  87833. resolveTimings(timestamp, log) {
  87834. //打印用时。 注:performance手机的精度只到整数位 。 sidebar中监听update时有高cpu的函数所以不要用demo测
  87835. if (!this.toggle) {
  87836. this.toggle = timestamp;
  87837. }
  87838. var duration = timestamp - this.toggle;
  87839. if (duration > 4000.0) {
  87840. if (log) {
  87841. var measures = performance.getEntriesByType("measure");
  87842. for (var i in this.fakeMeasure) {
  87843. measures.push(...this.fakeMeasure[i]);
  87844. }
  87845. var names = new Set();
  87846. for (var measure of measures) {
  87847. names.add(measure.name);
  87848. }
  87849. var groups = new Map();
  87850. for (var name of names) {
  87851. groups.set(name, {
  87852. measures: [],
  87853. sum: 0,
  87854. n: 0,
  87855. min: Infinity,
  87856. max: -Infinity
  87857. });
  87858. }
  87859. for (var _measure of measures) {
  87860. var group = groups.get(_measure.name);
  87861. group.measures.push(_measure);
  87862. group.sum += _measure.duration;
  87863. group.n++;
  87864. group.min = Math.min(group.min, _measure.duration);
  87865. group.max = Math.max(group.max, _measure.duration);
  87866. }
  87867. /* let glQueries = Potree.resolveQueries(this.renderer.getContext()); // resolveQueries 无
  87868. for(let [key, value] of glQueries){
  87869. let group = {
  87870. measures: value.map(v => {return {duration: v}}),
  87871. sum: value.reduce( (a, i) => a + i, 0),
  87872. n: value.length,
  87873. min: Math.min(...value),
  87874. max: Math.max(...value)
  87875. };
  87876. let groupname = `[tq] ${key}`;
  87877. groups.set(groupname, group);
  87878. names.add(groupname);
  87879. } */
  87880. for (var [_name, _group] of groups) {
  87881. _group.mean = _group.sum / _group.n;
  87882. /* group.measures.sort( (a, b) => a.duration - b.duration );
  87883. if(group.n === 1){
  87884. group.median = group.measures[0].duration;
  87885. }else if(group.n > 1){
  87886. group.median = group.measures[parseInt(group.n / 2)].duration;
  87887. }
  87888. */
  87889. var _measures = _group.measures.slice();
  87890. _measures.sort((a, b) => a.duration - b.duration);
  87891. if (_group.n === 1) {
  87892. _group.median = _measures[0].duration;
  87893. } else if (_group.n > 1) {
  87894. _group.median = _measures[parseInt(_group.n / 2)].duration;
  87895. }
  87896. }
  87897. var cn = Array.from(names).reduce((a, i) => Math.max(a, i.length), 0) + 5;
  87898. var cmin = 6;
  87899. var cmed = 6;
  87900. var cmax = 6;
  87901. var csam = 4;
  87902. var message = " ".concat("NAME".padEnd(cn), " |") + " ".concat("MIN".padStart(cmin), " |") + " ".concat("MEDIAN".padStart(cmed), " |") + " ".concat("MAX".padStart(cmax), " |") + " ".concat("AVE".padStart(cmax), " |") + " ".concat("SAMPLES".padStart(csam), " \n");
  87903. message += " ".concat("-".repeat(message.length), "\n");
  87904. names = Array.from(names).sort();
  87905. for (var _name2 of names) {
  87906. var _group2 = groups.get(_name2);
  87907. var min = _group2.min.toFixed(3);
  87908. var median = _group2.median.toFixed(3);
  87909. var max = _group2.max.toFixed(3);
  87910. var ave = _group2.mean.toFixed(3); //add
  87911. var n = _group2.n;
  87912. message += " ".concat(_name2.padEnd(cn), " |") + " ".concat(min.padStart(cmin), " |") + " ".concat(median.padStart(cmed), " |") + " ".concat(max.padStart(cmax), " |") + " ".concat(ave.padStart(cmax), " |") + " ".concat(n.toString().padStart(csam), "\n");
  87913. }
  87914. message += "\n";
  87915. console.log(message);
  87916. }
  87917. this.fakeMeasure = {}; //clear
  87918. performance.clearMarks();
  87919. performance.clearMeasures();
  87920. this.toggle = timestamp;
  87921. }
  87922. //注意,console.log本身用时挺高,降4倍时可能占用0.5毫秒,所以不能每帧都打印
  87923. }
  87924. loop(timestamp) {
  87925. //let startTime = performance.now()
  87926. //console.log('间隔:' /*, parseInt((startTime - this.lastEndTime)*100 )/100 */)
  87927. if (this.paused) return;
  87928. if (performance.getEntriesByName("loopWaitNext-start").length) viewer.addTimeMark('loopWaitNext', 'end');
  87929. if (this.stats) {
  87930. this.stats.begin();
  87931. }
  87932. performance.mark('loop-start'); // 无论有没有reportTimings都要获取,因为getBestCound需要
  87933. this.dispatchEvent('loopStart');
  87934. this.interacted = false;
  87935. this.shelterCount = {
  87936. byTex: 0,
  87937. byCloud: 0,
  87938. maxByTex: 100,
  87939. maxByCloud: 0
  87940. }; //清空 因ifPointBlockedByIntersect可能在任何时候触发,所以需要一开始就定义这个,且每次计算最大可计算次数太麻烦了就定义一个吧。
  87941. var deltaTime = this.clock.getDelta();
  87942. this.update(deltaTime, timestamp);
  87943. this.magnifier.render();
  87944. viewer.addTimeMark('loop2', 'start');
  87945. this.render();
  87946. viewer.addTimeMark('loop2', 'end');
  87947. this.setAllTilesets(model => model.runtime.update(deltaTime, this.renderer, this.mainViewport.camera));
  87948. {
  87949. var hasAnimation;
  87950. window.pauseAni || this.objs.children.forEach(model => {
  87951. //model.traverse(object=>object.isSkinnedMesh && object.computeBoundingSphere())
  87952. if (model.mixer && (model.clipChanged || model.actions.some(a => a._mixer._isActiveAction(a) && !a.paused))) {
  87953. //播放中或者动作状态改变
  87954. hasAnimation = true;
  87955. model.clipChanged = false;
  87956. model.mixer.update(deltaTime);
  87957. //console.log('mixer update', model.name)
  87958. }
  87959. }); //以后有空的话用frust判断是否在画面内,不在的话即使有动画也不要 update 和 render, 如果paused的话是不是也可以不update
  87960. hasAnimation && this.dispatchEvent('content_changed');
  87961. }
  87962. if (this.IKSolver) this.IKSolver.update();
  87963. // let vrActive = viewer.renderer.xr.isPresenting;
  87964. // if(vrActive){
  87965. // this.update(this.clock.getDelta(), timestamp);
  87966. // this.render();
  87967. // }else{
  87968. // this.update(this.clock.getDelta(), timestamp);
  87969. // this.render();
  87970. // }
  87971. Potree.framenumber++;
  87972. //-------------
  87973. this.images360.tileDownloader.update();
  87974. this.images360.panoRenderer.update();
  87975. this.images360.getNeighbours(this.interacted);
  87976. this.computeShelter();
  87977. //-------------
  87978. if (this.stats) {
  87979. this.stats.end();
  87980. }
  87981. this.warnMemory();
  87982. viewer.addTimeMark('loop', 'end');
  87983. viewer.addTimeMark('loopWaitNext', 'start');
  87984. this.computeFps();
  87985. this.resolveTimings(timestamp, Potree.measureTimings);
  87986. //Potree.measureTimings = 1
  87987. }
  87988. warnMemory() {
  87989. //内存高于2000可能崩溃
  87990. if (!performance.memory) return; //国产麒麟firefox不支持
  87991. var size = performance.memory.usedJSHeapSize / 1e6;
  87992. var minSize = 1500,
  87993. maxSize = 3000,
  87994. intervalTime = math.linearClamp(size, [minSize, maxSize * 1.2], [20000, 3000]);
  87995. if (size > minSize) {
  87996. Potree.Common.intervalTool.isWaiting('warnMemory', () => {
  87997. size = Math.round(size);
  87998. var L = math.linearClamp(size, [minSize, maxSize], [1, 0.5]); //L从白到红是1到0.5
  87999. Potree.Log('warning!内存告急!usedJSHeapSize:' + size, {
  88000. font: {
  88001. color: "#" + new Color().setHSL(0, 1, L).getHexString()
  88002. }
  88003. });
  88004. }, intervalTime);
  88005. }
  88006. }
  88007. computeFps11() {
  88008. var marks = performance.getEntriesByName("loop-start");
  88009. var start = performance.now();
  88010. if (marks.length && !document.hidden) {
  88011. //每次都获取最后一个加入列队。因为marks会定期清除,所以自己记录一个列队。(hidden时手动loop的不会计入)
  88012. var last = marks[marks.length - 1];
  88013. this.fpsCollect.push(last);
  88014. var maxCount = 1000;
  88015. if (this.fpsCollect.length > maxCount) {
  88016. this.fpsCollect.splice(0, 1);
  88017. }
  88018. var getFps = (sampleCount, oldValue, requestRendered) => {
  88019. var samples = this.fpsCollect.slice(-sampleCount);
  88020. var invalidTime = 0;
  88021. var lastInvalid,
  88022. invalidCount = 0;
  88023. samples.forEach((frame, i) => {
  88024. //扣除document.hidden时的时间
  88025. if ((frame.pageHidden || requestRendered && !frame.rendered) && i != samples.length - 1) {
  88026. //最后一个必须执行下面那段,最后再减1
  88027. invalidCount++;
  88028. lastInvalid || (lastInvalid = frame);
  88029. } else {
  88030. if (lastInvalid) {
  88031. invalidTime += frame.startTime - lastInvalid.startTime;
  88032. lastInvalid = null;
  88033. }
  88034. }
  88035. });
  88036. var dur = (last.startTime - samples[0].startTime - invalidTime) / 1000;
  88037. var frameCount = samples.length - invalidCount - 1; //有效帧数
  88038. if (frameCount > 1) {
  88039. if (requestRendered) {
  88040. console.log(frameCount, dur, frameCount / dur);
  88041. }
  88042. return frameCount / dur; //有的手机高刷可以达到90以上
  88043. } else {
  88044. return oldValue;
  88045. }
  88046. };
  88047. Potree.fps = getFps(70, Potree.fps); //即时
  88048. Potree.fps2 = getFps(maxCount, Potree.fps2); //较长时段
  88049. Potree.fpsRendered = getFps(70, Potree.fpsRendered, true); //一般只有加载东西或渲染的时候才卡,所以渲染过的fps更有意义。 暂时无视地图或其他viewer的渲染 (但一段时间内不一定有渲染,所以不一定得到)
  88050. //缺点:调试时因暂停导致fps变低
  88051. }
  88052. Potree.lastComFpsDur = performance.now() - start;
  88053. }
  88054. computeFps() {
  88055. var marks = performance.getEntriesByName("loop-start");
  88056. var start = performance.now();
  88057. if (marks.length && !document.hidden) {
  88058. //每次都获取最后一个加入列队。因为marks会定期清除,所以自己记录一个列队。(hidden时手动loop的不会计入)
  88059. var curFrame = marks[marks.length - 1];
  88060. var lastFrame = this.fpsCollect.lastFrame;
  88061. if (lastFrame && !lastFrame.pageHidden) {
  88062. var desc = {
  88063. dur: curFrame.startTime - lastFrame.startTime
  88064. };
  88065. var joinIn = (name, maxCount) => {
  88066. var collect = this.fpsCollect[name];
  88067. collect.push(desc);
  88068. collect.durSum += desc.dur;
  88069. if (collect.length > maxCount) {
  88070. collect.durSum -= collect[0].dur;
  88071. collect.splice(0, 1);
  88072. }
  88073. if (collect.length > 0) {
  88074. collect.fps = collect.length / collect.durSum * 1000;
  88075. }
  88076. };
  88077. joinIn('short', 100);
  88078. joinIn('long', 5000);
  88079. if (lastFrame.rendered) {
  88080. joinIn('rendered', 30), joinIn('renderedLong', 300);
  88081. //lastFrame.cameraChanged && (joinIn('camChanged',30), joinIn('camChangedLong',300))
  88082. }
  88083. Potree.fps = this.fpsCollect.short.fps; //即时
  88084. Potree.fps2 = this.fpsCollect.long.fps; //较长时段
  88085. Potree.fpsRendered = this.fpsCollect.rendered.fps; //一般只有加载东西或渲染的时候才卡,所以渲染过的fps更有意义。 暂时无视地图或其他viewer的渲染 (但一段时间内不一定有渲染,所以不一定得到)
  88086. Potree.fpsRendered2 = this.fpsCollect.renderedLong.fps;
  88087. /* Potree.fpsCamChanged = this.fpsCollect.camChanged.fps
  88088. Potree.fpsCamChanged2 = this.fpsCollect.camChangedLong.fps */
  88089. }
  88090. curFrame.cameraChanged = this.lastFrameChanged;
  88091. this.fpsCollect.lastFrame = curFrame;
  88092. }
  88093. Potree.lastComFpsDur = performance.now() - start;
  88094. }
  88095. postError(content) {
  88096. var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  88097. var message = this.postMessage(content, params);
  88098. message.element.addClass("potree_message_error");
  88099. return message;
  88100. }
  88101. postMessage(content) {
  88102. var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  88103. var message = new Message(content);
  88104. var animationDuration = 100;
  88105. message.element.css("display", "none");
  88106. message.elClose.click(() => {
  88107. message.element.slideToggle(animationDuration);
  88108. var index = this.messages.indexOf(message);
  88109. if (index >= 0) {
  88110. this.messages.splice(index, 1);
  88111. }
  88112. });
  88113. this.elMessages.prepend(message.element);
  88114. message.element.slideToggle(animationDuration);
  88115. this.messages.push(message);
  88116. if (params.duration !== undefined) {
  88117. var fadeDuration = 500;
  88118. var slideOutDuration = 200;
  88119. setTimeout(() => {
  88120. message.element.animate({
  88121. opacity: 0
  88122. }, fadeDuration);
  88123. message.element.slideToggle(slideOutDuration);
  88124. }, params.duration);
  88125. }
  88126. return message;
  88127. }
  88128. getBoundingBox(pointclouds) {
  88129. //可以直接返回viewer.bound
  88130. if (!this.bound) {
  88131. this.updateModelBound();
  88132. }
  88133. return this.bound.boundingBox.clone(); //this.scene.getBoundingBox(pointclouds);
  88134. }
  88135. updateModelBound(reason) {
  88136. this.boundNeedUpdate = false;
  88137. this.bound = Utils.computePointcloudsBound(this.scene.pointclouds.filter(pointcloud =>
  88138. //只求可见
  88139. pointcloud.visible || pointcloud.unvisibleReasons && pointcloud.unvisibleReasons.length == 1 && pointcloud.unvisibleReasons[0].reason == 'displayMode'));
  88140. if (Potree.settings.boundAddObjs) {
  88141. //加上obj的bound 需要确保都updateMatrixWorld过
  88142. this.objs.children.forEach(e => {
  88143. this.bound.boundingBox.union(e.boundingBox.clone().applyMatrix4(e.matrixWorld));
  88144. });
  88145. this.bound.boundingBox.getSize(this.bound.boundSize);
  88146. this.bound.boundingBox.getCenter(this.bound.center);
  88147. }
  88148. viewer.farWhenShowPano = Math.max(1000, this.bound.boundSize.length() * 10); //全景漫游时要能看到整个skybox 原本*2的但对于距离特远的数据集需要乘大一些否则会黑面
  88149. /* let boundPlane = new THREE.Box3()
  88150. boundPlane.expandByPoint(this.bound.boundingBox.min.clone())//最低高度为bound的最低
  88151. boundPlane.expandByPoint(this.bound.boundingBox.max.clone().setZ(this.bound.center.z))//最高高度为bound的中心高度
  88152. FirstPersonControls.boundPlane = boundPlane */
  88153. //FirstPersonControls.standardSpeed = THREE.Math.clamp( Math.sqrt(this.bound.boundSize.length() )/ 100 , 0.02,0.5); //在这个boundPlane中的速度
  88154. Potree.settings.editType == 'pano' && this.images360.updatePanoBound();
  88155. viewer.scene.pointclouds.forEach(e => {
  88156. //海拔范围
  88157. e.material.heightMin = this.bound.boundingBox.min.z;
  88158. e.material.heightMax = this.bound.boundingBox.max.z;
  88159. });
  88160. this.dispatchEvent({
  88161. type: 'updateModelBound'
  88162. });
  88163. }
  88164. waitForLoad(object, isLoadedCallback) {
  88165. //等待加载时显示loading。主要是贴图
  88166. this.waitQueue.push({
  88167. object,
  88168. isLoadedCallback
  88169. });
  88170. //console.warn('waitForLoad',object.id,this.waitQueue.length)
  88171. 1 === this.waitQueue.length && this.dispatchEvent({
  88172. type: "loading",
  88173. show: true
  88174. });
  88175. }
  88176. ifAllLoaded() {
  88177. if (this.waitQueue.length > 0) {
  88178. this.waitQueue = this.waitQueue.filter(function (e) {
  88179. return !e.isLoadedCallback();
  88180. });
  88181. }
  88182. //console.warn('ifAllLoaded', this.waitQueue.length)
  88183. 0 === this.waitQueue.length && this.dispatchEvent({
  88184. type: "loading",
  88185. show: false
  88186. });
  88187. }
  88188. cancelLoad(object) {
  88189. //add 突然出现还没加载完就被deactivateTiledPano但还在loading的情况,所以加了这个
  88190. this.waitQueue = this.waitQueue.filter(function (e) {
  88191. return e.object != object;
  88192. });
  88193. //console.log('cancelLoad', object.id)
  88194. this.ifAllLoaded();
  88195. }
  88196. setView() {
  88197. var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  88198. var callback = () => {
  88199. if (o.displayMode) {
  88200. Potree.settings.displayMode = o.displayMode;
  88201. }
  88202. if (!o.pano && o.currentPano) this.images360.currentPano = o.currentPano;
  88203. o.callback && o.callback();
  88204. };
  88205. if (o.pano != void 0) {
  88206. //pano 权重高于 position
  88207. this.images360.flyToPano(o);
  88208. } else {
  88209. this.mainViewport.view.setView($.extend({}, o, {
  88210. callback
  88211. }));
  88212. }
  88213. }
  88214. //设置点云为标准模式
  88215. setPointStandardMat(state, pointDensity, fitPointsize) {
  88216. console.log('setPointStandardMat', state);
  88217. if (state) {
  88218. if (this.pointStatesBefore) {
  88219. return console.warn('已设置过pointStatesBefore!');
  88220. }
  88221. this.pointStatesBefore = {
  88222. colorType: new Map(),
  88223. opacity: new Map(),
  88224. size: new Map(),
  88225. density: Potree.settings.pointDensity,
  88226. useEDL: this.getEDLEnabled(),
  88227. shape: viewer.scene.pointclouds[0].material.shape
  88228. };
  88229. viewer.scene.pointclouds.forEach(e => {
  88230. this.pointStatesBefore.opacity.set(e, e.temp.pointOpacity); //因为更改pointDensity时会自动变opacity,所以这项最先获取
  88231. this.pointStatesBefore.colorType.set(e, e.material.activeAttributeName);
  88232. fitPointsize && this.pointStatesBefore.size.set(e, e.temp.pointSize); //这项不一定有用,因为会被后期覆盖
  88233. });
  88234. if (pointDensity) Potree.settings.pointDensity = pointDensity; //万一之后切换到全景模式怎么办
  88235. if (fitPointsize) Potree.settings.sizeFitToLevel = true;
  88236. viewer.scene.pointclouds.forEach(e => {
  88237. e.material.activeAttributeName = this.pointStatesBefore.colorType.get(e) == 'ir' ? 'ir' : 'rgba';
  88238. e.material.shape = Potree.PointShape['SQUARE'];
  88239. fitPointsize && e.changePointSize(Potree.config.material.realPointSize, true);
  88240. e.changePointOpacity(1);
  88241. });
  88242. viewer.setEDLEnabled(false);
  88243. } else {
  88244. if (!this.pointStatesBefore) {
  88245. return console.error('未设置过pointStatesBefore!');
  88246. }
  88247. Potree.settings.sizeFitToLevel = false;
  88248. if (pointDensity) Potree.settings.pointDensity = this.pointStatesBefore.pointDensity;
  88249. viewer.scene.pointclouds.forEach(e => {
  88250. e.material.activeAttributeName = this.pointStatesBefore.colorType.get(e);
  88251. e.changePointOpacity(this.pointStatesBefore.opacity.get(e));
  88252. e.material.shape = this.pointStatesBefore.shape;
  88253. var size = this.pointStatesBefore.size.get(e);
  88254. if (size) e.changePointSize(size);
  88255. });
  88256. viewer.setEDLEnabled(this.pointStatesBefore.useEDL);
  88257. this.pointStatesBefore = null;
  88258. }
  88259. }
  88260. //调试时显示transformControl来调节object
  88261. transformObject(object) {
  88262. var seleted = viewer.inputHandler.selection[0];
  88263. if (!object) {
  88264. //取消
  88265. seleted && viewer.inputHandler.toggleSelection(seleted);
  88266. return;
  88267. }
  88268. if (seleted && seleted != object) {
  88269. //要更换,先取消
  88270. this.transformObject(null);
  88271. }
  88272. if (!object.boundingBox) {
  88273. object.boundingBox = new Box3(); //任意大小 只是为了显示黄色外框
  88274. //??? computeBoundingBox
  88275. }
  88276. if (!viewer.inputHandler.selection.includes(object)) {
  88277. viewer.inputHandler.toggleSelection(object);
  88278. }
  88279. }
  88280. pointInWhichPointcloud(pos) {
  88281. //选择最接近中心的那个 使用boundSphere
  88282. var result = Common$1.sortByScore(this.scene.pointclouds, [], [pointcloud => {
  88283. var size = pointcloud.pcoGeometry.tightBoundingBox.getSize(new Vector3());
  88284. var center = pointcloud.bound.getCenter(new Vector3());
  88285. var length = size.length() / 2;
  88286. var dis = pos.distanceTo(center);
  88287. return length / dis; //到数据集中心的距离占数据集大小越小越好
  88288. }]);
  88289. //若要求更准确的话,可以使用ifContainsPoint判断一下是否在bound中
  88290. var r = result[0];
  88291. return r && r.score > 1 ? result[0].item : null;
  88292. }
  88293. createHackMesh() {
  88294. //为了防止无depthTex的全景在pick点云时画面中仅有一个材质时会黑屏,所以在镜头前再加一个mesh。具体bug表现见bug记录。
  88295. if (this.scene.pointclouds.every(e => e.hasDepthTex) || viewer.images360.panos.length == 0) return;
  88296. var mesh = new Mesh(viewer.images360.panos[0].marker.geometry, new MeshBasicMaterial({
  88297. color: "#F00",
  88298. side: 2 /* ,depthTest:false */
  88299. }));
  88300. Potree.Utils.updateVisible(mesh, 'show', false);
  88301. this.images360.node.add(mesh);
  88302. var updatePos = () => {
  88303. var dir = this.mainViewport.view.direction;
  88304. var radius = this.images360.cube.scale.length();
  88305. mesh.position.copy(this.mainViewport.view.position).add(dir.multiplyScalar(radius)); //放置skybox之外
  88306. };
  88307. this.addEventListener('camera_changed', e => {
  88308. var _e$changeInfo, _e$changeInfo2;
  88309. if (e.viewport.name == 'MainView' && Potree.settings.displayMode == 'showPanos' && !this.images360.currentPano.depthTex && ((_e$changeInfo = e.changeInfo) !== null && _e$changeInfo !== void 0 && _e$changeInfo.positionChanged || (_e$changeInfo2 = e.changeInfo) !== null && _e$changeInfo2 !== void 0 && _e$changeInfo2.quaternionChanged)) {
  88310. updatePos();
  88311. }
  88312. });
  88313. var judge = () => {
  88314. var _this$images360$curre3;
  88315. if (!((_this$images360$curre3 = this.images360.currentPano) !== null && _this$images360$curre3 !== void 0 && _this$images360$curre3.depthTex) && Potree.settings.displayMode == 'showPanos') {
  88316. Potree.Utils.updateVisible(mesh, 'show', true);
  88317. } else {
  88318. Potree.Utils.updateVisible(mesh, 'show', false);
  88319. }
  88320. };
  88321. this.images360.addEventListener('flyToPanoDone', judge);
  88322. this.images360.addEventListener('endChangeMode', judge);
  88323. //不知道如果用点云计算非当前视角下的block会不会黑闪,如热点遮挡计算
  88324. }
  88325. /* createRoomEv(){
  88326. const environment = new RoomEnvironment();
  88327. const pmremGenerator = new THREE.PMREMGenerator( this.renderer );
  88328. }
  88329. */
  88330. setLoaders() {
  88331. this.fileManager = new LoadingManager(); //整体的load manager
  88332. this.fileManager.onLoad = () => {
  88333. console.log('All resources have been loaded');
  88334. this.fileManager.loading = false;
  88335. this.dispatchEvent('managerOnLoad');
  88336. // 在这里可以执行模型渲染、动画等操作
  88337. };
  88338. // 设置加载进度的回调函数(可选)
  88339. this.fileManager.onProgress = (item, loaded, total) => {
  88340. if (loaded < total) this.fileManager.loading = true;
  88341. console.log("Loading ".concat(item, ": ").concat(loaded, " of ").concat(total));
  88342. };
  88343. // 设置加载失败的回调函数(可选)
  88344. /* this.fileManager.onError = (url) => {
  88345. console.error(`Failed to load resource: ${url}`);
  88346. }; */
  88347. loaders = {
  88348. objLoaders: [],
  88349. //new OBJLoader( this.fileManager ),
  88350. mtlLoader: new MTLLoader(this.fileManager),
  88351. glbLoader: new GLTFLoader(undefined, this.renderer, Potree.settings.libsUrl),
  88352. plyLoader: new PLYLoader(this.fileManager),
  88353. dxfLoader: new DxfLoader(),
  88354. shapeLoader: new Potree.ShapefileLoader()
  88355. };
  88356. }
  88357. getObjLoader() {
  88358. var loader = loaders.objLoaders.find(e => !e.inUse);
  88359. if (!loader) {
  88360. loader = new OBJLoader(this.fileManager);
  88361. loader.inUse = true;
  88362. loaders.objLoaders.push(loader);
  88363. }
  88364. return loader;
  88365. }
  88366. modelLoaded(object) {
  88367. var fileInfo_ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  88368. var done = arguments.length > 2 ? arguments[2] : undefined;
  88369. //普通模型加载完以后
  88370. object.isModel = true;
  88371. var boundingBox = new Box3();
  88372. if (fileInfo_.parentInfo) {
  88373. object.name = fileInfo_.name;
  88374. fileInfo_.parentInfo.loadedCount++;
  88375. fileInfo_.parentInfo.modelGroup.add(object);
  88376. if (fileInfo_.parentInfo.loadedCount == fileInfo_.parentInfo.url.length) {
  88377. return this.modelLoaded(fileInfo_.parentInfo.modelGroup, fileInfo_.parentInfo, done);
  88378. } else {
  88379. return;
  88380. }
  88381. }
  88382. object.name = fileInfo_.name != void 0 ? fileInfo_.name : Potree.Common.getNameFromURL(fileInfo_.url, true); // fileInfo_.fileType
  88383. object.fileType = fileInfo_.fileType;
  88384. object.boundingBox = boundingBox; //未乘上matrixWorld的本地boundingBox
  88385. //fileInfo_.parentInfo || object.scale.set(1,1,1);//先获取原始的大小时的boundingBox
  88386. object.opacity = 1; //初始化 记录
  88387. object.updateMatrixWorld();
  88388. if (fileInfo_.id != void 0) object.dataset_id = fileInfo_.id;
  88389. fileInfo_.loadCostTime = Date.now() - fileInfo_.loadStartTime;
  88390. /* let weight = Math.round((total / 1024 / 1024) * 100) / 100;*/
  88391. console.log('加载完毕:', fileInfo_.name, Common$1.getNameFromURL(fileInfo_.url), '耗时(ms)', fileInfo_.loadCostTime /* 模型数据量:' + weight + 'M' */);
  88392. if (fileInfo_.fileType == '3dTiles') {
  88393. var isGroup = !object.runtime;
  88394. var _children = object.runtime ? [object] : object.children;
  88395. _children.forEach(object => {
  88396. var boundingBox_ = new Box3();
  88397. var tileset = object.runtime.getTileset();
  88398. //TileHeader: tileset.root
  88399. //参见另一个工程 TileRenderer.js preprocessNode //这个坐标位置几万…… let data = boundingVolume.halfAxes //但这个似乎是premultiply( transform );过后的,可能需还原下
  88400. var json = tileset.tileset;
  88401. var box = json.root.boundingVolume.box;
  88402. if (box) {
  88403. var center = new Vector3(box[0], box[1], box[2]);
  88404. var boundSize = new Vector3();
  88405. // get the extents of the bounds in each axis
  88406. var vecX = new Vector3(box[3], box[4], box[5]);
  88407. var vecY = new Vector3(box[6], box[7], box[8]);
  88408. var vecZ = new Vector3(box[9], box[10], box[11]);
  88409. var scaleX = vecX.length();
  88410. var scaleY = vecY.length();
  88411. var scaleZ = vecZ.length();
  88412. boundingBox_.min.set(-scaleX, -scaleY, -scaleZ);
  88413. boundingBox_.max.set(scaleX, scaleY, scaleZ);
  88414. if (isGroup) {
  88415. //如果是多个拼成的,每个都保留原先在parent中的offset。 如果是外层,作为独立个体,不用理会位置信息,直接放中央。
  88416. object.position.copy(center);
  88417. object.position.z *= -1;
  88418. boundingBox_.translate(object.position); //由于是内层,其位移会改变整体的boundingbox
  88419. }
  88420. } else if (json.root.boundingVolume.sphereOri) {
  88421. var sphereData = json.root.boundingVolume.sphereOri;
  88422. var _center = new Vector3(...sphereData);
  88423. var radius = sphereData[3];
  88424. /* let sphere = new THREE.Sphere(center, radius)
  88425. let box = sphere.getBoundingBox()
  88426. boundingBox.copy(box) */
  88427. boundingBox_.min.set(-radius, -radius, -radius);
  88428. boundingBox_.max.set(radius, radius, radius);
  88429. console.log('boundingVolume sphere', sphereData);
  88430. // boundingBox_.translate(center/* .negate() */)
  88431. //2025:很少有模型用这个,之前是哪个模型有的?目前看到cesium的模型有 'http://192.168.0.25/oss/manage/media-library/result/test/tileset.json',
  88432. } else {
  88433. return console.error('json boundingVolume 缺少信息');
  88434. }
  88435. //中心点居然没用。可能是漏用了什么信息,也许这和LVBADUI_qp是散的有关。
  88436. //console.log('3d tiles json',json)
  88437. /* json.root.refine = 'ADD';
  88438. json.refine = 'ADD'; */
  88439. boundingBox.union(boundingBox_);
  88440. });
  88441. } else {
  88442. Potree.Utils.setObjectLayers(object, 'model');
  88443. object.traverse(child => {
  88444. var is = child.isMesh || child instanceof Points || child.isLine;
  88445. if (is) {
  88446. var _fileInfo_$prop;
  88447. child.renderOrder = Potree.config.renderOrders.model;
  88448. var boundingBox_;
  88449. if (child instanceof SkinnedMesh) {
  88450. //animation
  88451. child.computeBoundingBox();
  88452. boundingBox_ = child.boundingBox;
  88453. } else {
  88454. child.geometry.computeBoundingBox();
  88455. boundingBox_ = child.geometry.boundingBox;
  88456. }
  88457. //获取在scale为1时,表现出的大小
  88458. boundingBox.union(boundingBox_.clone().applyMatrix4(child.matrixWorld)); //但感觉如果最外层object大小不为1,要还原下scale再乘
  88459. if (child instanceof SkinnedMesh) {
  88460. child.boundingBox = null; //delete 动画会导致bound改变, raycast干脆不用boundingBox了,否则之后要实时重计算
  88461. }
  88462. var changeMat = oldMat => {
  88463. var mat = oldMat;
  88464. if (fileInfo_.unlit && !(oldMat instanceof MeshBasicMaterial) /* || object.fileType == 'glb' */) {
  88465. //注释掉是因为已经写入到loader文件里了
  88466. mat = new MeshBasicMaterial({
  88467. name: oldMat.name,
  88468. map: oldMat.map,
  88469. opacity: oldMat.opacity,
  88470. color: oldMat.color,
  88471. skinning: oldMat.skinning
  88472. });
  88473. }
  88474. if (fileInfo_.useStandandMat && !(oldMat instanceof MeshStandardMaterial)) {
  88475. mat = new MeshStandardMaterial();
  88476. mat.roughness = 0.7;
  88477. mat.metalness = 0.5;
  88478. }
  88479. fileInfo_.metalness != void 0 && (mat.metalness = fileInfo_.metalness);
  88480. fileInfo_.roughness != void 0 && (mat.roughness = fileInfo_.roughness);
  88481. if (mat != oldMat) oldMat.dispose();
  88482. //纯色的还是不能用BasicMaterial
  88483. return mat;
  88484. };
  88485. if (child.material instanceof Array) {
  88486. //obj
  88487. child.material = child.material.map(m => changeMat(m));
  88488. } else {
  88489. child.material = changeMat(child.material);
  88490. }
  88491. if ((_fileInfo_$prop = fileInfo_.prop) !== null && _fileInfo_$prop !== void 0 && _fileInfo_$prop.is4dkkModel) {
  88492. child.material.color.set(1, 1, 1); //看到有obj不是白色
  88493. }
  88494. }
  88495. });
  88496. }
  88497. this.objs.add(object);
  88498. if (fileInfo_.transform) {
  88499. var setTransfrom = name => {
  88500. var value = fileInfo_.transform[name];
  88501. if (value == void 0) return;
  88502. if (value instanceof Array) {
  88503. object[name].fromArray(value);
  88504. } else {
  88505. object[name].copy(value);
  88506. }
  88507. };
  88508. setTransfrom('position');
  88509. setTransfrom('rotation');
  88510. setTransfrom('scale');
  88511. }
  88512. if (fileInfo_.moveWithPointcloud) {
  88513. object.updateMatrix();
  88514. object.matrixAutoUpdate = false;
  88515. object.matrix.premultiply(viewer.scene.pointclouds[0].transformMatrix); //默认跟随第一个数据集
  88516. object.matrixWorldNeedsUpdate = true;
  88517. }
  88518. object.updateMatrixWorld();
  88519. MergeEditor.getBoundCenter(object); //初始化
  88520. fileInfo_.objLoader && (fileInfo_.objLoader.inUse = false);
  88521. done && done(object, fileInfo_);
  88522. this.dispatchEvent({
  88523. type: 'modelLoaded',
  88524. model: object
  88525. });
  88526. //如果需要点击出现transform工具需要它有select事件 如 viewer.objs.children[1].addEventListener('select',()=>{})
  88527. }
  88528. async loadModel(fileInfo, done, onProgress_, onError) {
  88529. console.log('开始加载', fileInfo.name, Common$1.getNameFromURL(fileInfo.url));
  88530. var boundingBox = new Box3();
  88531. if (fileInfo.objurl) {
  88532. /* fileInfo.url = fileInfo.objurl, */fileInfo.fileType = 'obj'; //兼容最早的
  88533. }
  88534. if (fileInfo.url instanceof Array) {
  88535. if (fileInfo.url.length == 1) {
  88536. fileInfo.url = fileInfo.url[0];
  88537. } else {
  88538. fileInfo.loadedCount = 0;
  88539. fileInfo.modelGroup = new Object3D(); //parentGroup.name = fileInfo.title
  88540. fileInfo.url.forEach((url, i) => {
  88541. var fileInfoS = Common$1.CloneObject(fileInfo);
  88542. fileInfoS.url = url;
  88543. fileInfoS.name = 'child-' + i;
  88544. fileInfoS.parentInfo = fileInfo;
  88545. this.loadModel(fileInfoS, done, onProgress_, onError);
  88546. });
  88547. return;
  88548. }
  88549. }
  88550. fileInfo.url = Common$1.dealURL(fileInfo.url); //去除'+'
  88551. fileInfo.loadStartTime = Date.now();
  88552. //let fileType = fileInfo.tilesUrl ? '3dTiles' : fileInfo.objurl ? 'obj' : 'glb'
  88553. var loadDone = (object, fileInfo_) => {
  88554. this.modelLoaded(object, fileInfo_ || fileInfo, done);
  88555. };
  88556. var onProgress = function onProgress(xhr) {
  88557. if (xhr.lengthComputable) {
  88558. var percentComplete = xhr.loaded / xhr.total * 100;
  88559. //console.log( Math.round(percentComplete, 2) + '% downloaded' );
  88560. onProgress_ && onProgress_(percentComplete);
  88561. }
  88562. };
  88563. if (fileInfo.fileType == 'obj' && !fileInfo.objurl) {
  88564. var a = fileInfo.url.split('/');
  88565. var tails = a.pop().split('.');
  88566. var head = a.join('/') + '/';
  88567. var name = tails[0],
  88568. fileType = tails[1];
  88569. if (fileType == 'obj') {
  88570. fileInfo.objurl || (fileInfo.objurl = fileInfo.url);
  88571. fileInfo.mtlurl || (fileInfo.mtlurl = head + name + '.mtl');
  88572. } else {
  88573. fileInfo.fileType = 'glb';
  88574. }
  88575. }
  88576. if (fileInfo.fileType == 'obj') {
  88577. //暂时不支持数组
  88578. var objLoader = fileInfo.objLoader = this.getObjLoader();
  88579. var loadobj = () => {
  88580. objLoader.load(fileInfo.objurl, (object, total) => {
  88581. loadDone(object /* , total, fileInfo.objurl */);
  88582. }, onProgress, onError);
  88583. };
  88584. if (fileInfo.mtlurl) {
  88585. loaders.mtlLoader.load(fileInfo.mtlurl, materials => {
  88586. objLoader.setMaterials(materials); //因为这句所以不同obj不能用同一个objLoader,否则材质紊乱,模型变白
  88587. materials.preload();
  88588. loadobj();
  88589. }, onProgress, () => {
  88590. //console.log('mtl load failed, load obj directly')
  88591. loadobj();
  88592. });
  88593. } else {
  88594. loadobj();
  88595. }
  88596. } else if (fileInfo.fileType == 'glb') {
  88597. loaders.glbLoader.unlitMat = true; //!!fileInfo.unlit
  88598. loaders.glbLoader.load(fileInfo.url, (gltf, total) => {
  88599. console.log('loadGLTF', gltf, 'aniCount:', gltf.animations.length);
  88600. var model = gltf.scene;
  88601. if (gltf.animations.length) {
  88602. var skeleton = new SkeletonHelper(model);
  88603. viewer.scene.scene.add(skeleton);
  88604. model.skeletonHelper = skeleton; //注意:不能覆盖model.skeleton,因其另有 */
  88605. if (Potree.settings.isOfficial) {
  88606. Potree.Utils.updateVisible(skeleton, 'hide', false);
  88607. } else {
  88608. skeleton.material.opacity = 0.1;
  88609. skeleton.bones.forEach((bone, i) => {
  88610. var label = new Potree.TextSprite({
  88611. text: "".concat(i, " : ").concat(bone.name),
  88612. sizeInfo: {
  88613. width2d: 130
  88614. },
  88615. fontWeight: '',
  88616. fontsize: 20,
  88617. backgroundColor: {
  88618. r: 255,
  88619. g: 255,
  88620. b: 255,
  88621. a: 0
  88622. },
  88623. textColor: {
  88624. r: 255,
  88625. g: 255,
  88626. b: 255,
  88627. a: 1
  88628. }
  88629. });
  88630. label.sprite.material.depthTest = false;
  88631. bone.add(label);
  88632. });
  88633. }
  88634. var mixer = new AnimationMixer(model);
  88635. model.actions = [];
  88636. gltf.animations.forEach(ani => {
  88637. if (ani.tracks.filter(e => e instanceof QuaternionKeyframeTrack).length > 1) {
  88638. //>一帧的
  88639. model.actions.push(mixer.clipAction(ani));
  88640. }
  88641. });
  88642. model.mixer = mixer;
  88643. }
  88644. model.gltf = gltf;
  88645. //model.traverse(e=>e.frustumCulled = false) 为什么有的动画模型离近了会消失,173ver的不会
  88646. loadDone(model);
  88647. }, onProgress, onError);
  88648. } else if (fileInfo.fileType == 'ply') {
  88649. loaders.plyLoader.load(fileInfo.url, geometry => {
  88650. var object;
  88651. console.log('ply加载完毕', geometry);
  88652. if (!geometry.index) {
  88653. //点云
  88654. object = new Points(geometry, new PointsMaterial({
  88655. vertexColors: true,
  88656. size: 0.02
  88657. }));
  88658. //141M的点云,intersect费时300ms以上
  88659. } else {
  88660. //mesh
  88661. object = new Mesh(geometry);
  88662. }
  88663. loadDone(object);
  88664. });
  88665. } else if (fileInfo.fileType == '3dTiles') {
  88666. var result = await Loader3DTiles.load({
  88667. url: fileInfo.url,
  88668. gltfLoader: loaders.glbLoader,
  88669. //renderer: SceneRenderer.renderer
  88670. options: {
  88671. //dracoDecoderPath: '../utils/loaders/DRACOLoader/draco',
  88672. //basisTranscoderPath: '../utils/loaders/KTX2Loader/basis',
  88673. maximumScreenSpaceError: fileInfo.maximumScreenSpaceError || 80,
  88674. //越小越清晰。 如果本身tiles很密很小这个值就不能很大。
  88675. //maxDepth: 100,
  88676. //maximumMemoryUsage: 100, //缓存大小,见tiles3DMaxMemory。单位M(但实际结果是 2.5*maximumMemoryUsage + 750 。超过2G会崩, 所以应该小于540) 若太小,密集的tile反复加载很卡. (任务管理器刷新网页后若内存不掉就要结束进程否则虚高)
  88677. debug: browser.urlHasValue('tilesBox'),
  88678. //show box
  88679. parent: this.scene.scene,
  88680. is4dkkModel: fileInfo.is4dkkModel,
  88681. //是否是4dkk中的模型. 通常maximumScreenSpaceError需要10
  88682. updateTime: fileInfo.updateTime //加后缀防止缓存
  88683. //cesiumIONToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5OTc4MTFiYS1hYzhlLTQ3ZjYtYWJmMi1hODMwMWMxZGRiYTQiLCJpZCI6ODU1NDksImlhdCI6MTY1Mzc5NDc5N30.ldTi8bF3XvSOgnZrMITokRW4kE3i8Mwbarhk5OQbPsI',
  88684. }
  88685. });
  88686. //console.log(result)
  88687. result.model.runtime = result.runtime;
  88688. var loaded = false;
  88689. var tileset = result.runtime.getTileset();
  88690. tileset.addEventListener('endTileLoading', function (data) {
  88691. //Tileset3D
  88692. if (data.loadingCount == 0 && !loaded) {
  88693. loaded = true;
  88694. //console.log('loaded!!!!!!!!!!!!!')
  88695. }
  88696. });
  88697. tileset.addEventListener('tileLoaded', e => {
  88698. //每一个tile加载完要更改透明度
  88699. var master = result.model.parent == this.objs ? result.model : result.model.parent; //最多两层
  88700. MergeEditor.changeOpacity(e.tileContent, master.opacity);
  88701. if (master.panos) viewer.images360.judgeModelMat(e.tileContent);
  88702. //set Layers ?
  88703. Potree.Utils.setObjectLayers(e.tileContent, 'model');
  88704. fileInfo.side && e.tileContent.traverse(e => e.material && (e.material.side = side)); //新软件导出的带坐标的box型模型要反面才看的到,干脆双面
  88705. });
  88706. {
  88707. var vi = true;
  88708. Object.defineProperty(result.model, "visible", {
  88709. get: function get() {
  88710. return vi;
  88711. },
  88712. set: function set(v) {
  88713. vi = v;
  88714. result.model.visiChangeCallback();
  88715. }
  88716. });
  88717. }
  88718. var v = true;
  88719. result.model.visiChangeCallback = () => {
  88720. var visi = result.model.realVisible();
  88721. tileset.visible = visi; //同步,使不加载
  88722. if (v != visi) {
  88723. tileset.nextForceUpdate = true;
  88724. v = visi;
  88725. }
  88726. };
  88727. loadDone(result.model /* , null, fileInfo.url */);
  88728. } else if (fileInfo.fileType == 'dxf') {
  88729. loaders.dxfLoader.load(fileInfo.url, object => {
  88730. loadDone(object);
  88731. }, fileInfo);
  88732. } else if (fileInfo.fileType == 'shp') {
  88733. /* if(viewer.transform){
  88734. loaders.shapeLoader.transform = (v)=>{
  88735. let a = viewer.transform.lonlatTo4550.inverse(v)
  88736. return viewer.transform.lonlatToLocal.forward(a)
  88737. }
  88738. //loaders.shapeLoader.transform = viewer.transform.lonlatToLocal.forward;
  88739. } */
  88740. var shp = await loaders.shapeLoader.load(fileInfo.url, fileInfo.color);
  88741. var shpModel = shp.node;
  88742. loadDone(shpModel);
  88743. } else if (fileInfo.fileType == 'overlay') {
  88744. var overlay = new Overlay(fileInfo);
  88745. overlay.unableEdit = true;
  88746. this.scene.overlays.push(overlay);
  88747. loadDone(overlay);
  88748. } else if (fileInfo.fileType == '3dgs') {
  88749. var gsViewer = new GaussianSplats3D.Viewer({
  88750. 'dynamicScene': true,
  88751. //只有加上这个sh光影才会跟随模型位置变化而变化
  88752. rootElement: this.renderArea,
  88753. threeScene: this.scene.scene,
  88754. renderer: this.renderer,
  88755. camera: this.mainViewport.camera,
  88756. useBuiltInControls: false,
  88757. //dropInMode: true,
  88758. logLevel: 10,
  88759. //console info
  88760. antialiased: fileInfo.antialiased,
  88761. sharedMemoryForWorkers: location.host.includes("www.4dmodel.com") ? false : undefined,
  88762. //否则 报错 SharedArrayBuffer transfer requires self.crossOriginIsolated. 本地已经配置所以不会
  88763. sphericalHarmonicsDegree: 2 //最大支持的sh Level
  88764. });
  88765. //let path = Potree.resourcePath+'/models/gaussian/bonsai.ksplat';
  88766. gsViewer.addSplatScene(fileInfo.url, {
  88767. 'progressiveLoad': true
  88768. }).then(() => {
  88769. gsViewer.start();
  88770. //loadDone(gsViewer.splatMesh) //放这里才能看到逐步加载的过程,但会导致加载不完整。
  88771. gsViewer.splatMesh.updateMatrix();
  88772. gsViewer.splatMesh.updateMatrixWorld();
  88773. gsViewer.splatMesh.gsViewer = gsViewer;
  88774. gsViewer.splatMesh.onSplatTreeReadyCallback = () => {
  88775. loadDone(gsViewer.splatMesh);
  88776. var {
  88777. sceneMax,
  88778. sceneMin
  88779. } = gsViewer.splatMesh.splatTree.subTrees[0];
  88780. gsViewer.splatMesh.boundingBox.min.copy(sceneMin);
  88781. gsViewer.splatMesh.boundingBox.max.copy(sceneMax);
  88782. };
  88783. var selfRaycaster = new GaussianSplats3D.Raycaster();
  88784. gsViewer.splatMesh.raycast = function (raycaster, intersects) {
  88785. //重写
  88786. var hits = [];
  88787. selfRaycaster.ray.setParameters(raycaster.ray.origin, raycaster.ray.direction);
  88788. selfRaycaster.intersectSplatMesh(gsViewer.splatMesh, hits);
  88789. hits.forEach(e => {
  88790. e.object = gsViewer.splatMesh;
  88791. e.point = e.origin;
  88792. delete e.origin;
  88793. });
  88794. intersects.push(...hits);
  88795. }; //问题:感觉normal不准
  88796. var updateRegion = () => {
  88797. gsViewer.update(); //load
  88798. if (!gsViewer.splatMesh.visibleRegionChanging) {
  88799. viewer.removeEventListener('update', updateRegion);
  88800. } else {
  88801. viewer.dispatchEvent('content_changed');
  88802. }
  88803. };
  88804. viewer.addEventListener('update', updateRegion);
  88805. });
  88806. //window.gsViewer = gsViewer
  88807. viewer.addEventListener('render.begin2', e => {
  88808. if (e.name == 'scene') {
  88809. //gsViewer.selfDrivenUpdate()
  88810. gsViewer.update();
  88811. if (gsViewer.initialized && gsViewer.splatRenderReady) {}
  88812. }
  88813. });
  88814. }
  88815. }
  88816. removeModel(model) {
  88817. model.parent.remove(model);
  88818. var dispose = e => {
  88819. e.geometry && e.geometry.dispose();
  88820. e.material && e.material.dispose();
  88821. };
  88822. model.traverse(e => {
  88823. dispose(e);
  88824. });
  88825. if (Potree.settings.boundAddObjs && model.isChildOf(viewer.objs)) {
  88826. this.updateModelBound();
  88827. }
  88828. }
  88829. setAllTilesets() {
  88830. //让所有tileset执行fun。 objs里每个model最多两层tileset
  88831. var models = arguments.length == 2 ? [arguments[0]] : this.objs.children; //如果要设定某个model的tileset,就传第一个参数
  88832. var fun = arguments[1] || arguments[0];
  88833. models.forEach(e => {
  88834. if (e.fileType == '3dTiles') {
  88835. e.traverse(child => {
  88836. if (child.runtime) {
  88837. fun(child);
  88838. return {
  88839. stopContinue: true
  88840. };
  88841. }
  88842. });
  88843. }
  88844. });
  88845. }
  88846. setDisplay(state) {
  88847. var cause = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'setDisplay';
  88848. //如果创建了iframe,主页的需要隐藏的话需要释放一些内存出来。iframe关闭前也释放下比较保险
  88849. state = !!state;
  88850. this.setAllTilesets(model => {
  88851. var tileset = model.runtime.getTileset();
  88852. Potree.Utils.updateVisible(model, cause, state);
  88853. if (!state) tileset._cache.trim(); //使下一次update时dispose所有不可见的tiles
  88854. model.runtime.update(16, this.renderer, this.mainViewport.camera, true);
  88855. if (state) this.dispatchEvent('content_changed');
  88856. });
  88857. if (state) {
  88858. Potree.pointBudget = 6 * 1000 * 1000; //先随便写一个, 随后mergeEditor.updateMemoryUsage
  88859. } else {
  88860. Potree.pointBudget = 0;
  88861. Potree.updatePointClouds(this.scene.pointclouds, this.mainViewport.camera, this.mainViewport.resolution);
  88862. this.images360.panoRenderer.disposeIdelTargets(); //如果也能清空当前使用的就好了,但是恢复就需要时间
  88863. this.images360.depthSampler.clearTexData();
  88864. }
  88865. this.dispatchEvent({
  88866. type: 'setDisplay',
  88867. state
  88868. });
  88869. this.paused = !state;
  88870. }
  88871. setAniIK(model, object) {
  88872. //不知道为什么一加上胳膊一直动啊??
  88873. var handIndex = 9;
  88874. //model.skeletonHelper.bones[handIndex].attach( object ); //bone可以绑定一个球
  88875. var mesh = children[0].children[1]; //vanguard_Mesh
  88876. var iks = [{
  88877. target: 10,
  88878. //大拇指
  88879. effector: 9,
  88880. // 必须是第一个link的child 手腕
  88881. links: [{
  88882. index: 8 // 肘关节
  88883. /* rotationMin: new THREE.Vector3( 1.2, - 1.8, - .4 ),
  88884. rotationMax: new THREE.Vector3( 1.7, - 1.1, .3 ) */
  88885. }, {
  88886. index: 7 // 肩关节
  88887. /* rotationMin: new THREE.Vector3( 0.1, - 0.7, - 1.8 ),
  88888. rotationMax: new THREE.Vector3( 1.1, 0, - 1.4 ) */
  88889. }]
  88890. }];
  88891. var IKSolver = new CCDIKSolver(mesh, iks);
  88892. var ccdikhelper = new CCDIKHelper(mesh, iks, 1.5);
  88893. viewer.scene.scene.add(ccdikhelper);
  88894. viewer.IKSolver = IKSolver;
  88895. }
  88896. addFire() {
  88897. if (Potree.settings.number == 't-CwfhfqJ') {
  88898. var position = Potree.Utils.datasetPosTransform({
  88899. pointcloud: viewer.scene.pointclouds[0],
  88900. position: new Vector3(4.4318, -0.580291847759, -0.78),
  88901. fromDataset: true
  88902. });
  88903. viewer.modules.ParticleEditor.addParticle({
  88904. type: 'fire',
  88905. positions: [position],
  88906. radius: 0.42,
  88907. height: 10
  88908. });
  88909. viewer.modules.ParticleEditor.addParticle({
  88910. type: 'smoke',
  88911. positions: [new Vector3().addVectors(position, new Vector3(0, 0, 0.3))],
  88912. positionStyle: 'sphere',
  88913. positionRadius: 0.3,
  88914. sizeTween: [[0, 0.3, 0.9, 1], [0.05, 0.1, 1, 0.8]],
  88915. opacityBase: 0.2,
  88916. opacityTween: [[0, 0.3, 0.7, 0.95, 1], [0, 0.2, 1, 0.1, 0]],
  88917. velocityBase: new Vector3(0, 0, 1),
  88918. velocitySpread: new Vector3(0.2, 0.2, -0.3),
  88919. accelerationBase: 0.2,
  88920. accelerationSpread: 0.7,
  88921. radius: 0,
  88922. //particlesPerSecond : 30,
  88923. particleDeathAge: 3.0
  88924. });
  88925. viewer.modules.ParticleEditor.addParticle({
  88926. type: 'explode',
  88927. name: 'fire splash',
  88928. position: new Vector3().addVectors(position, new Vector3(0, 0, 0.3)),
  88929. size: 0.1,
  88930. sizeRange: 0.3,
  88931. sizeTween: [[0, 0.05, 0.3, 0.45], [0, 0.02, 0.1, 0.05]],
  88932. opacityTween: [[0, 0.05, 0.3, 0.45], [1, 1, 0.5, 0]],
  88933. speed: 1,
  88934. //sphere
  88935. speedRange: 4,
  88936. radius: 0.1,
  88937. acceleration: 0.3,
  88938. accelerationRange: 1,
  88939. particleSpaceTime: 0,
  88940. strength: 4
  88941. });
  88942. }
  88943. }
  88944. addVideo() {
  88945. if (Potree.settings.number != 'SS-t-P6zBR73Gke') return;
  88946. var geo = new PlaneGeometry(1, 1, 1, 1);
  88947. var videoInfo = this.videoInfo = [{
  88948. id: '40-2',
  88949. url: 'https://laser-oss.4dkankan.com/testdata/SS-t-P6zBR73Gke/temp/poi/2022/05/10/0aabafee-36b8-455d-9c11-0780bf694786.mp4',
  88950. rotation: [-1.494468618954883, -1.4987317433158989, -3.061254983446741],
  88951. position: [19.801820617361624, 2.884673619844108, -0.03362305858221648],
  88952. scale: [3.5741423153151763, 2.8738725275578703, 1]
  88953. }, {
  88954. id: 40,
  88955. /* rotation:[-1.534692822378723, 0.01083403560862361, 3.141535283661569],
  88956. position:[17.2934294239949861, 2.413510747928117, -0.008057029580231356], */
  88957. url: 'https://laser-oss.4dkankan.com/testdata/SS-t-P6zBR73Gke/temp/poi/2022/05/09/7896d6ef-a2d6-4fd7-949c-768782a5b484.mp4',
  88958. rotation: [-1.5487684197910518, 0.021848470169552752, -3.1387534893955236],
  88959. position: [17.277316608096, 2.0840432922115846, -0.0931149415437065],
  88960. scale: [2.0821757723834047, 0.6129478480765236, 1],
  88961. visibles: [40]
  88962. }];
  88963. var add = info => {
  88964. var video = $("<video controls=\"controls\" loop autoplay x5-playsinline=\"\" webkit-playsinline=\"true\" playsinline=\"true\" controlslist=\"nodownload\"></video>")[0];
  88965. video.setAttribute("crossOrigin", 'Anonymous');
  88966. video.src = info.url || Potree.resourcePath + "/video/".concat(Potree.settings.number, "/").concat(info.id, ".mp4");
  88967. var map = new VideoTexture(video);
  88968. var plane = this.videoPlane = new Mesh(geo, new MeshBasicMaterial({
  88969. color: "#ffffff",
  88970. transparent: !0,
  88971. depthTest: false,
  88972. opacity: 0,
  88973. //side:2,
  88974. map
  88975. }));
  88976. plane.position.fromArray(info.position);
  88977. plane.rotation.fromArray(info.rotation);
  88978. info.scale && plane.scale.fromArray(info.scale);
  88979. this.scene.scene.add(plane);
  88980. info.plane = plane;
  88981. plane.boundingBox = new Box3(new Vector3(0, -0.5, 0), new Vector3(1, -0.4, 0.2));
  88982. video.addEventListener('loadeddata', function (e) {
  88983. video.play();
  88984. if (!info.visibles /* ||!viewer.images360.currentPano || info.visibles.includes(viewer.images360.currentPano.id) */) {
  88985. plane.material.opacity = 1;
  88986. }
  88987. info.scale || plane.scale.set(video.videoWidth / 1000, video.videoHeight / 1000, 1); // 1080 * 1920
  88988. console.log('video loadeddata', info.id);
  88989. });
  88990. if (info.visibles) {
  88991. this.images360.addEventListener('flyToPano', e => {
  88992. //飞之前
  88993. if (info.visibles.includes(e.toPano.pano.id)) {
  88994. //出现
  88995. setTimeout(() => {
  88996. plane.visible = true;
  88997. video.currentTime = 0;
  88998. video.play();
  88999. if (video.paused) {
  89000. var startPlay = () => {
  89001. plane.visible && video.play();
  89002. this.removeEventListener('global_mousedown', startPlay);
  89003. };
  89004. this.addEventListener('global_mousedown', startPlay);
  89005. }
  89006. Potree.settings.zoom.enabled = false;
  89007. transitions.start(lerp.property(plane.material, "opacity", 1), e.toPano.duration * 0.4, () => {}, 0, easing['easeInOutQuad']);
  89008. }, e.toPano.duration * 0.6); //时间上不能和消失的重叠 延迟
  89009. } else {
  89010. //消失
  89011. transitions.start(lerp.property(plane.material, "opacity", 0), e.toPano.duration * 0.4, () => {
  89012. if (!info) {
  89013. plane.visible = false;
  89014. video.pause();
  89015. Potree.settings.zoom.enabled = true;
  89016. }
  89017. }, 0, easing['easeInOutQuad']);
  89018. }
  89019. });
  89020. }
  89021. var startPlay = () => {
  89022. video.play();
  89023. //video.pause()
  89024. //video.currentTime = 0.1;
  89025. this.removeEventListener('global_mousedown', startPlay);
  89026. };
  89027. this.addEventListener('global_mousedown', startPlay);
  89028. Potree.settings.isTest && plane.addEventListener('select', e => {
  89029. console.log(e);
  89030. });
  89031. };
  89032. videoInfo.forEach(info => {
  89033. add(info);
  89034. });
  89035. /* this.images360.addEventListener('flyToPano' ,(e)=>{//飞之前
  89036. if(Potree.settings.displayMode != 'showPanos') return
  89037. let info = videoInfo[e.toPano.pano.id]
  89038. if(info ){ //出现
  89039. setTimeout(()=>{
  89040. plane.visible = true;
  89041. plane.position.fromArray(info.position)
  89042. plane.rotation.fromArray(info.rotation)
  89043. video.src = Potree.resourcePath+`/video/${Potree.settings.number}/${e.toPano.pano.id}.mp4`
  89044. video.play();
  89045. video.currentTime = 0
  89046. Potree.settings.zoom.enabled = false
  89047. transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{
  89048. }, 0, easing['easeInOutQuad'])
  89049. }, e.toPano.duration*0.6) //时间上不能和消失的重叠 延迟
  89050. }
  89051. //消失
  89052. transitions.start(lerp.property(plane.material, "opacity", 0, ) , e.toPano.duration*0.4, ()=>{
  89053. if(!info){
  89054. plane.visible = false
  89055. video.pause()
  89056. Potree.settings.zoom.enabled = true
  89057. }
  89058. }, 0, easing['easeInOutQuad'])
  89059. })
  89060. this.images360.addEventListener('endChangeMode',(e)=>{ //暂时不处理初始加载时就在有视频的点位上的情况
  89061. if(e.mode == 'showPanos'){
  89062. let info = videoInfo[this.images360.currentPano.id]
  89063. if(info ){ //出现
  89064. plane.visible = true;
  89065. plane.position.fromArray(info.position)
  89066. plane.rotation.fromArray(info.rotation)
  89067. plane.material.opacity = 0
  89068. video.src = Potree.resourcePath+`/video/${Potree.settings.number}/${this.images360.currentPano.id}.mp4`
  89069. video.play();
  89070. video.currentTime = 0
  89071. Potree.settings.zoom.enabled = false
  89072. transitions.start(lerp.property(plane.material, "opacity", 1, (e)=>{console.log('fadeIn',e)}) , 300 , ()=>{
  89073. }, 0, easing['easeInOutQuad'])
  89074. }
  89075. }else{
  89076. plane.visible = false;
  89077. Potree.settings.zoom.enabled = true
  89078. }
  89079. })
  89080. */
  89081. }
  89082. /* addTube(){//加水管 自动生成
  89083. if(Potree.settings.number == 't-8KbK1JjubE'){
  89084. let boundingBox = new THREE.Box3()
  89085. boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
  89086. let radius = 0.08;
  89087. let radialSegments = 5
  89088. let radSegments = Math.PI*2 / radialSegments
  89089. var circlePts = [];//横截面
  89090. for(let i=0;i<radialSegments;i++){
  89091. let angle = radSegments * i;
  89092. circlePts.push(new THREE.Vector2(radius * Math.cos(angle), radius * Math.sin(angle) ))
  89093. }
  89094. var count = 0
  89095. var addMesh = (color, path, height)=>{//height:在path之上的高度,负数代表在path之下
  89096. var name = 'cylinder'+count
  89097. var mat = new THREE.MeshStandardMaterial({color, depthTest:false, roughness:0.4,metalness:0.5}) 
  89098. let linePath = path.map(e=>new THREE.Vector3().copy(e).setZ(e.z+height))
  89099. let geo = MeshDraw.getExtrudeGeo( circlePts, null,{ extrudePath:linePath, tension:0.2} )
  89100. var mesh = new THREE.Mesh(geo,mat);
  89101. mesh.name = name
  89102. window[name] = mesh
  89103. mesh.boundingBox = boundingBox
  89104. mesh.matrixAutoUpdate = false
  89105. mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
  89106. mesh.matrixWorldNeedsUpdate = true
  89107. this.scene.scene.add(mesh);
  89108. count ++
  89109. }
  89110. let linePath, height
  89111. //地上管子 黄色
  89112. 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}
  89113. ,{"x":43.58,"y":27.7,"z":-0.97},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右
  89114. , {"x":39.18,"y":36.71,"z":0.35},{"x":38.69,"y":36.04,"z":18.04} // 拐弯向上
  89115. ]
  89116. height = radius + 0.05;
  89117. addMesh('#b86', linePath, height)
  89118. //地下管子 藍色
  89119. 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}
  89120. ]
  89121. height = -0.5;
  89122. addMesh('#48a', linePath, height)
  89123. }
  89124. } */
  89125. addMonitor(data, model) {
  89126. if (!model) {
  89127. return console.warn('必须指定第二个参数为所附模型');
  89128. }
  89129. data = data || {
  89130. "sid": "gSMVdb159299",
  89131. "name": "1",
  89132. "panoId": "0",
  89133. "video": "https://newcntv.qcloudcdn.com/asp/hls/4000/0303000a/3/default/d907ef756138493e9fe5b35b4ab69642/4000.m3u8",
  89134. "posOri": {
  89135. "x": 0.75,
  89136. "y": 0.07,
  89137. "z": 1.5
  89138. },
  89139. "posOffset": {
  89140. "x": 0,
  89141. "y": 0,
  89142. "z": 0
  89143. },
  89144. "fov": 70,
  89145. "far": 3,
  89146. "yaw": 24,
  89147. "roll": 0,
  89148. "pitch": -1,
  89149. "videoType": 1
  89150. };
  89151. var monitor = new Monitor(data, model);
  89152. this.scene.monitors.push(monitor);
  89153. this.dispatchEvent('content_changed');
  89154. }
  89155. addTube(datas) {
  89156. var _loop = function _loop() {
  89157. if (number == Potree.settings.number) {
  89158. var data = datas[number];
  89159. var boundingBox = new Box3();
  89160. boundingBox.min.set(-1, -1, -1);
  89161. boundingBox.max.set(1, 1, 1);
  89162. index = 0;
  89163. function addMesh() {
  89164. var {
  89165. color,
  89166. path,
  89167. height,
  89168. fromDataset,
  89169. radius = 0.08,
  89170. datasetId = Potree.settings.originDatasetId,
  89171. tension = 0.3,
  89172. visiEntity
  89173. } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  89174. //height:在path之上的高度,负数代表在path之下
  89175. var name = 'tube_' + index;
  89176. var options = arguments[0];
  89177. var radialSegments = 5; //THREE.Math.clamp( Math.round(radius * 800), 10, 40)
  89178. var radSegments = Math.PI * 2 / radialSegments;
  89179. var circlePts = []; //横截面
  89180. for (var i = 0; i < radialSegments; i++) {
  89181. var angle = radSegments * i;
  89182. circlePts.push(new Vector2(radius * Math.cos(angle), radius * Math.sin(angle)));
  89183. }
  89184. //var mat = new THREE.MeshStandardMaterial({color, /* wireframe:true, depthTest:false,*/ roughness:0.9,metalness:0.3}) 
  89185. var mat = new DepthBasicMaterial({
  89186. color,
  89187. useDepth: false
  89188. });
  89189. var linePath = path.map(e => {
  89190. e instanceof Array && (e = new Vector3().fromArray(e));
  89191. var pos;
  89192. if (fromDataset) {
  89193. //获取:JSON.stringify(viewer.scene.measurements[0].dataset_points.map(e=>Potree.math.toPrecision(e.toArray(),3)))
  89194. pos = Potree.Utils.datasetPosTransform({
  89195. fromDataset: true,
  89196. position: e,
  89197. datasetId
  89198. });
  89199. } else {
  89200. pos = new Vector3().copy(e);
  89201. }
  89202. return pos.setZ(pos.z + height);
  89203. });
  89204. console.log(linePath);
  89205. var geo = MeshDraw.getExtrudeGeo(circlePts, null, Object.assign(options, {
  89206. extrudePath: linePath,
  89207. tension
  89208. }));
  89209. var mesh = new Mesh(geo, mat);
  89210. mesh.name = name;
  89211. window[name] = mesh;
  89212. mesh.boundingBox = boundingBox;
  89213. mesh.matrixAutoUpdate = false;
  89214. fromDataset || mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix);
  89215. mesh.matrixWorldNeedsUpdate = true;
  89216. viewer.scene.scene.add(mesh);
  89217. if (visiEntity) {
  89218. viewer.modules.SiteModel.bus.addEventListener('buildingChange', e => {
  89219. Potree.Utils.updateVisible(mesh, 'isInEntity', e.entity && e.entity.name == visiEntity);
  89220. });
  89221. }
  89222. {
  89223. mat.defines.mapOverlay = true;
  89224. var map = new TextureLoader().load(Potree.resourcePath + '/textures/rectangle.png', () => {
  89225. viewer.dispatchEvent('content_changed');
  89226. });
  89227. mat.uniforms.mapColor.value.set('#f00');
  89228. map.anisotropy = 2;
  89229. map.wrapS = RepeatWrapping;
  89230. map.wrapT = RepeatWrapping;
  89231. /* map.repeat.set(10,1.3)
  89232. map.offset.set(0,-0.15) */
  89233. mat.map = map;
  89234. //mat.map.repeat.x = Math.round(this.totalLength / this.halfPathWidth * 0.5) * (this.reverse ? -1 : 1)
  89235. mat.map.needsUpdate = true;
  89236. mat.setUV();
  89237. }
  89238. }
  89239. while (index < data.length) {
  89240. addMesh(data[index]);
  89241. index++;
  89242. }
  89243. }
  89244. },
  89245. index;
  89246. //加水管 自动生成
  89247. for (var number in datas) {
  89248. _loop();
  89249. }
  89250. /*
  89251. 可能用到的
  89252. viewer.scene.measurements.forEach(e=>e.edgeLabels.forEach(e=>Potree.Utils.updateVisible(e,'f',false)))
  89253. JSON.stringify(viewer.scene.measurements.find(e=>e.visible).dataset_points.map(e=>Potree.math.toPrecision(e.toArray(),3)))
  89254. */
  89255. }
  89256. addSprite(e) {
  89257. //api
  89258. var sprite;
  89259. if (e.text != void 0) {
  89260. sprite = new TextSprite(e);
  89261. } else {
  89262. var map = texLoader.load(src);
  89263. e.map = map;
  89264. sprite = new Sprite(e);
  89265. }
  89266. return sprite;
  89267. }
  89268. switchHotType() {
  89269. // add
  89270. var type = Potree.settings.showHotTemp ? 'temp' : Potree.settings.showHotIr ? 'ir' : null;
  89271. var _gradient = Gradients[type ? 'ir' : 'RAINBOW']; //e.material._gradient = Gradients[type == 'ir' ? 'ir' : 'RAINBOW']//渐变色阶
  89272. var gradientTex = Potree.ExtendPointCloudMaterial.generateGradientTexture(_gradient);
  89273. var min, max;
  89274. if (type) {
  89275. min = this.tempRange[type].min;
  89276. max = this.tempRange[type].max;
  89277. if (min > 0) {
  89278. var expand = (max - min) * 0.015; //微扩大,因为比min还小的是0, 0是未探测到温度,要区别出0和min,否则这俩将是一个颜色(但不能扩太多,因为界面标记了最低值,否则0就是最低值了)
  89279. min -= expand;
  89280. } else if (max < 0) {
  89281. var _expand = (max - min) * 0.015;
  89282. max -= _expand;
  89283. }
  89284. }
  89285. var objects = [viewer.images360.cube].concat(viewer.scene.pointclouds);
  89286. objects.forEach(e => {
  89287. e.material.uniforms.gradient.value = e.material.gradientTexture = gradientTex;
  89288. type && e.material.uniforms.temperRange.value.set(min, max);
  89289. });
  89290. viewer.scene.pointclouds.forEach(e => e.updateAttrAuto());
  89291. }
  89292. gatherTempRange(type, range) {
  89293. //收集温度范围
  89294. var oldRange = Common$1.CloneObject(this.tempRange);
  89295. if (range) {
  89296. //全景模式时
  89297. var {
  89298. min,
  89299. max
  89300. } = this.tempRange[type];
  89301. min = Math.min(range.min, min);
  89302. max = Math.max(range.max, max);
  89303. this.tempRange[type] = {
  89304. min,
  89305. max
  89306. };
  89307. } else {
  89308. //点云模式随着加载而扩充温度范围
  89309. viewer.scene.pointclouds.forEach(pointcloud => {
  89310. var _pointcloud$root$geom, _pointcloud$root$geom2;
  89311. var rootAttr = ((_pointcloud$root$geom = pointcloud.root.geometryNode) === null || _pointcloud$root$geom === void 0 ? void 0 : _pointcloud$root$geom.geometry.attributes) || ((_pointcloud$root$geom2 = pointcloud.root.geometry) === null || _pointcloud$root$geom2 === void 0 ? void 0 : _pointcloud$root$geom2.attributes);
  89312. if (!rootAttr) return false;
  89313. var types = ['temp', 'ir'].filter(e => rootAttr[e]);
  89314. if (types.length == 0) return true;
  89315. var nodesAttr = pointcloud.visibleNodes.map(e => e.geometryNode.geometry.attributes);
  89316. nodesAttr = [rootAttr].concat(nodesAttr).filter(e => !e[types[0]].tempRangeVisited_);
  89317. nodesAttr.forEach(attributes => {
  89318. types.forEach(type_ => {
  89319. var {
  89320. min,
  89321. max
  89322. } = this.tempRange[type_];
  89323. var range = attributes[type_].tempRange;
  89324. min = Math.min(range[0], min);
  89325. max = Math.max(range[1], max);
  89326. this.tempRange[type_] = {
  89327. min,
  89328. max
  89329. };
  89330. attributes[type_].tempRangeVisited_ = true;
  89331. });
  89332. });
  89333. /* pointcloud.visibleNodes.forEach(e=>{
  89334. if(e.tempRangeVisited)return
  89335. types.forEach(type_=>{
  89336. let {min,max} = this.tempRange[type_]
  89337. let range = e.geometryNode.geometry.attributes[type_].tempRange
  89338. min = Math.min(range[0], min)
  89339. max = Math.max(range[1], max)
  89340. this.tempRange[type_] = {min,max}
  89341. })
  89342. e.tempRangeVisited = true
  89343. }) */
  89344. });
  89345. }
  89346. if (!Common$1.ifSame(oldRange, this.tempRange)) {
  89347. this.switchHotType(); //update
  89348. console.log('tempRangeChanged', Common$1.CloneObject(this.tempRange));
  89349. this.dispatchEvent('tempRangeChanged');
  89350. }
  89351. return true;
  89352. //其实可以只识别低nodeLevel的range,会快一些吗,甚至只root的就行,不知道后面的会不会超过root的范围
  89353. }
  89354. }
  89355. ;
  89356. //------ CLIP 默认clipTask都是clipInside ----------------------
  89357. /*
  89358. 并集相当于加法,交集相当于乘法。 所有结果都能展开成多个乘积相加。
  89359. 假设有4个clipBoxes,ABCD, 如果是 A*B + C*D ,那么这是最终结果。 如果是 (A+B)*(C+D) = A*C+A*D+B*C+B*D
  89360. */
  89361. /*
  89362. let Clips = {
  89363. boxes : [],
  89364. unionGroups : [], //二维数组。最外层要求并集,里层要求交集(如果只有一个元素就是本身)。总结起来就是要求一堆交集的并集
  89365. shaderParams:{},
  89366. needsUpdate : true,
  89367. addClip(box, clipMethod){
  89368. //不允许重复
  89369. if(this.boxes.includes(box)){
  89370. return console.warn('addClip重复添加了box',box)
  89371. }
  89372. boxes.push(box)
  89373. if(clipMethod == 'any'){//并
  89374. this.unionGroups.push([box])
  89375. }else if(clipMethod == 'all'){//交
  89376. this.unionGroups.forEach(mixGroup=>mixGroup.push(box))
  89377. }
  89378. this.needsUpdate = true
  89379. },
  89380. removeClip(box){
  89381. if(!this.boxes.includes(box)){
  89382. return console.warn('removeClip没有找到该box',box)
  89383. }
  89384. var newGroups = [];
  89385. this.unionGroups.forEach(mixGroup=>{
  89386. if(mixGroup.length == 1 && mixGroup[0] == box)return;//直接删除
  89387. newGroups.push(mixGroup.filter(e=>e!=box));
  89388. })
  89389. this.unionGroups = newGroups;
  89390. this.needsUpdate = true
  89391. }
  89392. ,
  89393. clearClip(){
  89394. this.boxes = [];
  89395. this.unionGroups = []
  89396. this.needsUpdate = true
  89397. }
  89398. ,
  89399. updateShaderParams(){//没写完 - - 见 pointcloud clip.vs
  89400. //uniform mat4 clipBoxes[num_clipboxes];
  89401. //uniform int clipBoxGroupCount;
  89402. //uniform int mixClipIndices[clipboxGroupItemCount]; //把所有的要求都直接放到数组内
  89403. //这里需要转为Float32Array..? 参考material.setClipBoxes
  89404. let everyClipGroupCount = this.unionGroups.map(e=>e.length)
  89405. let mixClipIndices = []
  89406. this.unionGroups.forEach(e=>{
  89407. mixClipIndices.push(...e)
  89408. })
  89409. this.shaderParams = {
  89410. num_clipboxes : this.boxes.length,
  89411. clipBoxGroupCount : this.unionGroups.length,
  89412. everyClipGroupCount,
  89413. clipBoxIndexCount: mixClipIndices.length,
  89414. mixClipIndices
  89415. }
  89416. }
  89417. ,
  89418. getShaderParams(){//每次要传递参数到shader中,执行这个就好
  89419. if(this.needsUpdate){
  89420. this.updateShaderParams()
  89421. }
  89422. return this.shaderParams
  89423. }
  89424. }
  89425. */
  89426. /**
  89427. * @author mschuetz / http://mschuetz.at
  89428. *
  89429. * adapted from THREE.OrbitControls by
  89430. *
  89431. * @author qiao / https://github.com/qiao
  89432. * @author mrdoob / http://mrdoob.com
  89433. * @author alteredq / http://alteredqualia.com/
  89434. * @author WestLangley / http://github.com/WestLangley
  89435. * @author erich666 / http://erichaines.com
  89436. *
  89437. *
  89438. *
  89439. */
  89440. class OrbitControls$1 extends EventDispatcher$1 {
  89441. constructor(viewer) {
  89442. super();
  89443. this.viewer = viewer;
  89444. this.renderer = viewer.renderer;
  89445. this.scene = null;
  89446. this.sceneControls = new Scene();
  89447. this.rotationSpeed = 5;
  89448. this.fadeFactor = 20;
  89449. this.yawDelta = 0;
  89450. this.pitchDelta = 0;
  89451. this.panDelta = new Vector2(0, 0);
  89452. this.radiusDelta = 0;
  89453. this.doubleClockZoomEnabled = true;
  89454. this.tweens = [];
  89455. var drag = e => {
  89456. if (e.drag.object !== null) {
  89457. return;
  89458. }
  89459. if (e.drag.startHandled === undefined) {
  89460. e.drag.startHandled = true;
  89461. this.dispatchEvent({
  89462. type: 'start'
  89463. });
  89464. }
  89465. var ndrag = {
  89466. x: e.drag.lastDrag.x / this.renderer.domElement.clientWidth,
  89467. y: e.drag.lastDrag.y / this.renderer.domElement.clientHeight
  89468. };
  89469. if (e.drag.mouse === MOUSE$1.LEFT) {
  89470. this.yawDelta += ndrag.x * this.rotationSpeed;
  89471. this.pitchDelta += ndrag.y * this.rotationSpeed;
  89472. this.stopTweens();
  89473. } else if (e.drag.mouse === MOUSE$1.RIGHT) {
  89474. this.panDelta.x += ndrag.x;
  89475. this.panDelta.y += ndrag.y;
  89476. this.stopTweens();
  89477. }
  89478. };
  89479. var drop = e => {
  89480. this.dispatchEvent({
  89481. type: 'end'
  89482. });
  89483. };
  89484. var scroll = e => {
  89485. var resolvedRadius = this.scene.view.radius + this.radiusDelta;
  89486. this.radiusDelta += -e.delta * resolvedRadius * 0.1;
  89487. this.stopTweens();
  89488. };
  89489. var dblclick = e => {
  89490. if (this.doubleClockZoomEnabled) {
  89491. this.zoomToLocation(e.mouse);
  89492. }
  89493. };
  89494. var previousTouch = null;
  89495. var touchStart = e => {
  89496. previousTouch = e;
  89497. };
  89498. var touchEnd = e => {
  89499. previousTouch = e;
  89500. };
  89501. var touchMove = e => {
  89502. if (e.touches.length === 2 && previousTouch.touches.length === 2) {
  89503. var prev = previousTouch;
  89504. var curr = e;
  89505. var prevDX = prev.touches[0].pageX - prev.touches[1].pageX;
  89506. var prevDY = prev.touches[0].pageY - prev.touches[1].pageY;
  89507. var prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY);
  89508. var currDX = curr.touches[0].pageX - curr.touches[1].pageX;
  89509. var currDY = curr.touches[0].pageY - curr.touches[1].pageY;
  89510. var currDist = Math.sqrt(currDX * currDX + currDY * currDY);
  89511. var delta = currDist / prevDist;
  89512. var resolvedRadius = this.scene.view.radius + this.radiusDelta;
  89513. var newRadius = resolvedRadius / delta;
  89514. this.radiusDelta = newRadius - resolvedRadius;
  89515. this.stopTweens();
  89516. } else if (e.touches.length === 3 && previousTouch.touches.length === 3) {
  89517. var _prev = previousTouch;
  89518. var _curr = e;
  89519. var prevMeanX = (_prev.touches[0].pageX + _prev.touches[1].pageX + _prev.touches[2].pageX) / 3;
  89520. var prevMeanY = (_prev.touches[0].pageY + _prev.touches[1].pageY + _prev.touches[2].pageY) / 3;
  89521. var currMeanX = (_curr.touches[0].pageX + _curr.touches[1].pageX + _curr.touches[2].pageX) / 3;
  89522. var currMeanY = (_curr.touches[0].pageY + _curr.touches[1].pageY + _curr.touches[2].pageY) / 3;
  89523. var _delta = {
  89524. x: (currMeanX - prevMeanX) / this.renderer.domElement.clientWidth,
  89525. y: (currMeanY - prevMeanY) / this.renderer.domElement.clientHeight
  89526. };
  89527. this.panDelta.x += _delta.x;
  89528. this.panDelta.y += _delta.y;
  89529. this.stopTweens();
  89530. }
  89531. previousTouch = e;
  89532. };
  89533. this.addEventListener('touchstart', touchStart);
  89534. this.addEventListener('touchend', touchEnd);
  89535. this.addEventListener('touchmove', touchMove);
  89536. this.addEventListener('drag', drag);
  89537. this.addEventListener('drop', drop);
  89538. this.addEventListener('mousewheel', scroll);
  89539. this.addEventListener('dblclick', dblclick);
  89540. }
  89541. setScene(scene) {
  89542. this.scene = scene;
  89543. }
  89544. stop() {
  89545. this.yawDelta = 0;
  89546. this.pitchDelta = 0;
  89547. this.radiusDelta = 0;
  89548. this.panDelta.set(0, 0);
  89549. }
  89550. zoomToLocation(mouse) {
  89551. var camera = this.scene.getActiveCamera();
  89552. var I = Utils.getMousePointCloudIntersection(mouse, camera, this.viewer, this.scene.pointclouds, {
  89553. pickClipped: true
  89554. });
  89555. if (I === null) {
  89556. return;
  89557. }
  89558. var targetRadius = 0;
  89559. {
  89560. var minimumJumpDistance = 0.2;
  89561. var domElement = this.renderer.domElement;
  89562. var ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
  89563. var nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  89564. var lastNode = nodes[nodes.length - 1];
  89565. var radius = lastNode.getBoundingSphere(new Sphere()).radius;
  89566. targetRadius = Math.min(this.scene.view.radius, radius);
  89567. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  89568. }
  89569. var d = this.scene.view.direction.multiplyScalar(-1);
  89570. var cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  89571. // TODO Unused: let controlsTargetPosition = I.location;
  89572. var animationDuration = 600;
  89573. var easing = TWEEN.Easing.Quartic.Out;
  89574. {
  89575. // animate
  89576. var value = {
  89577. x: 0
  89578. };
  89579. var tween = new TWEEN.Tween(value).to({
  89580. x: 1
  89581. }, animationDuration);
  89582. tween.easing(easing);
  89583. this.tweens.push(tween);
  89584. var startPos = this.scene.view.position.clone();
  89585. var targetPos = cameraTargetPosition.clone();
  89586. var startRadius = this.scene.view.radius;
  89587. var _targetRadius = cameraTargetPosition.distanceTo(I.location);
  89588. tween.onUpdate(() => {
  89589. var t = value.x;
  89590. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  89591. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  89592. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  89593. this.scene.view.radius = (1 - t) * startRadius + t * _targetRadius;
  89594. this.viewer.setMoveSpeed(this.scene.view.radius);
  89595. });
  89596. tween.onComplete(() => {
  89597. this.tweens = this.tweens.filter(e => e !== tween);
  89598. });
  89599. tween.start();
  89600. }
  89601. }
  89602. stopTweens() {
  89603. this.tweens.forEach(e => e.stop());
  89604. this.tweens = [];
  89605. }
  89606. update(delta) {
  89607. var view = this.scene.view;
  89608. {
  89609. // apply rotation
  89610. var progression = Math.min(1, this.fadeFactor * delta);
  89611. var yaw = view.yaw;
  89612. var pitch = view.pitch;
  89613. var pivot = view.getPivot();
  89614. yaw -= progression * this.yawDelta;
  89615. pitch -= progression * this.pitchDelta;
  89616. view.yaw = yaw;
  89617. view.pitch = pitch;
  89618. var V = this.scene.view.direction.multiplyScalar(-view.radius);
  89619. var position = new Vector3().addVectors(pivot, V);
  89620. view.position.copy(position);
  89621. }
  89622. {
  89623. // apply pan
  89624. var _progression = Math.min(1, this.fadeFactor * delta);
  89625. var panDistance = _progression * view.radius * 3;
  89626. var px = -this.panDelta.x * panDistance;
  89627. var py = this.panDelta.y * panDistance;
  89628. view.pan(px, py);
  89629. }
  89630. {
  89631. // apply zoom
  89632. var _progression2 = Math.min(1, this.fadeFactor * delta);
  89633. // let radius = view.radius + progression * this.radiusDelta * view.radius * 0.1;
  89634. var radius = view.radius + _progression2 * this.radiusDelta;
  89635. var _V = view.direction.multiplyScalar(-radius);
  89636. var _position = new Vector3().addVectors(view.getPivot(), _V);
  89637. view.radius = radius;
  89638. view.position.copy(_position);
  89639. }
  89640. {
  89641. var speed = view.radius;
  89642. this.viewer.setMoveSpeed(speed);
  89643. }
  89644. {
  89645. // decelerate over time
  89646. var _progression3 = Math.min(1, this.fadeFactor * delta);
  89647. var attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  89648. this.yawDelta *= attenuation;
  89649. this.pitchDelta *= attenuation;
  89650. this.panDelta.multiplyScalar(attenuation);
  89651. // this.radiusDelta *= attenuation;
  89652. this.radiusDelta -= _progression3 * this.radiusDelta;
  89653. }
  89654. }
  89655. }
  89656. ;
  89657. /**
  89658. * @author mschuetz / http://mschuetz.at
  89659. *
  89660. * adapted from THREE.OrbitControls by
  89661. *
  89662. * @author qiao / https://github.com/qiao
  89663. * @author mrdoob / http://mrdoob.com
  89664. * @author alteredq / http://alteredqualia.com/
  89665. * @author WestLangley / http://github.com/WestLangley
  89666. * @author erich666 / http://erichaines.com
  89667. *
  89668. *
  89669. *
  89670. */
  89671. class FirstPersonControls$1 extends EventDispatcher$1 {
  89672. //old
  89673. constructor(viewer) {
  89674. super();
  89675. this.viewer = viewer;
  89676. this.renderer = viewer.renderer;
  89677. this.scene = null;
  89678. this.sceneControls = new Scene();
  89679. this.rotationSpeed = 200;
  89680. this.moveSpeed = 10;
  89681. this.lockElevation = false;
  89682. this.keys = {
  89683. FORWARD: ['W'.charCodeAt(0), 38],
  89684. BACKWARD: ['S'.charCodeAt(0), 40],
  89685. LEFT: ['A'.charCodeAt(0), 37],
  89686. RIGHT: ['D'.charCodeAt(0), 39],
  89687. UP: ['R'.charCodeAt(0), 33],
  89688. DOWN: ['F'.charCodeAt(0), 34]
  89689. };
  89690. this.fadeFactor = 50;
  89691. this.yawDelta = 0;
  89692. this.pitchDelta = 0;
  89693. this.translationDelta = new Vector3(0, 0, 0);
  89694. this.translationWorldDelta = new Vector3(0, 0, 0);
  89695. this.tweens = [];
  89696. var drag = e => {
  89697. if (e.drag.object !== null) {
  89698. return;
  89699. }
  89700. if (e.drag.startHandled === undefined) {
  89701. e.drag.startHandled = true;
  89702. this.dispatchEvent({
  89703. type: 'start'
  89704. });
  89705. }
  89706. var moveSpeed = this.viewer.getMoveSpeed();
  89707. var ndrag = {
  89708. x: e.drag.lastDrag.x / this.renderer.domElement.clientWidth,
  89709. y: e.drag.lastDrag.y / this.renderer.domElement.clientHeight
  89710. };
  89711. if (e.drag.mouse === MOUSE$1.LEFT) {
  89712. this.yawDelta += ndrag.x * this.rotationSpeed;
  89713. this.pitchDelta += ndrag.y * this.rotationSpeed;
  89714. } else if (e.drag.mouse === MOUSE$1.RIGHT) {
  89715. this.translationDelta.x -= ndrag.x * moveSpeed * 100;
  89716. this.translationDelta.z += ndrag.y * moveSpeed * 100;
  89717. }
  89718. };
  89719. var drop = e => {
  89720. this.dispatchEvent({
  89721. type: 'end'
  89722. });
  89723. };
  89724. var scroll = e => {
  89725. var speed = this.viewer.getMoveSpeed();
  89726. if (e.delta < 0) {
  89727. speed = speed * 0.9;
  89728. } else if (e.delta > 0) {
  89729. speed = speed / 0.9;
  89730. }
  89731. speed = Math.max(speed, 0.1);
  89732. this.viewer.setMoveSpeed(speed);
  89733. };
  89734. var dblclick = e => {
  89735. this.zoomToLocation(e.mouse);
  89736. };
  89737. this.addEventListener('drag', drag);
  89738. this.addEventListener('drop', drop);
  89739. this.addEventListener('mousewheel', scroll);
  89740. this.addEventListener('dblclick', dblclick);
  89741. }
  89742. setScene(scene) {
  89743. this.scene = scene;
  89744. }
  89745. stop() {
  89746. this.yawDelta = 0;
  89747. this.pitchDelta = 0;
  89748. this.translationDelta.set(0, 0, 0);
  89749. }
  89750. zoomToLocation(mouse) {
  89751. var camera = this.scene.getActiveCamera();
  89752. var I = Utils.getMousePointCloudIntersection(mouse, camera, this.viewer, this.scene.pointclouds);
  89753. if (I === null) {
  89754. return;
  89755. }
  89756. var targetRadius = 0;
  89757. {
  89758. var minimumJumpDistance = 0.2;
  89759. var domElement = this.renderer.domElement;
  89760. var ray = Utils.mouseToRay(mouse, camera, domElement.clientWidth, domElement.clientHeight);
  89761. var nodes = I.pointcloud.nodesOnRay(I.pointcloud.visibleNodes, ray);
  89762. var lastNode = nodes[nodes.length - 1];
  89763. var radius = lastNode.getBoundingSphere(new Sphere()).radius;
  89764. targetRadius = Math.min(this.scene.view.radius, radius);
  89765. targetRadius = Math.max(minimumJumpDistance, targetRadius);
  89766. }
  89767. var d = this.scene.view.direction.multiplyScalar(-1);
  89768. var cameraTargetPosition = new Vector3().addVectors(I.location, d.multiplyScalar(targetRadius));
  89769. // TODO Unused: let controlsTargetPosition = I.location;
  89770. var animationDuration = 600;
  89771. var easing = TWEEN.Easing.Quartic.Out;
  89772. {
  89773. // animate
  89774. var value = {
  89775. x: 0
  89776. };
  89777. var tween = new TWEEN.Tween(value).to({
  89778. x: 1
  89779. }, animationDuration);
  89780. tween.easing(easing);
  89781. this.tweens.push(tween);
  89782. var startPos = this.scene.view.position.clone();
  89783. var targetPos = cameraTargetPosition.clone();
  89784. var startRadius = this.scene.view.radius;
  89785. var _targetRadius = cameraTargetPosition.distanceTo(I.location);
  89786. tween.onUpdate(() => {
  89787. var t = value.x;
  89788. this.scene.view.position.x = (1 - t) * startPos.x + t * targetPos.x;
  89789. this.scene.view.position.y = (1 - t) * startPos.y + t * targetPos.y;
  89790. this.scene.view.position.z = (1 - t) * startPos.z + t * targetPos.z;
  89791. this.scene.view.radius = (1 - t) * startRadius + t * _targetRadius;
  89792. this.viewer.setMoveSpeed(this.scene.view.radius / 2.5);
  89793. });
  89794. tween.onComplete(() => {
  89795. this.tweens = this.tweens.filter(e => e !== tween);
  89796. });
  89797. tween.start();
  89798. }
  89799. }
  89800. update(delta) {
  89801. var view = this.scene.view;
  89802. {
  89803. // cancel move animations on user input
  89804. var changes = [this.yawDelta, this.pitchDelta, this.translationDelta.length(), this.translationWorldDelta.length()];
  89805. var changeHappens = changes.some(e => Math.abs(e) > 0.001);
  89806. if (changeHappens && this.tweens.length > 0) {
  89807. this.tweens.forEach(e => e.stop());
  89808. this.tweens = [];
  89809. }
  89810. }
  89811. {
  89812. // accelerate while input is given
  89813. var ih = this.viewer.inputHandler;
  89814. var moveForward = this.keys.FORWARD.some(e => ih.pressedKeys[e]);
  89815. var moveBackward = this.keys.BACKWARD.some(e => ih.pressedKeys[e]);
  89816. var moveLeft = this.keys.LEFT.some(e => ih.pressedKeys[e]);
  89817. var moveRight = this.keys.RIGHT.some(e => ih.pressedKeys[e]);
  89818. var moveUp = this.keys.UP.some(e => ih.pressedKeys[e]);
  89819. var moveDown = this.keys.DOWN.some(e => ih.pressedKeys[e]);
  89820. if (this.lockElevation) {
  89821. var dir = view.direction;
  89822. dir.z = 0;
  89823. dir.normalize();
  89824. if (moveForward && moveBackward) {
  89825. this.translationWorldDelta.set(0, 0, 0);
  89826. } else if (moveForward) {
  89827. this.translationWorldDelta.copy(dir.multiplyScalar(this.viewer.getMoveSpeed()));
  89828. } else if (moveBackward) {
  89829. this.translationWorldDelta.copy(dir.multiplyScalar(-this.viewer.getMoveSpeed()));
  89830. }
  89831. } else {
  89832. if (moveForward && moveBackward) {
  89833. this.translationDelta.y = 0;
  89834. } else if (moveForward) {
  89835. this.translationDelta.y = this.viewer.getMoveSpeed();
  89836. } else if (moveBackward) {
  89837. this.translationDelta.y = -this.viewer.getMoveSpeed();
  89838. }
  89839. }
  89840. if (moveLeft && moveRight) {
  89841. this.translationDelta.x = 0;
  89842. } else if (moveLeft) {
  89843. this.translationDelta.x = -this.viewer.getMoveSpeed();
  89844. } else if (moveRight) {
  89845. this.translationDelta.x = this.viewer.getMoveSpeed();
  89846. }
  89847. if (moveUp && moveDown) {
  89848. this.translationWorldDelta.z = 0;
  89849. } else if (moveUp) {
  89850. this.translationWorldDelta.z = this.viewer.getMoveSpeed();
  89851. } else if (moveDown) {
  89852. this.translationWorldDelta.z = -this.viewer.getMoveSpeed();
  89853. }
  89854. }
  89855. {
  89856. // apply rotation
  89857. var yaw = view.yaw;
  89858. var pitch = view.pitch;
  89859. yaw -= this.yawDelta * delta;
  89860. pitch -= this.pitchDelta * delta;
  89861. view.yaw = yaw;
  89862. view.pitch = pitch;
  89863. }
  89864. {
  89865. // apply translation
  89866. view.translate(this.translationDelta.x * delta, this.translationDelta.y * delta, this.translationDelta.z * delta);
  89867. view.translateWorld(this.translationWorldDelta.x * delta, this.translationWorldDelta.y * delta, this.translationWorldDelta.z * delta);
  89868. }
  89869. {
  89870. // set view target according to speed
  89871. view.radius = 3 * this.viewer.getMoveSpeed();
  89872. }
  89873. {
  89874. // decelerate over time
  89875. var attenuation = Math.max(0, 1 - this.fadeFactor * delta);
  89876. this.yawDelta *= attenuation;
  89877. this.pitchDelta *= attenuation;
  89878. this.translationDelta.multiplyScalar(attenuation);
  89879. this.translationWorldDelta.multiplyScalar(attenuation);
  89880. }
  89881. }
  89882. }
  89883. ;
  89884. OrthographicCamera.prototype.zoomTo = function (node) {
  89885. var factor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  89886. if (!node.geometry && !node.boundingBox) {
  89887. return;
  89888. }
  89889. // TODO
  89890. //let minWS = new THREE.Vector4(node.boundingBox.min.x, node.boundingBox.min.y, node.boundingBox.min.z, 1);
  89891. //let minVS = minWS.applyMatrix4(this.matrixWorldInverse);
  89892. //let right = node.boundingBox.max.x;
  89893. //let bottom = node.boundingBox.min.y;
  89894. //let top = node.boundingBox.max.y;
  89895. this.updateProjectionMatrix();
  89896. };
  89897. PerspectiveCamera.prototype.zoomTo = function (node, factor) {
  89898. if (!node.geometry && !node.boundingSphere && !node.boundingBox) {
  89899. return;
  89900. }
  89901. if (node.geometry && node.geometry.boundingSphere === null) {
  89902. node.geometry.computeBoundingSphere();
  89903. }
  89904. node.updateMatrixWorld();
  89905. var bs;
  89906. if (node.boundingSphere) {
  89907. bs = node.boundingSphere;
  89908. } else if (node.geometry && node.geometry.boundingSphere) {
  89909. bs = node.geometry.boundingSphere;
  89910. } else {
  89911. bs = node.boundingBox.getBoundingSphere(new Sphere());
  89912. }
  89913. var _factor = factor || 1;
  89914. bs = bs.clone().applyMatrix4(node.matrixWorld);
  89915. var radius = bs.radius;
  89916. var fovr = this.fov * Math.PI / 180;
  89917. if (this.aspect < 1) {
  89918. fovr = fovr * this.aspect;
  89919. }
  89920. var distanceFactor = Math.abs(radius / Math.sin(fovr / 2)) * _factor;
  89921. var offset = this.getWorldDirection(new Vector3()).multiplyScalar(-distanceFactor);
  89922. this.position.copy(bs.center.clone().add(offset));
  89923. };
  89924. Ray.prototype.distanceToPlaneWithNegative = function (plane) {
  89925. var denominator = plane.normal.dot(this.direction);
  89926. if (denominator === 0) {
  89927. // line is coplanar, return origin
  89928. if (plane.distanceToPoint(this.origin) === 0) {
  89929. return 0;
  89930. }
  89931. // Null is preferable to undefined since undefined means.... it is undefined
  89932. return null;
  89933. }
  89934. var t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
  89935. return t;
  89936. };
  89937. //export * from "./Potree_update_visibility.js"; //因加载顺序问题,该文件直接在shim中重写
  89938. var workerPool = new WorkerPool();
  89939. var version = {
  89940. major: 1,
  89941. minor: 8,
  89942. suffix: '.0'
  89943. };
  89944. var lru = new LRU();
  89945. console.log('Potree ' + version.major + '.' + version.minor + version.suffix);
  89946. var pointBudget = 1 * 1000 * 1000;
  89947. var framenumber = 0;
  89948. var numNodesLoading = 0;
  89949. var maxNodesLoading = 6; //4;
  89950. var debug = {};
  89951. exports.scriptPath = "";
  89952. if (document.currentScript && document.currentScript.src) {
  89953. exports.scriptPath = new URL(document.currentScript.src + '/..').href;
  89954. if (exports.scriptPath.slice(-1) === '/') {
  89955. exports.scriptPath = exports.scriptPath.slice(0, -1);
  89956. }
  89957. } 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)) })) {
  89958. 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;
  89959. if (exports.scriptPath.slice(-1) === '/') {
  89960. exports.scriptPath = exports.scriptPath.slice(0, -1);
  89961. }
  89962. } else {
  89963. 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?');
  89964. }
  89965. var resourcePath = exports.scriptPath + '/resources';
  89966. //add:
  89967. async function loadFile(path, params, callback, onError) {
  89968. params = params || {};
  89969. var fetchMethod = params.fetchMethod || 'get';
  89970. delete params.fetchMethod;
  89971. if (Potree.fileServer) {
  89972. Potree.fileServer[fetchMethod](path, {
  89973. params
  89974. }).then(data => {
  89975. if (data.data) data = data.data;
  89976. if (data.data) data = data.data; //融合页面getdataset需要查找两次data
  89977. callback && callback(data);
  89978. }).catch(onError);
  89979. } else {
  89980. try {
  89981. if (Object.keys(params).length > 0) {
  89982. path += '?';
  89983. var index = 0;
  89984. for (var i in params) {
  89985. if (index > 0) path += '&';
  89986. path += i;
  89987. path += '=';
  89988. path += params[i];
  89989. index++;
  89990. }
  89991. }
  89992. var info = {};
  89993. if (fetchMethod == 'post') info.method = 'POST';
  89994. if (Potree.fileStorage) {
  89995. //本地直接获取
  89996. Potree.fileStorage.get(path).then(data => {
  89997. if (data.data) data = data.data;
  89998. if (data.data) data = data.data; //融合页面getdataset需要查找两次data
  89999. callback && callback(data);
  90000. }).catch(onError);
  90001. } else {
  90002. var response = await fetch(path, info);
  90003. if (!response.ok) {
  90004. console.log('loadFile失败', path);
  90005. return onError && onError();
  90006. }
  90007. var text = await response.text();
  90008. var data = params.returnText ? text : JSON.parse(text);
  90009. if (data.data) data = data.data;
  90010. callback && callback(data);
  90011. return data;
  90012. }
  90013. } catch (e) {
  90014. console.log('loadFile出错', e);
  90015. onError && onError(e);
  90016. }
  90017. }
  90018. //查询: http://192.168.0.26:8080/doc.html#/default/filter-%E6%BC%AB%E6%B8%B8%E7%82%B9/filterUsingGET
  90019. }
  90020. async function loadDatasets(callback, sceneCode, onError, prefix) {
  90021. //之后直接把path写进来
  90022. var path;
  90023. sceneCode = sceneCode || Potree.settings.number;
  90024. if (Potree.fileServer) {
  90025. path = "/laser/dataset/".concat(sceneCode, "/getDataSet");
  90026. } else {
  90027. //path = `${Potree.settings.urls.prefix2}/indoor/${Potree.settings.number}/api/datasets`
  90028. //现在只能加载得了本地的了
  90029. path = "".concat(prefix || Potree.settings.urls.prefix, "/laser/dataset/").concat(sceneCode, "/getDataSet");
  90030. //path = `${Potree.scriptPath}/data/${sceneCode}/getDataSet.json`
  90031. }
  90032. return loadFile(path, null, callback, onError);
  90033. }
  90034. function loadNeighborFile() {
  90035. if (Potree.config.neighbourPath) {
  90036. var path = "".concat(Potree.scriptPath, "/").concat(Potree.config.neighbourPath);
  90037. loadFile(path, null, data => {
  90038. Potree.extraNeighbours = data;
  90039. var _loop = function _loop(datasetid) {
  90040. var pointcloud = viewer.scene.pointclouds.find(e => e.dataset_id == datasetid);
  90041. var types = ['enable', 'unable'];
  90042. types.forEach(type => {
  90043. if (!data[datasetid][type]) return;
  90044. var _loop2 = function _loop2(id1) {
  90045. data[datasetid][type][id1].forEach(id2 => {
  90046. var pano2,
  90047. sid = id2;
  90048. if (!id2.includes('|')) {
  90049. sid = datasetid + '|' + id2;
  90050. }
  90051. Potree.setExtraNeighbour(datasetid + '|' + id1, sid, type, {
  90052. dontWrite: true
  90053. });
  90054. });
  90055. };
  90056. for (var id1 in data[datasetid][type]) {
  90057. _loop2(id1);
  90058. }
  90059. });
  90060. };
  90061. for (var datasetid in data) {
  90062. _loop(datasetid);
  90063. }
  90064. });
  90065. }
  90066. }
  90067. /*
  90068. Potree.setExtraNeighbour('1765955963253690368|90','1768872851646451713|7', 'enable' )
  90069. JSON.stringify(Potree.extraNeighbours)
  90070. */
  90071. function setExtraNeighbour(sid1, sid2, type) {
  90072. var {
  90073. dontWrite
  90074. } = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  90075. if (!Potree.extraNeighbours) Potree.extraNeighbours = {};
  90076. (() => {
  90077. if (!dontWrite) {
  90078. if (sid1 > sid2) {
  90079. //顺序固定一下要不然两边都要写
  90080. var temp = sid1; //对调
  90081. sid1 = sid2;
  90082. sid2 = temp;
  90083. }
  90084. var id1 = sid1.split('|')[1],
  90085. id2,
  90086. object;
  90087. object = Potree.extraNeighbours[sid1.split('|')[0]];
  90088. if (!object) {
  90089. if (type == 'clear') return;
  90090. object = Potree.extraNeighbours[sid1.split('|')[0]] = {};
  90091. }
  90092. if (type != 'clear') {
  90093. if (!object[type]) {
  90094. object[type] = {};
  90095. }
  90096. if (!object[type][id1]) {
  90097. object[type][id1] = [];
  90098. }
  90099. }
  90100. if (sid1.split('|')[0] == sid2.split('|')[0]) {
  90101. id2 = sid2.split('|')[1];
  90102. } else {
  90103. id2 = sid2;
  90104. }
  90105. var remove = type_ => {
  90106. if (object[type_] && object[type_][id1]) {
  90107. var index = object[type_][id1].indexOf(id2);
  90108. index > -1 && object[type_][id1].splice(index, 1);
  90109. }
  90110. };
  90111. if (type != 'clear') {
  90112. if (!object[type][id1].includes(id2)) {
  90113. object[type][id1].push(id2);
  90114. }
  90115. } else {
  90116. remove('unable');
  90117. }
  90118. var anotherType = type == 'enable' ? 'unable' : 'enable';
  90119. remove(anotherType);
  90120. }
  90121. })();
  90122. var pano1 = viewer.images360.getPano(sid1, 'sid'),
  90123. pano2 = viewer.images360.getPano(sid2, 'sid');
  90124. if (type == 'enable') {
  90125. viewer.images360.neighbourMap[pano1.id][pano2.id] = 1; //用0和1 表示是在此被强制修改的
  90126. viewer.images360.neighbourMap[pano2.id][pano1.id] = 1;
  90127. pano1.neighbours.push(pano2);
  90128. pano2.neighbours.push(pano1);
  90129. } else {
  90130. if (type == 'clear') {
  90131. viewer.images360.neighbourMap[pano1.id][pano2.id] = undefined;
  90132. viewer.images360.neighbourMap[pano2.id][pano1.id] = undefined;
  90133. } else {
  90134. viewer.images360.neighbourMap[pano1.id][pano2.id] = 0;
  90135. viewer.images360.neighbourMap[pano2.id][pano1.id] = 0;
  90136. }
  90137. var index = pano1.neighbours.indexOf(pano2);
  90138. index > -1 && pano1.neighbours.splice(index, 1);
  90139. index = pano2.neighbours.indexOf(pano1);
  90140. index > -1 && pano2.neighbours.splice(index, 1);
  90141. }
  90142. }
  90143. /* 开启漫游点通行的强制设置: 在浏览器中加入后缀 &neighGui,如 http://127.0.0.1:5002/offline.html?m=1829339452406239232&neighGui#/
  90144. 开启后面板右侧会出现一列按钮。 在需要更改连通性的两个漫游点点击第一个按钮,就能选中点位。然后点击第二个按钮可以强行连接漫游点,使原本无法通行的两个漫游点可以互相通行;
  90145. 类似的,第三个按钮则是强行断开漫游点,使原本可以通行的两个漫游点无法通行。 第四个按钮则用于取消设置。点击第五个按钮可以导出设置好的数据在剪贴板里,直接粘贴到extraNeighbours.js里保存, 该文件在离线包的 www\static\lib\potree里。下次刷新场景设置就生效了。
  90146. 注意:settings中neighbourPath需要设置才会读取extraNeighbours.js。 如果新的离线包也需要设置的话就先创建一个空的extraNeighbours.js
  90147. Enable Roaming Point Passage Forced Settings:
  90148. Add the suffix &neighGui to the URL in the browser, for example:http://127.0.0.1:5002/offline.html?m=1829339452406239232&neighGui#/
  90149. 󠁪After enabling, a column of buttons will appear on the right side of the backend panel.
  90150. To change the connectivity between two roaming points, click the first button on both points to select them. Then, click the second button to forcibly connect the roaming points, allowing two originally unconnected roaming points to become interconnected.Similarly, the third button forcibly disconnects the roaming points, preventing two originally connected roaming points from being accessible to each other.The fourth button is used to cancel the settings.
  90151. Clicking the fifth button exports the configured data to the clipboard. You can directly paste this data into extraNeighbours.js located in the offline package's www\static\lib\potree directory. The settings will take effect the next time you refresh the scene.
  90152. */
  90153. function setNeighborGui() {
  90154. //&neighGui
  90155. if (!Potree.settings.showNeighSetGui) return;
  90156. var button1 = $('<button style="bottom:70%; background:#fff;">Select current roaming point</button>');
  90157. var button2 = $('<button style="bottom:60%; background:#0F4;">Make the two points absolutely connected</button>');
  90158. var button3 = $('<button style="bottom:50%; background:#766;">Make the two points absolutely disconnected</button>');
  90159. var button4 = $('<button style="bottom:40%; background:#ffffff4d;">Clear the connection state of these two points</button>');
  90160. var button5 = $('<button style="bottom:30%; background:#cacfff;">Copy Connections data </button>');
  90161. [button1, button2, button3, button4, button5].forEach(button => {
  90162. button.css({
  90163. right: '4px',
  90164. 'z-index': 100,
  90165. position: 'absolute',
  90166. width: '130px',
  90167. padding: '4px',
  90168. 'border-radius': '6px',
  90169. color: '#222'
  90170. });
  90171. viewer.renderer.domElement.parentElement.appendChild(button[0]);
  90172. });
  90173. var bgColor = {
  90174. normal: {
  90175. r: 0,
  90176. g: 0,
  90177. b: 0,
  90178. a: 0.4
  90179. },
  90180. connected: {
  90181. r: 0,
  90182. g: 240,
  90183. b: 100,
  90184. a: 0.6
  90185. },
  90186. disconnected: {
  90187. r: 130,
  90188. g: 120,
  90189. b: 120,
  90190. a: 0.6
  90191. }
  90192. };
  90193. var createLabel = () => {
  90194. var panoLabel = new Potree.TextSprite({
  90195. sizeInfo: {
  90196. minSize: 40,
  90197. maxSize: 150,
  90198. nearBound: 1,
  90199. farBound: 50
  90200. },
  90201. backgroundColor: bgColor.normal,
  90202. textColor: {
  90203. r: 255,
  90204. g: 255,
  90205. b: 255,
  90206. a: 1
  90207. },
  90208. margin: {
  90209. x: 20,
  90210. y: 14
  90211. },
  90212. fontsize: 20,
  90213. borderRadius: 20,
  90214. renderOrder: 10,
  90215. depthTest: false,
  90216. text: 'default'
  90217. });
  90218. viewer.images360.node.add(panoLabel);
  90219. panoLabel.visible = false;
  90220. Potree.Utils.setObjectLayers(panoLabel, 'bothMapAndScene');
  90221. return panoLabel;
  90222. };
  90223. var panoLabels = [createLabel(), createLabel()];
  90224. var panoSelected = [];
  90225. var updateButton = () => {
  90226. if (panoSelected.length == 2) {
  90227. button2.show();
  90228. button3.show();
  90229. button4.show();
  90230. } else {
  90231. button2.hide();
  90232. button3.hide();
  90233. button4.hide();
  90234. }
  90235. };
  90236. var updateLabel = () => {
  90237. var i = 0;
  90238. var connectState;
  90239. if (panoSelected.length == 2) {
  90240. connectState = viewer.images360.neighbourMap[panoSelected[0].id][panoSelected[1].id];
  90241. }
  90242. while (i < 2) {
  90243. if (panoSelected[i]) {
  90244. panoLabels[i].visible = true;
  90245. panoLabels[i].position.copy(panoSelected[i].position);
  90246. panoLabels[i].position.z -= 0.5;
  90247. var text = ['SID of current point:', panoSelected[i].sid];
  90248. if (connectState === 1) {
  90249. text.push('Already absolutely connected to:', panoSelected[(i + 1) % 2].sid);
  90250. panoLabels[i].setBackgroundColor(bgColor.connected);
  90251. } else if (connectState === 0) {
  90252. text.push('Already absolutely disconnected to:', panoSelected[(i + 1) % 2].sid);
  90253. panoLabels[i].setBackgroundColor(bgColor.disconnected);
  90254. } else {
  90255. panoLabels[i].setBackgroundColor(bgColor.normal);
  90256. }
  90257. panoLabels[i].setText(text);
  90258. } else {
  90259. panoLabels[i].visible = false;
  90260. }
  90261. i++;
  90262. }
  90263. viewer.dispatchEvent('content_changed');
  90264. viewer.mapViewer.dispatchEvent('content_changed');
  90265. };
  90266. button1.on('click', e => {
  90267. if (!viewer.images360.isAtPano()) return alert('Please walk to the roaming point before clicking');
  90268. if (panoSelected.includes(viewer.images360.currentPano)) return;
  90269. if (panoSelected.length == 2) {
  90270. panoSelected.splice(0, 1);
  90271. }
  90272. panoSelected.push(viewer.images360.currentPano);
  90273. updateLabel();
  90274. updateButton();
  90275. });
  90276. button2.on('click', e => {
  90277. Potree.setExtraNeighbour(panoSelected[0].sid, panoSelected[1].sid, 'enable');
  90278. updateLabel();
  90279. });
  90280. button3.on('click', e => {
  90281. Potree.setExtraNeighbour(panoSelected[0].sid, panoSelected[1].sid, 'unable');
  90282. updateLabel();
  90283. });
  90284. button4.on('click', e => {
  90285. Potree.setExtraNeighbour(panoSelected[0].sid, panoSelected[1].sid, 'clear');
  90286. updateLabel();
  90287. });
  90288. button5.on('click', e => {
  90289. navigator.clipboard.writeText(JSON.stringify(Potree.extraNeighbours || {}));
  90290. });
  90291. updateButton();
  90292. updateLabel();
  90293. }
  90294. //目前上传平面图后如果不点击保存按钮,数据还是旧的不生效
  90295. async function loadMapEntity(datasetId, force) {
  90296. if (!Potree.settings.floorplanEnable && !force && (Potree.fileServer || Potree.fileStorage)) return; /* 等待平面图类型定义好会加载 */
  90297. var loaded = 0;
  90298. var needLoads = datasetId == 'all' ? viewer.scene.pointclouds.map(e => e.dataset_id) : [datasetId];
  90299. var callback = (dataset_id, floorplanType, data) => {
  90300. if (!data || data.length == 0) return console.log('平面图没有数据', dataset_id, floorplanType);
  90301. //要防止旧的比新的先获取到导致覆盖新的,因为两种type随时可能切换
  90302. if (floorplanType != Potree.settings.floorplanType[dataset_id]) return; //如果请求的floorplanType不是当前最新的floorplanType就返回
  90303. var map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'floorplan_' + dataset_id);
  90304. if (map) {
  90305. viewer.mapViewer.mapLayer.removeMap(map);
  90306. }
  90307. var mapNew = viewer.mapViewer.mapLayer.addMapEntity(data.data || data, dataset_id);
  90308. if (map) {
  90309. mapNew.visibleReasons = map.visibleReasons;
  90310. mapNew.unvisibleReasons = map.unvisibleReasons;
  90311. }
  90312. loaded++;
  90313. };
  90314. needLoads.forEach(dataset_id => {
  90315. var floorplanType = Potree.settings.floorplanType[dataset_id],
  90316. prefix = '';
  90317. if (!Potree.fileServer) {
  90318. prefix = Potree.settings.urls.prefix;
  90319. }
  90320. if (!floorplanType) return;
  90321. var path;
  90322. /* if(Potree.fileServer){
  90323. path = `/laser/tiledMap/${Potree.settings.number}/tiledMap/${floorplanType}/${dataset_id}`
  90324. }else{
  90325. path = `${Potree.settings.urls.prefix2}/indoor/${Potree.settings.number}/api/tiled_maps`
  90326. } */
  90327. path = "".concat(prefix, "/laser/tiledMap/").concat(Potree.settings.number, "/tiledMap/").concat(floorplanType, "/").concat(dataset_id);
  90328. Potree.settings.floorplanRequests[dataset_id] = true; //开始加载了
  90329. return loadFile(path, null, callback.bind(this, dataset_id, floorplanType));
  90330. });
  90331. }
  90332. async function loadPanos(datasetId, callback, number) {
  90333. var path;
  90334. number = number || Potree.settings.number;
  90335. //let query = `?datasetId=${datasetId}` //`?lat=${center.lat}&lon=${center.lon}&radius=200000`
  90336. if (Potree.fileServer && !Potree.settings.mergeType) {
  90337. path = "/laser/filter/".concat(number, "/query");
  90338. } /* else if(Potree.settings.mergeType2){ //每个场景只加载初始数据集
  90339. path = `${Potree.settings.urls.prefix}/laser/filter/${number}/query`
  90340. } */else {
  90341. path = "".concat(Potree.settings.urls.prefix, "/laser/filter/").concat(number, "/query");
  90342. }
  90343. return loadFile(path, {
  90344. datasetId: datasetId
  90345. }, callback);
  90346. }
  90347. async function loadPanosInfo(callback) {
  90348. var path;
  90349. if (Potree.fileServer) {} else {
  90350. path = "".concat(Potree.scriptPath, "/data/panoEdit/vision_edit.txt");
  90351. }
  90352. return loadFile(path, null, callback);
  90353. }
  90354. function load4dkkPanos(sceneCode, model, defaultRotation, done, tileRes) {
  90355. //加载四维看看的漫游点并转换
  90356. model.is4dkkModel = true;
  90357. model.panos = [];
  90358. //模拟点云,需要rotX(90)+平移一段才能和四维看看的bound一样
  90359. var rot1M = new THREE.Matrix4().makeRotationFromEuler(defaultRotation);
  90360. var pos1 = new THREE.Vector3();
  90361. if (model.fileType == '3dTiles') {
  90362. pos1.fromArray(model.runtime.getTileset().tileset.root.boundingVolume.box.slice(0, 3)); //必须要平移一段才能重合
  90363. pos1.copy(Potree.math.convertVector.ZupToYup(pos1));
  90364. //rot1M.makeRotationX(Math.PI/2);
  90365. }
  90366. var pos1M = new THREE.Matrix4().setPosition(pos1);
  90367. model.posRot1MatrixInvert = new THREE.Matrix4().multiplyMatrices(pos1M, rot1M).invert();
  90368. model.rot1MatrixInvert = rot1M.clone().invert();
  90369. model.transformMatrix = new THREE.Matrix4();
  90370. model.rotateMatrix = new THREE.Matrix4();
  90371. model.transformInvMatrix = new THREE.Matrix4();
  90372. model.rotateInvMatrix = new THREE.Matrix4();
  90373. model.datasetData = {
  90374. sceneVersion: 'V4',
  90375. mapping: model.props.raw.mapping
  90376. };
  90377. model.tileRes = tileRes;
  90378. model.bound = new THREE.Box3();
  90379. var path;
  90380. if (sceneCode.includes('/')) {
  90381. path = sceneCode;
  90382. } else {
  90383. var prefix = Potree.settings.urls.getPrefix(8, model) || 'https://4dkk.4dage.com';
  90384. //path = `${prefix}/swkk/${sceneCode}/wwwroot/scene_view_data/${sceneCode}/images/vision.txt`
  90385. if (Potree.settings.urls.templates.vision) {
  90386. path = prefix + Potree.Common.replaceAll(Potree.settings.urls.templates.vision, '{sceneCode}', sceneCode);
  90387. } else {
  90388. path = "".concat(prefix, "/scene_view_data/").concat(sceneCode, "/images/vision.txt");
  90389. }
  90390. }
  90391. model.sceneCode = sceneCode;
  90392. loadFile(path, {}, data => {
  90393. var panoData = data.sweepLocations.map(e => {
  90394. var qua = e.pose.rotation;
  90395. return {
  90396. file_id: e.uuid,
  90397. dataset_location: new THREE.Vector3().copy(e.pose.translation).toArray(),
  90398. dataset_floor_location: new THREE.Vector3().copy(e.puck).toArray(),
  90399. dataset_orientation: [qua.w, qua.x, qua.y, qua.z]
  90400. };
  90401. });
  90402. viewer.images360.addPanoData(panoData, model);
  90403. viewer.images360.loadDone();
  90404. viewer.scene.add360Images(viewer.images360);
  90405. {
  90406. //neighbourMap全部填满,否则之后会被修改
  90407. data.sweepLocations.forEach(pano1Data => {
  90408. var pano1 = model.panos.find(e => e.originID == pano1Data.uuid);
  90409. model.panos.forEach((pano2, i) => {
  90410. if (pano1 == pano2) return;
  90411. var v = pano1Data.visibles.includes(i);
  90412. viewer.images360.neighbourMap[pano1.id][pano2.id] = v;
  90413. viewer.images360.neighbourMap[pano2.id][pano1.id] = v;
  90414. if (v) {
  90415. pano1.neighbours.includes(pano2) || pano1.neighbours.push(pano2);
  90416. pano2.neighbours.includes(pano1) || pano2.neighbours.push(pano1);
  90417. }
  90418. });
  90419. });
  90420. }
  90421. viewer.modules.MergeEditor.modelTransformCallback(model, true); //初始化pano的pose
  90422. done && done();
  90423. });
  90424. /* neighbours: e.visibles3 || e.visibles,
  90425. noBlocks: e.visibles2,
  90426. seeMarkers: e.visibles, */
  90427. }
  90428. async function loadImgVersion(callback) {
  90429. if (Potree.settings.isLocal || !Potree.settings.isOfficial) {
  90430. //potree本地请求不到
  90431. return callback({});
  90432. }
  90433. var path;
  90434. path = "/laser/init/getSceneNumVersion/".concat(Potree.settings.number);
  90435. return loadFile(path, {
  90436. fetchMethod: 'post'
  90437. }, callback, callback);
  90438. }
  90439. function setLonlat(lon, lat) {
  90440. var lonlat = [lon, lat];
  90441. if (window.AMapWith84 && Potree.settings.mapCompany != 'google') {
  90442. //需要转换为高德的,但该函数不准确,转入后再转出,和原来的有偏差. navvis的我看data中存的globalLocation直接输入到高德地图后的定位和其要展示的定位一致,而我们要转为高德后才一致,猜测是navvis后台转为了高德可用的经纬度。 若不转的话,其他看起来没问题,仅高德地图定位不准确,因其为被加密后的火星坐标系。
  90443. lonlat = AMapWith84.wgs84ToAMap({
  90444. x: lon,
  90445. y: lat
  90446. });
  90447. lonlat = [lonlat.x, lonlat.y];
  90448. }
  90449. proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
  90450. if (Potree.settings.showMap3d) {
  90451. //Web Mercator(全球矩形,高纬度地区面积变形极大)
  90452. proj4.defs("LOCAL_orgin", "+proj=merc +a=6378137 +b=6378137 +lat_ts=" + lonlat[1] + " +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs");
  90453. var xyOnMap = proj4("WGS84", "LOCAL_orgin", lonlat.slice()); //偏移,使原点在lonlat处。
  90454. //以lonlat为中心点的全球矩形
  90455. proj4.defs("LOCAL", "+proj=merc +a=6378137 +b=6378137 +lat_ts=" + lonlat[1] + " +lon_0=" + lonlat[0] + " +x_0=0 +y_0=" + -xyOnMap[1] + " +k=1 +units=m +nadgrids=@null +wktext +no_defs");
  90456. //lat_ts:在此纬度上无比例失真 问题:为什么地图y不会以该新原点居中,南北极依然在两端,范围没变,似乎只是把整体往下偏移。看不出比例在中心纬度是1:1 -.-
  90457. } else {
  90458. //横轴墨卡托投影(远离中央的区域变形严重,边缘弯曲。 优点似乎是xy向缩放比例一样,更适用局部地图,但因非绝对矩形不太适合在web显示)
  90459. proj4.defs("LOCAL", "+proj=tmerc +ellps=WGS84 +lon_0=" + lonlat[0].toPrecision(15) + " +lat_0=" + lonlat[1].toPrecision(15)); //高德坐标系
  90460. }
  90461. var transform1 = proj4("WGS84", "LOCAL"); //这个ok 是展开的平面投影 LOCAL即NAVVIS:TMERC
  90462. var transform2 = proj4("+proj=tmerc +lat_0=0 +lon_0=123 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs;");
  90463. //注:转入后再转出,和原来的有偏差。如果输入是local坐标,数字越大偏差越大,当百万时就明显了。如果是lonlat,很奇怪经度小于50时就乱了。
  90464. viewer.transform = {
  90465. lonlatToLocal: transform1,
  90466. lonlatTo4550: transform2 // 转大地坐标EPSG:4550
  90467. };
  90468. if (window.transform) {
  90469. viewer.transform.lonlatToLocal = window.transform.lonlatToLocal;
  90470. }
  90471. Potree.Log("setLonlat ".concat(lon, ", ").concat(lat), {
  90472. font: {
  90473. color: "#f49",
  90474. fontSize: 13
  90475. }
  90476. });
  90477. if (window.AMapWith84 && Potree.settings.mapCompany != 'google') {
  90478. //需要转换, 因本地高德用的lonlat和数据里的84不一样. (google地图在国内也用的高德,国外84)
  90479. var change = transform => {
  90480. var forward = transform.forward;
  90481. var inverse = transform.inverse;
  90482. transform.forward = function (e, not84) {
  90483. var needTran = e.x == void 0;
  90484. if (needTran) var a1 = {
  90485. x: e[0],
  90486. y: e[1]
  90487. };else var a1 = e;
  90488. var a = not84 ? a1 : AMapWith84.wgs84ToAMap(a1);
  90489. if (needTran) {
  90490. a = [a.x, a.y];
  90491. e[2] != void 0 && (a[2] = e[2]);
  90492. } else {
  90493. e.z != void 0 && (a.z = e.z);
  90494. }
  90495. return forward(a);
  90496. };
  90497. transform.inverse = function (e, not84) {
  90498. var needTran = e.x == void 0;
  90499. var a = inverse(e);
  90500. needTran && (a = {
  90501. x: a[0],
  90502. y: a[1]
  90503. });
  90504. a = not84 ? a : AMapWith84.aMapToWgs84(a);
  90505. if (needTran) {
  90506. a = [a.x, a.y];
  90507. e[2] != void 0 && (a[2] = e[2]);
  90508. } else {
  90509. e.z != void 0 && (a.z = e.z);
  90510. }
  90511. return a;
  90512. };
  90513. };
  90514. for (var f in viewer.transform) {
  90515. change(viewer.transform[f]);
  90516. }
  90517. //注意:把几万米转成经纬度再转回来差值会很大
  90518. }
  90519. viewer.dispatchEvent('setLonlat');
  90520. }
  90521. //site_model
  90522. /* {
  90523. "area": 2503.30551910935,
  90524. "attributes": {},
  90525. "center": [
  90526. 113.59568277455075,
  90527. 22.366566635195288,
  90528. 12.78751625
  90529. ],
  90530. "children": [],
  90531. "geometry_hash": 1891071345,
  90532. "id": 10,
  90533. "name": "港湾一号",
  90534. "parentId": null,
  90535. "polygon": {
  90536. "coordinates": [
  90537. [
  90538. [
  90539. 113.59590810534583,
  90540. 22.36679132753878
  90541. ],
  90542. [
  90543. 113.59590810534583,
  90544. 22.366807172528629
  90545. ],
  90546. [
  90547. 113.59545610274934,
  90548. 22.366807172528629
  90549. ],
  90550. [
  90551. 113.59545610274934,
  90552. 22.36679132753878
  90553. ]
  90554. ]
  90555. ],
  90556. "type": "Polygon"
  90557. },
  90558. "type": "BUILDING",
  90559. "volume": null,
  90560. "z_max": null,
  90561. "z_min": null
  90562. }
  90563. */
  90564. function Log$1() {
  90565. var args = Array.from(arguments);
  90566. var params = args[args.length - 1];
  90567. if (params && params.font) {
  90568. params = params.font, args.pop();
  90569. } else params = {};
  90570. var str = '',
  90571. color = params.color || '#13f',
  90572. fontSize = params.fontSize || 12;
  90573. args.forEach((e, i) => {
  90574. i > 0 && (str += ' , ');
  90575. /* if(params.toFixed && typeof e == 'number'){
  90576. e = e.toFixed(params.toFixed)
  90577. } */
  90578. if (params.toFixed) {
  90579. e = Potree.math.toPrecision(e, params.toFixed);
  90580. }
  90581. str += e; //object可以JSON.stringify,但不是所有都行
  90582. });
  90583. console.warn("%c".concat(str), "color:".concat(color, ";font-size:").concat(fontSize, "px"));
  90584. }
  90585. function loadPointCloud$1(path, name, sceneCode, timeStamp, callback, onError) {
  90586. var loaded = function loaded(e) {
  90587. e.pointcloud.name = name;
  90588. e.pointcloud.sceneCode = sceneCode; //对应4dkk的场景码
  90589. callback(e);
  90590. };
  90591. var promise = new Promise(resolve => {
  90592. // load pointcloud
  90593. if (!path) {
  90594. // TODO: callback? comment? Hello? Bueller? Anyone?
  90595. } else if (path.indexOf('ept.json') > 0) {
  90596. EptLoader.load(path, function (geometry) {
  90597. if (!geometry) {
  90598. console.error(new Error("failed to load point cloud from URL: ".concat(path)));
  90599. } else {
  90600. var pointcloud = new ExtendPointCloudOctree(geometry);
  90601. //loaded(pointcloud);
  90602. resolve({
  90603. type: 'pointcloud_loaded',
  90604. pointcloud: pointcloud
  90605. });
  90606. }
  90607. });
  90608. } else if (path.indexOf('cloud.js') > 0) {
  90609. POCLoader.load(path, timeStamp, function (geometry) {
  90610. if (!geometry) {
  90611. //callback({type: 'loading_failed'});
  90612. console.error(new Error("failed to load point cloud from URL: ".concat(path)));
  90613. onError && onError();
  90614. } else {
  90615. var pointcloud = new ExtendPointCloudOctree(geometry);
  90616. // loaded(pointcloud);
  90617. resolve({
  90618. type: 'pointcloud_loaded',
  90619. pointcloud: pointcloud
  90620. });
  90621. }
  90622. });
  90623. } /* else if (path.indexOf('metadata.json') > 0) { //部分浏览器(如uc)不支持NodeLoader中的1n的大数据写法
  90624. Potree.OctreeLoader.load(path).then(e => {
  90625. let geometry = e.geometry;
  90626. if(!geometry){
  90627. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  90628. }else{
  90629. let pointcloud = new ExtendPointCloudOctree(geometry);
  90630. let aPosition = pointcloud.getAttribute("position");
  90631. let material = pointcloud.material;
  90632. material.elevationRange = [
  90633. aPosition.range[0][2],
  90634. aPosition.range[1][2],
  90635. ];
  90636. // loaded(pointcloud);
  90637. resolve({type: 'pointcloud_loaded', pointcloud: pointcloud});
  90638. }
  90639. });
  90640. OctreeLoader.load(path, function (geometry) {
  90641. if (!geometry) {
  90642. //callback({type: 'loading_failed'});
  90643. console.error(new Error(`failed to load point cloud from URL: ${path}`));
  90644. } else {
  90645. let pointcloud = new ExtendPointCloudOctree(geometry);
  90646. // loaded(pointcloud);
  90647. resolve({type: 'pointcloud_loaded', pointcloud: pointcloud});
  90648. }
  90649. });
  90650. } */else if (path.indexOf('.vpc') > 0) {
  90651. PointCloudArena4DGeometry.load(path, function (geometry) {
  90652. if (!geometry) {
  90653. //callback({type: 'loading_failed'});
  90654. console.error(new Error("failed to load point cloud from URL: ".concat(path)));
  90655. } else {
  90656. var pointcloud = new PointCloudArena4D(geometry);
  90657. // loaded(pointcloud);
  90658. resolve({
  90659. type: 'pointcloud_loaded',
  90660. pointcloud: pointcloud
  90661. });
  90662. }
  90663. });
  90664. } else {
  90665. //callback({'type': 'loading_failed'});
  90666. console.error(new Error("failed to load point cloud from URL: ".concat(path)));
  90667. }
  90668. });
  90669. if (callback) {
  90670. promise.then(pointcloud => {
  90671. loaded(pointcloud);
  90672. });
  90673. } else {
  90674. return promise;
  90675. }
  90676. }
  90677. ;
  90678. // add selectgroup
  90679. (function ($) {
  90680. $.fn.extend({
  90681. selectgroup: function selectgroup() {
  90682. var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  90683. var elGroup = $(this);
  90684. var rootID = elGroup.prop("id");
  90685. var groupID = "".concat(rootID);
  90686. var groupTitle = args.title !== undefined ? args.title : "";
  90687. var elButtons = [];
  90688. elGroup.find("option").each((index, value) => {
  90689. var buttonID = $(value).prop("id");
  90690. var label = $(value).html();
  90691. var optionValue = $(value).prop("value");
  90692. var elButton = $("\n\t\t\t\t\t<span style=\"flex-grow: 1; display: inherit\">\n\t\t\t\t\t<label for=\"".concat(buttonID, "\" class=\"ui-button\" style=\"width: 100%; padding: .4em .1em\">").concat(label, "</label>\n\t\t\t\t\t<input type=\"radio\" name=\"").concat(groupID, "\" id=\"").concat(buttonID, "\" value=\"").concat(optionValue, "\" style=\"display: none\"/>\n\t\t\t\t\t</span>\n\t\t\t\t"));
  90693. var elLabel = elButton.find("label");
  90694. var elInput = elButton.find("input");
  90695. elInput.change(() => {
  90696. elGroup.find("label").removeClass("ui-state-active");
  90697. elGroup.find("label").addClass("ui-state-default");
  90698. if (elInput.is(":checked")) {
  90699. elLabel.addClass("ui-state-active");
  90700. } else {
  90701. //elLabel.addClass("ui-state-default");
  90702. }
  90703. });
  90704. elButtons.push(elButton);
  90705. });
  90706. var elFieldset = $("\n\t\t\t\t<fieldset style=\"border: none; margin: 0px; padding: 0px\">\n\t\t\t\t\t<legend>".concat(groupTitle, "</legend>\n\t\t\t\t\t<span style=\"display: flex\">\n\n\t\t\t\t\t</span>\n\t\t\t\t</fieldset>\n\t\t\t"));
  90707. var elButtonContainer = elFieldset.find("span");
  90708. for (var elButton of elButtons) {
  90709. elButtonContainer.append(elButton);
  90710. }
  90711. elButtonContainer.find("label").each((index, value) => {
  90712. $(value).css("margin", "0px");
  90713. $(value).css("border-radius", "0px");
  90714. $(value).css("border", "1px solid black");
  90715. $(value).css("border-left", "none");
  90716. });
  90717. elButtonContainer.find("label:first").each((index, value) => {
  90718. $(value).css("border-radius", "4px 0px 0px 4px");
  90719. });
  90720. elButtonContainer.find("label:last").each((index, value) => {
  90721. $(value).css("border-radius", "0px 4px 4px 0px");
  90722. $(value).css("border-left", "none");
  90723. });
  90724. elGroup.empty();
  90725. elGroup.append(elFieldset);
  90726. }
  90727. });
  90728. })(jQuery);
  90729. //在这之后export的内容才赋值到Potree中
  90730. exports.Action = Action;
  90731. exports.Annotation = Annotation;
  90732. exports.Box3Helper = Box3Helper$1;
  90733. exports.BoxVolume = BoxVolume$1;
  90734. exports.CameraAnimation = CameraAnimation$1;
  90735. exports.CameraMode = CameraMode;
  90736. exports.ClassificationScheme = ClassificationScheme;
  90737. exports.ClipMethod = ClipMethod;
  90738. exports.ClipTask = ClipTask;
  90739. exports.ClipVolume = ClipVolume;
  90740. exports.ClippingTool = ClippingTool;
  90741. exports.ElevationGradientRepeat = ElevationGradientRepeat;
  90742. exports.Enum = Enum;
  90743. exports.EnumItem = EnumItem;
  90744. exports.EptBinaryLoader = EptBinaryLoader;
  90745. exports.EptKey = EptKey;
  90746. exports.EptLaszipLoader = EptLaszipLoader;
  90747. exports.EptLazBatcher = EptLazBatcher;
  90748. exports.EptLoader = EptLoader;
  90749. exports.EptZstandardLoader = EptZstandardLoader;
  90750. exports.EventDispatcher = EventDispatcher$1;
  90751. exports.ExtendPointCloudMaterial = ExtendPointCloudMaterial;
  90752. exports.ExtendPointCloudOctree = ExtendPointCloudOctree;
  90753. exports.ExtendScene = ExtendScene;
  90754. exports.EyeDomeLightingMaterial = EyeDomeLightingMaterial;
  90755. exports.Features = Features;
  90756. exports.FirstPersonControls = FirstPersonControls$1;
  90757. exports.GeoPackageLoader = GeoPackageLoader;
  90758. exports.Geopackage = Geopackage$1;
  90759. exports.Gradients = Gradients;
  90760. exports.HierarchicalSlider = HierarchicalSlider;
  90761. exports.Images360 = Images360;
  90762. exports.KeyCodes = KeyCodes;
  90763. exports.LRU = LRU;
  90764. exports.LRUItem = LRUItem;
  90765. exports.LengthUnits = LengthUnits;
  90766. exports.LineDraw = LineDraw;
  90767. exports.Log = Log$1;
  90768. exports.MOUSE = MOUSE$1;
  90769. exports.MapViewer = MapViewer;
  90770. exports.Measure = Measure$1;
  90771. exports.MeasuringTool = MeasuringTool;
  90772. exports.MeshDraw = MeshDraw;
  90773. exports.Message = Message;
  90774. exports.NodeLoader = NodeLoader;
  90775. exports.NormalizationEDLMaterial = NormalizationEDLMaterial;
  90776. exports.NormalizationMaterial = NormalizationMaterial;
  90777. exports.OctreeLoader = OctreeLoader;
  90778. exports.OrbitControls = OrbitControls$1;
  90779. exports.OrientedImage = OrientedImage;
  90780. exports.OrientedImageLoader = OrientedImageLoader;
  90781. exports.OrientedImages = OrientedImages;
  90782. exports.POCLoader = POCLoader;
  90783. exports.Path = Path$1;
  90784. exports.PointAttribute = PointAttribute;
  90785. exports.PointAttributeTypes = PointAttributeTypes;
  90786. exports.PointAttributes = PointAttributes;
  90787. exports.PointCloudEptGeometry = PointCloudEptGeometry;
  90788. exports.PointCloudEptGeometryNode = PointCloudEptGeometryNode;
  90789. exports.PointCloudOctreeGeometry = PointCloudOctreeGeometry;
  90790. exports.PointCloudOctreeGeometryNode = PointCloudOctreeGeometryNode;
  90791. exports.PointCloudSM = PointCloudSM;
  90792. exports.PointCloudTree = PointCloudTree;
  90793. exports.PointCloudTreeNode = PointCloudTreeNode;
  90794. exports.PointShape = PointShape$1;
  90795. exports.PointSizeType = PointSizeType;
  90796. exports.Points = Points$1;
  90797. exports.PolygonClipVolume = PolygonClipVolume;
  90798. exports.Profile = Profile;
  90799. exports.ProfileData = ProfileData;
  90800. exports.ProfileRequest = ProfileRequest;
  90801. exports.ProfileTool = ProfileTool;
  90802. exports.Renderer = Renderer;
  90803. exports.ScreenBoxSelectTool = ScreenBoxSelectTool;
  90804. exports.ShapefileLoader = ShapefileLoader;
  90805. exports.SphereVolume = SphereVolume$2;
  90806. exports.Splat = Splat;
  90807. exports.SpotLightHelper = SpotLightHelper$1;
  90808. exports.TextSprite = TextSprite$2;
  90809. exports.TransformationTool = TransformationTool;
  90810. exports.TreeType = TreeType;
  90811. exports.Utils = Utils;
  90812. exports.Version = Version;
  90813. exports.Viewer = Viewer;
  90814. exports.Volume = Volume$1;
  90815. exports.VolumeTool = VolumeTool;
  90816. exports.WorkerPool = WorkerPool;
  90817. exports.XHRFactory = XHRFactory;
  90818. exports.config = config$1;
  90819. exports.debug = debug;
  90820. exports.framenumber = framenumber;
  90821. exports.load4dkkPanos = load4dkkPanos;
  90822. exports.loadDatasets = loadDatasets;
  90823. exports.loadFile = loadFile;
  90824. exports.loadImgVersion = loadImgVersion;
  90825. exports.loadMapEntity = loadMapEntity;
  90826. exports.loadNeighborFile = loadNeighborFile;
  90827. exports.loadPanos = loadPanos;
  90828. exports.loadPanosInfo = loadPanosInfo;
  90829. exports.loadPointCloud = loadPointCloud$1;
  90830. exports.loadProject = loadProject;
  90831. exports.lru = lru;
  90832. exports.maxNodesLoading = maxNodesLoading;
  90833. exports.mergeEditStart = mergeEditStart;
  90834. exports.numNodesLoading = numNodesLoading;
  90835. exports.panoEditStart = panoEditStart;
  90836. exports.pointBudget = pointBudget;
  90837. exports.resourcePath = resourcePath;
  90838. exports.saveProject = saveProject;
  90839. exports.setExtraNeighbour = setExtraNeighbour;
  90840. exports.setLonlat = setLonlat;
  90841. exports.setNeighborGui = setNeighborGui;
  90842. exports.settings = settings;
  90843. exports.start = start;
  90844. exports.version = version;
  90845. exports.workerPool = workerPool;
  90846. Object.defineProperty(exports, '__esModule', { value: true });
  90847. })));
  90848. //# sourceMappingURL=potree.js.map