Three.js 760 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049
  1. // Three.js - http://github.com/mrdoob/three.js
  2. /**
  3. * @author mr.doob / http://mrdoob.com/
  4. */
  5. var THREE = THREE || { REVISION: '50dev' };
  6. if ( ! self.console ) {
  7. self.console = {
  8. info: function () {},
  9. log: function () {},
  10. debug: function () {},
  11. warn: function () {},
  12. error: function () {}
  13. };
  14. }
  15. if ( ! self.Int32Array ) {
  16. self.Int32Array = Array;
  17. self.Float32Array = Array;
  18. }
  19. // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  20. // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
  21. // requestAnimationFrame polyfill by Erik Möller
  22. // fixes from Paul Irish and Tino Zijdel
  23. ( function () {
  24. var lastTime = 0;
  25. var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
  26. for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++ x ) {
  27. window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
  28. window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
  29. }
  30. if ( !window.requestAnimationFrame ) {
  31. window.requestAnimationFrame = function ( callback, element ) {
  32. var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
  33. var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall );
  34. lastTime = currTime + timeToCall;
  35. return id;
  36. };
  37. }
  38. if ( !window.cancelAnimationFrame ) {
  39. window.cancelAnimationFrame = function ( id ) { clearTimeout( id ); };
  40. }
  41. }() );
  42. // MATERIAL CONSTANTS
  43. // shading
  44. THREE.NoShading = 0;
  45. THREE.FlatShading = 1;
  46. THREE.SmoothShading = 2;
  47. // colors
  48. THREE.NoColors = 0;
  49. THREE.FaceColors = 1;
  50. THREE.VertexColors = 2;
  51. // blending modes
  52. THREE.NoBlending = 0;
  53. THREE.NormalBlending = 1;
  54. THREE.AdditiveBlending = 2;
  55. THREE.SubtractiveBlending = 3;
  56. THREE.MultiplyBlending = 4;
  57. THREE.CustomBlending = 5;
  58. // custom blending equations
  59. // (numbers start from 100 not to clash with other
  60. // mappings to OpenGL constants defined in Texture.js)
  61. THREE.AddEquation = 100;
  62. THREE.SubtractEquation = 101;
  63. THREE.ReverseSubtractEquation = 102;
  64. // custom blending destination factors
  65. THREE.ZeroFactor = 200;
  66. THREE.OneFactor = 201;
  67. THREE.SrcColorFactor = 202;
  68. THREE.OneMinusSrcColorFactor = 203;
  69. THREE.SrcAlphaFactor = 204;
  70. THREE.OneMinusSrcAlphaFactor = 205;
  71. THREE.DstAlphaFactor = 206;
  72. THREE.OneMinusDstAlphaFactor = 207;
  73. // custom blending source factors
  74. //THREE.ZeroFactor = 200;
  75. //THREE.OneFactor = 201;
  76. //THREE.SrcAlphaFactor = 204;
  77. //THREE.OneMinusSrcAlphaFactor = 205;
  78. //THREE.DstAlphaFactor = 206;
  79. //THREE.OneMinusDstAlphaFactor = 207;
  80. THREE.DstColorFactor = 208;
  81. THREE.OneMinusDstColorFactor = 209;
  82. THREE.SrcAlphaSaturateFactor = 210;
  83. // TEXTURE CONSTANTS
  84. THREE.MultiplyOperation = 0;
  85. THREE.MixOperation = 1;
  86. // Mapping modes
  87. THREE.UVMapping = function () {};
  88. THREE.CubeReflectionMapping = function () {};
  89. THREE.CubeRefractionMapping = function () {};
  90. THREE.SphericalReflectionMapping = function () {};
  91. THREE.SphericalRefractionMapping = function () {};
  92. // Wrapping modes
  93. THREE.RepeatWrapping = 1000;
  94. THREE.ClampToEdgeWrapping = 1001;
  95. THREE.MirroredRepeatWrapping = 1002;
  96. // Filters
  97. THREE.NearestFilter = 1003;
  98. THREE.NearestMipMapNearestFilter = 1004;
  99. THREE.NearestMipMapLinearFilter = 1005;
  100. THREE.LinearFilter = 1006;
  101. THREE.LinearMipMapNearestFilter = 1007;
  102. THREE.LinearMipMapLinearFilter = 1008;
  103. // Data types
  104. THREE.UnsignedByteType = 1009;
  105. THREE.ByteType = 1010;
  106. THREE.ShortType = 1011;
  107. THREE.UnsignedShortType = 1012;
  108. THREE.IntType = 1013;
  109. THREE.UnsignedIntType = 1014;
  110. THREE.FloatType = 1015;
  111. // Pixel types
  112. //THREE.UnsignedByteType = 1009;
  113. THREE.UnsignedShort4444Type = 1016;
  114. THREE.UnsignedShort5551Type = 1017;
  115. THREE.UnsignedShort565Type = 1018;
  116. // Pixel formats
  117. THREE.AlphaFormat = 1019;
  118. THREE.RGBFormat = 1020;
  119. THREE.RGBAFormat = 1021;
  120. THREE.LuminanceFormat = 1022;
  121. THREE.LuminanceAlphaFormat = 1023;
  122. /**
  123. * @author alteredq / http://alteredqualia.com/
  124. */
  125. THREE.Clock = function ( autoStart ) {
  126. this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
  127. this.startTime = 0;
  128. this.oldTime = 0;
  129. this.elapsedTime = 0;
  130. this.running = false;
  131. };
  132. THREE.Clock.prototype.start = function () {
  133. this.startTime = Date.now();
  134. this.oldTime = this.startTime;
  135. this.running = true;
  136. };
  137. THREE.Clock.prototype.stop = function () {
  138. this.getElapsedTime();
  139. this.running = false;
  140. };
  141. THREE.Clock.prototype.getElapsedTime = function () {
  142. this.elapsedTime += this.getDelta();
  143. return this.elapsedTime;
  144. };
  145. THREE.Clock.prototype.getDelta = function () {
  146. var diff = 0;
  147. if ( this.autoStart && ! this.running ) {
  148. this.start();
  149. }
  150. if ( this.running ) {
  151. var newTime = Date.now();
  152. diff = 0.001 * ( newTime - this.oldTime );
  153. this.oldTime = newTime;
  154. this.elapsedTime += diff;
  155. }
  156. return diff;
  157. };/**
  158. * @author mr.doob / http://mrdoob.com/
  159. */
  160. THREE.Color = function ( hex ) {
  161. if ( hex !== undefined ) this.setHex( hex );
  162. return this;
  163. };
  164. THREE.Color.prototype = {
  165. constructor: THREE.Color,
  166. r: 1, g: 1, b: 1,
  167. copy: function ( color ) {
  168. this.r = color.r;
  169. this.g = color.g;
  170. this.b = color.b;
  171. return this;
  172. },
  173. copyGammaToLinear: function ( color ) {
  174. this.r = color.r * color.r;
  175. this.g = color.g * color.g;
  176. this.b = color.b * color.b;
  177. return this;
  178. },
  179. copyLinearToGamma: function ( color ) {
  180. this.r = Math.sqrt( color.r );
  181. this.g = Math.sqrt( color.g );
  182. this.b = Math.sqrt( color.b );
  183. return this;
  184. },
  185. convertGammaToLinear: function () {
  186. var r = this.r, g = this.g, b = this.b;
  187. this.r = r * r;
  188. this.g = g * g;
  189. this.b = b * b;
  190. return this;
  191. },
  192. convertLinearToGamma: function () {
  193. this.r = Math.sqrt( this.r );
  194. this.g = Math.sqrt( this.g );
  195. this.b = Math.sqrt( this.b );
  196. return this;
  197. },
  198. setRGB: function ( r, g, b ) {
  199. this.r = r;
  200. this.g = g;
  201. this.b = b;
  202. return this;
  203. },
  204. setHSV: function ( h, s, v ) {
  205. // based on MochiKit implementation by Bob Ippolito
  206. // h,s,v ranges are < 0.0 - 1.0 >
  207. var i, f, p, q, t;
  208. if ( v === 0 ) {
  209. this.r = this.g = this.b = 0;
  210. } else {
  211. i = Math.floor( h * 6 );
  212. f = ( h * 6 ) - i;
  213. p = v * ( 1 - s );
  214. q = v * ( 1 - ( s * f ) );
  215. t = v * ( 1 - ( s * ( 1 - f ) ) );
  216. if ( i === 0 ) {
  217. this.r = v;
  218. this.g = t;
  219. this.b = p;
  220. } else if ( i === 1 ) {
  221. this.r = q;
  222. this.g = v;
  223. this.b = p;
  224. } else if ( i === 2 ) {
  225. this.r = p;
  226. this.g = v;
  227. this.b = t;
  228. } else if ( i === 3 ) {
  229. this.r = p;
  230. this.g = q;
  231. this.b = v;
  232. } else if ( i === 4 ) {
  233. this.r = t;
  234. this.g = p;
  235. this.b = v;
  236. } else if ( i === 5 ) {
  237. this.r = v;
  238. this.g = p;
  239. this.b = q;
  240. }
  241. }
  242. return this;
  243. },
  244. setHex: function ( hex ) {
  245. hex = Math.floor( hex );
  246. this.r = ( hex >> 16 & 255 ) / 255;
  247. this.g = ( hex >> 8 & 255 ) / 255;
  248. this.b = ( hex & 255 ) / 255;
  249. return this;
  250. },
  251. lerpSelf: function ( color, alpha ) {
  252. this.r += ( color.r - this.r ) * alpha;
  253. this.g += ( color.g - this.g ) * alpha;
  254. this.b += ( color.b - this.b ) * alpha;
  255. return this;
  256. },
  257. getHex: function () {
  258. return Math.floor( this.r * 255 ) << 16 ^ Math.floor( this.g * 255 ) << 8 ^ Math.floor( this.b * 255 );
  259. },
  260. getContextStyle: function () {
  261. return 'rgb(' + Math.floor( this.r * 255 ) + ',' + Math.floor( this.g * 255 ) + ',' + Math.floor( this.b * 255 ) + ')';
  262. },
  263. clone: function () {
  264. return new THREE.Color().setRGB( this.r, this.g, this.b );
  265. }
  266. };
  267. /**
  268. * @author mr.doob / http://mrdoob.com/
  269. * @author philogb / http://blog.thejit.org/
  270. * @author egraether / http://egraether.com/
  271. * @author zz85 / http://www.lab4games.net/zz85/blog
  272. */
  273. THREE.Vector2 = function ( x, y ) {
  274. this.x = x || 0;
  275. this.y = y || 0;
  276. };
  277. THREE.Vector2.prototype = {
  278. constructor: THREE.Vector2,
  279. set: function ( x, y ) {
  280. this.x = x;
  281. this.y = y;
  282. return this;
  283. },
  284. copy: function ( v ) {
  285. this.x = v.x;
  286. this.y = v.y;
  287. return this;
  288. },
  289. add: function ( a, b ) {
  290. this.x = a.x + b.x;
  291. this.y = a.y + b.y;
  292. return this;
  293. },
  294. addSelf: function ( v ) {
  295. this.x += v.x;
  296. this.y += v.y;
  297. return this;
  298. },
  299. sub: function ( a, b ) {
  300. this.x = a.x - b.x;
  301. this.y = a.y - b.y;
  302. return this;
  303. },
  304. subSelf: function ( v ) {
  305. this.x -= v.x;
  306. this.y -= v.y;
  307. return this;
  308. },
  309. multiplyScalar: function ( s ) {
  310. this.x *= s;
  311. this.y *= s;
  312. return this;
  313. },
  314. divideScalar: function ( s ) {
  315. if ( s ) {
  316. this.x /= s;
  317. this.y /= s;
  318. } else {
  319. this.set( 0, 0 );
  320. }
  321. return this;
  322. },
  323. negate: function() {
  324. return this.multiplyScalar( - 1 );
  325. },
  326. dot: function ( v ) {
  327. return this.x * v.x + this.y * v.y;
  328. },
  329. lengthSq: function () {
  330. return this.x * this.x + this.y * this.y;
  331. },
  332. length: function () {
  333. return Math.sqrt( this.lengthSq() );
  334. },
  335. normalize: function () {
  336. return this.divideScalar( this.length() );
  337. },
  338. distanceTo: function ( v ) {
  339. return Math.sqrt( this.distanceToSquared( v ) );
  340. },
  341. distanceToSquared: function ( v ) {
  342. var dx = this.x - v.x, dy = this.y - v.y;
  343. return dx * dx + dy * dy;
  344. },
  345. setLength: function ( l ) {
  346. return this.normalize().multiplyScalar( l );
  347. },
  348. lerpSelf: function ( v, alpha ) {
  349. this.x += ( v.x - this.x ) * alpha;
  350. this.y += ( v.y - this.y ) * alpha;
  351. return this;
  352. },
  353. equals: function( v ) {
  354. return ( ( v.x === this.x ) && ( v.y === this.y ) );
  355. },
  356. isZero: function () {
  357. return ( this.lengthSq() < 0.0001 /* almostZero */ );
  358. },
  359. clone: function () {
  360. return new THREE.Vector2( this.x, this.y );
  361. }
  362. };
  363. /**
  364. * @author mr.doob / http://mrdoob.com/
  365. * @author kile / http://kile.stravaganza.org/
  366. * @author philogb / http://blog.thejit.org/
  367. * @author mikael emtinger / http://gomo.se/
  368. * @author egraether / http://egraether.com/
  369. * @author WestLangley / http://github.com/WestLangley
  370. */
  371. THREE.Vector3 = function ( x, y, z ) {
  372. this.x = x || 0;
  373. this.y = y || 0;
  374. this.z = z || 0;
  375. };
  376. THREE.Vector3.prototype = {
  377. constructor: THREE.Vector3,
  378. set: function ( x, y, z ) {
  379. this.x = x;
  380. this.y = y;
  381. this.z = z;
  382. return this;
  383. },
  384. setX: function ( x ) {
  385. this.x = x;
  386. return this;
  387. },
  388. setY: function ( y ) {
  389. this.y = y;
  390. return this;
  391. },
  392. setZ: function ( z ) {
  393. this.z = z;
  394. return this;
  395. },
  396. copy: function ( v ) {
  397. this.x = v.x;
  398. this.y = v.y;
  399. this.z = v.z;
  400. return this;
  401. },
  402. add: function ( a, b ) {
  403. this.x = a.x + b.x;
  404. this.y = a.y + b.y;
  405. this.z = a.z + b.z;
  406. return this;
  407. },
  408. addSelf: function ( v ) {
  409. this.x += v.x;
  410. this.y += v.y;
  411. this.z += v.z;
  412. return this;
  413. },
  414. addScalar: function ( s ) {
  415. this.x += s;
  416. this.y += s;
  417. this.z += s;
  418. return this;
  419. },
  420. sub: function ( a, b ) {
  421. this.x = a.x - b.x;
  422. this.y = a.y - b.y;
  423. this.z = a.z - b.z;
  424. return this;
  425. },
  426. subSelf: function ( v ) {
  427. this.x -= v.x;
  428. this.y -= v.y;
  429. this.z -= v.z;
  430. return this;
  431. },
  432. multiply: function ( a, b ) {
  433. this.x = a.x * b.x;
  434. this.y = a.y * b.y;
  435. this.z = a.z * b.z;
  436. return this;
  437. },
  438. multiplySelf: function ( v ) {
  439. this.x *= v.x;
  440. this.y *= v.y;
  441. this.z *= v.z;
  442. return this;
  443. },
  444. multiplyScalar: function ( s ) {
  445. this.x *= s;
  446. this.y *= s;
  447. this.z *= s;
  448. return this;
  449. },
  450. divideSelf: function ( v ) {
  451. this.x /= v.x;
  452. this.y /= v.y;
  453. this.z /= v.z;
  454. return this;
  455. },
  456. divideScalar: function ( s ) {
  457. if ( s ) {
  458. this.x /= s;
  459. this.y /= s;
  460. this.z /= s;
  461. } else {
  462. this.x = 0;
  463. this.y = 0;
  464. this.z = 0;
  465. }
  466. return this;
  467. },
  468. negate: function() {
  469. return this.multiplyScalar( - 1 );
  470. },
  471. dot: function ( v ) {
  472. return this.x * v.x + this.y * v.y + this.z * v.z;
  473. },
  474. lengthSq: function () {
  475. return this.x * this.x + this.y * this.y + this.z * this.z;
  476. },
  477. length: function () {
  478. return Math.sqrt( this.lengthSq() );
  479. },
  480. lengthManhattan: function () {
  481. return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
  482. },
  483. normalize: function () {
  484. return this.divideScalar( this.length() );
  485. },
  486. setLength: function ( l ) {
  487. return this.normalize().multiplyScalar( l );
  488. },
  489. lerpSelf: function ( v, alpha ) {
  490. this.x += ( v.x - this.x ) * alpha;
  491. this.y += ( v.y - this.y ) * alpha;
  492. this.z += ( v.z - this.z ) * alpha;
  493. return this;
  494. },
  495. cross: function ( a, b ) {
  496. this.x = a.y * b.z - a.z * b.y;
  497. this.y = a.z * b.x - a.x * b.z;
  498. this.z = a.x * b.y - a.y * b.x;
  499. return this;
  500. },
  501. crossSelf: function ( v ) {
  502. var x = this.x, y = this.y, z = this.z;
  503. this.x = y * v.z - z * v.y;
  504. this.y = z * v.x - x * v.z;
  505. this.z = x * v.y - y * v.x;
  506. return this;
  507. },
  508. distanceTo: function ( v ) {
  509. return Math.sqrt( this.distanceToSquared( v ) );
  510. },
  511. distanceToSquared: function ( v ) {
  512. return new THREE.Vector3().sub( this, v ).lengthSq();
  513. },
  514. getPositionFromMatrix: function ( m ) {
  515. this.x = m.elements[12];
  516. this.y = m.elements[13];
  517. this.z = m.elements[14];
  518. return this;
  519. },
  520. setEulerFromRotationMatrix: function ( m, order ) {
  521. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  522. // clamp, to handle numerical problems
  523. function clamp( x ) {
  524. return Math.min( Math.max( x, -1 ), 1 );
  525. }
  526. var te = m.elements;
  527. var m11 = te[0], m12 = te[4], m13 = te[8];
  528. var m21 = te[1], m22 = te[5], m23 = te[9];
  529. var m31 = te[2], m32 = te[6], m33 = te[10];
  530. if ( order === undefined || order === 'XYZ' ) {
  531. this.y = Math.asin( clamp( m13 ) );
  532. if ( Math.abs( m13 ) < 0.99999 ) {
  533. this.x = Math.atan2( - m23, m33 );
  534. this.z = Math.atan2( - m12, m11 );
  535. } else {
  536. this.x = Math.atan2( m21, m22 );
  537. this.z = 0;
  538. }
  539. } else if ( order === 'YXZ' ) {
  540. this.x = Math.asin( - clamp( m23 ) );
  541. if ( Math.abs( m23 ) < 0.99999 ) {
  542. this.y = Math.atan2( m13, m33 );
  543. this.z = Math.atan2( m21, m22 );
  544. } else {
  545. this.y = Math.atan2( - m31, m11 );
  546. this.z = 0;
  547. }
  548. } else if ( order === 'ZXY' ) {
  549. this.x = Math.asin( clamp( m32 ) );
  550. if ( Math.abs( m32 ) < 0.99999 ) {
  551. this.y = Math.atan2( - m31, m33 );
  552. this.z = Math.atan2( - m12, m22 );
  553. } else {
  554. this.y = 0;
  555. this.z = Math.atan2( m13, m11 );
  556. }
  557. } else if ( order === 'ZYX' ) {
  558. this.y = Math.asin( - clamp( m31 ) );
  559. if ( Math.abs( m31 ) < 0.99999 ) {
  560. this.x = Math.atan2( m32, m33 );
  561. this.z = Math.atan2( m21, m11 );
  562. } else {
  563. this.x = 0;
  564. this.z = Math.atan2( - m12, m22 );
  565. }
  566. } else if ( order === 'YZX' ) {
  567. this.z = Math.asin( clamp( m21 ) );
  568. if ( Math.abs( m21 ) < 0.99999 ) {
  569. this.x = Math.atan2( - m23, m22 );
  570. this.y = Math.atan2( - m31, m11 );
  571. } else {
  572. this.x = 0;
  573. this.y = Math.atan2( m31, m33 );
  574. }
  575. } else if ( order === 'XZY' ) {
  576. this.z = Math.asin( - clamp( m12 ) );
  577. if ( Math.abs( m12 ) < 0.99999 ) {
  578. this.x = Math.atan2( m32, m22 );
  579. this.y = Math.atan2( m13, m11 );
  580. } else {
  581. this.x = Math.atan2( - m13, m33 );
  582. this.y = 0;
  583. }
  584. }
  585. return this;
  586. },
  587. setEulerFromQuaternion: function ( q, order ) {
  588. // q is assumed to be normalized
  589. // clamp, to handle numerical problems
  590. function clamp( x ) {
  591. return Math.min( Math.max( x, -1 ), 1 );
  592. }
  593. // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
  594. var sqx = q.x * q.x;
  595. var sqy = q.y * q.y;
  596. var sqz = q.z * q.z;
  597. var sqw = q.w * q.w;
  598. if ( order === undefined || order === 'XYZ' ) {
  599. this.x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );
  600. this.y = Math.asin( clamp( 2 * ( q.x * q.z + q.y * q.w ) ) );
  601. this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );
  602. } else if ( order === 'YXZ' ) {
  603. this.x = Math.asin( clamp( 2 * ( q.x * q.w - q.y * q.z ) ) );
  604. this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );
  605. this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );
  606. } else if ( order === 'ZXY' ) {
  607. this.x = Math.asin( clamp( 2 * ( q.x * q.w + q.y * q.z ) ) );
  608. this.y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );
  609. this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );
  610. } else if ( order === 'ZYX' ) {
  611. this.x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );
  612. this.y = Math.asin( clamp( 2 * ( q.y * q.w - q.x * q.z ) ) );
  613. this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );
  614. } else if ( order === 'YZX' ) {
  615. this.x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );
  616. this.y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );
  617. this.z = Math.asin( clamp( 2 * ( q.x * q.y + q.z * q.w ) ) );
  618. } else if ( order === 'XZY' ) {
  619. this.x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );
  620. this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );
  621. this.z = Math.asin( clamp( 2 * ( q.z * q.w - q.x * q.y ) ) );
  622. }
  623. return this;
  624. },
  625. getScaleFromMatrix: function ( m ) {
  626. var sx = this.set( m.elements[0], m.elements[1], m.elements[2] ).length();
  627. var sy = this.set( m.elements[4], m.elements[5], m.elements[6] ).length();
  628. var sz = this.set( m.elements[8], m.elements[9], m.elements[10] ).length();
  629. this.x = sx;
  630. this.y = sy;
  631. this.z = sz;
  632. return this;
  633. },
  634. equals: function ( v ) {
  635. return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
  636. },
  637. isZero: function () {
  638. return ( this.lengthSq() < 0.0001 /* almostZero */ );
  639. },
  640. clone: function () {
  641. return new THREE.Vector3( this.x, this.y, this.z );
  642. }
  643. };
  644. /**
  645. * @author supereggbert / http://www.paulbrunt.co.uk/
  646. * @author philogb / http://blog.thejit.org/
  647. * @author mikael emtinger / http://gomo.se/
  648. * @author egraether / http://egraether.com/
  649. * @author WestLangley / http://github.com/WestLangley
  650. */
  651. THREE.Vector4 = function ( x, y, z, w ) {
  652. this.x = x || 0;
  653. this.y = y || 0;
  654. this.z = z || 0;
  655. this.w = ( w !== undefined ) ? w : 1;
  656. };
  657. THREE.Vector4.prototype = {
  658. constructor: THREE.Vector4,
  659. set: function ( x, y, z, w ) {
  660. this.x = x;
  661. this.y = y;
  662. this.z = z;
  663. this.w = w;
  664. return this;
  665. },
  666. copy: function ( v ) {
  667. this.x = v.x;
  668. this.y = v.y;
  669. this.z = v.z;
  670. this.w = ( v.w !== undefined ) ? v.w : 1;
  671. return this;
  672. },
  673. add: function ( a, b ) {
  674. this.x = a.x + b.x;
  675. this.y = a.y + b.y;
  676. this.z = a.z + b.z;
  677. this.w = a.w + b.w;
  678. return this;
  679. },
  680. addSelf: function ( v ) {
  681. this.x += v.x;
  682. this.y += v.y;
  683. this.z += v.z;
  684. this.w += v.w;
  685. return this;
  686. },
  687. sub: function ( a, b ) {
  688. this.x = a.x - b.x;
  689. this.y = a.y - b.y;
  690. this.z = a.z - b.z;
  691. this.w = a.w - b.w;
  692. return this;
  693. },
  694. subSelf: function ( v ) {
  695. this.x -= v.x;
  696. this.y -= v.y;
  697. this.z -= v.z;
  698. this.w -= v.w;
  699. return this;
  700. },
  701. multiplyScalar: function ( s ) {
  702. this.x *= s;
  703. this.y *= s;
  704. this.z *= s;
  705. this.w *= s;
  706. return this;
  707. },
  708. divideScalar: function ( s ) {
  709. if ( s ) {
  710. this.x /= s;
  711. this.y /= s;
  712. this.z /= s;
  713. this.w /= s;
  714. } else {
  715. this.x = 0;
  716. this.y = 0;
  717. this.z = 0;
  718. this.w = 1;
  719. }
  720. return this;
  721. },
  722. negate: function() {
  723. return this.multiplyScalar( -1 );
  724. },
  725. dot: function ( v ) {
  726. return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
  727. },
  728. lengthSq: function () {
  729. return this.dot( this );
  730. },
  731. length: function () {
  732. return Math.sqrt( this.lengthSq() );
  733. },
  734. normalize: function () {
  735. return this.divideScalar( this.length() );
  736. },
  737. setLength: function ( l ) {
  738. return this.normalize().multiplyScalar( l );
  739. },
  740. lerpSelf: function ( v, alpha ) {
  741. this.x += ( v.x - this.x ) * alpha;
  742. this.y += ( v.y - this.y ) * alpha;
  743. this.z += ( v.z - this.z ) * alpha;
  744. this.w += ( v.w - this.w ) * alpha;
  745. return this;
  746. },
  747. clone: function () {
  748. return new THREE.Vector4( this.x, this.y, this.z, this.w );
  749. },
  750. setAxisAngleFromQuaternion: function ( q ) {
  751. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
  752. // q is assumed to be normalized
  753. this.w = 2 * Math.acos( q.w );
  754. var s = Math.sqrt( 1 - q.w * q.w );
  755. if ( s < 0.0001 ) {
  756. this.x = 1;
  757. this.y = 0;
  758. this.z = 0;
  759. } else {
  760. this.x = q.x / s;
  761. this.y = q.y / s;
  762. this.z = q.z / s;
  763. }
  764. return this;
  765. },
  766. setAxisAngleFromRotationMatrix: function ( m ) {
  767. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
  768. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  769. var angle, x, y, z, // variables for result
  770. epsilon = 0.01, // margin to allow for rounding errors
  771. epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
  772. te = m.elements,
  773. m11 = te[0], m12 = te[4], m13 = te[8],
  774. m21 = te[1], m22 = te[5], m23 = te[9],
  775. m31 = te[2], m32 = te[6], m33 = te[10];
  776. if ( ( Math.abs( m12 - m21 ) < epsilon )
  777. && ( Math.abs( m13 - m31 ) < epsilon )
  778. && ( Math.abs( m23 - m32 ) < epsilon ) ) {
  779. // singularity found
  780. // first check for identity matrix which must have +1 for all terms
  781. // in leading diagonal and zero in other terms
  782. if ( ( Math.abs( m12 + m21 ) < epsilon2 )
  783. && ( Math.abs( m13 + m31 ) < epsilon2 )
  784. && ( Math.abs( m23 + m32 ) < epsilon2 )
  785. && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
  786. // this singularity is identity matrix so angle = 0
  787. this.set( 1, 0, 0, 0 );
  788. return this; // zero angle, arbitrary axis
  789. }
  790. // otherwise this singularity is angle = 180
  791. angle = Math.PI;
  792. var xx = ( m11 + 1 ) / 2;
  793. var yy = ( m22 + 1 ) / 2;
  794. var zz = ( m33 + 1 ) / 2;
  795. var xy = ( m12 + m21 ) / 4;
  796. var xz = ( m13 + m31 ) / 4;
  797. var yz = ( m23 + m32 ) / 4;
  798. if ( ( xx > yy ) && ( xx > zz ) ) { // m11 is the largest diagonal term
  799. if ( xx < epsilon ) {
  800. x = 0;
  801. y = 0.707106781;
  802. z = 0.707106781;
  803. } else {
  804. x = Math.sqrt( xx );
  805. y = xy / x;
  806. z = xz / x;
  807. }
  808. } else if ( yy > zz ) { // m22 is the largest diagonal term
  809. if ( yy < epsilon ) {
  810. x = 0.707106781;
  811. y = 0;
  812. z = 0.707106781;
  813. } else {
  814. y = Math.sqrt( yy );
  815. x = xy / y;
  816. z = yz / y;
  817. }
  818. } else { // m33 is the largest diagonal term so base result on this
  819. if ( zz < epsilon ) {
  820. x = 0.707106781;
  821. y = 0.707106781;
  822. z = 0;
  823. } else {
  824. z = Math.sqrt( zz );
  825. x = xz / z;
  826. y = yz / z;
  827. }
  828. }
  829. this.set( x, y, z, angle );
  830. return this; // return 180 deg rotation
  831. }
  832. // as we have reached here there are no singularities so we can handle normally
  833. var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
  834. + ( m13 - m31 ) * ( m13 - m31 )
  835. + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
  836. if ( Math.abs( s ) < 0.001 ) s = 1;
  837. // prevent divide by zero, should not happen if matrix is orthogonal and should be
  838. // caught by singularity test above, but I've left it in just in case
  839. this.x = ( m32 - m23 ) / s;
  840. this.y = ( m13 - m31 ) / s;
  841. this.z = ( m21 - m12 ) / s;
  842. this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
  843. return this;
  844. }
  845. };
  846. /**
  847. * https://github.com/mrdoob/eventtarget.js/
  848. */
  849. THREE.EventTarget = function () {
  850. var listeners = {};
  851. this.addEventListener = function ( type, listener ) {
  852. if ( listeners[ type ] === undefined ) {
  853. listeners[ type ] = [];
  854. }
  855. if ( listeners[ type ].indexOf( listener ) === - 1 ) {
  856. listeners[ type ].push( listener );
  857. }
  858. };
  859. this.dispatchEvent = function ( event ) {
  860. for ( var listener in listeners[ event.type ] ) {
  861. listeners[ event.type ][ listener ]( event );
  862. }
  863. };
  864. this.removeEventListener = function ( type, listener ) {
  865. var index = listeners[ type ].indexOf( listener );
  866. if ( index !== - 1 ) {
  867. listeners[ type ].splice( index, 1 );
  868. }
  869. };
  870. };
  871. /**
  872. * @author mrdoob / http://mrdoob.com/
  873. * @author alteredq / http://alteredqualia.com/
  874. */
  875. THREE.Frustum = function ( ) {
  876. this.planes = [
  877. new THREE.Vector4(),
  878. new THREE.Vector4(),
  879. new THREE.Vector4(),
  880. new THREE.Vector4(),
  881. new THREE.Vector4(),
  882. new THREE.Vector4()
  883. ];
  884. };
  885. THREE.Frustum.prototype.setFromMatrix = function ( m ) {
  886. var plane;
  887. var planes = this.planes;
  888. var me = m.elements;
  889. var me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
  890. var me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
  891. var me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
  892. var me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
  893. planes[ 0 ].set( me3 - me0, me7 - me4, me11 - me8, me15 - me12 );
  894. planes[ 1 ].set( me3 + me0, me7 + me4, me11 + me8, me15 + me12 );
  895. planes[ 2 ].set( me3 + me1, me7 + me5, me11 + me9, me15 + me13 );
  896. planes[ 3 ].set( me3 - me1, me7 - me5, me11 - me9, me15 - me13 );
  897. planes[ 4 ].set( me3 - me2, me7 - me6, me11 - me10, me15 - me14 );
  898. planes[ 5 ].set( me3 + me2, me7 + me6, me11 + me10, me15 + me14 );
  899. for ( var i = 0; i < 6; i ++ ) {
  900. plane = planes[ i ];
  901. plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) );
  902. }
  903. };
  904. THREE.Frustum.prototype.contains = function ( object ) {
  905. var distance = 0.0;
  906. var planes = this.planes;
  907. var matrix = object.matrixWorld;
  908. var me = matrix.elements;
  909. var radius = - object.geometry.boundingSphere.radius * matrix.getMaxScaleOnAxis();
  910. for ( var i = 0; i < 6; i ++ ) {
  911. distance = planes[ i ].x * me[12] + planes[ i ].y * me[13] + planes[ i ].z * me[14] + planes[ i ].w;
  912. if ( distance <= radius ) return false;
  913. }
  914. return true;
  915. };
  916. THREE.Frustum.__v1 = new THREE.Vector3();
  917. /**
  918. * @author mr.doob / http://mrdoob.com/
  919. */
  920. THREE.Ray = function ( origin, direction, near, far ) {
  921. this.origin = origin || new THREE.Vector3();
  922. this.direction = direction || new THREE.Vector3();
  923. this.near = near || 0;
  924. this.far = far || Infinity;
  925. //
  926. var a = new THREE.Vector3();
  927. var b = new THREE.Vector3();
  928. var c = new THREE.Vector3();
  929. var d = new THREE.Vector3();
  930. var originCopy = new THREE.Vector3();
  931. var directionCopy = new THREE.Vector3();
  932. var vector = new THREE.Vector3();
  933. var normal = new THREE.Vector3();
  934. var intersectPoint = new THREE.Vector3();
  935. var descSort = function ( a, b ) {
  936. return a.distance - b.distance;
  937. };
  938. //
  939. var v0 = new THREE.Vector3(), v1 = new THREE.Vector3(), v2 = new THREE.Vector3();
  940. var dot, intersect, distance;
  941. var distanceFromIntersection = function ( origin, direction, position ) {
  942. v0.sub( position, origin );
  943. dot = v0.dot( direction );
  944. intersect = v1.add( origin, v2.copy( direction ).multiplyScalar( dot ) );
  945. distance = position.distanceTo( intersect );
  946. return distance;
  947. }
  948. // http://www.blackpawn.com/texts/pointinpoly/default.html
  949. var dot00, dot01, dot02, dot11, dot12, invDenom, u, v;
  950. var pointInFace3 = function ( p, a, b, c ) {
  951. v0.sub( c, a );
  952. v1.sub( b, a );
  953. v2.sub( p, a );
  954. dot00 = v0.dot( v0 );
  955. dot01 = v0.dot( v1 );
  956. dot02 = v0.dot( v2 );
  957. dot11 = v1.dot( v1 );
  958. dot12 = v1.dot( v2 );
  959. invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 );
  960. u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
  961. v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
  962. return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 );
  963. }
  964. //
  965. var precision = 0.0001;
  966. this.setPrecision = function ( value ) {
  967. precision = value;
  968. };
  969. this.intersectObject = function ( object, recursive ) {
  970. var intersect, intersects = [];
  971. if ( recursive === true ) {
  972. for ( var i = 0, l = object.children.length; i < l; i ++ ) {
  973. Array.prototype.push.apply( intersects, this.intersectObject( object.children[ i ], recursive ) );
  974. }
  975. }
  976. if ( object instanceof THREE.Particle ) {
  977. distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
  978. if ( distance > object.scale.x ) {
  979. return [];
  980. }
  981. intersect = {
  982. distance: distance,
  983. point: object.position,
  984. face: null,
  985. object: object
  986. };
  987. intersects.push( intersect );
  988. } else if ( object instanceof THREE.Mesh ) {
  989. // Checking boundingSphere
  990. var scale = THREE.Frustum.__v1.set( object.matrixWorld.getColumnX().length(), object.matrixWorld.getColumnY().length(), object.matrixWorld.getColumnZ().length() );
  991. var scaledRadius = object.geometry.boundingSphere.radius * Math.max( scale.x, Math.max( scale.y, scale.z ) );
  992. // Checking distance to ray
  993. distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
  994. if ( distance > scaledRadius) {
  995. return intersects;
  996. }
  997. // Checking faces
  998. var f, fl, face, dot, scalar,
  999. rangeSq = this.range * this.range,
  1000. geometry = object.geometry,
  1001. vertices = geometry.vertices,
  1002. objMatrix;
  1003. object.matrixRotationWorld.extractRotation( object.matrixWorld );
  1004. for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
  1005. face = geometry.faces[ f ];
  1006. originCopy.copy( this.origin );
  1007. directionCopy.copy( this.direction );
  1008. objMatrix = object.matrixWorld;
  1009. // determine if ray intersects the plane of the face
  1010. // note: this works regardless of the direction of the face normal
  1011. vector = objMatrix.multiplyVector3( vector.copy( face.centroid ) ).subSelf( originCopy );
  1012. normal = object.matrixRotationWorld.multiplyVector3( normal.copy( face.normal ) );
  1013. dot = directionCopy.dot( normal );
  1014. // bail if ray and plane are parallel
  1015. if ( Math.abs( dot ) < precision ) continue;
  1016. // calc distance to plane
  1017. scalar = normal.dot( vector ) / dot;
  1018. // if negative distance, then plane is behind ray
  1019. if ( scalar < 0 ) continue;
  1020. if ( object.doubleSided || ( object.flipSided ? dot > 0 : dot < 0 ) ) {
  1021. intersectPoint.add( originCopy, directionCopy.multiplyScalar( scalar ) );
  1022. distance = originCopy.distanceTo( intersectPoint );
  1023. if ( distance < this.near ) continue;
  1024. if ( distance > this.far ) continue;
  1025. if ( face instanceof THREE.Face3 ) {
  1026. a = objMatrix.multiplyVector3( a.copy( vertices[ face.a ] ) );
  1027. b = objMatrix.multiplyVector3( b.copy( vertices[ face.b ] ) );
  1028. c = objMatrix.multiplyVector3( c.copy( vertices[ face.c ] ) );
  1029. if ( pointInFace3( intersectPoint, a, b, c ) ) {
  1030. intersect = {
  1031. distance: distance,
  1032. point: intersectPoint.clone(),
  1033. face: face,
  1034. object: object
  1035. };
  1036. intersects.push( intersect );
  1037. }
  1038. } else if ( face instanceof THREE.Face4 ) {
  1039. a = objMatrix.multiplyVector3( a.copy( vertices[ face.a ] ) );
  1040. b = objMatrix.multiplyVector3( b.copy( vertices[ face.b ] ) );
  1041. c = objMatrix.multiplyVector3( c.copy( vertices[ face.c ] ) );
  1042. d = objMatrix.multiplyVector3( d.copy( vertices[ face.d ] ) );
  1043. if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
  1044. intersect = {
  1045. distance: distance,
  1046. point: intersectPoint.clone(),
  1047. face: face,
  1048. object: object
  1049. };
  1050. intersects.push( intersect );
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. intersects.sort( descSort );
  1057. return intersects;
  1058. };
  1059. this.intersectObjects = function ( objects, recursive ) {
  1060. var intersects = [];
  1061. for ( var i = 0, l = objects.length; i < l; i ++ ) {
  1062. Array.prototype.push.apply( intersects, this.intersectObject( objects[ i ], recursive ) );
  1063. }
  1064. intersects.sort( descSort );
  1065. return intersects;
  1066. };
  1067. };
  1068. /**
  1069. * @author mr.doob / http://mrdoob.com/
  1070. */
  1071. THREE.Rectangle = function () {
  1072. var _left = 0;
  1073. var _top = 0;
  1074. var _right = 0;
  1075. var _bottom = 0;
  1076. var _width = 0;
  1077. var _height = 0;
  1078. var _isEmpty = true;
  1079. function resize() {
  1080. _width = _right - _left;
  1081. _height = _bottom - _top;
  1082. }
  1083. this.getX = function () {
  1084. return _left;
  1085. };
  1086. this.getY = function () {
  1087. return _top;
  1088. };
  1089. this.getWidth = function () {
  1090. return _width;
  1091. };
  1092. this.getHeight = function () {
  1093. return _height;
  1094. };
  1095. this.getLeft = function() {
  1096. return _left;
  1097. };
  1098. this.getTop = function() {
  1099. return _top;
  1100. };
  1101. this.getRight = function() {
  1102. return _right;
  1103. };
  1104. this.getBottom = function() {
  1105. return _bottom;
  1106. };
  1107. this.set = function ( left, top, right, bottom ) {
  1108. _isEmpty = false;
  1109. _left = left; _top = top;
  1110. _right = right; _bottom = bottom;
  1111. resize();
  1112. };
  1113. this.addPoint = function ( x, y ) {
  1114. if ( _isEmpty === true ) {
  1115. _isEmpty = false;
  1116. _left = x; _top = y;
  1117. _right = x; _bottom = y;
  1118. resize();
  1119. } else {
  1120. _left = _left < x ? _left : x; // Math.min( _left, x );
  1121. _top = _top < y ? _top : y; // Math.min( _top, y );
  1122. _right = _right > x ? _right : x; // Math.max( _right, x );
  1123. _bottom = _bottom > y ? _bottom : y; // Math.max( _bottom, y );
  1124. resize();
  1125. }
  1126. };
  1127. this.add3Points = function ( x1, y1, x2, y2, x3, y3 ) {
  1128. if ( _isEmpty === true ) {
  1129. _isEmpty = false;
  1130. _left = x1 < x2 ? ( x1 < x3 ? x1 : x3 ) : ( x2 < x3 ? x2 : x3 );
  1131. _top = y1 < y2 ? ( y1 < y3 ? y1 : y3 ) : ( y2 < y3 ? y2 : y3 );
  1132. _right = x1 > x2 ? ( x1 > x3 ? x1 : x3 ) : ( x2 > x3 ? x2 : x3 );
  1133. _bottom = y1 > y2 ? ( y1 > y3 ? y1 : y3 ) : ( y2 > y3 ? y2 : y3 );
  1134. resize();
  1135. } else {
  1136. _left = x1 < x2 ? ( x1 < x3 ? ( x1 < _left ? x1 : _left ) : ( x3 < _left ? x3 : _left ) ) : ( x2 < x3 ? ( x2 < _left ? x2 : _left ) : ( x3 < _left ? x3 : _left ) );
  1137. _top = y1 < y2 ? ( y1 < y3 ? ( y1 < _top ? y1 : _top ) : ( y3 < _top ? y3 : _top ) ) : ( y2 < y3 ? ( y2 < _top ? y2 : _top ) : ( y3 < _top ? y3 : _top ) );
  1138. _right = x1 > x2 ? ( x1 > x3 ? ( x1 > _right ? x1 : _right ) : ( x3 > _right ? x3 : _right ) ) : ( x2 > x3 ? ( x2 > _right ? x2 : _right ) : ( x3 > _right ? x3 : _right ) );
  1139. _bottom = y1 > y2 ? ( y1 > y3 ? ( y1 > _bottom ? y1 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ) : ( y2 > y3 ? ( y2 > _bottom ? y2 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) );
  1140. resize();
  1141. };
  1142. };
  1143. this.addRectangle = function ( r ) {
  1144. if ( _isEmpty === true ) {
  1145. _isEmpty = false;
  1146. _left = r.getLeft(); _top = r.getTop();
  1147. _right = r.getRight(); _bottom = r.getBottom();
  1148. resize();
  1149. } else {
  1150. _left = _left < r.getLeft() ? _left : r.getLeft(); // Math.min(_left, r.getLeft() );
  1151. _top = _top < r.getTop() ? _top : r.getTop(); // Math.min(_top, r.getTop() );
  1152. _right = _right > r.getRight() ? _right : r.getRight(); // Math.max(_right, r.getRight() );
  1153. _bottom = _bottom > r.getBottom() ? _bottom : r.getBottom(); // Math.max(_bottom, r.getBottom() );
  1154. resize();
  1155. }
  1156. };
  1157. this.inflate = function ( v ) {
  1158. _left -= v; _top -= v;
  1159. _right += v; _bottom += v;
  1160. resize();
  1161. };
  1162. this.minSelf = function ( r ) {
  1163. _left = _left > r.getLeft() ? _left : r.getLeft(); // Math.max( _left, r.getLeft() );
  1164. _top = _top > r.getTop() ? _top : r.getTop(); // Math.max( _top, r.getTop() );
  1165. _right = _right < r.getRight() ? _right : r.getRight(); // Math.min( _right, r.getRight() );
  1166. _bottom = _bottom < r.getBottom() ? _bottom : r.getBottom(); // Math.min( _bottom, r.getBottom() );
  1167. resize();
  1168. };
  1169. this.intersects = function ( r ) {
  1170. // http://gamemath.com/2011/09/detecting-whether-two-boxes-overlap/
  1171. if ( _right < r.getLeft() ) return false;
  1172. if ( _left > r.getRight() ) return false;
  1173. if ( _bottom < r.getTop() ) return false;
  1174. if ( _top > r.getBottom() ) return false;
  1175. return true;
  1176. };
  1177. this.empty = function () {
  1178. _isEmpty = true;
  1179. _left = 0; _top = 0;
  1180. _right = 0; _bottom = 0;
  1181. resize();
  1182. };
  1183. this.isEmpty = function () {
  1184. return _isEmpty;
  1185. };
  1186. };
  1187. /**
  1188. * @author alteredq / http://alteredqualia.com/
  1189. */
  1190. THREE.Math = {
  1191. // Clamp value to range <a, b>
  1192. clamp: function ( x, a, b ) {
  1193. return ( x < a ) ? a : ( ( x > b ) ? b : x );
  1194. },
  1195. // Clamp value to range <a, inf)
  1196. clampBottom: function ( x, a ) {
  1197. return x < a ? a : x;
  1198. },
  1199. // Linear mapping from range <a1, a2> to range <b1, b2>
  1200. mapLinear: function ( x, a1, a2, b1, b2 ) {
  1201. return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
  1202. },
  1203. // Random float from <0, 1> with 16 bits of randomness
  1204. // (standard Math.random() creates repetitive patterns when applied over larger space)
  1205. random16: function () {
  1206. return ( 65280 * Math.random() + 255 * Math.random() ) / 65535;
  1207. },
  1208. // Random integer from <low, high> interval
  1209. randInt: function ( low, high ) {
  1210. return low + Math.floor( Math.random() * ( high - low + 1 ) );
  1211. },
  1212. // Random float from <low, high> interval
  1213. randFloat: function ( low, high ) {
  1214. return low + Math.random() * ( high - low );
  1215. },
  1216. // Random float from <-range/2, range/2> interval
  1217. randFloatSpread: function ( range ) {
  1218. return range * ( 0.5 - Math.random() );
  1219. },
  1220. sign: function ( x ) {
  1221. return ( x < 0 ) ? -1 : ( ( x > 0 ) ? 1 : 0 );
  1222. }
  1223. };
  1224. /**
  1225. * @author alteredq / http://alteredqualia.com/
  1226. */
  1227. THREE.Matrix3 = function () {
  1228. this.elements = new Float32Array(9);
  1229. };
  1230. THREE.Matrix3.prototype = {
  1231. constructor: THREE.Matrix3,
  1232. getInverse: function ( matrix ) {
  1233. // input: THREE.Matrix4
  1234. // ( based on http://code.google.com/p/webgl-mjs/ )
  1235. var me = matrix.elements;
  1236. var a11 = me[10] * me[5] - me[6] * me[9];
  1237. var a21 = - me[10] * me[1] + me[2] * me[9];
  1238. var a31 = me[6] * me[1] - me[2] * me[5];
  1239. var a12 = - me[10] * me[4] + me[6] * me[8];
  1240. var a22 = me[10] * me[0] - me[2] * me[8];
  1241. var a32 = - me[6] * me[0] + me[2] * me[4];
  1242. var a13 = me[9] * me[4] - me[5] * me[8];
  1243. var a23 = - me[9] * me[0] + me[1] * me[8];
  1244. var a33 = me[5] * me[0] - me[1] * me[4];
  1245. var det = me[0] * a11 + me[1] * a12 + me[2] * a13;
  1246. // no inverse
  1247. if ( det === 0 ) {
  1248. console.warn( "Matrix3.getInverse(): determinant == 0" );
  1249. }
  1250. var idet = 1.0 / det;
  1251. var m = this.elements;
  1252. m[ 0 ] = idet * a11; m[ 1 ] = idet * a21; m[ 2 ] = idet * a31;
  1253. m[ 3 ] = idet * a12; m[ 4 ] = idet * a22; m[ 5 ] = idet * a32;
  1254. m[ 6 ] = idet * a13; m[ 7 ] = idet * a23; m[ 8 ] = idet * a33;
  1255. return this;
  1256. },
  1257. transpose: function () {
  1258. var tmp, m = this.elements;
  1259. tmp = m[1]; m[1] = m[3]; m[3] = tmp;
  1260. tmp = m[2]; m[2] = m[6]; m[6] = tmp;
  1261. tmp = m[5]; m[5] = m[7]; m[7] = tmp;
  1262. return this;
  1263. },
  1264. transposeIntoArray: function ( r ) {
  1265. var m = this.m;
  1266. r[ 0 ] = m[ 0 ];
  1267. r[ 1 ] = m[ 3 ];
  1268. r[ 2 ] = m[ 6 ];
  1269. r[ 3 ] = m[ 1 ];
  1270. r[ 4 ] = m[ 4 ];
  1271. r[ 5 ] = m[ 7 ];
  1272. r[ 6 ] = m[ 2 ];
  1273. r[ 7 ] = m[ 5 ];
  1274. r[ 8 ] = m[ 8 ];
  1275. return this;
  1276. }
  1277. };
  1278. /**
  1279. * @author mr.doob / http://mrdoob.com/
  1280. * @author supereggbert / http://www.paulbrunt.co.uk/
  1281. * @author philogb / http://blog.thejit.org/
  1282. * @author jordi_ros / http://plattsoft.com
  1283. * @author D1plo1d / http://github.com/D1plo1d
  1284. * @author alteredq / http://alteredqualia.com/
  1285. * @author mikael emtinger / http://gomo.se/
  1286. * @author timknip / http://www.floorplanner.com/
  1287. */
  1288. THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
  1289. this.elements = new Float32Array( 16 );
  1290. this.set(
  1291. ( n11 !== undefined ) ? n11 : 1, n12 || 0, n13 || 0, n14 || 0,
  1292. n21 || 0, ( n22 !== undefined ) ? n22 : 1, n23 || 0, n24 || 0,
  1293. n31 || 0, n32 || 0, ( n33 !== undefined ) ? n33 : 1, n34 || 0,
  1294. n41 || 0, n42 || 0, n43 || 0, ( n44 !== undefined ) ? n44 : 1
  1295. );
  1296. };
  1297. THREE.Matrix4.prototype = {
  1298. constructor: THREE.Matrix4,
  1299. set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
  1300. var te = this.elements;
  1301. te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
  1302. te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
  1303. te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
  1304. te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
  1305. return this;
  1306. },
  1307. identity: function () {
  1308. this.set(
  1309. 1, 0, 0, 0,
  1310. 0, 1, 0, 0,
  1311. 0, 0, 1, 0,
  1312. 0, 0, 0, 1
  1313. );
  1314. return this;
  1315. },
  1316. copy: function ( m ) {
  1317. var me = m.elements;
  1318. this.set(
  1319. me[0], me[4], me[8], me[12],
  1320. me[1], me[5], me[9], me[13],
  1321. me[2], me[6], me[10], me[14],
  1322. me[3], me[7], me[11], me[15]
  1323. );
  1324. return this;
  1325. },
  1326. lookAt: function ( eye, target, up ) {
  1327. var te = this.elements;
  1328. var x = THREE.Matrix4.__v1;
  1329. var y = THREE.Matrix4.__v2;
  1330. var z = THREE.Matrix4.__v3;
  1331. z.sub( eye, target ).normalize();
  1332. if ( z.length() === 0 ) {
  1333. z.z = 1;
  1334. }
  1335. x.cross( up, z ).normalize();
  1336. if ( x.length() === 0 ) {
  1337. z.x += 0.0001;
  1338. x.cross( up, z ).normalize();
  1339. }
  1340. y.cross( z, x );
  1341. te[0] = x.x; te[4] = y.x; te[8] = z.x;
  1342. te[1] = x.y; te[5] = y.y; te[9] = z.y;
  1343. te[2] = x.z; te[6] = y.z; te[10] = z.z;
  1344. return this;
  1345. },
  1346. multiply: function ( a, b ) {
  1347. var ae = a.elements;
  1348. var be = b.elements;
  1349. var te = this.elements;
  1350. var a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
  1351. var a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
  1352. var a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
  1353. var a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
  1354. var b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
  1355. var b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
  1356. var b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
  1357. var b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
  1358. te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
  1359. te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
  1360. te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
  1361. te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
  1362. te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
  1363. te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
  1364. te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
  1365. te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
  1366. te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
  1367. te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
  1368. te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
  1369. te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
  1370. te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
  1371. te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
  1372. te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
  1373. te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
  1374. return this;
  1375. },
  1376. multiplySelf: function ( m ) {
  1377. return this.multiply( this, m );
  1378. },
  1379. multiplyToArray: function ( a, b, r ) {
  1380. var te = this.elements;
  1381. this.multiply( a, b );
  1382. r[ 0 ] = te[0]; r[ 1 ] = te[1]; r[ 2 ] = te[2]; r[ 3 ] = te[3];
  1383. r[ 4 ] = te[4]; r[ 5 ] = te[5]; r[ 6 ] = te[6]; r[ 7 ] = te[7];
  1384. r[ 8 ] = te[8]; r[ 9 ] = te[9]; r[ 10 ] = te[10]; r[ 11 ] = te[11];
  1385. r[ 12 ] = te[12]; r[ 13 ] = te[13]; r[ 14 ] = te[14]; r[ 15 ] = te[15];
  1386. return this;
  1387. },
  1388. multiplyScalar: function ( s ) {
  1389. var te = this.elements;
  1390. te[0] *= s; te[4] *= s; te[8] *= s; te[12] *= s;
  1391. te[1] *= s; te[5] *= s; te[9] *= s; te[13] *= s;
  1392. te[2] *= s; te[6] *= s; te[10] *= s; te[14] *= s;
  1393. te[3] *= s; te[7] *= s; te[11] *= s; te[15] *= s;
  1394. return this;
  1395. },
  1396. multiplyVector3: function ( v ) {
  1397. var te = this.elements;
  1398. var vx = v.x, vy = v.y, vz = v.z;
  1399. var d = 1 / ( te[3] * vx + te[7] * vy + te[11] * vz + te[15] );
  1400. v.x = ( te[0] * vx + te[4] * vy + te[8] * vz + te[12] ) * d;
  1401. v.y = ( te[1] * vx + te[5] * vy + te[9] * vz + te[13] ) * d;
  1402. v.z = ( te[2] * vx + te[6] * vy + te[10] * vz + te[14] ) * d;
  1403. return v;
  1404. },
  1405. multiplyVector4: function ( v ) {
  1406. var te = this.elements;
  1407. var vx = v.x, vy = v.y, vz = v.z, vw = v.w;
  1408. v.x = te[0] * vx + te[4] * vy + te[8] * vz + te[12] * vw;
  1409. v.y = te[1] * vx + te[5] * vy + te[9] * vz + te[13] * vw;
  1410. v.z = te[2] * vx + te[6] * vy + te[10] * vz + te[14] * vw;
  1411. v.w = te[3] * vx + te[7] * vy + te[11] * vz + te[15] * vw;
  1412. return v;
  1413. },
  1414. multiplyVector3Array: function ( a ) {
  1415. var tmp = THREE.Matrix4.__v1;
  1416. for ( var i = 0, il = a.length; i < il; i += 3 ) {
  1417. tmp.x = a[ i ];
  1418. tmp.y = a[ i + 1 ];
  1419. tmp.z = a[ i + 2 ];
  1420. this.multiplyVector3( tmp );
  1421. a[ i ] = tmp.x;
  1422. a[ i + 1 ] = tmp.y;
  1423. a[ i + 2 ] = tmp.z;
  1424. }
  1425. return a;
  1426. },
  1427. rotateAxis: function ( v ) {
  1428. var te = this.elements;
  1429. var vx = v.x, vy = v.y, vz = v.z;
  1430. v.x = vx * te[0] + vy * te[4] + vz * te[8];
  1431. v.y = vx * te[1] + vy * te[5] + vz * te[9];
  1432. v.z = vx * te[2] + vy * te[6] + vz * te[10];
  1433. v.normalize();
  1434. return v;
  1435. },
  1436. crossVector: function ( a ) {
  1437. var te = this.elements;
  1438. var v = new THREE.Vector4();
  1439. v.x = te[0] * a.x + te[4] * a.y + te[8] * a.z + te[12] * a.w;
  1440. v.y = te[1] * a.x + te[5] * a.y + te[9] * a.z + te[13] * a.w;
  1441. v.z = te[2] * a.x + te[6] * a.y + te[10] * a.z + te[14] * a.w;
  1442. v.w = ( a.w ) ? te[3] * a.x + te[7] * a.y + te[11] * a.z + te[15] * a.w : 1;
  1443. return v;
  1444. },
  1445. determinant: function () {
  1446. var te = this.elements;
  1447. var n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12];
  1448. var n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13];
  1449. var n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14];
  1450. var n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15];
  1451. //TODO: make this more efficient
  1452. //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  1453. return (
  1454. n14 * n23 * n32 * n41-
  1455. n13 * n24 * n32 * n41-
  1456. n14 * n22 * n33 * n41+
  1457. n12 * n24 * n33 * n41+
  1458. n13 * n22 * n34 * n41-
  1459. n12 * n23 * n34 * n41-
  1460. n14 * n23 * n31 * n42+
  1461. n13 * n24 * n31 * n42+
  1462. n14 * n21 * n33 * n42-
  1463. n11 * n24 * n33 * n42-
  1464. n13 * n21 * n34 * n42+
  1465. n11 * n23 * n34 * n42+
  1466. n14 * n22 * n31 * n43-
  1467. n12 * n24 * n31 * n43-
  1468. n14 * n21 * n32 * n43+
  1469. n11 * n24 * n32 * n43+
  1470. n12 * n21 * n34 * n43-
  1471. n11 * n22 * n34 * n43-
  1472. n13 * n22 * n31 * n44+
  1473. n12 * n23 * n31 * n44+
  1474. n13 * n21 * n32 * n44-
  1475. n11 * n23 * n32 * n44-
  1476. n12 * n21 * n33 * n44+
  1477. n11 * n22 * n33 * n44
  1478. );
  1479. },
  1480. transpose: function () {
  1481. var te = this.elements;
  1482. var tmp;
  1483. tmp = te[1]; te[1] = te[4]; te[4] = tmp;
  1484. tmp = te[2]; te[2] = te[8]; te[8] = tmp;
  1485. tmp = te[6]; te[6] = te[9]; te[9] = tmp;
  1486. tmp = te[3]; te[3] = te[12]; te[12] = tmp;
  1487. tmp = te[7]; te[7] = te[13]; te[13] = tmp;
  1488. tmp = te[11]; te[11] = te[14]; te[14] = tmp;
  1489. return this;
  1490. },
  1491. flattenToArray: function ( flat ) {
  1492. var te = this.elements;
  1493. flat[ 0 ] = te[0]; flat[ 1 ] = te[1]; flat[ 2 ] = te[2]; flat[ 3 ] = te[3];
  1494. flat[ 4 ] = te[4]; flat[ 5 ] = te[5]; flat[ 6 ] = te[6]; flat[ 7 ] = te[7];
  1495. flat[ 8 ] = te[8]; flat[ 9 ] = te[9]; flat[ 10 ] = te[10]; flat[ 11 ] = te[11];
  1496. flat[ 12 ] = te[12]; flat[ 13 ] = te[13]; flat[ 14 ] = te[14]; flat[ 15 ] = te[15];
  1497. return flat;
  1498. },
  1499. flattenToArrayOffset: function( flat, offset ) {
  1500. var te = this.elements;
  1501. flat[ offset ] = te[0];
  1502. flat[ offset + 1 ] = te[1];
  1503. flat[ offset + 2 ] = te[2];
  1504. flat[ offset + 3 ] = te[3];
  1505. flat[ offset + 4 ] = te[4];
  1506. flat[ offset + 5 ] = te[5];
  1507. flat[ offset + 6 ] = te[6];
  1508. flat[ offset + 7 ] = te[7];
  1509. flat[ offset + 8 ] = te[8];
  1510. flat[ offset + 9 ] = te[9];
  1511. flat[ offset + 10 ] = te[10];
  1512. flat[ offset + 11 ] = te[11];
  1513. flat[ offset + 12 ] = te[12];
  1514. flat[ offset + 13 ] = te[13];
  1515. flat[ offset + 14 ] = te[14];
  1516. flat[ offset + 15 ] = te[15];
  1517. return flat;
  1518. },
  1519. getPosition: function () {
  1520. var te = this.elements;
  1521. return THREE.Matrix4.__v1.set( te[12], te[13], te[14] );
  1522. },
  1523. setPosition: function ( v ) {
  1524. var te = this.elements;
  1525. te[12] = v.x;
  1526. te[13] = v.y;
  1527. te[14] = v.z;
  1528. return this;
  1529. },
  1530. getColumnX: function () {
  1531. var te = this.elements;
  1532. return THREE.Matrix4.__v1.set( te[0], te[1], te[2] );
  1533. },
  1534. getColumnY: function () {
  1535. var te = this.elements;
  1536. return THREE.Matrix4.__v1.set( te[4], te[5], te[6] );
  1537. },
  1538. getColumnZ: function() {
  1539. var te = this.elements;
  1540. return THREE.Matrix4.__v1.set( te[8], te[9], te[10] );
  1541. },
  1542. getInverse: function ( m ) {
  1543. // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
  1544. var te = this.elements;
  1545. var me = m.elements;
  1546. var n11 = me[0], n12 = me[4], n13 = me[8], n14 = me[12];
  1547. var n21 = me[1], n22 = me[5], n23 = me[9], n24 = me[13];
  1548. var n31 = me[2], n32 = me[6], n33 = me[10], n34 = me[14];
  1549. var n41 = me[3], n42 = me[7], n43 = me[11], n44 = me[15];
  1550. te[0] = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
  1551. te[4] = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
  1552. te[8] = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;
  1553. te[12] = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;
  1554. te[1] = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;
  1555. te[5] = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;
  1556. te[9] = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;
  1557. te[13] = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;
  1558. te[2] = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;
  1559. te[6] = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;
  1560. te[10] = n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;
  1561. te[14] = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;
  1562. te[3] = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;
  1563. te[7] = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;
  1564. te[11] = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;
  1565. te[15] = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;
  1566. this.multiplyScalar( 1 / m.determinant() );
  1567. return this;
  1568. },
  1569. setRotationFromEuler: function ( v, order ) {
  1570. var te = this.elements;
  1571. var x = v.x, y = v.y, z = v.z;
  1572. var a = Math.cos( x ), b = Math.sin( x );
  1573. var c = Math.cos( y ), d = Math.sin( y );
  1574. var e = Math.cos( z ), f = Math.sin( z );
  1575. if ( order === undefined || order === 'XYZ' ) {
  1576. var ae = a * e, af = a * f, be = b * e, bf = b * f;
  1577. te[0] = c * e;
  1578. te[4] = - c * f;
  1579. te[8] = d;
  1580. te[1] = af + be * d;
  1581. te[5] = ae - bf * d;
  1582. te[9] = - b * c;
  1583. te[2] = bf - ae * d;
  1584. te[6] = be + af * d;
  1585. te[10] = a * c;
  1586. } else if ( order === 'YXZ' ) {
  1587. var ce = c * e, cf = c * f, de = d * e, df = d * f;
  1588. te[0] = ce + df * b;
  1589. te[4] = de * b - cf;
  1590. te[8] = a * d;
  1591. te[1] = a * f;
  1592. te[5] = a * e;
  1593. te[9] = - b;
  1594. te[2] = cf * b - de;
  1595. te[6] = df + ce * b;
  1596. te[10] = a * c;
  1597. } else if ( order === 'ZXY' ) {
  1598. var ce = c * e, cf = c * f, de = d * e, df = d * f;
  1599. te[0] = ce - df * b;
  1600. te[4] = - a * f;
  1601. te[8] = de + cf * b;
  1602. te[1] = cf + de * b;
  1603. te[5] = a * e;
  1604. te[9] = df - ce * b;
  1605. te[2] = - a * d;
  1606. te[6] = b;
  1607. te[10] = a * c;
  1608. } else if ( order === 'ZYX' ) {
  1609. var ae = a * e, af = a * f, be = b * e, bf = b * f;
  1610. te[0] = c * e;
  1611. te[4] = be * d - af;
  1612. te[8] = ae * d + bf;
  1613. te[1] = c * f;
  1614. te[5] = bf * d + ae;
  1615. te[9] = af * d - be;
  1616. te[2] = - d;
  1617. te[6] = b * c;
  1618. te[10] = a * c;
  1619. } else if ( order === 'YZX' ) {
  1620. var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
  1621. te[0] = c * e;
  1622. te[4] = bd - ac * f;
  1623. te[8] = bc * f + ad;
  1624. te[1] = f;
  1625. te[5] = a * e;
  1626. te[9] = - b * e;
  1627. te[2] = - d * e;
  1628. te[6] = ad * f + bc;
  1629. te[10] = ac - bd * f;
  1630. } else if ( order === 'XZY' ) {
  1631. var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
  1632. te[0] = c * e;
  1633. te[4] = - f;
  1634. te[8] = d * e;
  1635. te[1] = ac * f + bd;
  1636. te[5] = a * e;
  1637. te[9] = ad * f - bc;
  1638. te[2] = bc * f - ad;
  1639. te[6] = b * e;
  1640. te[10] = bd * f + ac;
  1641. }
  1642. return this;
  1643. },
  1644. setRotationFromQuaternion: function ( q ) {
  1645. var te = this.elements;
  1646. var x = q.x, y = q.y, z = q.z, w = q.w;
  1647. var x2 = x + x, y2 = y + y, z2 = z + z;
  1648. var xx = x * x2, xy = x * y2, xz = x * z2;
  1649. var yy = y * y2, yz = y * z2, zz = z * z2;
  1650. var wx = w * x2, wy = w * y2, wz = w * z2;
  1651. te[0] = 1 - ( yy + zz );
  1652. te[4] = xy - wz;
  1653. te[8] = xz + wy;
  1654. te[1] = xy + wz;
  1655. te[5] = 1 - ( xx + zz );
  1656. te[9] = yz - wx;
  1657. te[2] = xz - wy;
  1658. te[6] = yz + wx;
  1659. te[10] = 1 - ( xx + yy );
  1660. return this;
  1661. },
  1662. compose: function ( translation, rotation, scale ) {
  1663. var te = this.elements;
  1664. var mRotation = THREE.Matrix4.__m1;
  1665. var mScale = THREE.Matrix4.__m2;
  1666. mRotation.identity();
  1667. mRotation.setRotationFromQuaternion( rotation );
  1668. mScale.makeScale( scale.x, scale.y, scale.z );
  1669. this.multiply( mRotation, mScale );
  1670. te[12] = translation.x;
  1671. te[13] = translation.y;
  1672. te[14] = translation.z;
  1673. return this;
  1674. },
  1675. decompose: function ( translation, rotation, scale ) {
  1676. var te = this.elements;
  1677. // grab the axis vectors
  1678. var x = THREE.Matrix4.__v1;
  1679. var y = THREE.Matrix4.__v2;
  1680. var z = THREE.Matrix4.__v3;
  1681. x.set( te[0], te[1], te[2] );
  1682. y.set( te[4], te[5], te[6] );
  1683. z.set( te[8], te[9], te[10] );
  1684. translation = ( translation instanceof THREE.Vector3 ) ? translation : new THREE.Vector3();
  1685. rotation = ( rotation instanceof THREE.Quaternion ) ? rotation : new THREE.Quaternion();
  1686. scale = ( scale instanceof THREE.Vector3 ) ? scale : new THREE.Vector3();
  1687. scale.x = x.length();
  1688. scale.y = y.length();
  1689. scale.z = z.length();
  1690. translation.x = te[12];
  1691. translation.y = te[13];
  1692. translation.z = te[14];
  1693. // scale the rotation part
  1694. var matrix = THREE.Matrix4.__m1;
  1695. matrix.copy( this );
  1696. matrix.elements[0] /= scale.x;
  1697. matrix.elements[1] /= scale.x;
  1698. matrix.elements[2] /= scale.x;
  1699. matrix.elements[4] /= scale.y;
  1700. matrix.elements[5] /= scale.y;
  1701. matrix.elements[6] /= scale.y;
  1702. matrix.elements[8] /= scale.z;
  1703. matrix.elements[9] /= scale.z;
  1704. matrix.elements[10] /= scale.z;
  1705. rotation.setFromRotationMatrix( matrix );
  1706. return [ translation, rotation, scale ];
  1707. },
  1708. extractPosition: function ( m ) {
  1709. var te = this.elements;
  1710. var me = m.elements;
  1711. te[12] = me[12];
  1712. te[13] = me[13];
  1713. te[14] = me[14];
  1714. return this;
  1715. },
  1716. extractRotation: function ( m ) {
  1717. var te = this.elements;
  1718. var me = m.elements;
  1719. var vector = THREE.Matrix4.__v1;
  1720. var scaleX = 1 / vector.set( me[0], me[1], me[2] ).length();
  1721. var scaleY = 1 / vector.set( me[4], me[5], me[6] ).length();
  1722. var scaleZ = 1 / vector.set( me[8], me[9], me[10] ).length();
  1723. te[0] = me[0] * scaleX;
  1724. te[1] = me[1] * scaleX;
  1725. te[2] = me[2] * scaleX;
  1726. te[4] = me[4] * scaleY;
  1727. te[5] = me[5] * scaleY;
  1728. te[6] = me[6] * scaleY;
  1729. te[8] = me[8] * scaleZ;
  1730. te[9] = me[9] * scaleZ;
  1731. te[10] = me[10] * scaleZ;
  1732. return this;
  1733. },
  1734. //
  1735. translate: function ( v ) {
  1736. var te = this.elements;
  1737. var x = v.x, y = v.y, z = v.z;
  1738. te[12] = te[0] * x + te[4] * y + te[8] * z + te[12];
  1739. te[13] = te[1] * x + te[5] * y + te[9] * z + te[13];
  1740. te[14] = te[2] * x + te[6] * y + te[10] * z + te[14];
  1741. te[15] = te[3] * x + te[7] * y + te[11] * z + te[15];
  1742. return this;
  1743. },
  1744. rotateX: function ( angle ) {
  1745. var te = this.elements;
  1746. var m12 = te[4];
  1747. var m22 = te[5];
  1748. var m32 = te[6];
  1749. var m42 = te[7];
  1750. var m13 = te[8];
  1751. var m23 = te[9];
  1752. var m33 = te[10];
  1753. var m43 = te[11];
  1754. var c = Math.cos( angle );
  1755. var s = Math.sin( angle );
  1756. te[4] = c * m12 + s * m13;
  1757. te[5] = c * m22 + s * m23;
  1758. te[6] = c * m32 + s * m33;
  1759. te[7] = c * m42 + s * m43;
  1760. te[8] = c * m13 - s * m12;
  1761. te[9] = c * m23 - s * m22;
  1762. te[10] = c * m33 - s * m32;
  1763. te[11] = c * m43 - s * m42;
  1764. return this;
  1765. },
  1766. rotateY: function ( angle ) {
  1767. var te = this.elements;
  1768. var m11 = te[0];
  1769. var m21 = te[1];
  1770. var m31 = te[2];
  1771. var m41 = te[3];
  1772. var m13 = te[8];
  1773. var m23 = te[9];
  1774. var m33 = te[10];
  1775. var m43 = te[11];
  1776. var c = Math.cos( angle );
  1777. var s = Math.sin( angle );
  1778. te[0] = c * m11 - s * m13;
  1779. te[1] = c * m21 - s * m23;
  1780. te[2] = c * m31 - s * m33;
  1781. te[3] = c * m41 - s * m43;
  1782. te[8] = c * m13 + s * m11;
  1783. te[9] = c * m23 + s * m21;
  1784. te[10] = c * m33 + s * m31;
  1785. te[11] = c * m43 + s * m41;
  1786. return this;
  1787. },
  1788. rotateZ: function ( angle ) {
  1789. var te = this.elements;
  1790. var m11 = te[0];
  1791. var m21 = te[1];
  1792. var m31 = te[2];
  1793. var m41 = te[3];
  1794. var m12 = te[4];
  1795. var m22 = te[5];
  1796. var m32 = te[6];
  1797. var m42 = te[7];
  1798. var c = Math.cos( angle );
  1799. var s = Math.sin( angle );
  1800. te[0] = c * m11 + s * m12;
  1801. te[1] = c * m21 + s * m22;
  1802. te[2] = c * m31 + s * m32;
  1803. te[3] = c * m41 + s * m42;
  1804. te[4] = c * m12 - s * m11;
  1805. te[5] = c * m22 - s * m21;
  1806. te[6] = c * m32 - s * m31;
  1807. te[7] = c * m42 - s * m41;
  1808. return this;
  1809. },
  1810. rotateByAxis: function ( axis, angle ) {
  1811. var te = this.elements;
  1812. // optimize by checking axis
  1813. if ( axis.x === 1 && axis.y === 0 && axis.z === 0 ) {
  1814. return this.rotateX( angle );
  1815. } else if ( axis.x === 0 && axis.y === 1 && axis.z === 0 ) {
  1816. return this.rotateY( angle );
  1817. } else if ( axis.x === 0 && axis.y === 0 && axis.z === 1 ) {
  1818. return this.rotateZ( angle );
  1819. }
  1820. var x = axis.x, y = axis.y, z = axis.z;
  1821. var n = Math.sqrt(x * x + y * y + z * z);
  1822. x /= n;
  1823. y /= n;
  1824. z /= n;
  1825. var xx = x * x, yy = y * y, zz = z * z;
  1826. var c = Math.cos( angle );
  1827. var s = Math.sin( angle );
  1828. var oneMinusCosine = 1 - c;
  1829. var xy = x * y * oneMinusCosine;
  1830. var xz = x * z * oneMinusCosine;
  1831. var yz = y * z * oneMinusCosine;
  1832. var xs = x * s;
  1833. var ys = y * s;
  1834. var zs = z * s;
  1835. var r11 = xx + (1 - xx) * c;
  1836. var r21 = xy + zs;
  1837. var r31 = xz - ys;
  1838. var r12 = xy - zs;
  1839. var r22 = yy + (1 - yy) * c;
  1840. var r32 = yz + xs;
  1841. var r13 = xz + ys;
  1842. var r23 = yz - xs;
  1843. var r33 = zz + (1 - zz) * c;
  1844. var m11 = te[0], m21 = te[1], m31 = te[2], m41 = te[3];
  1845. var m12 = te[4], m22 = te[5], m32 = te[6], m42 = te[7];
  1846. var m13 = te[8], m23 = te[9], m33 = te[10], m43 = te[11];
  1847. var m14 = te[12], m24 = te[13], m34 = te[14], m44 = te[15];
  1848. te[0] = r11 * m11 + r21 * m12 + r31 * m13;
  1849. te[1] = r11 * m21 + r21 * m22 + r31 * m23;
  1850. te[2] = r11 * m31 + r21 * m32 + r31 * m33;
  1851. te[3] = r11 * m41 + r21 * m42 + r31 * m43;
  1852. te[4] = r12 * m11 + r22 * m12 + r32 * m13;
  1853. te[5] = r12 * m21 + r22 * m22 + r32 * m23;
  1854. te[6] = r12 * m31 + r22 * m32 + r32 * m33;
  1855. te[7] = r12 * m41 + r22 * m42 + r32 * m43;
  1856. te[8] = r13 * m11 + r23 * m12 + r33 * m13;
  1857. te[9] = r13 * m21 + r23 * m22 + r33 * m23;
  1858. te[10] = r13 * m31 + r23 * m32 + r33 * m33;
  1859. te[11] = r13 * m41 + r23 * m42 + r33 * m43;
  1860. return this;
  1861. },
  1862. scale: function ( v ) {
  1863. var te = this.elements;
  1864. var x = v.x, y = v.y, z = v.z;
  1865. te[0] *= x; te[4] *= y; te[8] *= z;
  1866. te[1] *= x; te[5] *= y; te[9] *= z;
  1867. te[2] *= x; te[6] *= y; te[10] *= z;
  1868. te[3] *= x; te[7] *= y; te[11] *= z;
  1869. return this;
  1870. },
  1871. getMaxScaleOnAxis: function () {
  1872. var te = this.elements;
  1873. var scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
  1874. var scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
  1875. var scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
  1876. return Math.sqrt( Math.max( scaleXSq, Math.max( scaleYSq, scaleZSq ) ) );
  1877. },
  1878. //
  1879. makeTranslation: function ( x, y, z ) {
  1880. this.set(
  1881. 1, 0, 0, x,
  1882. 0, 1, 0, y,
  1883. 0, 0, 1, z,
  1884. 0, 0, 0, 1
  1885. );
  1886. return this;
  1887. },
  1888. makeRotationX: function ( theta ) {
  1889. var c = Math.cos( theta ), s = Math.sin( theta );
  1890. this.set(
  1891. 1, 0, 0, 0,
  1892. 0, c, -s, 0,
  1893. 0, s, c, 0,
  1894. 0, 0, 0, 1
  1895. );
  1896. return this;
  1897. },
  1898. makeRotationY: function ( theta ) {
  1899. var c = Math.cos( theta ), s = Math.sin( theta );
  1900. this.set(
  1901. c, 0, s, 0,
  1902. 0, 1, 0, 0,
  1903. -s, 0, c, 0,
  1904. 0, 0, 0, 1
  1905. );
  1906. return this;
  1907. },
  1908. makeRotationZ: function ( theta ) {
  1909. var c = Math.cos( theta ), s = Math.sin( theta );
  1910. this.set(
  1911. c, -s, 0, 0,
  1912. s, c, 0, 0,
  1913. 0, 0, 1, 0,
  1914. 0, 0, 0, 1
  1915. );
  1916. return this;
  1917. },
  1918. makeRotationAxis: function ( axis, angle ) {
  1919. // Based on http://www.gamedev.net/reference/articles/article1199.asp
  1920. var c = Math.cos( angle );
  1921. var s = Math.sin( angle );
  1922. var t = 1 - c;
  1923. var x = axis.x, y = axis.y, z = axis.z;
  1924. var tx = t * x, ty = t * y;
  1925. this.set(
  1926. tx * x + c, tx * y - s * z, tx * z + s * y, 0,
  1927. tx * y + s * z, ty * y + c, ty * z - s * x, 0,
  1928. tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
  1929. 0, 0, 0, 1
  1930. );
  1931. return this;
  1932. },
  1933. makeScale: function ( x, y, z ) {
  1934. this.set(
  1935. x, 0, 0, 0,
  1936. 0, y, 0, 0,
  1937. 0, 0, z, 0,
  1938. 0, 0, 0, 1
  1939. );
  1940. return this;
  1941. },
  1942. makeFrustum: function ( left, right, bottom, top, near, far ) {
  1943. var te = this.elements;
  1944. var x = 2 * near / ( right - left );
  1945. var y = 2 * near / ( top - bottom );
  1946. var a = ( right + left ) / ( right - left );
  1947. var b = ( top + bottom ) / ( top - bottom );
  1948. var c = - ( far + near ) / ( far - near );
  1949. var d = - 2 * far * near / ( far - near );
  1950. te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
  1951. te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
  1952. te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
  1953. te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
  1954. return this;
  1955. },
  1956. makePerspective: function ( fov, aspect, near, far ) {
  1957. var ymax = near * Math.tan( fov * Math.PI / 360 );
  1958. var ymin = - ymax;
  1959. var xmin = ymin * aspect;
  1960. var xmax = ymax * aspect;
  1961. return this.makeFrustum( xmin, xmax, ymin, ymax, near, far );
  1962. },
  1963. makeOrthographic: function ( left, right, top, bottom, near, far ) {
  1964. var te = this.elements;
  1965. var w = right - left;
  1966. var h = top - bottom;
  1967. var p = far - near;
  1968. var x = ( right + left ) / w;
  1969. var y = ( top + bottom ) / h;
  1970. var z = ( far + near ) / p;
  1971. te[0] = 2 / w; te[4] = 0; te[8] = 0; te[12] = -x;
  1972. te[1] = 0; te[5] = 2 / h; te[9] = 0; te[13] = -y;
  1973. te[2] = 0; te[6] = 0; te[10] = -2 / p; te[14] = -z;
  1974. te[3] = 0; te[7] = 0; te[11] = 0; te[15] = 1;
  1975. return this;
  1976. },
  1977. clone: function () {
  1978. var te = this.elements;
  1979. return new THREE.Matrix4(
  1980. te[0], te[4], te[8], te[12],
  1981. te[1], te[5], te[9], te[13],
  1982. te[2], te[6], te[10], te[14],
  1983. te[3], te[7], te[11], te[15]
  1984. );
  1985. }
  1986. };
  1987. THREE.Matrix4.__v1 = new THREE.Vector3();
  1988. THREE.Matrix4.__v2 = new THREE.Vector3();
  1989. THREE.Matrix4.__v3 = new THREE.Vector3();
  1990. THREE.Matrix4.__m1 = new THREE.Matrix4();
  1991. THREE.Matrix4.__m2 = new THREE.Matrix4();
  1992. /**
  1993. * @author mr.doob / http://mrdoob.com/
  1994. * @author mikael emtinger / http://gomo.se/
  1995. * @author alteredq / http://alteredqualia.com/
  1996. */
  1997. THREE.Object3D = function () {
  1998. this.id = THREE.Object3DCount ++;
  1999. this.name = '';
  2000. this.parent = undefined;
  2001. this.children = [];
  2002. this.up = new THREE.Vector3( 0, 1, 0 );
  2003. this.position = new THREE.Vector3();
  2004. this.rotation = new THREE.Vector3();
  2005. this.eulerOrder = 'XYZ';
  2006. this.scale = new THREE.Vector3( 1, 1, 1 );
  2007. this.doubleSided = false;
  2008. this.flipSided = false;
  2009. this.renderDepth = null;
  2010. this.rotationAutoUpdate = true;
  2011. this.matrix = new THREE.Matrix4();
  2012. this.matrixWorld = new THREE.Matrix4();
  2013. this.matrixRotationWorld = new THREE.Matrix4();
  2014. this.matrixAutoUpdate = true;
  2015. this.matrixWorldNeedsUpdate = true;
  2016. this.quaternion = new THREE.Quaternion();
  2017. this.useQuaternion = false;
  2018. this.boundRadius = 0.0;
  2019. this.boundRadiusScale = 1.0;
  2020. this.visible = true;
  2021. this.castShadow = false;
  2022. this.receiveShadow = false;
  2023. this.frustumCulled = true;
  2024. this._vector = new THREE.Vector3();
  2025. };
  2026. THREE.Object3D.prototype = {
  2027. constructor: THREE.Object3D,
  2028. applyMatrix: function ( matrix ) {
  2029. this.matrix.multiply( matrix, this.matrix );
  2030. this.scale.getScaleFromMatrix( this.matrix );
  2031. var mat = new THREE.Matrix4().extractRotation( this.matrix );
  2032. this.rotation.setEulerFromRotationMatrix( mat, this.eulerOrder );
  2033. this.position.getPositionFromMatrix( this.matrix );
  2034. },
  2035. translate: function ( distance, axis ) {
  2036. this.matrix.rotateAxis( axis );
  2037. this.position.addSelf( axis.multiplyScalar( distance ) );
  2038. },
  2039. translateX: function ( distance ) {
  2040. this.translate( distance, this._vector.set( 1, 0, 0 ) );
  2041. },
  2042. translateY: function ( distance ) {
  2043. this.translate( distance, this._vector.set( 0, 1, 0 ) );
  2044. },
  2045. translateZ: function ( distance ) {
  2046. this.translate( distance, this._vector.set( 0, 0, 1 ) );
  2047. },
  2048. lookAt: function ( vector ) {
  2049. // TODO: Add hierarchy support.
  2050. this.matrix.lookAt( vector, this.position, this.up );
  2051. if ( this.rotationAutoUpdate ) {
  2052. this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
  2053. }
  2054. },
  2055. add: function ( object ) {
  2056. if ( object === this ) {
  2057. console.warn( 'THREE.Object3D.add: An object can\'t be added as a child of itself.' );
  2058. return;
  2059. }
  2060. if ( object instanceof THREE.Object3D ) {
  2061. if ( object.parent !== undefined ) {
  2062. object.parent.remove( object );
  2063. }
  2064. object.parent = this;
  2065. this.children.push( object );
  2066. // add to scene
  2067. var scene = this;
  2068. while ( scene.parent !== undefined ) {
  2069. scene = scene.parent;
  2070. }
  2071. if ( scene !== undefined && scene instanceof THREE.Scene ) {
  2072. scene.__addObject( object );
  2073. }
  2074. }
  2075. },
  2076. remove: function ( object ) {
  2077. var index = this.children.indexOf( object );
  2078. if ( index !== - 1 ) {
  2079. object.parent = undefined;
  2080. this.children.splice( index, 1 );
  2081. // remove from scene
  2082. var scene = this;
  2083. while ( scene.parent !== undefined ) {
  2084. scene = scene.parent;
  2085. }
  2086. if ( scene !== undefined && scene instanceof THREE.Scene ) {
  2087. scene.__removeObject( object );
  2088. }
  2089. }
  2090. },
  2091. getChildByName: function ( name, recursive ) {
  2092. var c, cl, child;
  2093. for ( c = 0, cl = this.children.length; c < cl; c ++ ) {
  2094. child = this.children[ c ];
  2095. if ( child.name === name ) {
  2096. return child;
  2097. }
  2098. if ( recursive ) {
  2099. child = child.getChildByName( name, recursive );
  2100. if ( child !== undefined ) {
  2101. return child;
  2102. }
  2103. }
  2104. }
  2105. return undefined;
  2106. },
  2107. updateMatrix: function () {
  2108. this.matrix.setPosition( this.position );
  2109. if ( this.useQuaternion === true ) {
  2110. this.matrix.setRotationFromQuaternion( this.quaternion );
  2111. } else {
  2112. this.matrix.setRotationFromEuler( this.rotation, this.eulerOrder );
  2113. }
  2114. if ( this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) {
  2115. this.matrix.scale( this.scale );
  2116. this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) );
  2117. }
  2118. this.matrixWorldNeedsUpdate = true;
  2119. },
  2120. updateMatrixWorld: function ( force ) {
  2121. if ( this.matrixAutoUpdate === true ) this.updateMatrix();
  2122. if ( this.matrixWorldNeedsUpdate === true || force === true ) {
  2123. if ( this.parent !== undefined ) {
  2124. this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
  2125. } else {
  2126. this.matrixWorld.copy( this.matrix );
  2127. }
  2128. this.matrixWorldNeedsUpdate = false;
  2129. force = true;
  2130. }
  2131. // update children
  2132. for ( var i = 0, l = this.children.length; i < l; i ++ ) {
  2133. this.children[ i ].updateMatrixWorld( force );
  2134. }
  2135. },
  2136. worldToLocal: function ( vector ) {
  2137. return THREE.Object3D.__m1.getInverse( this.matrixWorld ).multiplyVector3( vector );
  2138. },
  2139. localToWorld: function ( vector ) {
  2140. return this.matrixWorld.multiplyVector3( vector );
  2141. }
  2142. };
  2143. THREE.Object3D.__m1 = new THREE.Matrix4();
  2144. THREE.Object3DCount = 0;
  2145. /**
  2146. * @author mr.doob / http://mrdoob.com/
  2147. * @author supereggbert / http://www.paulbrunt.co.uk/
  2148. * @author julianwa / https://github.com/julianwa
  2149. */
  2150. THREE.Projector = function() {
  2151. var _object, _objectCount, _objectPool = [],
  2152. _vertex, _vertexCount, _vertexPool = [],
  2153. _face, _face3Count, _face3Pool = [], _face4Count, _face4Pool = [],
  2154. _line, _lineCount, _linePool = [],
  2155. _particle, _particleCount, _particlePool = [],
  2156. _renderData = { objects: [], sprites: [], lights: [], elements: [] },
  2157. _vector3 = new THREE.Vector3(),
  2158. _vector4 = new THREE.Vector4(),
  2159. _projScreenMatrix = new THREE.Matrix4(),
  2160. _projScreenobjectMatrixWorld = new THREE.Matrix4(),
  2161. _frustum = new THREE.Frustum(),
  2162. _clippedVertex1PositionScreen = new THREE.Vector4(),
  2163. _clippedVertex2PositionScreen = new THREE.Vector4(),
  2164. _face3VertexNormals;
  2165. this.projectVector = function ( vector, camera ) {
  2166. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  2167. _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
  2168. _projScreenMatrix.multiplyVector3( vector );
  2169. return vector;
  2170. };
  2171. this.unprojectVector = function ( vector, camera ) {
  2172. camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
  2173. _projScreenMatrix.multiply( camera.matrixWorld, camera.projectionMatrixInverse );
  2174. _projScreenMatrix.multiplyVector3( vector );
  2175. return vector;
  2176. };
  2177. this.pickingRay = function ( vector, camera ) {
  2178. var end, ray, t;
  2179. // set two vectors with opposing z values
  2180. vector.z = -1.0;
  2181. end = new THREE.Vector3( vector.x, vector.y, 1.0 );
  2182. this.unprojectVector( vector, camera );
  2183. this.unprojectVector( end, camera );
  2184. // find direction from vector to end
  2185. end.subSelf( vector ).normalize();
  2186. return new THREE.Ray( vector, end );
  2187. };
  2188. function projectGraph( root, sort ) {
  2189. _objectCount = 0;
  2190. _renderData.objects.length = 0;
  2191. _renderData.sprites.length = 0;
  2192. _renderData.lights.length = 0;
  2193. var projectObject = function ( object ) {
  2194. if ( object.visible === false ) return;
  2195. if ( ( object instanceof THREE.Mesh || object instanceof THREE.Line ) &&
  2196. ( object.frustumCulled === false || _frustum.contains( object ) === true ) ) {
  2197. _vector3.copy( object.matrixWorld.getPosition() );
  2198. _projScreenMatrix.multiplyVector3( _vector3 );
  2199. _object = getNextObjectInPool();
  2200. _object.object = object;
  2201. _object.z = _vector3.z;
  2202. _renderData.objects.push( _object );
  2203. } else if ( object instanceof THREE.Sprite || object instanceof THREE.Particle ) {
  2204. _vector3.copy( object.matrixWorld.getPosition() );
  2205. _projScreenMatrix.multiplyVector3( _vector3 );
  2206. _object = getNextObjectInPool();
  2207. _object.object = object;
  2208. _object.z = _vector3.z;
  2209. _renderData.sprites.push( _object );
  2210. } else if ( object instanceof THREE.Light ) {
  2211. _renderData.lights.push( object );
  2212. }
  2213. for ( var c = 0, cl = object.children.length; c < cl; c ++ ) {
  2214. projectObject( object.children[ c ] );
  2215. }
  2216. };
  2217. projectObject( root );
  2218. if ( sort === true ) _renderData.objects.sort( painterSort );
  2219. return _renderData;
  2220. };
  2221. this.projectScene = function ( scene, camera, sort ) {
  2222. var near = camera.near, far = camera.far, visible = false,
  2223. o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object,
  2224. objectMatrixWorld, objectMatrixWorldRotation,
  2225. geometry, geometryMaterials, vertices, vertex, vertexPositionScreen,
  2226. faces, face, faceVertexNormals, normal, faceVertexUvs, uvs,
  2227. v1, v2, v3, v4;
  2228. _face3Count = 0;
  2229. _face4Count = 0;
  2230. _lineCount = 0;
  2231. _particleCount = 0;
  2232. _renderData.elements.length = 0;
  2233. if ( camera.parent === undefined ) {
  2234. console.warn( 'DEPRECATED: Camera hasn\'t been added to a Scene. Adding it...' );
  2235. scene.add( camera );
  2236. }
  2237. scene.updateMatrixWorld();
  2238. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  2239. _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
  2240. _frustum.setFromMatrix( _projScreenMatrix );
  2241. _renderData = projectGraph( scene, false );
  2242. for ( o = 0, ol = _renderData.objects.length; o < ol; o++ ) {
  2243. object = _renderData.objects[ o ].object;
  2244. objectMatrixWorld = object.matrixWorld;
  2245. _vertexCount = 0;
  2246. if ( object instanceof THREE.Mesh ) {
  2247. geometry = object.geometry;
  2248. geometryMaterials = object.geometry.materials;
  2249. vertices = geometry.vertices;
  2250. faces = geometry.faces;
  2251. faceVertexUvs = geometry.faceVertexUvs;
  2252. objectMatrixWorldRotation = object.matrixRotationWorld.extractRotation( objectMatrixWorld );
  2253. for ( v = 0, vl = vertices.length; v < vl; v ++ ) {
  2254. _vertex = getNextVertexInPool();
  2255. _vertex.positionWorld.copy( vertices[ v ] );
  2256. objectMatrixWorld.multiplyVector3( _vertex.positionWorld );
  2257. _vertex.positionScreen.copy( _vertex.positionWorld );
  2258. _projScreenMatrix.multiplyVector4( _vertex.positionScreen );
  2259. _vertex.positionScreen.x /= _vertex.positionScreen.w;
  2260. _vertex.positionScreen.y /= _vertex.positionScreen.w;
  2261. _vertex.visible = _vertex.positionScreen.z > near && _vertex.positionScreen.z < far;
  2262. }
  2263. for ( f = 0, fl = faces.length; f < fl; f ++ ) {
  2264. face = faces[ f ];
  2265. if ( face instanceof THREE.Face3 ) {
  2266. v1 = _vertexPool[ face.a ];
  2267. v2 = _vertexPool[ face.b ];
  2268. v3 = _vertexPool[ face.c ];
  2269. if ( v1.visible === true && v2.visible === true && v3.visible === true ) {
  2270. visible = ( ( v3.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
  2271. ( v3.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
  2272. if ( object.doubleSided === true || visible !== object.flipSided ) {
  2273. _face = getNextFace3InPool();
  2274. _face.v1.copy( v1 );
  2275. _face.v2.copy( v2 );
  2276. _face.v3.copy( v3 );
  2277. } else {
  2278. continue;
  2279. }
  2280. } else {
  2281. continue;
  2282. }
  2283. } else if ( face instanceof THREE.Face4 ) {
  2284. v1 = _vertexPool[ face.a ];
  2285. v2 = _vertexPool[ face.b ];
  2286. v3 = _vertexPool[ face.c ];
  2287. v4 = _vertexPool[ face.d ];
  2288. if ( v1.visible === true && v2.visible === true && v3.visible === true && v4.visible === true ) {
  2289. visible = ( v4.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
  2290. ( v4.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 ||
  2291. ( v2.positionScreen.x - v3.positionScreen.x ) * ( v4.positionScreen.y - v3.positionScreen.y ) -
  2292. ( v2.positionScreen.y - v3.positionScreen.y ) * ( v4.positionScreen.x - v3.positionScreen.x ) < 0;
  2293. if ( object.doubleSided === true || visible !== object.flipSided ) {
  2294. _face = getNextFace4InPool();
  2295. _face.v1.copy( v1 );
  2296. _face.v2.copy( v2 );
  2297. _face.v3.copy( v3 );
  2298. _face.v4.copy( v4 );
  2299. } else {
  2300. continue;
  2301. }
  2302. } else {
  2303. continue;
  2304. }
  2305. }
  2306. _face.normalWorld.copy( face.normal );
  2307. if ( visible === false && ( object.flipSided === true || object.doubleSided === true ) ) _face.normalWorld.negate();
  2308. objectMatrixWorldRotation.multiplyVector3( _face.normalWorld );
  2309. _face.centroidWorld.copy( face.centroid );
  2310. objectMatrixWorld.multiplyVector3( _face.centroidWorld );
  2311. _face.centroidScreen.copy( _face.centroidWorld );
  2312. _projScreenMatrix.multiplyVector3( _face.centroidScreen );
  2313. faceVertexNormals = face.vertexNormals;
  2314. for ( n = 0, nl = faceVertexNormals.length; n < nl; n ++ ) {
  2315. normal = _face.vertexNormalsWorld[ n ];
  2316. normal.copy( faceVertexNormals[ n ] );
  2317. if ( visible === false && ( object.flipSided === true || object.doubleSided === true ) ) normal.negate();
  2318. objectMatrixWorldRotation.multiplyVector3( normal );
  2319. }
  2320. for ( c = 0, cl = faceVertexUvs.length; c < cl; c ++ ) {
  2321. uvs = faceVertexUvs[ c ][ f ];
  2322. if ( uvs === undefined ) continue;
  2323. for ( u = 0, ul = uvs.length; u < ul; u ++ ) {
  2324. _face.uvs[ c ][ u ] = uvs[ u ];
  2325. }
  2326. }
  2327. _face.material = object.material;
  2328. _face.faceMaterial = face.materialIndex !== null ? geometryMaterials[ face.materialIndex ] : null;
  2329. _face.z = _face.centroidScreen.z;
  2330. _renderData.elements.push( _face );
  2331. }
  2332. } else if ( object instanceof THREE.Line ) {
  2333. _projScreenobjectMatrixWorld.multiply( _projScreenMatrix, objectMatrixWorld );
  2334. vertices = object.geometry.vertices;
  2335. v1 = getNextVertexInPool();
  2336. v1.positionScreen.copy( vertices[ 0 ] );
  2337. _projScreenobjectMatrixWorld.multiplyVector4( v1.positionScreen );
  2338. // Handle LineStrip and LinePieces
  2339. var step = object.type === THREE.LinePieces ? 2 : 1;
  2340. for ( v = 1, vl = vertices.length; v < vl; v ++ ) {
  2341. v1 = getNextVertexInPool();
  2342. v1.positionScreen.copy( vertices[ v ] );
  2343. _projScreenobjectMatrixWorld.multiplyVector4( v1.positionScreen );
  2344. if ( ( v + 1 ) % step > 0 ) continue;
  2345. v2 = _vertexPool[ _vertexCount - 2 ];
  2346. _clippedVertex1PositionScreen.copy( v1.positionScreen );
  2347. _clippedVertex2PositionScreen.copy( v2.positionScreen );
  2348. if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
  2349. // Perform the perspective divide
  2350. _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
  2351. _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
  2352. _line = getNextLineInPool();
  2353. _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
  2354. _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
  2355. _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
  2356. _line.material = object.material;
  2357. _renderData.elements.push( _line );
  2358. }
  2359. }
  2360. }
  2361. }
  2362. for ( o = 0, ol = _renderData.sprites.length; o < ol; o++ ) {
  2363. object = _renderData.sprites[ o ].object;
  2364. objectMatrixWorld = object.matrixWorld;
  2365. if ( object instanceof THREE.Particle ) {
  2366. _vector4.set( objectMatrixWorld.elements[12], objectMatrixWorld.elements[13], objectMatrixWorld.elements[14], 1 );
  2367. _projScreenMatrix.multiplyVector4( _vector4 );
  2368. _vector4.z /= _vector4.w;
  2369. if ( _vector4.z > 0 && _vector4.z < 1 ) {
  2370. _particle = getNextParticleInPool();
  2371. _particle.x = _vector4.x / _vector4.w;
  2372. _particle.y = _vector4.y / _vector4.w;
  2373. _particle.z = _vector4.z;
  2374. _particle.rotation = object.rotation.z;
  2375. _particle.scale.x = object.scale.x * Math.abs( _particle.x - ( _vector4.x + camera.projectionMatrix.elements[0] ) / ( _vector4.w + camera.projectionMatrix.elements[12] ) );
  2376. _particle.scale.y = object.scale.y * Math.abs( _particle.y - ( _vector4.y + camera.projectionMatrix.elements[5] ) / ( _vector4.w + camera.projectionMatrix.elements[13] ) );
  2377. _particle.material = object.material;
  2378. _renderData.elements.push( _particle );
  2379. }
  2380. }
  2381. }
  2382. sort && _renderData.elements.sort( painterSort );
  2383. return _renderData;
  2384. };
  2385. // Pools
  2386. function getNextObjectInPool() {
  2387. var object;
  2388. if ( _objectCount === _objectPool.length ) {
  2389. object = new THREE.RenderableObject();
  2390. _objectPool.push( object );
  2391. } else {
  2392. object = _objectPool[ _objectCount ];
  2393. }
  2394. _objectCount ++;
  2395. return object;
  2396. }
  2397. function getNextVertexInPool() {
  2398. var vertex;
  2399. if ( _vertexCount === _vertexPool.length ) {
  2400. vertex = new THREE.RenderableVertex();
  2401. _vertexPool.push( vertex );
  2402. } else {
  2403. vertex = _vertexPool[ _vertexCount ];
  2404. }
  2405. _vertexCount ++;
  2406. return vertex;
  2407. }
  2408. function getNextFace3InPool() {
  2409. var face;
  2410. if ( _face3Count === _face3Pool.length ) {
  2411. face = new THREE.RenderableFace3();
  2412. _face3Pool.push( face );
  2413. } else {
  2414. face = _face3Pool[ _face3Count ];
  2415. }
  2416. _face3Count ++;
  2417. return face;
  2418. }
  2419. function getNextFace4InPool() {
  2420. var face;
  2421. if ( _face4Count === _face4Pool.length ) {
  2422. face = new THREE.RenderableFace4();
  2423. _face4Pool.push( face );
  2424. } else {
  2425. face = _face4Pool[ _face4Count ];
  2426. }
  2427. _face4Count ++;
  2428. return face;
  2429. }
  2430. function getNextLineInPool() {
  2431. var line;
  2432. if ( _lineCount === _linePool.length ) {
  2433. line = new THREE.RenderableLine();
  2434. _linePool.push( line );
  2435. } else {
  2436. line = _linePool[ _lineCount ];
  2437. }
  2438. _lineCount ++;
  2439. return line;
  2440. }
  2441. function getNextParticleInPool() {
  2442. var particle;
  2443. if ( _particleCount === _particlePool.length ) {
  2444. particle = new THREE.RenderableParticle();
  2445. _particlePool.push( particle );
  2446. } else {
  2447. particle = _particlePool[ _particleCount ];
  2448. }
  2449. _particleCount ++;
  2450. return particle;
  2451. }
  2452. //
  2453. function painterSort( a, b ) {
  2454. return b.z - a.z;
  2455. }
  2456. function clipLine( s1, s2 ) {
  2457. var alpha1 = 0, alpha2 = 1,
  2458. // Calculate the boundary coordinate of each vertex for the near and far clip planes,
  2459. // Z = -1 and Z = +1, respectively.
  2460. bc1near = s1.z + s1.w,
  2461. bc2near = s2.z + s2.w,
  2462. bc1far = - s1.z + s1.w,
  2463. bc2far = - s2.z + s2.w;
  2464. if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
  2465. // Both vertices lie entirely within all clip planes.
  2466. return true;
  2467. } else if ( ( bc1near < 0 && bc2near < 0) || (bc1far < 0 && bc2far < 0 ) ) {
  2468. // Both vertices lie entirely outside one of the clip planes.
  2469. return false;
  2470. } else {
  2471. // The line segment spans at least one clip plane.
  2472. if ( bc1near < 0 ) {
  2473. // v1 lies outside the near plane, v2 inside
  2474. alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
  2475. } else if ( bc2near < 0 ) {
  2476. // v2 lies outside the near plane, v1 inside
  2477. alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
  2478. }
  2479. if ( bc1far < 0 ) {
  2480. // v1 lies outside the far plane, v2 inside
  2481. alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
  2482. } else if ( bc2far < 0 ) {
  2483. // v2 lies outside the far plane, v2 inside
  2484. alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
  2485. }
  2486. if ( alpha2 < alpha1 ) {
  2487. // The line segment spans two boundaries, but is outside both of them.
  2488. // (This can't happen when we're only clipping against just near/far but good
  2489. // to leave the check here for future usage if other clip planes are added.)
  2490. return false;
  2491. } else {
  2492. // Update the s1 and s2 vertices to match the clipped line segment.
  2493. s1.lerpSelf( s2, alpha1 );
  2494. s2.lerpSelf( s1, 1 - alpha2 );
  2495. return true;
  2496. }
  2497. }
  2498. }
  2499. };
  2500. /**
  2501. * @author mikael emtinger / http://gomo.se/
  2502. * @author alteredq / http://alteredqualia.com/
  2503. * @author WestLangley / http://github.com/WestLangley
  2504. */
  2505. THREE.Quaternion = function( x, y, z, w ) {
  2506. this.x = x || 0;
  2507. this.y = y || 0;
  2508. this.z = z || 0;
  2509. this.w = ( w !== undefined ) ? w : 1;
  2510. };
  2511. THREE.Quaternion.prototype = {
  2512. constructor: THREE.Quaternion,
  2513. set: function ( x, y, z, w ) {
  2514. this.x = x;
  2515. this.y = y;
  2516. this.z = z;
  2517. this.w = w;
  2518. return this;
  2519. },
  2520. copy: function ( q ) {
  2521. this.x = q.x;
  2522. this.y = q.y;
  2523. this.z = q.z;
  2524. this.w = q.w;
  2525. return this;
  2526. },
  2527. setFromEuler: function ( v, order ) {
  2528. // http://www.mathworks.com/matlabcentral/fileexchange/
  2529. // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
  2530. // content/SpinCalc.m
  2531. var c1 = Math.cos( v.x / 2 );
  2532. var c2 = Math.cos( v.y / 2 );
  2533. var c3 = Math.cos( v.z / 2 );
  2534. var s1 = Math.sin( v.x / 2 );
  2535. var s2 = Math.sin( v.y / 2 );
  2536. var s3 = Math.sin( v.z / 2 );
  2537. if ( order === undefined || order === 'XYZ' ) {
  2538. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  2539. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  2540. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  2541. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  2542. } else if ( order === 'YXZ' ) {
  2543. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  2544. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  2545. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  2546. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  2547. } else if ( order === 'ZXY' ) {
  2548. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  2549. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  2550. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  2551. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  2552. } else if ( order === 'ZYX' ) {
  2553. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  2554. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  2555. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  2556. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  2557. } else if ( order === 'YZX' ) {
  2558. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  2559. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  2560. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  2561. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  2562. } else if ( order === 'XZY' ) {
  2563. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  2564. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  2565. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  2566. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  2567. }
  2568. return this;
  2569. },
  2570. setFromAxisAngle: function ( axis, angle ) {
  2571. // from http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
  2572. // axis have to be normalized
  2573. var halfAngle = angle / 2,
  2574. s = Math.sin( halfAngle );
  2575. this.x = axis.x * s;
  2576. this.y = axis.y * s;
  2577. this.z = axis.z * s;
  2578. this.w = Math.cos( halfAngle );
  2579. return this;
  2580. },
  2581. setFromRotationMatrix: function ( m ) {
  2582. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  2583. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  2584. var te = m.elements,
  2585. m11 = te[0], m12 = te[4], m13 = te[8],
  2586. m21 = te[1], m22 = te[5], m23 = te[9],
  2587. m31 = te[2], m32 = te[6], m33 = te[10],
  2588. trace = m11 + m22 + m33,
  2589. s;
  2590. if( trace > 0 ) {
  2591. s = 0.5 / Math.sqrt( trace + 1.0 );
  2592. this.w = 0.25 / s;
  2593. this.x = ( m32 - m23 ) * s;
  2594. this.y = ( m13 - m31 ) * s;
  2595. this.z = ( m21 - m12 ) * s;
  2596. } else if ( m11 > m22 && m11 > m33 ) {
  2597. s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
  2598. this.w = (m32 - m23 ) / s;
  2599. this.x = 0.25 * s;
  2600. this.y = (m12 + m21 ) / s;
  2601. this.z = (m13 + m31 ) / s;
  2602. } else if (m22 > m33) {
  2603. s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
  2604. this.w = (m13 - m31 ) / s;
  2605. this.x = (m12 + m21 ) / s;
  2606. this.y = 0.25 * s;
  2607. this.z = (m23 + m32 ) / s;
  2608. } else {
  2609. s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
  2610. this.w = ( m21 - m12 ) / s;
  2611. this.x = ( m13 + m31 ) / s;
  2612. this.y = ( m23 + m32 ) / s;
  2613. this.z = 0.25 * s;
  2614. }
  2615. return this;
  2616. },
  2617. calculateW : function () {
  2618. this.w = - Math.sqrt( Math.abs( 1.0 - this.x * this.x - this.y * this.y - this.z * this.z ) );
  2619. return this;
  2620. },
  2621. inverse: function () {
  2622. this.x *= -1;
  2623. this.y *= -1;
  2624. this.z *= -1;
  2625. return this;
  2626. },
  2627. length: function () {
  2628. return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
  2629. },
  2630. normalize: function () {
  2631. var l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
  2632. if ( l === 0 ) {
  2633. this.x = 0;
  2634. this.y = 0;
  2635. this.z = 0;
  2636. this.w = 0;
  2637. } else {
  2638. l = 1 / l;
  2639. this.x = this.x * l;
  2640. this.y = this.y * l;
  2641. this.z = this.z * l;
  2642. this.w = this.w * l;
  2643. }
  2644. return this;
  2645. },
  2646. multiply: function ( a, b ) {
  2647. // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  2648. this.x = a.x * b.w + a.y * b.z - a.z * b.y + a.w * b.x;
  2649. this.y = -a.x * b.z + a.y * b.w + a.z * b.x + a.w * b.y;
  2650. this.z = a.x * b.y - a.y * b.x + a.z * b.w + a.w * b.z;
  2651. this.w = -a.x * b.x - a.y * b.y - a.z * b.z + a.w * b.w;
  2652. return this;
  2653. },
  2654. multiplySelf: function ( b ) {
  2655. var qax = this.x, qay = this.y, qaz = this.z, qaw = this.w,
  2656. qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w;
  2657. this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
  2658. this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
  2659. this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
  2660. this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
  2661. return this;
  2662. },
  2663. multiplyVector3: function ( vector, dest ) {
  2664. if ( !dest ) { dest = vector; }
  2665. var x = vector.x, y = vector.y, z = vector.z,
  2666. qx = this.x, qy = this.y, qz = this.z, qw = this.w;
  2667. // calculate quat * vector
  2668. var ix = qw * x + qy * z - qz * y,
  2669. iy = qw * y + qz * x - qx * z,
  2670. iz = qw * z + qx * y - qy * x,
  2671. iw = -qx * x - qy * y - qz * z;
  2672. // calculate result * inverse quat
  2673. dest.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
  2674. dest.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
  2675. dest.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  2676. return dest;
  2677. },
  2678. slerpSelf: function ( qb, t ) {
  2679. var x = this.x, y = this.y, z = this.z, w = this.w;
  2680. // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
  2681. var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
  2682. if ( cosHalfTheta < 0 ) {
  2683. this.w = -qb.w;
  2684. this.x = -qb.x;
  2685. this.y = -qb.y;
  2686. this.z = -qb.z;
  2687. cosHalfTheta = -cosHalfTheta;
  2688. } else {
  2689. this.copy( qb );
  2690. }
  2691. if ( cosHalfTheta >= 1.0 ) {
  2692. this.w = w;
  2693. this.x = x;
  2694. this.y = y;
  2695. this.z = z;
  2696. return this;
  2697. }
  2698. var halfTheta = Math.acos( cosHalfTheta );
  2699. var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
  2700. if ( Math.abs( sinHalfTheta ) < 0.001 ) {
  2701. this.w = 0.5 * ( w + this.w );
  2702. this.x = 0.5 * ( x + this.x );
  2703. this.y = 0.5 * ( y + this.y );
  2704. this.z = 0.5 * ( z + this.z );
  2705. return this;
  2706. }
  2707. var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
  2708. ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
  2709. this.w = ( w * ratioA + this.w * ratioB );
  2710. this.x = ( x * ratioA + this.x * ratioB );
  2711. this.y = ( y * ratioA + this.y * ratioB );
  2712. this.z = ( z * ratioA + this.z * ratioB );
  2713. return this;
  2714. },
  2715. clone: function () {
  2716. return new THREE.Quaternion( this.x, this.y, this.z, this.w );
  2717. }
  2718. }
  2719. THREE.Quaternion.slerp = function ( qa, qb, qm, t ) {
  2720. // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
  2721. var cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
  2722. if ( cosHalfTheta < 0 ) {
  2723. qm.w = -qb.w;
  2724. qm.x = -qb.x;
  2725. qm.y = -qb.y;
  2726. qm.z = -qb.z;
  2727. cosHalfTheta = -cosHalfTheta;
  2728. } else {
  2729. qm.copy( qb );
  2730. }
  2731. if ( Math.abs( cosHalfTheta ) >= 1.0 ) {
  2732. qm.w = qa.w;
  2733. qm.x = qa.x;
  2734. qm.y = qa.y;
  2735. qm.z = qa.z;
  2736. return qm;
  2737. }
  2738. var halfTheta = Math.acos( cosHalfTheta );
  2739. var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
  2740. if ( Math.abs( sinHalfTheta ) < 0.001 ) {
  2741. qm.w = 0.5 * ( qa.w + qm.w );
  2742. qm.x = 0.5 * ( qa.x + qm.x );
  2743. qm.y = 0.5 * ( qa.y + qm.y );
  2744. qm.z = 0.5 * ( qa.z + qm.z );
  2745. return qm;
  2746. }
  2747. var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta;
  2748. var ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
  2749. qm.w = ( qa.w * ratioA + qm.w * ratioB );
  2750. qm.x = ( qa.x * ratioA + qm.x * ratioB );
  2751. qm.y = ( qa.y * ratioA + qm.y * ratioB );
  2752. qm.z = ( qa.z * ratioA + qm.z * ratioB );
  2753. return qm;
  2754. }
  2755. /**
  2756. * @author mr.doob / http://mrdoob.com/
  2757. */
  2758. THREE.Vertex = function () {
  2759. console.warn( 'THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.')
  2760. };
  2761. /**
  2762. * @author mr.doob / http://mrdoob.com/
  2763. * @author alteredq / http://alteredqualia.com/
  2764. */
  2765. THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
  2766. this.a = a;
  2767. this.b = b;
  2768. this.c = c;
  2769. this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
  2770. this.vertexNormals = normal instanceof Array ? normal : [ ];
  2771. this.color = color instanceof THREE.Color ? color : new THREE.Color();
  2772. this.vertexColors = color instanceof Array ? color : [];
  2773. this.vertexTangents = [];
  2774. this.materialIndex = materialIndex;
  2775. this.centroid = new THREE.Vector3();
  2776. };
  2777. THREE.Face3.prototype = {
  2778. constructor: THREE.Face3,
  2779. clone: function () {
  2780. var face = new THREE.Face3( this.a, this.b, this.c );
  2781. face.normal.copy( this.normal );
  2782. face.color.copy( this.color );
  2783. face.centroid.copy( this.centroid );
  2784. face.materialIndex = this.materialIndex;
  2785. var i, il;
  2786. for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
  2787. for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone();
  2788. for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();
  2789. return face;
  2790. }
  2791. };
  2792. /**
  2793. * @author mr.doob / http://mrdoob.com/
  2794. * @author alteredq / http://alteredqualia.com/
  2795. */
  2796. THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
  2797. this.a = a;
  2798. this.b = b;
  2799. this.c = c;
  2800. this.d = d;
  2801. this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
  2802. this.vertexNormals = normal instanceof Array ? normal : [ ];
  2803. this.color = color instanceof THREE.Color ? color : new THREE.Color();
  2804. this.vertexColors = color instanceof Array ? color : [];
  2805. this.vertexTangents = [];
  2806. this.materialIndex = materialIndex;
  2807. this.centroid = new THREE.Vector3();
  2808. };
  2809. THREE.Face4.prototype = {
  2810. constructor: THREE.Face4,
  2811. clone: function () {
  2812. var face = new THREE.Face4( this.a, this.b, this.c, this.d );
  2813. face.normal.copy( this.normal );
  2814. face.color.copy( this.color );
  2815. face.centroid.copy( this.centroid );
  2816. face.materialIndex = this.materialIndex;
  2817. var i, il;
  2818. for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
  2819. for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone();
  2820. for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();
  2821. return face;
  2822. }
  2823. };
  2824. /**
  2825. * @author mr.doob / http://mrdoob.com/
  2826. */
  2827. THREE.UV = function ( u, v ) {
  2828. this.u = u || 0;
  2829. this.v = v || 0;
  2830. };
  2831. THREE.UV.prototype = {
  2832. constructor: THREE.UV,
  2833. set: function ( u, v ) {
  2834. this.u = u;
  2835. this.v = v;
  2836. return this;
  2837. },
  2838. copy: function ( uv ) {
  2839. this.u = uv.u;
  2840. this.v = uv.v;
  2841. return this;
  2842. },
  2843. lerpSelf: function ( uv, alpha ) {
  2844. this.u += ( uv.u - this.u ) * alpha;
  2845. this.v += ( uv.v - this.v ) * alpha;
  2846. return this;
  2847. },
  2848. clone: function () {
  2849. return new THREE.UV( this.u, this.v );
  2850. }
  2851. };
  2852. /**
  2853. * @author mr.doob / http://mrdoob.com/
  2854. * @author kile / http://kile.stravaganza.org/
  2855. * @author alteredq / http://alteredqualia.com/
  2856. * @author mikael emtinger / http://gomo.se/
  2857. * @author zz85 / http://www.lab4games.net/zz85/blog
  2858. */
  2859. THREE.Geometry = function () {
  2860. this.id = THREE.GeometryCount ++;
  2861. this.name = '';
  2862. this.vertices = [];
  2863. this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
  2864. this.materials = [];
  2865. this.faces = [];
  2866. this.faceUvs = [[]];
  2867. this.faceVertexUvs = [[]];
  2868. this.morphTargets = [];
  2869. this.morphColors = [];
  2870. this.morphNormals = [];
  2871. this.skinWeights = [];
  2872. this.skinIndices = [];
  2873. this.boundingBox = null;
  2874. this.boundingSphere = null;
  2875. this.hasTangents = false;
  2876. this.dynamic = false; // unless set to true the *Arrays will be deleted once sent to a buffer
  2877. };
  2878. THREE.Geometry.prototype = {
  2879. constructor : THREE.Geometry,
  2880. applyMatrix: function ( matrix ) {
  2881. var matrixRotation = new THREE.Matrix4();
  2882. matrixRotation.extractRotation( matrix );
  2883. for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
  2884. var vertex = this.vertices[ i ];
  2885. matrix.multiplyVector3( vertex );
  2886. }
  2887. for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
  2888. var face = this.faces[ i ];
  2889. matrixRotation.multiplyVector3( face.normal );
  2890. for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  2891. matrixRotation.multiplyVector3( face.vertexNormals[ j ] );
  2892. }
  2893. matrix.multiplyVector3( face.centroid );
  2894. }
  2895. },
  2896. computeCentroids: function () {
  2897. var f, fl, face;
  2898. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2899. face = this.faces[ f ];
  2900. face.centroid.set( 0, 0, 0 );
  2901. if ( face instanceof THREE.Face3 ) {
  2902. face.centroid.addSelf( this.vertices[ face.a ] );
  2903. face.centroid.addSelf( this.vertices[ face.b ] );
  2904. face.centroid.addSelf( this.vertices[ face.c ] );
  2905. face.centroid.divideScalar( 3 );
  2906. } else if ( face instanceof THREE.Face4 ) {
  2907. face.centroid.addSelf( this.vertices[ face.a ] );
  2908. face.centroid.addSelf( this.vertices[ face.b ] );
  2909. face.centroid.addSelf( this.vertices[ face.c ] );
  2910. face.centroid.addSelf( this.vertices[ face.d ] );
  2911. face.centroid.divideScalar( 4 );
  2912. }
  2913. }
  2914. },
  2915. computeFaceNormals: function () {
  2916. var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
  2917. cb = new THREE.Vector3(), ab = new THREE.Vector3();
  2918. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2919. face = this.faces[ f ];
  2920. vA = this.vertices[ face.a ];
  2921. vB = this.vertices[ face.b ];
  2922. vC = this.vertices[ face.c ];
  2923. cb.sub( vC, vB );
  2924. ab.sub( vA, vB );
  2925. cb.crossSelf( ab );
  2926. if ( !cb.isZero() ) {
  2927. cb.normalize();
  2928. }
  2929. face.normal.copy( cb );
  2930. }
  2931. },
  2932. computeVertexNormals: function () {
  2933. var v, vl, f, fl, face, vertices;
  2934. // create internal buffers for reuse when calling this method repeatedly
  2935. // (otherwise memory allocation / deallocation every frame is big resource hog)
  2936. if ( this.__tmpVertices === undefined ) {
  2937. this.__tmpVertices = new Array( this.vertices.length );
  2938. vertices = this.__tmpVertices;
  2939. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  2940. vertices[ v ] = new THREE.Vector3();
  2941. }
  2942. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2943. face = this.faces[ f ];
  2944. if ( face instanceof THREE.Face3 ) {
  2945. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  2946. } else if ( face instanceof THREE.Face4 ) {
  2947. face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  2948. }
  2949. }
  2950. } else {
  2951. vertices = this.__tmpVertices;
  2952. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  2953. vertices[ v ].set( 0, 0, 0 );
  2954. }
  2955. }
  2956. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2957. face = this.faces[ f ];
  2958. if ( face instanceof THREE.Face3 ) {
  2959. vertices[ face.a ].addSelf( face.normal );
  2960. vertices[ face.b ].addSelf( face.normal );
  2961. vertices[ face.c ].addSelf( face.normal );
  2962. } else if ( face instanceof THREE.Face4 ) {
  2963. vertices[ face.a ].addSelf( face.normal );
  2964. vertices[ face.b ].addSelf( face.normal );
  2965. vertices[ face.c ].addSelf( face.normal );
  2966. vertices[ face.d ].addSelf( face.normal );
  2967. }
  2968. }
  2969. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  2970. vertices[ v ].normalize();
  2971. }
  2972. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2973. face = this.faces[ f ];
  2974. if ( face instanceof THREE.Face3 ) {
  2975. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  2976. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  2977. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  2978. } else if ( face instanceof THREE.Face4 ) {
  2979. face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
  2980. face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
  2981. face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
  2982. face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
  2983. }
  2984. }
  2985. },
  2986. computeMorphNormals: function () {
  2987. var i, il, f, fl, face;
  2988. // save original normals
  2989. // - create temp variables on first access
  2990. // otherwise just copy (for faster repeated calls)
  2991. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  2992. face = this.faces[ f ];
  2993. if ( ! face.__originalFaceNormal ) {
  2994. face.__originalFaceNormal = face.normal.clone();
  2995. } else {
  2996. face.__originalFaceNormal.copy( face.normal );
  2997. }
  2998. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  2999. for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  3000. if ( ! face.__originalVertexNormals[ i ] ) {
  3001. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  3002. } else {
  3003. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  3004. }
  3005. }
  3006. }
  3007. // use temp geometry to compute face and vertex normals for each morph
  3008. var tmpGeo = new THREE.Geometry();
  3009. tmpGeo.faces = this.faces;
  3010. for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  3011. // create on first access
  3012. if ( ! this.morphNormals[ i ] ) {
  3013. this.morphNormals[ i ] = {};
  3014. this.morphNormals[ i ].faceNormals = [];
  3015. this.morphNormals[ i ].vertexNormals = [];
  3016. var dstNormalsFace = this.morphNormals[ i ].faceNormals;
  3017. var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  3018. var faceNormal, vertexNormals;
  3019. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  3020. face = this.faces[ f ];
  3021. faceNormal = new THREE.Vector3();
  3022. if ( face instanceof THREE.Face3 ) {
  3023. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
  3024. } else {
  3025. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };
  3026. }
  3027. dstNormalsFace.push( faceNormal );
  3028. dstNormalsVertex.push( vertexNormals );
  3029. }
  3030. }
  3031. var morphNormals = this.morphNormals[ i ];
  3032. // set vertices to morph target
  3033. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  3034. // compute morph normals
  3035. tmpGeo.computeFaceNormals();
  3036. tmpGeo.computeVertexNormals();
  3037. // store morph normals
  3038. var faceNormal, vertexNormals;
  3039. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  3040. face = this.faces[ f ];
  3041. faceNormal = morphNormals.faceNormals[ f ];
  3042. vertexNormals = morphNormals.vertexNormals[ f ];
  3043. faceNormal.copy( face.normal );
  3044. if ( face instanceof THREE.Face3 ) {
  3045. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  3046. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  3047. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  3048. } else {
  3049. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  3050. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  3051. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  3052. vertexNormals.d.copy( face.vertexNormals[ 3 ] );
  3053. }
  3054. }
  3055. }
  3056. // restore original normals
  3057. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  3058. face = this.faces[ f ];
  3059. face.normal = face.__originalFaceNormal;
  3060. face.vertexNormals = face.__originalVertexNormals;
  3061. }
  3062. },
  3063. computeTangents: function () {
  3064. // based on http://www.terathon.com/code/tangent.html
  3065. // tangents go to vertices
  3066. var f, fl, v, vl, i, il, vertexIndex,
  3067. face, uv, vA, vB, vC, uvA, uvB, uvC,
  3068. x1, x2, y1, y2, z1, z2,
  3069. s1, s2, t1, t2, r, t, test,
  3070. tan1 = [], tan2 = [],
  3071. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  3072. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  3073. n = new THREE.Vector3(), w;
  3074. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  3075. tan1[ v ] = new THREE.Vector3();
  3076. tan2[ v ] = new THREE.Vector3();
  3077. }
  3078. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  3079. vA = context.vertices[ a ];
  3080. vB = context.vertices[ b ];
  3081. vC = context.vertices[ c ];
  3082. uvA = uv[ ua ];
  3083. uvB = uv[ ub ];
  3084. uvC = uv[ uc ];
  3085. x1 = vB.x - vA.x;
  3086. x2 = vC.x - vA.x;
  3087. y1 = vB.y - vA.y;
  3088. y2 = vC.y - vA.y;
  3089. z1 = vB.z - vA.z;
  3090. z2 = vC.z - vA.z;
  3091. s1 = uvB.u - uvA.u;
  3092. s2 = uvC.u - uvA.u;
  3093. t1 = uvB.v - uvA.v;
  3094. t2 = uvC.v - uvA.v;
  3095. r = 1.0 / ( s1 * t2 - s2 * t1 );
  3096. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  3097. ( t2 * y1 - t1 * y2 ) * r,
  3098. ( t2 * z1 - t1 * z2 ) * r );
  3099. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  3100. ( s1 * y2 - s2 * y1 ) * r,
  3101. ( s1 * z2 - s2 * z1 ) * r );
  3102. tan1[ a ].addSelf( sdir );
  3103. tan1[ b ].addSelf( sdir );
  3104. tan1[ c ].addSelf( sdir );
  3105. tan2[ a ].addSelf( tdir );
  3106. tan2[ b ].addSelf( tdir );
  3107. tan2[ c ].addSelf( tdir );
  3108. }
  3109. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  3110. face = this.faces[ f ];
  3111. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  3112. if ( face instanceof THREE.Face3 ) {
  3113. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  3114. } else if ( face instanceof THREE.Face4 ) {
  3115. handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
  3116. handleTriangle( this, face.b, face.c, face.d, 1, 2, 3 );
  3117. }
  3118. }
  3119. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  3120. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  3121. face = this.faces[ f ];
  3122. for ( i = 0; i < face.vertexNormals.length; i++ ) {
  3123. n.copy( face.vertexNormals[ i ] );
  3124. vertexIndex = face[ faceIndex[ i ] ];
  3125. t = tan1[ vertexIndex ];
  3126. // Gram-Schmidt orthogonalize
  3127. tmp.copy( t );
  3128. tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
  3129. // Calculate handedness
  3130. tmp2.cross( face.vertexNormals[ i ], t );
  3131. test = tmp2.dot( tan2[ vertexIndex ] );
  3132. w = (test < 0.0) ? -1.0 : 1.0;
  3133. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  3134. }
  3135. }
  3136. this.hasTangents = true;
  3137. },
  3138. computeBoundingBox: function () {
  3139. if ( ! this.boundingBox ) {
  3140. this.boundingBox = { min: new THREE.Vector3(), max: new THREE.Vector3() };
  3141. }
  3142. if ( this.vertices.length > 0 ) {
  3143. var position, firstPosition = this.vertices[ 0 ];
  3144. this.boundingBox.min.copy( firstPosition );
  3145. this.boundingBox.max.copy( firstPosition );
  3146. var min = this.boundingBox.min,
  3147. max = this.boundingBox.max;
  3148. for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
  3149. position = this.vertices[ v ];
  3150. if ( position.x < min.x ) {
  3151. min.x = position.x;
  3152. } else if ( position.x > max.x ) {
  3153. max.x = position.x;
  3154. }
  3155. if ( position.y < min.y ) {
  3156. min.y = position.y;
  3157. } else if ( position.y > max.y ) {
  3158. max.y = position.y;
  3159. }
  3160. if ( position.z < min.z ) {
  3161. min.z = position.z;
  3162. } else if ( position.z > max.z ) {
  3163. max.z = position.z;
  3164. }
  3165. }
  3166. } else {
  3167. this.boundingBox.min.set( 0, 0, 0 );
  3168. this.boundingBox.max.set( 0, 0, 0 );
  3169. }
  3170. },
  3171. computeBoundingSphere: function () {
  3172. if ( ! this.boundingSphere ) this.boundingSphere = { radius: 0 };
  3173. var radius, maxRadius = 0;
  3174. for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  3175. radius = this.vertices[ v ].length();
  3176. if ( radius > maxRadius ) maxRadius = radius;
  3177. }
  3178. this.boundingSphere.radius = maxRadius;
  3179. },
  3180. /*
  3181. * Checks for duplicate vertices with hashmap.
  3182. * Duplicated vertices are removed
  3183. * and faces' vertices are updated.
  3184. */
  3185. mergeVertices: function() {
  3186. var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
  3187. var unique = [], changes = [];
  3188. var v, key;
  3189. var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
  3190. var precision = Math.pow( 10, precisionPoints );
  3191. var i,il, face;
  3192. var abcd = 'abcd', o, k, j, jl, u;
  3193. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  3194. v = this.vertices[ i ];
  3195. key = [ Math.round( v.x * precision ), Math.round( v.y * precision ), Math.round( v.z * precision ) ].join( '_' );
  3196. if ( verticesMap[ key ] === undefined ) {
  3197. verticesMap[ key ] = i;
  3198. unique.push( this.vertices[ i ] );
  3199. changes[ i ] = unique.length - 1;
  3200. } else {
  3201. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  3202. changes[ i ] = changes[ verticesMap[ key ] ];
  3203. }
  3204. };
  3205. // Start to patch face indices
  3206. for( i = 0, il = this.faces.length; i < il; i ++ ) {
  3207. face = this.faces[ i ];
  3208. if ( face instanceof THREE.Face3 ) {
  3209. face.a = changes[ face.a ];
  3210. face.b = changes[ face.b ];
  3211. face.c = changes[ face.c ];
  3212. } else if ( face instanceof THREE.Face4 ) {
  3213. face.a = changes[ face.a ];
  3214. face.b = changes[ face.b ];
  3215. face.c = changes[ face.c ];
  3216. face.d = changes[ face.d ];
  3217. // check dups in (a, b, c, d) and convert to -> face3
  3218. o = [ face.a, face.b, face.c, face.d ];
  3219. for ( k = 3; k > 0; k -- ) {
  3220. if ( o.indexOf( face[ abcd[ k ] ] ) !== k ) {
  3221. // console.log('faces', face.a, face.b, face.c, face.d, 'dup at', k);
  3222. o.splice( k, 1 );
  3223. this.faces[ i ] = new THREE.Face3( o[0], o[1], o[2], face.normal, face.color, face.materialIndex );
  3224. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  3225. u = this.faceVertexUvs[ j ][ i ];
  3226. if ( u ) u.splice( k, 1 );
  3227. }
  3228. this.faces[ i ].vertexColors = face.vertexColors;
  3229. break;
  3230. }
  3231. }
  3232. }
  3233. }
  3234. // Use unique set of vertices
  3235. var diff = this.vertices.length - unique.length;
  3236. this.vertices = unique;
  3237. return diff;
  3238. }
  3239. };
  3240. THREE.GeometryCount = 0;
  3241. /**
  3242. * Spline from Tween.js, slightly optimized (and trashed)
  3243. * http://sole.github.com/tween.js/examples/05_spline.html
  3244. *
  3245. * @author mrdoob / http://mrdoob.com/
  3246. * @author alteredq / http://alteredqualia.com/
  3247. */
  3248. THREE.Spline = function ( points ) {
  3249. this.points = points;
  3250. var c = [], v3 = { x: 0, y: 0, z: 0 },
  3251. point, intPoint, weight, w2, w3,
  3252. pa, pb, pc, pd;
  3253. this.initFromArray = function( a ) {
  3254. this.points = [];
  3255. for ( var i = 0; i < a.length; i++ ) {
  3256. this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] };
  3257. }
  3258. };
  3259. this.getPoint = function ( k ) {
  3260. point = ( this.points.length - 1 ) * k;
  3261. intPoint = Math.floor( point );
  3262. weight = point - intPoint;
  3263. c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
  3264. c[ 1 ] = intPoint;
  3265. c[ 2 ] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
  3266. c[ 3 ] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
  3267. pa = this.points[ c[ 0 ] ];
  3268. pb = this.points[ c[ 1 ] ];
  3269. pc = this.points[ c[ 2 ] ];
  3270. pd = this.points[ c[ 3 ] ];
  3271. w2 = weight * weight;
  3272. w3 = weight * w2;
  3273. v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 );
  3274. v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 );
  3275. v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 );
  3276. return v3;
  3277. };
  3278. this.getControlPointsArray = function () {
  3279. var i, p, l = this.points.length,
  3280. coords = [];
  3281. for ( i = 0; i < l; i ++ ) {
  3282. p = this.points[ i ];
  3283. coords[ i ] = [ p.x, p.y, p.z ];
  3284. }
  3285. return coords;
  3286. };
  3287. // approximate length by summing linear segments
  3288. this.getLength = function ( nSubDivisions ) {
  3289. var i, index, nSamples, position,
  3290. point = 0, intPoint = 0, oldIntPoint = 0,
  3291. oldPosition = new THREE.Vector3(),
  3292. tmpVec = new THREE.Vector3(),
  3293. chunkLengths = [],
  3294. totalLength = 0;
  3295. // first point has 0 length
  3296. chunkLengths[ 0 ] = 0;
  3297. if ( !nSubDivisions ) nSubDivisions = 100;
  3298. nSamples = this.points.length * nSubDivisions;
  3299. oldPosition.copy( this.points[ 0 ] );
  3300. for ( i = 1; i < nSamples; i ++ ) {
  3301. index = i / nSamples;
  3302. position = this.getPoint( index );
  3303. tmpVec.copy( position );
  3304. totalLength += tmpVec.distanceTo( oldPosition );
  3305. oldPosition.copy( position );
  3306. point = ( this.points.length - 1 ) * index;
  3307. intPoint = Math.floor( point );
  3308. if ( intPoint != oldIntPoint ) {
  3309. chunkLengths[ intPoint ] = totalLength;
  3310. oldIntPoint = intPoint;
  3311. }
  3312. }
  3313. // last point ends with total length
  3314. chunkLengths[ chunkLengths.length ] = totalLength;
  3315. return { chunks: chunkLengths, total: totalLength };
  3316. };
  3317. this.reparametrizeByArcLength = function ( samplingCoef ) {
  3318. var i, j,
  3319. index, indexCurrent, indexNext,
  3320. linearDistance, realDistance,
  3321. sampling, position,
  3322. newpoints = [],
  3323. tmpVec = new THREE.Vector3(),
  3324. sl = this.getLength();
  3325. newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() );
  3326. for ( i = 1; i < this.points.length; i++ ) {
  3327. //tmpVec.copy( this.points[ i - 1 ] );
  3328. //linearDistance = tmpVec.distanceTo( this.points[ i ] );
  3329. realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ];
  3330. sampling = Math.ceil( samplingCoef * realDistance / sl.total );
  3331. indexCurrent = ( i - 1 ) / ( this.points.length - 1 );
  3332. indexNext = i / ( this.points.length - 1 );
  3333. for ( j = 1; j < sampling - 1; j++ ) {
  3334. index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent );
  3335. position = this.getPoint( index );
  3336. newpoints.push( tmpVec.copy( position ).clone() );
  3337. }
  3338. newpoints.push( tmpVec.copy( this.points[ i ] ).clone() );
  3339. }
  3340. this.points = newpoints;
  3341. };
  3342. // Catmull-Rom
  3343. function interpolate( p0, p1, p2, p3, t, t2, t3 ) {
  3344. var v0 = ( p2 - p0 ) * 0.5,
  3345. v1 = ( p3 - p1 ) * 0.5;
  3346. return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
  3347. };
  3348. };
  3349. /**
  3350. * @author mr.doob / http://mrdoob.com/
  3351. * @author mikael emtinger / http://gomo.se/
  3352. */
  3353. THREE.Camera = function () {
  3354. THREE.Object3D.call( this );
  3355. this.matrixWorldInverse = new THREE.Matrix4();
  3356. this.projectionMatrix = new THREE.Matrix4();
  3357. this.projectionMatrixInverse = new THREE.Matrix4();
  3358. };
  3359. THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
  3360. THREE.Camera.prototype.lookAt = function ( vector ) {
  3361. // TODO: Add hierarchy support.
  3362. this.matrix.lookAt( this.position, vector, this.up );
  3363. if ( this.rotationAutoUpdate === true ) {
  3364. this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
  3365. }
  3366. };
  3367. /**
  3368. * @author alteredq / http://alteredqualia.com/
  3369. */
  3370. THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
  3371. THREE.Camera.call( this );
  3372. this.left = left;
  3373. this.right = right;
  3374. this.top = top;
  3375. this.bottom = bottom;
  3376. this.near = ( near !== undefined ) ? near : 0.1;
  3377. this.far = ( far !== undefined ) ? far : 2000;
  3378. this.updateProjectionMatrix();
  3379. };
  3380. THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
  3381. THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
  3382. this.projectionMatrix.makeOrthographic( this.left, this.right, this.top, this.bottom, this.near, this.far );
  3383. };
  3384. /**
  3385. * @author mr.doob / http://mrdoob.com/
  3386. * @author greggman / http://games.greggman.com/
  3387. * @author zz85 / http://www.lab4games.net/zz85/blog
  3388. */
  3389. THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
  3390. THREE.Camera.call( this );
  3391. this.fov = fov !== undefined ? fov : 50;
  3392. this.aspect = aspect !== undefined ? aspect : 1;
  3393. this.near = near !== undefined ? near : 0.1;
  3394. this.far = far !== undefined ? far : 2000;
  3395. this.updateProjectionMatrix();
  3396. };
  3397. THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype );
  3398. /**
  3399. * Uses Focal Length (in mm) to estimate and set FOV
  3400. * 35mm (fullframe) camera is used if frame size is not specified;
  3401. * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
  3402. */
  3403. THREE.PerspectiveCamera.prototype.setLens = function ( focalLength, frameHeight ) {
  3404. frameHeight = frameHeight !== undefined ? frameHeight : 24;
  3405. this.fov = 2 * Math.atan( frameHeight / ( focalLength * 2 ) ) * ( 180 / Math.PI );
  3406. this.updateProjectionMatrix();
  3407. }
  3408. /**
  3409. * Sets an offset in a larger frustum. This is useful for multi-window or
  3410. * multi-monitor/multi-machine setups.
  3411. *
  3412. * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
  3413. * the monitors are in grid like this
  3414. *
  3415. * +---+---+---+
  3416. * | A | B | C |
  3417. * +---+---+---+
  3418. * | D | E | F |
  3419. * +---+---+---+
  3420. *
  3421. * then for each monitor you would call it like this
  3422. *
  3423. * var w = 1920;
  3424. * var h = 1080;
  3425. * var fullWidth = w * 3;
  3426. * var fullHeight = h * 2;
  3427. *
  3428. * --A--
  3429. * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
  3430. * --B--
  3431. * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
  3432. * --C--
  3433. * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
  3434. * --D--
  3435. * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
  3436. * --E--
  3437. * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
  3438. * --F--
  3439. * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
  3440. *
  3441. * Note there is no reason monitors have to be the same size or in a grid.
  3442. */
  3443. THREE.PerspectiveCamera.prototype.setViewOffset = function ( fullWidth, fullHeight, x, y, width, height ) {
  3444. this.fullWidth = fullWidth;
  3445. this.fullHeight = fullHeight;
  3446. this.x = x;
  3447. this.y = y;
  3448. this.width = width;
  3449. this.height = height;
  3450. this.updateProjectionMatrix();
  3451. };
  3452. THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
  3453. if ( this.fullWidth ) {
  3454. var aspect = this.fullWidth / this.fullHeight;
  3455. var top = Math.tan( this.fov * Math.PI / 360 ) * this.near;
  3456. var bottom = -top;
  3457. var left = aspect * bottom;
  3458. var right = aspect * top;
  3459. var width = Math.abs( right - left );
  3460. var height = Math.abs( top - bottom );
  3461. this.projectionMatrix.makeFrustum(
  3462. left + this.x * width / this.fullWidth,
  3463. left + ( this.x + this.width ) * width / this.fullWidth,
  3464. top - ( this.y + this.height ) * height / this.fullHeight,
  3465. top - this.y * height / this.fullHeight,
  3466. this.near,
  3467. this.far
  3468. );
  3469. } else {
  3470. this.projectionMatrix.makePerspective( this.fov, this.aspect, this.near, this.far );
  3471. }
  3472. };
  3473. /**
  3474. * @author mr.doob / http://mrdoob.com/
  3475. * @author alteredq / http://alteredqualia.com/
  3476. */
  3477. THREE.Light = function ( hex ) {
  3478. THREE.Object3D.call( this );
  3479. this.color = new THREE.Color( hex );
  3480. };
  3481. THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
  3482. /**
  3483. * @author mr.doob / http://mrdoob.com/
  3484. */
  3485. THREE.AmbientLight = function ( hex ) {
  3486. THREE.Light.call( this, hex );
  3487. };
  3488. THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
  3489. /**
  3490. * @author mr.doob / http://mrdoob.com/
  3491. * @author alteredq / http://alteredqualia.com/
  3492. */
  3493. THREE.DirectionalLight = function ( hex, intensity, distance ) {
  3494. THREE.Light.call( this, hex );
  3495. this.position = new THREE.Vector3( 0, 1, 0 );
  3496. this.target = new THREE.Object3D();
  3497. this.intensity = ( intensity !== undefined ) ? intensity : 1;
  3498. this.distance = ( distance !== undefined ) ? distance : 0;
  3499. this.castShadow = false;
  3500. this.onlyShadow = false;
  3501. //
  3502. this.shadowCameraNear = 50;
  3503. this.shadowCameraFar = 5000;
  3504. this.shadowCameraLeft = -500;
  3505. this.shadowCameraRight = 500;
  3506. this.shadowCameraTop = 500;
  3507. this.shadowCameraBottom = -500;
  3508. this.shadowCameraVisible = false;
  3509. this.shadowBias = 0;
  3510. this.shadowDarkness = 0.5;
  3511. this.shadowMapWidth = 512;
  3512. this.shadowMapHeight = 512;
  3513. //
  3514. this.shadowCascade = false;
  3515. this.shadowCascadeOffset = new THREE.Vector3( 0, 0, -1000 );
  3516. this.shadowCascadeCount = 2;
  3517. this.shadowCascadeBias = [ 0, 0, 0 ];
  3518. this.shadowCascadeWidth = [ 512, 512, 512 ];
  3519. this.shadowCascadeHeight = [ 512, 512, 512 ];
  3520. this.shadowCascadeNearZ = [ -1.000, 0.990, 0.998 ];
  3521. this.shadowCascadeFarZ = [ 0.990, 0.998, 1.000 ];
  3522. this.shadowCascadeArray = [];
  3523. //
  3524. this.shadowMap = null;
  3525. this.shadowMapSize = null;
  3526. this.shadowCamera = null;
  3527. this.shadowMatrix = null;
  3528. };
  3529. THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );
  3530. /**
  3531. * @author mr.doob / http://mrdoob.com/
  3532. */
  3533. THREE.PointLight = function ( hex, intensity, distance ) {
  3534. THREE.Light.call( this, hex );
  3535. this.position = new THREE.Vector3( 0, 0, 0 );
  3536. this.intensity = ( intensity !== undefined ) ? intensity : 1;
  3537. this.distance = ( distance !== undefined ) ? distance : 0;
  3538. };
  3539. THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
  3540. /**
  3541. * @author alteredq / http://alteredqualia.com/
  3542. */
  3543. THREE.SpotLight = function ( hex, intensity, distance, angle, exponent ) {
  3544. THREE.Light.call( this, hex );
  3545. this.position = new THREE.Vector3( 0, 1, 0 );
  3546. this.target = new THREE.Object3D();
  3547. this.intensity = ( intensity !== undefined ) ? intensity : 1;
  3548. this.distance = ( distance !== undefined ) ? distance : 0;
  3549. this.angle = ( angle !== undefined ) ? angle : Math.PI / 2;
  3550. this.exponent = ( exponent !== undefined ) ? exponent : 10;
  3551. this.castShadow = false;
  3552. this.onlyShadow = false;
  3553. //
  3554. this.shadowCameraNear = 50;
  3555. this.shadowCameraFar = 5000;
  3556. this.shadowCameraFov = 50;
  3557. this.shadowCameraVisible = false;
  3558. this.shadowBias = 0;
  3559. this.shadowDarkness = 0.5;
  3560. this.shadowMapWidth = 512;
  3561. this.shadowMapHeight = 512;
  3562. //
  3563. this.shadowMap = null;
  3564. this.shadowMapSize = null;
  3565. this.shadowCamera = null;
  3566. this.shadowMatrix = null;
  3567. };
  3568. THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
  3569. /**
  3570. * @author alteredq / http://alteredqualia.com/
  3571. */
  3572. THREE.Loader = function ( showStatus ) {
  3573. this.showStatus = showStatus;
  3574. this.statusDomElement = showStatus ? THREE.Loader.prototype.addStatusElement() : null;
  3575. this.onLoadStart = function () {};
  3576. this.onLoadProgress = function () {};
  3577. this.onLoadComplete = function () {};
  3578. };
  3579. THREE.Loader.prototype = {
  3580. constructor: THREE.Loader,
  3581. crossOrigin: 'anonymous',
  3582. addStatusElement: function () {
  3583. var e = document.createElement( "div" );
  3584. e.style.position = "absolute";
  3585. e.style.right = "0px";
  3586. e.style.top = "0px";
  3587. e.style.fontSize = "0.8em";
  3588. e.style.textAlign = "left";
  3589. e.style.background = "rgba(0,0,0,0.25)";
  3590. e.style.color = "#fff";
  3591. e.style.width = "120px";
  3592. e.style.padding = "0.5em 0.5em 0.5em 0.5em";
  3593. e.style.zIndex = 1000;
  3594. e.innerHTML = "Loading ...";
  3595. return e;
  3596. },
  3597. updateProgress: function ( progress ) {
  3598. var message = "Loaded ";
  3599. if ( progress.total ) {
  3600. message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%";
  3601. } else {
  3602. message += ( progress.loaded / 1000 ).toFixed(2) + " KB";
  3603. }
  3604. this.statusDomElement.innerHTML = message;
  3605. },
  3606. extractUrlBase: function ( url ) {
  3607. var parts = url.split( '/' );
  3608. parts.pop();
  3609. return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
  3610. },
  3611. initMaterials: function ( scope, materials, texturePath ) {
  3612. scope.materials = [];
  3613. for ( var i = 0; i < materials.length; ++ i ) {
  3614. scope.materials[ i ] = THREE.Loader.prototype.createMaterial( materials[ i ], texturePath );
  3615. }
  3616. },
  3617. hasNormals: function ( scope ) {
  3618. var m, i, il = scope.materials.length;
  3619. for( i = 0; i < il; i ++ ) {
  3620. m = scope.materials[ i ];
  3621. if ( m instanceof THREE.ShaderMaterial ) return true;
  3622. }
  3623. return false;
  3624. },
  3625. createMaterial: function ( m, texturePath ) {
  3626. var _this = this;
  3627. function is_pow2( n ) {
  3628. var l = Math.log( n ) / Math.LN2;
  3629. return Math.floor( l ) == l;
  3630. }
  3631. function nearest_pow2( n ) {
  3632. var l = Math.log( n ) / Math.LN2;
  3633. return Math.pow( 2, Math.round( l ) );
  3634. }
  3635. function load_image( where, url ) {
  3636. var image = new Image();
  3637. image.onload = function () {
  3638. if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
  3639. var width = nearest_pow2( this.width );
  3640. var height = nearest_pow2( this.height );
  3641. where.image.width = width;
  3642. where.image.height = height;
  3643. where.image.getContext( '2d' ).drawImage( this, 0, 0, width, height );
  3644. } else {
  3645. where.image = this;
  3646. }
  3647. where.needsUpdate = true;
  3648. };
  3649. image.crossOrigin = _this.crossOrigin;
  3650. image.src = url;
  3651. }
  3652. function create_texture( where, name, sourceFile, repeat, offset, wrap ) {
  3653. var texture = document.createElement( 'canvas' );
  3654. where[ name ] = new THREE.Texture( texture );
  3655. where[ name ].sourceFile = sourceFile;
  3656. if( repeat ) {
  3657. where[ name ].repeat.set( repeat[ 0 ], repeat[ 1 ] );
  3658. if ( repeat[ 0 ] != 1 ) where[ name ].wrapS = THREE.RepeatWrapping;
  3659. if ( repeat[ 1 ] != 1 ) where[ name ].wrapT = THREE.RepeatWrapping;
  3660. }
  3661. if ( offset ) {
  3662. where[ name ].offset.set( offset[ 0 ], offset[ 1 ] );
  3663. }
  3664. if ( wrap ) {
  3665. var wrapMap = {
  3666. "repeat": THREE.RepeatWrapping,
  3667. "mirror": THREE.MirroredRepeatWrapping
  3668. }
  3669. if ( wrapMap[ wrap[ 0 ] ] !== undefined ) where[ name ].wrapS = wrapMap[ wrap[ 0 ] ];
  3670. if ( wrapMap[ wrap[ 1 ] ] !== undefined ) where[ name ].wrapT = wrapMap[ wrap[ 1 ] ];
  3671. }
  3672. load_image( where[ name ], texturePath + "/" + sourceFile );
  3673. }
  3674. function rgb2hex( rgb ) {
  3675. return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
  3676. }
  3677. // defaults
  3678. var mtype = "MeshLambertMaterial";
  3679. var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, wireframe: m.wireframe };
  3680. // parameters from model file
  3681. if ( m.shading ) {
  3682. var shading = m.shading.toLowerCase();
  3683. if ( shading === "phong" ) mtype = "MeshPhongMaterial";
  3684. else if ( shading === "basic" ) mtype = "MeshBasicMaterial";
  3685. }
  3686. if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
  3687. mpars.blending = THREE[ m.blending ];
  3688. }
  3689. if ( m.transparent !== undefined || m.opacity < 1.0 ) {
  3690. mpars.transparent = m.transparent;
  3691. }
  3692. if ( m.depthTest !== undefined ) {
  3693. mpars.depthTest = m.depthTest;
  3694. }
  3695. if ( m.depthWrite !== undefined ) {
  3696. mpars.depthWrite = m.depthWrite;
  3697. }
  3698. if ( m.vertexColors !== undefined ) {
  3699. if ( m.vertexColors == "face" ) {
  3700. mpars.vertexColors = THREE.FaceColors;
  3701. } else if ( m.vertexColors ) {
  3702. mpars.vertexColors = THREE.VertexColors;
  3703. }
  3704. }
  3705. // colors
  3706. if ( m.colorDiffuse ) {
  3707. mpars.color = rgb2hex( m.colorDiffuse );
  3708. } else if ( m.DbgColor ) {
  3709. mpars.color = m.DbgColor;
  3710. }
  3711. if ( m.colorSpecular ) {
  3712. mpars.specular = rgb2hex( m.colorSpecular );
  3713. }
  3714. if ( m.colorAmbient ) {
  3715. mpars.ambient = rgb2hex( m.colorAmbient );
  3716. }
  3717. // modifiers
  3718. if ( m.transparency ) {
  3719. mpars.opacity = m.transparency;
  3720. }
  3721. if ( m.specularCoef ) {
  3722. mpars.shininess = m.specularCoef;
  3723. }
  3724. // textures
  3725. if ( m.mapDiffuse && texturePath ) {
  3726. create_texture( mpars, "map", m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap );
  3727. }
  3728. if ( m.mapLight && texturePath ) {
  3729. create_texture( mpars, "lightMap", m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap );
  3730. }
  3731. if ( m.mapNormal && texturePath ) {
  3732. create_texture( mpars, "normalMap", m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap );
  3733. }
  3734. if ( m.mapSpecular && texturePath ) {
  3735. create_texture( mpars, "specularMap", m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap );
  3736. }
  3737. // special case for normal mapped material
  3738. if ( m.mapNormal ) {
  3739. var shader = THREE.ShaderUtils.lib[ "normal" ];
  3740. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  3741. uniforms[ "tNormal" ].texture = mpars.normalMap;
  3742. if ( m.mapNormalFactor ) {
  3743. uniforms[ "uNormalScale" ].value = m.mapNormalFactor;
  3744. }
  3745. if ( mpars.map ) {
  3746. uniforms[ "tDiffuse" ].texture = mpars.map;
  3747. uniforms[ "enableDiffuse" ].value = true;
  3748. }
  3749. if ( mpars.specularMap ) {
  3750. uniforms[ "tSpecular" ].texture = mpars.specularMap;
  3751. uniforms[ "enableSpecular" ].value = true;
  3752. }
  3753. if ( mpars.lightMap ) {
  3754. uniforms[ "tAO" ].texture = mpars.lightMap;
  3755. uniforms[ "enableAO" ].value = true;
  3756. }
  3757. // for the moment don't handle displacement texture
  3758. uniforms[ "uDiffuseColor" ].value.setHex( mpars.color );
  3759. uniforms[ "uSpecularColor" ].value.setHex( mpars.specular );
  3760. uniforms[ "uAmbientColor" ].value.setHex( mpars.ambient );
  3761. uniforms[ "uShininess" ].value = mpars.shininess;
  3762. if ( mpars.opacity !== undefined ) {
  3763. uniforms[ "uOpacity" ].value = mpars.opacity;
  3764. }
  3765. var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
  3766. var material = new THREE.ShaderMaterial( parameters );
  3767. } else {
  3768. var material = new THREE[ mtype ]( mpars );
  3769. }
  3770. if ( m.DbgName !== undefined ) material.name = m.DbgName;
  3771. return material;
  3772. }
  3773. };
  3774. /**
  3775. * @author alteredq / http://alteredqualia.com/
  3776. */
  3777. THREE.BinaryLoader = function ( showStatus ) {
  3778. THREE.Loader.call( this, showStatus );
  3779. };
  3780. THREE.BinaryLoader.prototype = Object.create( THREE.Loader.prototype );
  3781. // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
  3782. // - binary models consist of two files: JS and BIN
  3783. // - parameters
  3784. // - url (required)
  3785. // - callback (required)
  3786. // - texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
  3787. // - binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
  3788. THREE.BinaryLoader.prototype.load = function( url, callback, texturePath, binaryPath ) {
  3789. texturePath = texturePath ? texturePath : this.extractUrlBase( url );
  3790. binaryPath = binaryPath ? binaryPath : this.extractUrlBase( url );
  3791. var callbackProgress = this.showProgress ? THREE.Loader.prototype.updateProgress : null;
  3792. this.onLoadStart();
  3793. // #1 load JS part via web worker
  3794. this.loadAjaxJSON( this, url, callback, texturePath, binaryPath, callbackProgress );
  3795. };
  3796. THREE.BinaryLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, binaryPath, callbackProgress ) {
  3797. var xhr = new XMLHttpRequest();
  3798. xhr.onreadystatechange = function () {
  3799. if ( xhr.readyState == 4 ) {
  3800. if ( xhr.status == 200 || xhr.status == 0 ) {
  3801. var json = JSON.parse( xhr.responseText );
  3802. context.loadAjaxBuffers( json, callback, binaryPath, texturePath, callbackProgress );
  3803. } else {
  3804. console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  3805. }
  3806. }
  3807. };
  3808. xhr.open( "GET", url, true );
  3809. if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
  3810. xhr.setRequestHeader( "Content-Type", "text/plain" );
  3811. xhr.send( null );
  3812. };
  3813. THREE.BinaryLoader.prototype.loadAjaxBuffers = function ( json, callback, binaryPath, texturePath, callbackProgress ) {
  3814. var xhr = new XMLHttpRequest(),
  3815. url = binaryPath + "/" + json.buffers;
  3816. var length = 0;
  3817. xhr.onreadystatechange = function () {
  3818. if ( xhr.readyState == 4 ) {
  3819. if ( xhr.status == 200 || xhr.status == 0 ) {
  3820. THREE.BinaryLoader.prototype.createBinModel( xhr.response, callback, texturePath, json.materials );
  3821. } else {
  3822. console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  3823. }
  3824. } else if ( xhr.readyState == 3 ) {
  3825. if ( callbackProgress ) {
  3826. if ( length == 0 ) {
  3827. length = xhr.getResponseHeader( "Content-Length" );
  3828. }
  3829. callbackProgress( { total: length, loaded: xhr.responseText.length } );
  3830. }
  3831. } else if ( xhr.readyState == 2 ) {
  3832. length = xhr.getResponseHeader( "Content-Length" );
  3833. }
  3834. };
  3835. xhr.open( "GET", url, true );
  3836. xhr.responseType = "arraybuffer";
  3837. xhr.send( null );
  3838. };
  3839. // Binary AJAX parser
  3840. THREE.BinaryLoader.prototype.createBinModel = function ( data, callback, texturePath, materials ) {
  3841. var Model = function ( texturePath ) {
  3842. var scope = this,
  3843. currentOffset = 0,
  3844. md,
  3845. normals = [],
  3846. uvs = [],
  3847. start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
  3848. start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
  3849. tri_size, quad_size,
  3850. len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
  3851. len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
  3852. THREE.Geometry.call( this );
  3853. THREE.Loader.prototype.initMaterials( scope, materials, texturePath );
  3854. md = parseMetaData( data, currentOffset );
  3855. currentOffset += md.header_bytes;
  3856. /*
  3857. md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  3858. md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
  3859. md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  3860. md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  3861. */
  3862. // buffers sizes
  3863. tri_size = md.vertex_index_bytes * 3 + md.material_index_bytes;
  3864. quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
  3865. len_tri_flat = md.ntri_flat * ( tri_size );
  3866. len_tri_smooth = md.ntri_smooth * ( tri_size + md.normal_index_bytes * 3 );
  3867. len_tri_flat_uv = md.ntri_flat_uv * ( tri_size + md.uv_index_bytes * 3 );
  3868. len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
  3869. len_quad_flat = md.nquad_flat * ( quad_size );
  3870. len_quad_smooth = md.nquad_smooth * ( quad_size + md.normal_index_bytes * 4 );
  3871. len_quad_flat_uv = md.nquad_flat_uv * ( quad_size + md.uv_index_bytes * 4 );
  3872. len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
  3873. // read buffers
  3874. currentOffset += init_vertices( currentOffset );
  3875. currentOffset += init_normals( currentOffset );
  3876. currentOffset += handlePadding( md.nnormals * 3 );
  3877. currentOffset += init_uvs( currentOffset );
  3878. start_tri_flat = currentOffset;
  3879. start_tri_smooth = start_tri_flat + len_tri_flat + handlePadding( md.ntri_flat * 2 );
  3880. start_tri_flat_uv = start_tri_smooth + len_tri_smooth + handlePadding( md.ntri_smooth * 2 );
  3881. start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
  3882. start_quad_flat = start_tri_smooth_uv + len_tri_smooth_uv + handlePadding( md.ntri_smooth_uv * 2 );
  3883. start_quad_smooth = start_quad_flat + len_quad_flat + handlePadding( md.nquad_flat * 2 );
  3884. start_quad_flat_uv = start_quad_smooth + len_quad_smooth + handlePadding( md.nquad_smooth * 2 );
  3885. start_quad_smooth_uv= start_quad_flat_uv + len_quad_flat_uv + handlePadding( md.nquad_flat_uv * 2 );
  3886. // have to first process faces with uvs
  3887. // so that face and uv indices match
  3888. init_triangles_flat_uv( start_tri_flat_uv );
  3889. init_triangles_smooth_uv( start_tri_smooth_uv );
  3890. init_quads_flat_uv( start_quad_flat_uv );
  3891. init_quads_smooth_uv( start_quad_smooth_uv );
  3892. // now we can process untextured faces
  3893. init_triangles_flat( start_tri_flat );
  3894. init_triangles_smooth( start_tri_smooth );
  3895. init_quads_flat( start_quad_flat );
  3896. init_quads_smooth( start_quad_smooth );
  3897. this.computeCentroids();
  3898. this.computeFaceNormals();
  3899. if ( THREE.Loader.prototype.hasNormals( this ) ) this.computeTangents();
  3900. function handlePadding( n ) {
  3901. return ( n % 4 ) ? ( 4 - n % 4 ) : 0;
  3902. };
  3903. function parseMetaData( data, offset ) {
  3904. var metaData = {
  3905. 'signature' :parseString( data, offset, 12 ),
  3906. 'header_bytes' :parseUChar8( data, offset + 12 ),
  3907. 'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
  3908. 'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
  3909. 'uv_coordinate_bytes' :parseUChar8( data, offset + 15 ),
  3910. 'vertex_index_bytes' :parseUChar8( data, offset + 16 ),
  3911. 'normal_index_bytes' :parseUChar8( data, offset + 17 ),
  3912. 'uv_index_bytes' :parseUChar8( data, offset + 18 ),
  3913. 'material_index_bytes' :parseUChar8( data, offset + 19 ),
  3914. 'nvertices' :parseUInt32( data, offset + 20 ),
  3915. 'nnormals' :parseUInt32( data, offset + 20 + 4*1 ),
  3916. 'nuvs' :parseUInt32( data, offset + 20 + 4*2 ),
  3917. 'ntri_flat' :parseUInt32( data, offset + 20 + 4*3 ),
  3918. 'ntri_smooth' :parseUInt32( data, offset + 20 + 4*4 ),
  3919. 'ntri_flat_uv' :parseUInt32( data, offset + 20 + 4*5 ),
  3920. 'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4*6 ),
  3921. 'nquad_flat' :parseUInt32( data, offset + 20 + 4*7 ),
  3922. 'nquad_smooth' :parseUInt32( data, offset + 20 + 4*8 ),
  3923. 'nquad_flat_uv' :parseUInt32( data, offset + 20 + 4*9 ),
  3924. 'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4*10 )
  3925. };
  3926. /*
  3927. console.log( "signature: " + metaData.signature );
  3928. console.log( "header_bytes: " + metaData.header_bytes );
  3929. console.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
  3930. console.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
  3931. console.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
  3932. console.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
  3933. console.log( "normal_index_bytes: " + metaData.normal_index_bytes );
  3934. console.log( "uv_index_bytes: " + metaData.uv_index_bytes );
  3935. console.log( "material_index_bytes: " + metaData.material_index_bytes );
  3936. console.log( "nvertices: " + metaData.nvertices );
  3937. console.log( "nnormals: " + metaData.nnormals );
  3938. console.log( "nuvs: " + metaData.nuvs );
  3939. console.log( "ntri_flat: " + metaData.ntri_flat );
  3940. console.log( "ntri_smooth: " + metaData.ntri_smooth );
  3941. console.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
  3942. console.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
  3943. console.log( "nquad_flat: " + metaData.nquad_flat );
  3944. console.log( "nquad_smooth: " + metaData.nquad_smooth );
  3945. console.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
  3946. console.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
  3947. var total = metaData.header_bytes
  3948. + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
  3949. + metaData.nnormals * metaData.normal_coordinate_bytes * 3
  3950. + metaData.nuvs * metaData.uv_coordinate_bytes * 2
  3951. + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
  3952. + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
  3953. + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
  3954. + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
  3955. + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
  3956. + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
  3957. + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
  3958. + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
  3959. console.log( "total bytes: " + total );
  3960. */
  3961. return metaData;
  3962. };
  3963. function parseString( data, offset, length ) {
  3964. var charArray = new Uint8Array( data, offset, length );
  3965. var text = "";
  3966. for ( var i = 0; i < length; i ++ ) {
  3967. text += String.fromCharCode( charArray[ offset + i ] );
  3968. }
  3969. return text;
  3970. };
  3971. function parseUChar8( data, offset ) {
  3972. var charArray = new Uint8Array( data, offset, 1 );
  3973. return charArray[ 0 ];
  3974. };
  3975. function parseUInt32( data, offset ) {
  3976. var intArray = new Uint32Array( data, offset, 1 );
  3977. return intArray[ 0 ];
  3978. };
  3979. function init_vertices( start ) {
  3980. var nElements = md.nvertices;
  3981. var coordArray = new Float32Array( data, start, nElements * 3 );
  3982. var i, x, y, z;
  3983. for( i = 0; i < nElements; i ++ ) {
  3984. x = coordArray[ i * 3 ];
  3985. y = coordArray[ i * 3 + 1 ];
  3986. z = coordArray[ i * 3 + 2 ];
  3987. vertex( scope, x, y, z );
  3988. }
  3989. return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
  3990. };
  3991. function init_normals( start ) {
  3992. var nElements = md.nnormals;
  3993. if ( nElements ) {
  3994. var normalArray = new Int8Array( data, start, nElements * 3 );
  3995. var i, x, y, z;
  3996. for( i = 0; i < nElements; i ++ ) {
  3997. x = normalArray[ i * 3 ];
  3998. y = normalArray[ i * 3 + 1 ];
  3999. z = normalArray[ i * 3 + 2 ];
  4000. normals.push( x/127, y/127, z/127 );
  4001. }
  4002. }
  4003. return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
  4004. };
  4005. function init_uvs( start ) {
  4006. var nElements = md.nuvs;
  4007. if ( nElements ) {
  4008. var uvArray = new Float32Array( data, start, nElements * 2 );
  4009. var i, u, v;
  4010. for( i = 0; i < nElements; i ++ ) {
  4011. u = uvArray[ i * 2 ];
  4012. v = uvArray[ i * 2 + 1 ];
  4013. uvs.push( u, v );
  4014. }
  4015. }
  4016. return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
  4017. };
  4018. function init_uvs3( nElements, offset ) {
  4019. var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
  4020. var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
  4021. for( i = 0; i < nElements; i ++ ) {
  4022. uva = uvIndexBuffer[ i * 3 ];
  4023. uvb = uvIndexBuffer[ i * 3 + 1 ];
  4024. uvc = uvIndexBuffer[ i * 3 + 2 ];
  4025. u1 = uvs[ uva*2 ];
  4026. v1 = uvs[ uva*2 + 1 ];
  4027. u2 = uvs[ uvb*2 ];
  4028. v2 = uvs[ uvb*2 + 1 ];
  4029. u3 = uvs[ uvc*2 ];
  4030. v3 = uvs[ uvc*2 + 1 ];
  4031. uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
  4032. }
  4033. };
  4034. function init_uvs4( nElements, offset ) {
  4035. var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
  4036. var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );
  4037. for( i = 0; i < nElements; i ++ ) {
  4038. uva = uvIndexBuffer[ i * 4 ];
  4039. uvb = uvIndexBuffer[ i * 4 + 1 ];
  4040. uvc = uvIndexBuffer[ i * 4 + 2 ];
  4041. uvd = uvIndexBuffer[ i * 4 + 3 ];
  4042. u1 = uvs[ uva*2 ];
  4043. v1 = uvs[ uva*2 + 1 ];
  4044. u2 = uvs[ uvb*2 ];
  4045. v2 = uvs[ uvb*2 + 1 ];
  4046. u3 = uvs[ uvc*2 ];
  4047. v3 = uvs[ uvc*2 + 1 ];
  4048. u4 = uvs[ uvd*2 ];
  4049. v4 = uvs[ uvd*2 + 1 ];
  4050. uv4( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3, u4, v4 );
  4051. }
  4052. };
  4053. function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {
  4054. var i, a, b, c, m;
  4055. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
  4056. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  4057. for( i = 0; i < nElements; i ++ ) {
  4058. a = vertexIndexBuffer[ i * 3 ];
  4059. b = vertexIndexBuffer[ i * 3 + 1 ];
  4060. c = vertexIndexBuffer[ i * 3 + 2 ];
  4061. m = materialIndexBuffer[ i ];
  4062. f3( scope, a, b, c, m );
  4063. }
  4064. };
  4065. function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {
  4066. var i, a, b, c, d, m;
  4067. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
  4068. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  4069. for( i = 0; i < nElements; i ++ ) {
  4070. a = vertexIndexBuffer[ i * 4 ];
  4071. b = vertexIndexBuffer[ i * 4 + 1 ];
  4072. c = vertexIndexBuffer[ i * 4 + 2 ];
  4073. d = vertexIndexBuffer[ i * 4 + 3 ];
  4074. m = materialIndexBuffer[ i ];
  4075. f4( scope, a, b, c, d, m );
  4076. }
  4077. };
  4078. function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
  4079. var i, a, b, c, m;
  4080. var na, nb, nc;
  4081. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
  4082. var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
  4083. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  4084. for( i = 0; i < nElements; i ++ ) {
  4085. a = vertexIndexBuffer[ i * 3 ];
  4086. b = vertexIndexBuffer[ i * 3 + 1 ];
  4087. c = vertexIndexBuffer[ i * 3 + 2 ];
  4088. na = normalIndexBuffer[ i * 3 ];
  4089. nb = normalIndexBuffer[ i * 3 + 1 ];
  4090. nc = normalIndexBuffer[ i * 3 + 2 ];
  4091. m = materialIndexBuffer[ i ];
  4092. f3n( scope, normals, a, b, c, m, na, nb, nc );
  4093. }
  4094. };
  4095. function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
  4096. var i, a, b, c, d, m;
  4097. var na, nb, nc, nd;
  4098. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
  4099. var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
  4100. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  4101. for( i = 0; i < nElements; i ++ ) {
  4102. a = vertexIndexBuffer[ i * 4 ];
  4103. b = vertexIndexBuffer[ i * 4 + 1 ];
  4104. c = vertexIndexBuffer[ i * 4 + 2 ];
  4105. d = vertexIndexBuffer[ i * 4 + 3 ];
  4106. na = normalIndexBuffer[ i * 4 ];
  4107. nb = normalIndexBuffer[ i * 4 + 1 ];
  4108. nc = normalIndexBuffer[ i * 4 + 2 ];
  4109. nd = normalIndexBuffer[ i * 4 + 3 ];
  4110. m = materialIndexBuffer[ i ];
  4111. f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd );
  4112. }
  4113. };
  4114. function init_triangles_flat( start ) {
  4115. var nElements = md.ntri_flat;
  4116. if ( nElements ) {
  4117. var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4118. init_faces3_flat( nElements, start, offsetMaterials );
  4119. }
  4120. };
  4121. function init_triangles_flat_uv( start ) {
  4122. var nElements = md.ntri_flat_uv;
  4123. if ( nElements ) {
  4124. var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4125. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4126. init_faces3_flat( nElements, start, offsetMaterials );
  4127. init_uvs3( nElements, offsetUvs );
  4128. }
  4129. };
  4130. function init_triangles_smooth( start ) {
  4131. var nElements = md.ntri_smooth;
  4132. if ( nElements ) {
  4133. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4134. var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4135. init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
  4136. }
  4137. };
  4138. function init_triangles_smooth_uv( start ) {
  4139. var nElements = md.ntri_smooth_uv;
  4140. if ( nElements ) {
  4141. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4142. var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4143. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  4144. init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
  4145. init_uvs3( nElements, offsetUvs );
  4146. }
  4147. };
  4148. function init_quads_flat( start ) {
  4149. var nElements = md.nquad_flat;
  4150. if ( nElements ) {
  4151. var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4152. init_faces4_flat( nElements, start, offsetMaterials );
  4153. }
  4154. };
  4155. function init_quads_flat_uv( start ) {
  4156. var nElements = md.nquad_flat_uv;
  4157. if ( nElements ) {
  4158. var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4159. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4160. init_faces4_flat( nElements, start, offsetMaterials );
  4161. init_uvs4( nElements, offsetUvs );
  4162. }
  4163. };
  4164. function init_quads_smooth( start ) {
  4165. var nElements = md.nquad_smooth;
  4166. if ( nElements ) {
  4167. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4168. var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4169. init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
  4170. }
  4171. };
  4172. function init_quads_smooth_uv( start ) {
  4173. var nElements = md.nquad_smooth_uv;
  4174. if ( nElements ) {
  4175. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4176. var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4177. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  4178. init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
  4179. init_uvs4( nElements, offsetUvs );
  4180. }
  4181. };
  4182. };
  4183. function vertex ( scope, x, y, z ) {
  4184. scope.vertices.push( new THREE.Vector3( x, y, z ) );
  4185. };
  4186. function f3 ( scope, a, b, c, mi ) {
  4187. scope.faces.push( new THREE.Face3( a, b, c, null, null, mi ) );
  4188. };
  4189. function f4 ( scope, a, b, c, d, mi ) {
  4190. scope.faces.push( new THREE.Face4( a, b, c, d, null, null, mi ) );
  4191. };
  4192. function f3n ( scope, normals, a, b, c, mi, na, nb, nc ) {
  4193. var nax = normals[ na*3 ],
  4194. nay = normals[ na*3 + 1 ],
  4195. naz = normals[ na*3 + 2 ],
  4196. nbx = normals[ nb*3 ],
  4197. nby = normals[ nb*3 + 1 ],
  4198. nbz = normals[ nb*3 + 2 ],
  4199. ncx = normals[ nc*3 ],
  4200. ncy = normals[ nc*3 + 1 ],
  4201. ncz = normals[ nc*3 + 2 ];
  4202. scope.faces.push( new THREE.Face3( a, b, c,
  4203. [new THREE.Vector3( nax, nay, naz ),
  4204. new THREE.Vector3( nbx, nby, nbz ),
  4205. new THREE.Vector3( ncx, ncy, ncz )],
  4206. null,
  4207. mi ) );
  4208. };
  4209. function f4n ( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) {
  4210. var nax = normals[ na*3 ],
  4211. nay = normals[ na*3 + 1 ],
  4212. naz = normals[ na*3 + 2 ],
  4213. nbx = normals[ nb*3 ],
  4214. nby = normals[ nb*3 + 1 ],
  4215. nbz = normals[ nb*3 + 2 ],
  4216. ncx = normals[ nc*3 ],
  4217. ncy = normals[ nc*3 + 1 ],
  4218. ncz = normals[ nc*3 + 2 ],
  4219. ndx = normals[ nd*3 ],
  4220. ndy = normals[ nd*3 + 1 ],
  4221. ndz = normals[ nd*3 + 2 ];
  4222. scope.faces.push( new THREE.Face4( a, b, c, d,
  4223. [new THREE.Vector3( nax, nay, naz ),
  4224. new THREE.Vector3( nbx, nby, nbz ),
  4225. new THREE.Vector3( ncx, ncy, ncz ),
  4226. new THREE.Vector3( ndx, ndy, ndz )],
  4227. null,
  4228. mi ) );
  4229. };
  4230. function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
  4231. var uv = [];
  4232. uv.push( new THREE.UV( u1, v1 ) );
  4233. uv.push( new THREE.UV( u2, v2 ) );
  4234. uv.push( new THREE.UV( u3, v3 ) );
  4235. where.push( uv );
  4236. };
  4237. function uv4 ( where, u1, v1, u2, v2, u3, v3, u4, v4 ) {
  4238. var uv = [];
  4239. uv.push( new THREE.UV( u1, v1 ) );
  4240. uv.push( new THREE.UV( u2, v2 ) );
  4241. uv.push( new THREE.UV( u3, v3 ) );
  4242. uv.push( new THREE.UV( u4, v4 ) );
  4243. where.push( uv );
  4244. };
  4245. Model.prototype = Object.create( THREE.Geometry.prototype );
  4246. callback( new Model( texturePath ) );
  4247. };
  4248. /**
  4249. * @author mrdoob / http://mrdoob.com/
  4250. */
  4251. THREE.ImageLoader = function () {
  4252. THREE.EventTarget.call( this );
  4253. this.crossOrigin = null;
  4254. };
  4255. THREE.ImageLoader.prototype = {
  4256. constructor: THREE.ImageLoader,
  4257. load: function ( url ) {
  4258. var scope = this;
  4259. var image = new Image();
  4260. image.addEventListener( 'load', function () {
  4261. scope.dispatchEvent( { type: 'load', content: image } );
  4262. }, false );
  4263. image.addEventListener( 'error', function () {
  4264. scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
  4265. }, false );
  4266. if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
  4267. image.src = url;
  4268. }
  4269. }
  4270. /**
  4271. * @author mrdoob / http://mrdoob.com/
  4272. * @author alteredq / http://alteredqualia.com/
  4273. */
  4274. THREE.JSONLoader = function ( showStatus ) {
  4275. THREE.Loader.call( this, showStatus );
  4276. };
  4277. THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype );
  4278. THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
  4279. var scope = this;
  4280. texturePath = texturePath ? texturePath : this.extractUrlBase( url );
  4281. this.onLoadStart();
  4282. this.loadAjaxJSON( this, url, callback, texturePath );
  4283. };
  4284. THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, callbackProgress ) {
  4285. var xhr = new XMLHttpRequest();
  4286. var length = 0;
  4287. xhr.onreadystatechange = function () {
  4288. if ( xhr.readyState === xhr.DONE ) {
  4289. if ( xhr.status === 200 || xhr.status === 0 ) {
  4290. if ( xhr.responseText ) {
  4291. var json = JSON.parse( xhr.responseText );
  4292. context.createModel( json, callback, texturePath );
  4293. } else {
  4294. console.warn( "THREE.JSONLoader: [" + url + "] seems to be unreachable or file there is empty" );
  4295. }
  4296. // in context of more complex asset initialization
  4297. // do not block on single failed file
  4298. // maybe should go even one more level up
  4299. context.onLoadComplete();
  4300. } else {
  4301. console.error( "THREE.JSONLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  4302. }
  4303. } else if ( xhr.readyState === xhr.LOADING ) {
  4304. if ( callbackProgress ) {
  4305. if ( length === 0 ) {
  4306. length = xhr.getResponseHeader( "Content-Length" );
  4307. }
  4308. callbackProgress( { total: length, loaded: xhr.responseText.length } );
  4309. }
  4310. } else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
  4311. length = xhr.getResponseHeader( "Content-Length" );
  4312. }
  4313. };
  4314. xhr.open( "GET", url, true );
  4315. if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
  4316. xhr.setRequestHeader( "Content-Type", "text/plain" );
  4317. xhr.send( null );
  4318. };
  4319. THREE.JSONLoader.prototype.createModel = function ( json, callback, texturePath ) {
  4320. var scope = this,
  4321. geometry = new THREE.Geometry(),
  4322. scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
  4323. this.initMaterials( geometry, json.materials, texturePath );
  4324. parseModel( scale );
  4325. parseSkin();
  4326. parseMorphing( scale );
  4327. geometry.computeCentroids();
  4328. geometry.computeFaceNormals();
  4329. if ( this.hasNormals( geometry ) ) geometry.computeTangents();
  4330. function parseModel( scale ) {
  4331. function isBitSet( value, position ) {
  4332. return value & ( 1 << position );
  4333. }
  4334. var i, j, fi,
  4335. offset, zLength, nVertices,
  4336. colorIndex, normalIndex, uvIndex, materialIndex,
  4337. type,
  4338. isQuad,
  4339. hasMaterial,
  4340. hasFaceUv, hasFaceVertexUv,
  4341. hasFaceNormal, hasFaceVertexNormal,
  4342. hasFaceColor, hasFaceVertexColor,
  4343. vertex, face, color, normal,
  4344. uvLayer, uvs, u, v,
  4345. faces = json.faces,
  4346. vertices = json.vertices,
  4347. normals = json.normals,
  4348. colors = json.colors,
  4349. nUvLayers = 0;
  4350. // disregard empty arrays
  4351. for ( i = 0; i < json.uvs.length; i++ ) {
  4352. if ( json.uvs[ i ].length ) nUvLayers ++;
  4353. }
  4354. for ( i = 0; i < nUvLayers; i++ ) {
  4355. geometry.faceUvs[ i ] = [];
  4356. geometry.faceVertexUvs[ i ] = [];
  4357. }
  4358. offset = 0;
  4359. zLength = vertices.length;
  4360. while ( offset < zLength ) {
  4361. vertex = new THREE.Vector3();
  4362. vertex.x = vertices[ offset ++ ] * scale;
  4363. vertex.y = vertices[ offset ++ ] * scale;
  4364. vertex.z = vertices[ offset ++ ] * scale;
  4365. geometry.vertices.push( vertex );
  4366. }
  4367. offset = 0;
  4368. zLength = faces.length;
  4369. while ( offset < zLength ) {
  4370. type = faces[ offset ++ ];
  4371. isQuad = isBitSet( type, 0 );
  4372. hasMaterial = isBitSet( type, 1 );
  4373. hasFaceUv = isBitSet( type, 2 );
  4374. hasFaceVertexUv = isBitSet( type, 3 );
  4375. hasFaceNormal = isBitSet( type, 4 );
  4376. hasFaceVertexNormal = isBitSet( type, 5 );
  4377. hasFaceColor = isBitSet( type, 6 );
  4378. hasFaceVertexColor = isBitSet( type, 7 );
  4379. //console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
  4380. if ( isQuad ) {
  4381. face = new THREE.Face4();
  4382. face.a = faces[ offset ++ ];
  4383. face.b = faces[ offset ++ ];
  4384. face.c = faces[ offset ++ ];
  4385. face.d = faces[ offset ++ ];
  4386. nVertices = 4;
  4387. } else {
  4388. face = new THREE.Face3();
  4389. face.a = faces[ offset ++ ];
  4390. face.b = faces[ offset ++ ];
  4391. face.c = faces[ offset ++ ];
  4392. nVertices = 3;
  4393. }
  4394. if ( hasMaterial ) {
  4395. materialIndex = faces[ offset ++ ];
  4396. face.materialIndex = materialIndex;
  4397. }
  4398. // to get face <=> uv index correspondence
  4399. fi = geometry.faces.length;
  4400. if ( hasFaceUv ) {
  4401. for ( i = 0; i < nUvLayers; i++ ) {
  4402. uvLayer = json.uvs[ i ];
  4403. uvIndex = faces[ offset ++ ];
  4404. u = uvLayer[ uvIndex * 2 ];
  4405. v = uvLayer[ uvIndex * 2 + 1 ];
  4406. geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v );
  4407. }
  4408. }
  4409. if ( hasFaceVertexUv ) {
  4410. for ( i = 0; i < nUvLayers; i++ ) {
  4411. uvLayer = json.uvs[ i ];
  4412. uvs = [];
  4413. for ( j = 0; j < nVertices; j ++ ) {
  4414. uvIndex = faces[ offset ++ ];
  4415. u = uvLayer[ uvIndex * 2 ];
  4416. v = uvLayer[ uvIndex * 2 + 1 ];
  4417. uvs[ j ] = new THREE.UV( u, v );
  4418. }
  4419. geometry.faceVertexUvs[ i ][ fi ] = uvs;
  4420. }
  4421. }
  4422. if ( hasFaceNormal ) {
  4423. normalIndex = faces[ offset ++ ] * 3;
  4424. normal = new THREE.Vector3();
  4425. normal.x = normals[ normalIndex ++ ];
  4426. normal.y = normals[ normalIndex ++ ];
  4427. normal.z = normals[ normalIndex ];
  4428. face.normal = normal;
  4429. }
  4430. if ( hasFaceVertexNormal ) {
  4431. for ( i = 0; i < nVertices; i++ ) {
  4432. normalIndex = faces[ offset ++ ] * 3;
  4433. normal = new THREE.Vector3();
  4434. normal.x = normals[ normalIndex ++ ];
  4435. normal.y = normals[ normalIndex ++ ];
  4436. normal.z = normals[ normalIndex ];
  4437. face.vertexNormals.push( normal );
  4438. }
  4439. }
  4440. if ( hasFaceColor ) {
  4441. colorIndex = faces[ offset ++ ];
  4442. color = new THREE.Color( colors[ colorIndex ] );
  4443. face.color = color;
  4444. }
  4445. if ( hasFaceVertexColor ) {
  4446. for ( i = 0; i < nVertices; i++ ) {
  4447. colorIndex = faces[ offset ++ ];
  4448. color = new THREE.Color( colors[ colorIndex ] );
  4449. face.vertexColors.push( color );
  4450. }
  4451. }
  4452. geometry.faces.push( face );
  4453. }
  4454. };
  4455. function parseSkin() {
  4456. var i, l, x, y, z, w, a, b, c, d;
  4457. if ( json.skinWeights ) {
  4458. for ( i = 0, l = json.skinWeights.length; i < l; i += 2 ) {
  4459. x = json.skinWeights[ i ];
  4460. y = json.skinWeights[ i + 1 ];
  4461. z = 0;
  4462. w = 0;
  4463. geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
  4464. }
  4465. }
  4466. if ( json.skinIndices ) {
  4467. for ( i = 0, l = json.skinIndices.length; i < l; i += 2 ) {
  4468. a = json.skinIndices[ i ];
  4469. b = json.skinIndices[ i + 1 ];
  4470. c = 0;
  4471. d = 0;
  4472. geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
  4473. }
  4474. }
  4475. geometry.bones = json.bones;
  4476. geometry.animation = json.animation;
  4477. };
  4478. function parseMorphing( scale ) {
  4479. if ( json.morphTargets !== undefined ) {
  4480. var i, l, v, vl, dstVertices, srcVertices;
  4481. for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
  4482. geometry.morphTargets[ i ] = {};
  4483. geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
  4484. geometry.morphTargets[ i ].vertices = [];
  4485. dstVertices = geometry.morphTargets[ i ].vertices;
  4486. srcVertices = json.morphTargets [ i ].vertices;
  4487. for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
  4488. var vertex = new THREE.Vector3();
  4489. vertex.x = srcVertices[ v ] * scale;
  4490. vertex.y = srcVertices[ v + 1 ] * scale;
  4491. vertex.z = srcVertices[ v + 2 ] * scale;
  4492. dstVertices.push( vertex );
  4493. }
  4494. }
  4495. }
  4496. if ( json.morphColors !== undefined ) {
  4497. var i, l, c, cl, dstColors, srcColors, color;
  4498. for ( i = 0, l = json.morphColors.length; i < l; i++ ) {
  4499. geometry.morphColors[ i ] = {};
  4500. geometry.morphColors[ i ].name = json.morphColors[ i ].name;
  4501. geometry.morphColors[ i ].colors = [];
  4502. dstColors = geometry.morphColors[ i ].colors;
  4503. srcColors = json.morphColors [ i ].colors;
  4504. for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) {
  4505. color = new THREE.Color( 0xffaa00 );
  4506. color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
  4507. dstColors.push( color );
  4508. }
  4509. }
  4510. }
  4511. };
  4512. callback( geometry );
  4513. };
  4514. /**
  4515. * @author mrdoob / http://mrdoob.com/
  4516. * @author alteredq / http://alteredqualia.com/
  4517. */
  4518. THREE.GeometryLoader = function () {
  4519. THREE.EventTarget.call( this );
  4520. this.crossOrigin = null;
  4521. this.path = null;
  4522. };
  4523. THREE.GeometryLoader.prototype = {
  4524. constructor: THREE.GeometryLoader,
  4525. load: function ( url ) {
  4526. var scope = this;
  4527. var geometry = null;
  4528. if ( scope.path === null ) {
  4529. var parts = url.split( '/' ); parts.pop();
  4530. scope.path = ( parts.length < 1 ? '.' : parts.join( '/' ) );
  4531. }
  4532. //
  4533. var xhr = new XMLHttpRequest();
  4534. xhr.addEventListener( 'load', function ( event ) {
  4535. if ( event.target.responseText ) {
  4536. geometry = scope.parse( JSON.parse( event.target.responseText ), monitor );
  4537. } else {
  4538. scope.dispatchEvent( { type: 'error', message: 'Invalid file [' + url + ']' } );
  4539. }
  4540. }, false );
  4541. xhr.addEventListener( 'error', function () {
  4542. scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
  4543. }, false );
  4544. xhr.open( 'GET', url, true );
  4545. xhr.send( null );
  4546. //
  4547. var monitor = new THREE.LoadingMonitor();
  4548. monitor.addEventListener( 'load', function ( event ) {
  4549. scope.dispatchEvent( { type: 'load', content: geometry } );
  4550. } );
  4551. monitor.add( xhr );
  4552. },
  4553. parse: function ( data, monitor ) {
  4554. var scope = this;
  4555. var geometry = new THREE.Geometry();
  4556. var scale = ( data.scale !== undefined ) ? 1 / data.scale : 1;
  4557. // materials
  4558. if ( data.materials ) {
  4559. geometry.materials = [];
  4560. for ( var i = 0; i < data.materials.length; ++ i ) {
  4561. var m = data.materials[ i ];
  4562. function isPow2( n ) {
  4563. var l = Math.log( n ) / Math.LN2;
  4564. return Math.floor( l ) == l;
  4565. }
  4566. function nearestPow2( n ) {
  4567. var l = Math.log( n ) / Math.LN2;
  4568. return Math.pow( 2, Math.round( l ) );
  4569. }
  4570. function createTexture( where, name, sourceFile, repeat, offset, wrap ) {
  4571. where[ name ] = new THREE.Texture();
  4572. where[ name ].sourceFile = sourceFile;
  4573. if ( repeat ) {
  4574. where[ name ].repeat.set( repeat[ 0 ], repeat[ 1 ] );
  4575. if ( repeat[ 0 ] != 1 ) where[ name ].wrapS = THREE.RepeatWrapping;
  4576. if ( repeat[ 1 ] != 1 ) where[ name ].wrapT = THREE.RepeatWrapping;
  4577. }
  4578. if ( offset ) {
  4579. where[ name ].offset.set( offset[ 0 ], offset[ 1 ] );
  4580. }
  4581. if ( wrap ) {
  4582. var wrapMap = {
  4583. "repeat": THREE.RepeatWrapping,
  4584. "mirror": THREE.MirroredRepeatWrapping
  4585. }
  4586. if ( wrapMap[ wrap[ 0 ] ] !== undefined ) where[ name ].wrapS = wrapMap[ wrap[ 0 ] ];
  4587. if ( wrapMap[ wrap[ 1 ] ] !== undefined ) where[ name ].wrapT = wrapMap[ wrap[ 1 ] ];
  4588. }
  4589. // load image
  4590. var texture = where[ name ];
  4591. var loader = new THREE.ImageLoader();
  4592. loader.addEventListener( 'load', function ( event ) {
  4593. var image = event.content;
  4594. if ( !isPow2( image.width ) || !isPow2( image.height ) ) {
  4595. var width = nearestPow2( image.width );
  4596. var height = nearestPow2( image.height );
  4597. texture.image = document.createElement( 'canvas' );
  4598. texture.image.width = width;
  4599. texture.image.height = height;
  4600. texture.image.getContext( '2d' ).drawImage( image, 0, 0, width, height );
  4601. } else {
  4602. texture.image = image;
  4603. }
  4604. texture.needsUpdate = true;
  4605. } );
  4606. loader.crossOrigin = scope.crossOrigin;
  4607. loader.load( scope.path + '/' + sourceFile );
  4608. if ( monitor ) monitor.add( loader );
  4609. }
  4610. function rgb2hex( rgb ) {
  4611. return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
  4612. }
  4613. // defaults
  4614. var mtype = "MeshLambertMaterial";
  4615. var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, wireframe: m.wireframe };
  4616. // parameters from model file
  4617. if ( m.shading ) {
  4618. var shading = m.shading.toLowerCase();
  4619. if ( shading === "phong" ) mtype = "MeshPhongMaterial";
  4620. else if ( shading === "basic" ) mtype = "MeshBasicMaterial";
  4621. }
  4622. if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
  4623. mpars.blending = THREE[ m.blending ];
  4624. }
  4625. if ( m.transparent !== undefined || m.opacity < 1.0 ) {
  4626. mpars.transparent = m.transparent;
  4627. }
  4628. if ( m.depthTest !== undefined ) {
  4629. mpars.depthTest = m.depthTest;
  4630. }
  4631. if ( m.depthWrite !== undefined ) {
  4632. mpars.depthWrite = m.depthWrite;
  4633. }
  4634. if ( m.vertexColors !== undefined ) {
  4635. if ( m.vertexColors == "face" ) {
  4636. mpars.vertexColors = THREE.FaceColors;
  4637. } else if ( m.vertexColors ) {
  4638. mpars.vertexColors = THREE.VertexColors;
  4639. }
  4640. }
  4641. // colors
  4642. if ( m.colorDiffuse ) {
  4643. mpars.color = rgb2hex( m.colorDiffuse );
  4644. } else if ( m.DbgColor ) {
  4645. mpars.color = m.DbgColor;
  4646. }
  4647. if ( m.colorSpecular ) {
  4648. mpars.specular = rgb2hex( m.colorSpecular );
  4649. }
  4650. if ( m.colorAmbient ) {
  4651. mpars.ambient = rgb2hex( m.colorAmbient );
  4652. }
  4653. // modifiers
  4654. if ( m.transparency ) {
  4655. mpars.opacity = m.transparency;
  4656. }
  4657. if ( m.specularCoef ) {
  4658. mpars.shininess = m.specularCoef;
  4659. }
  4660. // textures
  4661. if ( m.mapDiffuse ) {
  4662. createTexture( mpars, "map", m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap );
  4663. }
  4664. if ( m.mapLight ) {
  4665. createTexture( mpars, "lightMap", m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap );
  4666. }
  4667. if ( m.mapNormal ) {
  4668. createTexture( mpars, "normalMap", m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap );
  4669. }
  4670. if ( m.mapSpecular ) {
  4671. createTexture( mpars, "specularMap", m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap );
  4672. }
  4673. // special case for normal mapped material
  4674. if ( m.mapNormal ) {
  4675. var shader = THREE.ShaderUtils.lib[ "normal" ];
  4676. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  4677. uniforms[ "tNormal" ].texture = mpars.normalMap;
  4678. if ( m.mapNormalFactor ) {
  4679. uniforms[ "uNormalScale" ].value = m.mapNormalFactor;
  4680. }
  4681. if ( mpars.map ) {
  4682. uniforms[ "tDiffuse" ].texture = mpars.map;
  4683. uniforms[ "enableDiffuse" ].value = true;
  4684. }
  4685. if ( mpars.specularMap ) {
  4686. uniforms[ "tSpecular" ].texture = mpars.specularMap;
  4687. uniforms[ "enableSpecular" ].value = true;
  4688. }
  4689. if ( mpars.lightMap ) {
  4690. uniforms[ "tAO" ].texture = mpars.lightMap;
  4691. uniforms[ "enableAO" ].value = true;
  4692. }
  4693. // for the moment don't handle displacement texture
  4694. uniforms[ "uDiffuseColor" ].value.setHex( mpars.color );
  4695. uniforms[ "uSpecularColor" ].value.setHex( mpars.specular );
  4696. uniforms[ "uAmbientColor" ].value.setHex( mpars.ambient );
  4697. uniforms[ "uShininess" ].value = mpars.shininess;
  4698. if ( mpars.opacity !== undefined ) {
  4699. uniforms[ "uOpacity" ].value = mpars.opacity;
  4700. }
  4701. var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
  4702. var material = new THREE.ShaderMaterial( parameters );
  4703. } else {
  4704. var material = new THREE[ mtype ]( mpars );
  4705. }
  4706. if ( m.DbgName !== undefined ) material.name = m.DbgName;
  4707. geometry.materials[ i ] = material;
  4708. }
  4709. }
  4710. // geometry
  4711. function isBitSet( value, position ) {
  4712. return value & ( 1 << position );
  4713. }
  4714. var faces = data.faces;
  4715. var vertices = data.vertices;
  4716. var normals = data.normals;
  4717. var colors = data.colors;
  4718. var nUvLayers = 0;
  4719. // disregard empty arrays
  4720. if ( data.uvs ) {
  4721. for ( var i = 0; i < data.uvs.length; i ++ ) {
  4722. if ( data.uvs[ i ].length ) nUvLayers ++;
  4723. }
  4724. }
  4725. for ( var i = 0; i < nUvLayers; i ++ ) {
  4726. geometry.faceUvs[ i ] = [];
  4727. geometry.faceVertexUvs[ i ] = [];
  4728. }
  4729. var offset = 0;
  4730. var zLength = vertices.length;
  4731. while ( offset < zLength ) {
  4732. var vertex = new THREE.Vector3();
  4733. vertex.x = vertices[ offset ++ ] * scale;
  4734. vertex.y = vertices[ offset ++ ] * scale;
  4735. vertex.z = vertices[ offset ++ ] * scale;
  4736. geometry.vertices.push( vertex );
  4737. }
  4738. offset = 0;
  4739. zLength = faces.length;
  4740. while ( offset < zLength ) {
  4741. var type = faces[ offset ++ ];
  4742. var isQuad = isBitSet( type, 0 );
  4743. var hasMaterial = isBitSet( type, 1 );
  4744. var hasFaceUv = isBitSet( type, 2 );
  4745. var hasFaceVertexUv = isBitSet( type, 3 );
  4746. var hasFaceNormal = isBitSet( type, 4 );
  4747. var hasFaceVertexNormal = isBitSet( type, 5 );
  4748. var hasFaceColor = isBitSet( type, 6 );
  4749. var hasFaceVertexColor = isBitSet( type, 7 );
  4750. // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
  4751. if ( isQuad ) {
  4752. var face = new THREE.Face4();
  4753. face.a = faces[ offset ++ ];
  4754. face.b = faces[ offset ++ ];
  4755. face.c = faces[ offset ++ ];
  4756. face.d = faces[ offset ++ ];
  4757. var nVertices = 4;
  4758. } else {
  4759. var face = new THREE.Face3();
  4760. face.a = faces[ offset ++ ];
  4761. face.b = faces[ offset ++ ];
  4762. face.c = faces[ offset ++ ];
  4763. var nVertices = 3;
  4764. }
  4765. if ( hasMaterial ) {
  4766. var materialIndex = faces[ offset ++ ];
  4767. face.materialIndex = materialIndex;
  4768. }
  4769. // to get face <=> uv index correspondence
  4770. var fi = geometry.faces.length;
  4771. if ( hasFaceUv ) {
  4772. for ( var i = 0; i < nUvLayers; i ++ ) {
  4773. var uvLayer = data.uvs[ i ];
  4774. var uvIndex = faces[ offset ++ ];
  4775. var u = uvLayer[ uvIndex * 2 ];
  4776. var v = uvLayer[ uvIndex * 2 + 1 ];
  4777. geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v );
  4778. }
  4779. }
  4780. if ( hasFaceVertexUv ) {
  4781. for ( var i = 0; i < nUvLayers; i ++ ) {
  4782. var uvLayer = data.uvs[ i ];
  4783. var uvs = [];
  4784. for ( var j = 0; j < nVertices; j ++ ) {
  4785. var uvIndex = faces[ offset ++ ];
  4786. var u = uvLayer[ uvIndex * 2 ];
  4787. var v = uvLayer[ uvIndex * 2 + 1 ];
  4788. uvs[ j ] = new THREE.UV( u, v );
  4789. }
  4790. geometry.faceVertexUvs[ i ][ fi ] = uvs;
  4791. }
  4792. }
  4793. if ( hasFaceNormal ) {
  4794. var normalIndex = faces[ offset ++ ] * 3;
  4795. var normal = new THREE.Vector3();
  4796. normal.x = normals[ normalIndex ++ ];
  4797. normal.y = normals[ normalIndex ++ ];
  4798. normal.z = normals[ normalIndex ];
  4799. face.normal = normal;
  4800. }
  4801. if ( hasFaceVertexNormal ) {
  4802. for ( i = 0; i < nVertices; i ++ ) {
  4803. var normalIndex = faces[ offset ++ ] * 3;
  4804. var normal = new THREE.Vector3();
  4805. normal.x = normals[ normalIndex ++ ];
  4806. normal.y = normals[ normalIndex ++ ];
  4807. normal.z = normals[ normalIndex ];
  4808. face.vertexNormals.push( normal );
  4809. }
  4810. }
  4811. if ( hasFaceColor ) {
  4812. var colorIndex = faces[ offset ++ ];
  4813. face.color = new THREE.Color( colors[ colorIndex ] );
  4814. }
  4815. if ( hasFaceVertexColor ) {
  4816. for ( var i = 0; i < nVertices; i ++ ) {
  4817. var colorIndex = faces[ offset ++ ];
  4818. face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
  4819. }
  4820. }
  4821. geometry.faces.push( face );
  4822. }
  4823. // skin
  4824. if ( data.skinWeights ) {
  4825. for ( var i = 0, l = data.skinWeights.length; i < l; i += 2 ) {
  4826. var x = data.skinWeights[ i ];
  4827. var y = data.skinWeights[ i + 1 ];
  4828. var z = 0;
  4829. var w = 0;
  4830. geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
  4831. }
  4832. }
  4833. if ( data.skinIndices ) {
  4834. for ( var i = 0, l = data.skinIndices.length; i < l; i += 2 ) {
  4835. var a = data.skinIndices[ i ];
  4836. var b = data.skinIndices[ i + 1 ];
  4837. var c = 0;
  4838. var d = 0;
  4839. geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
  4840. }
  4841. }
  4842. geometry.bones = data.bones;
  4843. geometry.animation = data.animation;
  4844. // morphing
  4845. if ( data.morphTargets ) {
  4846. for ( var i = 0, l = data.morphTargets.length; i < l; i ++ ) {
  4847. geometry.morphTargets[ i ] = {};
  4848. geometry.morphTargets[ i ].name = data.morphTargets[ i ].name;
  4849. geometry.morphTargets[ i ].vertices = [];
  4850. var dstVertices = geometry.morphTargets[ i ].vertices;
  4851. var srcVertices = data.morphTargets [ i ].vertices;
  4852. for( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
  4853. var vertex = new THREE.Vector3();
  4854. vertex.x = srcVertices[ v ] * scale;
  4855. vertex.y = srcVertices[ v + 1 ] * scale;
  4856. vertex.z = srcVertices[ v + 2 ] * scale;
  4857. dstVertices.push( vertex );
  4858. }
  4859. }
  4860. }
  4861. if ( data.morphColors ) {
  4862. for ( var i = 0, l = data.morphColors.length; i < l; i++ ) {
  4863. geometry.morphColors[ i ] = {};
  4864. geometry.morphColors[ i ].name = data.morphColors[ i ].name;
  4865. geometry.morphColors[ i ].colors = [];
  4866. var dstColors = geometry.morphColors[ i ].colors;
  4867. var srcColors = data.morphColors [ i ].colors;
  4868. for ( var c = 0, cl = srcColors.length; c < cl; c += 3 ) {
  4869. var color = new THREE.Color( 0xffaa00 );
  4870. color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
  4871. dstColors.push( color );
  4872. }
  4873. }
  4874. }
  4875. geometry.computeCentroids();
  4876. geometry.computeFaceNormals();
  4877. return geometry;
  4878. }
  4879. };
  4880. /**
  4881. * @author alteredq / http://alteredqualia.com/
  4882. */
  4883. THREE.SceneLoader = function () {
  4884. this.onLoadStart = function () {};
  4885. this.onLoadProgress = function() {};
  4886. this.onLoadComplete = function () {};
  4887. this.callbackSync = function () {};
  4888. this.callbackProgress = function () {};
  4889. };
  4890. THREE.SceneLoader.prototype.constructor = THREE.SceneLoader;
  4891. THREE.SceneLoader.prototype.load = function( url, callbackFinished ) {
  4892. var context = this;
  4893. var xhr = new XMLHttpRequest();
  4894. xhr.onreadystatechange = function () {
  4895. if ( xhr.readyState === 4 ) {
  4896. if ( xhr.status === 200 || xhr.status === 0 ) {
  4897. var json = JSON.parse( xhr.responseText );
  4898. context.createScene( json, callbackFinished, url );
  4899. } else {
  4900. console.error( "THREE.SceneLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  4901. }
  4902. }
  4903. };
  4904. xhr.open( "GET", url, true );
  4905. if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
  4906. xhr.setRequestHeader( "Content-Type", "text/plain" );
  4907. xhr.send( null );
  4908. };
  4909. THREE.SceneLoader.prototype.createScene = function ( json, callbackFinished, url ) {
  4910. var scope = this;
  4911. var urlBase = THREE.Loader.prototype.extractUrlBase( url );
  4912. var dg, dm, dd, dl, dc, df, dt,
  4913. g, o, m, l, d, p, r, q, s, c, t, f, tt, pp, u,
  4914. geometry, material, camera, fog,
  4915. texture, images,
  4916. light,
  4917. data, binLoader, jsonLoader,
  4918. counter_models, counter_textures,
  4919. total_models, total_textures,
  4920. result;
  4921. data = json;
  4922. binLoader = new THREE.BinaryLoader();
  4923. jsonLoader = new THREE.JSONLoader();
  4924. counter_models = 0;
  4925. counter_textures = 0;
  4926. result = {
  4927. scene: new THREE.Scene(),
  4928. geometries: {},
  4929. materials: {},
  4930. textures: {},
  4931. objects: {},
  4932. cameras: {},
  4933. lights: {},
  4934. fogs: {},
  4935. empties: {}
  4936. };
  4937. if ( data.transform ) {
  4938. var position = data.transform.position,
  4939. rotation = data.transform.rotation,
  4940. scale = data.transform.scale;
  4941. if ( position )
  4942. result.scene.position.set( position[ 0 ], position[ 1 ], position [ 2 ] );
  4943. if ( rotation )
  4944. result.scene.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation [ 2 ] );
  4945. if ( scale )
  4946. result.scene.scale.set( scale[ 0 ], scale[ 1 ], scale [ 2 ] );
  4947. if ( position || rotation || scale ) {
  4948. result.scene.updateMatrix();
  4949. result.scene.updateMatrixWorld();
  4950. }
  4951. }
  4952. function get_url( source_url, url_type ) {
  4953. if ( url_type == "relativeToHTML" ) {
  4954. return source_url;
  4955. } else {
  4956. return urlBase + "/" + source_url;
  4957. }
  4958. };
  4959. function handle_objects() {
  4960. var object;
  4961. for( dd in data.objects ) {
  4962. if ( !result.objects[ dd ] ) {
  4963. o = data.objects[ dd ];
  4964. if ( o.geometry !== undefined ) {
  4965. geometry = result.geometries[ o.geometry ];
  4966. // geometry already loaded
  4967. if ( geometry ) {
  4968. var hasNormals = false;
  4969. // not anymore support for multiple materials
  4970. // shouldn't really be array
  4971. material = result.materials[ o.materials[ 0 ] ];
  4972. hasNormals = material instanceof THREE.ShaderMaterial;
  4973. if ( hasNormals ) {
  4974. geometry.computeTangents();
  4975. }
  4976. p = o.position;
  4977. r = o.rotation;
  4978. q = o.quaternion;
  4979. s = o.scale;
  4980. m = o.matrix;
  4981. // turn off quaternions, for the moment
  4982. q = 0;
  4983. if ( o.materials.length == 0 ) {
  4984. material = new THREE.MeshFaceMaterial();
  4985. }
  4986. // dirty hack to handle meshes with multiple materials
  4987. // just use face materials defined in model
  4988. if ( o.materials.length > 1 ) {
  4989. material = new THREE.MeshFaceMaterial();
  4990. }
  4991. object = new THREE.Mesh( geometry, material );
  4992. object.name = dd;
  4993. if ( m ) {
  4994. object.matrixAutoUpdate = false;
  4995. object.matrix.set( m[0], m[1], m[2], m[3],
  4996. m[4], m[5], m[6], m[7],
  4997. m[8], m[9], m[10], m[11],
  4998. m[12], m[13], m[14], m[15]);
  4999. } else {
  5000. object.position.set( p[0], p[1], p[2] );
  5001. if ( q ) {
  5002. object.quaternion.set( q[0], q[1], q[2], q[3] );
  5003. object.useQuaternion = true;
  5004. } else {
  5005. object.rotation.set( r[0], r[1], r[2] );
  5006. }
  5007. object.scale.set( s[0], s[1], s[2] );
  5008. }
  5009. object.visible = o.visible;
  5010. object.doubleSided = o.doubleSided;
  5011. object.castShadow = o.castShadow;
  5012. object.receiveShadow = o.receiveShadow;
  5013. result.scene.add( object );
  5014. result.objects[ dd ] = object;
  5015. }
  5016. // pure Object3D
  5017. } else {
  5018. p = o.position;
  5019. r = o.rotation;
  5020. q = o.quaternion;
  5021. s = o.scale;
  5022. // turn off quaternions, for the moment
  5023. q = 0;
  5024. object = new THREE.Object3D();
  5025. object.name = dd;
  5026. object.position.set( p[0], p[1], p[2] );
  5027. if ( q ) {
  5028. object.quaternion.set( q[0], q[1], q[2], q[3] );
  5029. object.useQuaternion = true;
  5030. } else {
  5031. object.rotation.set( r[0], r[1], r[2] );
  5032. }
  5033. object.scale.set( s[0], s[1], s[2] );
  5034. object.visible = ( o.visible !== undefined ) ? o.visible : false;
  5035. result.scene.add( object );
  5036. result.objects[ dd ] = object;
  5037. result.empties[ dd ] = object;
  5038. }
  5039. }
  5040. }
  5041. };
  5042. function handle_mesh( geo, id ) {
  5043. result.geometries[ id ] = geo;
  5044. handle_objects();
  5045. };
  5046. function create_callback( id ) {
  5047. return function( geo ) {
  5048. handle_mesh( geo, id );
  5049. counter_models -= 1;
  5050. scope.onLoadComplete();
  5051. async_callback_gate();
  5052. }
  5053. };
  5054. function create_callback_embed( id ) {
  5055. return function( geo ) {
  5056. result.geometries[ id ] = geo;
  5057. }
  5058. };
  5059. function async_callback_gate() {
  5060. var progress = {
  5061. totalModels : total_models,
  5062. totalTextures : total_textures,
  5063. loadedModels : total_models - counter_models,
  5064. loadedTextures : total_textures - counter_textures
  5065. };
  5066. scope.callbackProgress( progress, result );
  5067. scope.onLoadProgress();
  5068. if( counter_models === 0 && counter_textures === 0 ) {
  5069. callbackFinished( result );
  5070. }
  5071. };
  5072. var callbackTexture = function ( count ) {
  5073. counter_textures -= count;
  5074. async_callback_gate();
  5075. scope.onLoadComplete();
  5076. };
  5077. // must use this instead of just directly calling callbackTexture
  5078. // because of closure in the calling context loop
  5079. var generateTextureCallback = function ( count ) {
  5080. return function() {
  5081. callbackTexture( count );
  5082. };
  5083. };
  5084. // first go synchronous elements
  5085. // cameras
  5086. for( dc in data.cameras ) {
  5087. c = data.cameras[ dc ];
  5088. if ( c.type === "perspective" ) {
  5089. camera = new THREE.PerspectiveCamera( c.fov, c.aspect, c.near, c.far );
  5090. } else if ( c.type === "ortho" ) {
  5091. camera = new THREE.OrthographicCamera( c.left, c.right, c.top, c.bottom, c.near, c.far );
  5092. }
  5093. p = c.position;
  5094. t = c.target;
  5095. u = c.up;
  5096. camera.position.set( p[0], p[1], p[2] );
  5097. camera.target = new THREE.Vector3( t[0], t[1], t[2] );
  5098. if ( u ) camera.up.set( u[0], u[1], u[2] );
  5099. result.cameras[ dc ] = camera;
  5100. }
  5101. // lights
  5102. var hex, intensity;
  5103. for ( dl in data.lights ) {
  5104. l = data.lights[ dl ];
  5105. hex = ( l.color !== undefined ) ? l.color : 0xffffff;
  5106. intensity = ( l.intensity !== undefined ) ? l.intensity : 1;
  5107. if ( l.type === "directional" ) {
  5108. p = l.direction;
  5109. light = new THREE.DirectionalLight( hex, intensity );
  5110. light.position.set( p[0], p[1], p[2] );
  5111. light.position.normalize();
  5112. } else if ( l.type === "point" ) {
  5113. p = l.position;
  5114. d = l.distance;
  5115. light = new THREE.PointLight( hex, intensity, d );
  5116. light.position.set( p[0], p[1], p[2] );
  5117. } else if ( l.type === "ambient" ) {
  5118. light = new THREE.AmbientLight( hex );
  5119. }
  5120. result.scene.add( light );
  5121. result.lights[ dl ] = light;
  5122. }
  5123. // fogs
  5124. for( df in data.fogs ) {
  5125. f = data.fogs[ df ];
  5126. if ( f.type === "linear" ) {
  5127. fog = new THREE.Fog( 0x000000, f.near, f.far );
  5128. } else if ( f.type === "exp2" ) {
  5129. fog = new THREE.FogExp2( 0x000000, f.density );
  5130. }
  5131. c = f.color;
  5132. fog.color.setRGB( c[0], c[1], c[2] );
  5133. result.fogs[ df ] = fog;
  5134. }
  5135. // defaults
  5136. if ( result.cameras && data.defaults.camera ) {
  5137. result.currentCamera = result.cameras[ data.defaults.camera ];
  5138. }
  5139. if ( result.fogs && data.defaults.fog ) {
  5140. result.scene.fog = result.fogs[ data.defaults.fog ];
  5141. }
  5142. c = data.defaults.bgcolor;
  5143. result.bgColor = new THREE.Color();
  5144. result.bgColor.setRGB( c[0], c[1], c[2] );
  5145. result.bgColorAlpha = data.defaults.bgalpha;
  5146. // now come potentially asynchronous elements
  5147. // geometries
  5148. // count how many models will be loaded asynchronously
  5149. for( dg in data.geometries ) {
  5150. g = data.geometries[ dg ];
  5151. if ( g.type == "bin_mesh" || g.type == "ascii_mesh" ) {
  5152. counter_models += 1;
  5153. scope.onLoadStart();
  5154. }
  5155. }
  5156. total_models = counter_models;
  5157. for ( dg in data.geometries ) {
  5158. g = data.geometries[ dg ];
  5159. if ( g.type === "cube" ) {
  5160. geometry = new THREE.CubeGeometry( g.width, g.height, g.depth, g.segmentsWidth, g.segmentsHeight, g.segmentsDepth, null, g.flipped, g.sides );
  5161. result.geometries[ dg ] = geometry;
  5162. } else if ( g.type === "plane" ) {
  5163. geometry = new THREE.PlaneGeometry( g.width, g.height, g.segmentsWidth, g.segmentsHeight );
  5164. result.geometries[ dg ] = geometry;
  5165. } else if ( g.type === "sphere" ) {
  5166. geometry = new THREE.SphereGeometry( g.radius, g.segmentsWidth, g.segmentsHeight );
  5167. result.geometries[ dg ] = geometry;
  5168. } else if ( g.type === "cylinder" ) {
  5169. geometry = new THREE.CylinderGeometry( g.topRad, g.botRad, g.height, g.radSegs, g.heightSegs );
  5170. result.geometries[ dg ] = geometry;
  5171. } else if ( g.type === "torus" ) {
  5172. geometry = new THREE.TorusGeometry( g.radius, g.tube, g.segmentsR, g.segmentsT );
  5173. result.geometries[ dg ] = geometry;
  5174. } else if ( g.type === "icosahedron" ) {
  5175. geometry = new THREE.IcosahedronGeometry( g.radius, g.subdivisions );
  5176. result.geometries[ dg ] = geometry;
  5177. } else if ( g.type === "bin_mesh" ) {
  5178. binLoader.load( get_url( g.url, data.urlBaseType ), create_callback( dg ) );
  5179. } else if ( g.type === "ascii_mesh" ) {
  5180. jsonLoader.load( get_url( g.url, data.urlBaseType ), create_callback( dg ) );
  5181. } else if ( g.type === "embedded_mesh" ) {
  5182. var modelJson = data.embeds[ g.id ],
  5183. texture_path = "";
  5184. // pass metadata along to jsonLoader so it knows the format version
  5185. modelJson.metadata = data.metadata;
  5186. if ( modelJson ) {
  5187. jsonLoader.createModel( modelJson, create_callback_embed( dg ), texture_path );
  5188. }
  5189. }
  5190. }
  5191. // textures
  5192. // count how many textures will be loaded asynchronously
  5193. for( dt in data.textures ) {
  5194. tt = data.textures[ dt ];
  5195. if( tt.url instanceof Array ) {
  5196. counter_textures += tt.url.length;
  5197. for( var n = 0; n < tt.url.length; n ++ ) {
  5198. scope.onLoadStart();
  5199. }
  5200. } else {
  5201. counter_textures += 1;
  5202. scope.onLoadStart();
  5203. }
  5204. }
  5205. total_textures = counter_textures;
  5206. for( dt in data.textures ) {
  5207. tt = data.textures[ dt ];
  5208. if ( tt.mapping !== undefined && THREE[ tt.mapping ] !== undefined ) {
  5209. tt.mapping = new THREE[ tt.mapping ]();
  5210. }
  5211. if( tt.url instanceof Array ) {
  5212. var count = tt.url.length;
  5213. var url_array = [];
  5214. for( var i = 0; i < count; i ++ ) {
  5215. url_array[ i ] = get_url( tt.url[ i ], data.urlBaseType );
  5216. }
  5217. texture = THREE.ImageUtils.loadTextureCube( url_array, tt.mapping, generateTextureCallback( count ) );
  5218. } else {
  5219. texture = THREE.ImageUtils.loadTexture( get_url( tt.url, data.urlBaseType ), tt.mapping, generateTextureCallback( 1 ) );
  5220. if ( THREE[ tt.minFilter ] !== undefined )
  5221. texture.minFilter = THREE[ tt.minFilter ];
  5222. if ( THREE[ tt.magFilter ] !== undefined )
  5223. texture.magFilter = THREE[ tt.magFilter ];
  5224. if ( tt.repeat ) {
  5225. texture.repeat.set( tt.repeat[ 0 ], tt.repeat[ 1 ] );
  5226. if ( tt.repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
  5227. if ( tt.repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
  5228. }
  5229. if ( tt.offset ) {
  5230. texture.offset.set( tt.offset[ 0 ], tt.offset[ 1 ] );
  5231. }
  5232. // handle wrap after repeat so that default repeat can be overriden
  5233. if ( tt.wrap ) {
  5234. var wrapMap = {
  5235. "repeat" : THREE.RepeatWrapping,
  5236. "mirror" : THREE.MirroredRepeatWrapping
  5237. }
  5238. if ( wrapMap[ tt.wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ tt.wrap[ 0 ] ];
  5239. if ( wrapMap[ tt.wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ tt.wrap[ 1 ] ];
  5240. }
  5241. }
  5242. result.textures[ dt ] = texture;
  5243. }
  5244. // materials
  5245. for ( dm in data.materials ) {
  5246. m = data.materials[ dm ];
  5247. for ( pp in m.parameters ) {
  5248. if ( pp === "envMap" || pp === "map" || pp === "lightMap" ) {
  5249. m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ];
  5250. } else if ( pp === "shading" ) {
  5251. m.parameters[ pp ] = ( m.parameters[ pp ] == "flat" ) ? THREE.FlatShading : THREE.SmoothShading;
  5252. } else if ( pp === "blending" ) {
  5253. m.parameters[ pp ] = m.parameters[ pp ] in THREE ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending;
  5254. } else if ( pp === "combine" ) {
  5255. m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation;
  5256. } else if ( pp === "vertexColors" ) {
  5257. if ( m.parameters[ pp ] == "face" ) {
  5258. m.parameters[ pp ] = THREE.FaceColors;
  5259. // default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false
  5260. } else if ( m.parameters[ pp ] ) {
  5261. m.parameters[ pp ] = THREE.VertexColors;
  5262. }
  5263. }
  5264. }
  5265. if ( m.parameters.opacity !== undefined && m.parameters.opacity < 1.0 ) {
  5266. m.parameters.transparent = true;
  5267. }
  5268. if ( m.parameters.normalMap ) {
  5269. var shader = THREE.ShaderUtils.lib[ "normal" ];
  5270. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  5271. var diffuse = m.parameters.color;
  5272. var specular = m.parameters.specular;
  5273. var ambient = m.parameters.ambient;
  5274. var shininess = m.parameters.shininess;
  5275. uniforms[ "tNormal" ].texture = result.textures[ m.parameters.normalMap ];
  5276. if ( m.parameters.normalMapFactor ) {
  5277. uniforms[ "uNormalScale" ].value = m.parameters.normalMapFactor;
  5278. }
  5279. if ( m.parameters.map ) {
  5280. uniforms[ "tDiffuse" ].texture = m.parameters.map;
  5281. uniforms[ "enableDiffuse" ].value = true;
  5282. }
  5283. if ( m.parameters.lightMap ) {
  5284. uniforms[ "tAO" ].texture = m.parameters.lightMap;
  5285. uniforms[ "enableAO" ].value = true;
  5286. }
  5287. if ( m.parameters.specularMap ) {
  5288. uniforms[ "tSpecular" ].texture = result.textures[ m.parameters.specularMap ];
  5289. uniforms[ "enableSpecular" ].value = true;
  5290. }
  5291. uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
  5292. uniforms[ "uSpecularColor" ].value.setHex( specular );
  5293. uniforms[ "uAmbientColor" ].value.setHex( ambient );
  5294. uniforms[ "uShininess" ].value = shininess;
  5295. if ( m.parameters.opacity ) {
  5296. uniforms[ "uOpacity" ].value = m.parameters.opacity;
  5297. }
  5298. var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
  5299. material = new THREE.ShaderMaterial( parameters );
  5300. } else {
  5301. material = new THREE[ m.type ]( m.parameters );
  5302. }
  5303. result.materials[ dm ] = material;
  5304. }
  5305. // objects ( synchronous init of procedural primitives )
  5306. handle_objects();
  5307. // synchronous callback
  5308. scope.callbackSync( result );
  5309. // just in case there are no async elements
  5310. async_callback_gate();
  5311. };
  5312. /**
  5313. * @author mrdoob / http://mrdoob.com/
  5314. */
  5315. THREE.TextureLoader = function () {
  5316. THREE.EventTarget.call( this );
  5317. this.crossOrigin = null;
  5318. };
  5319. THREE.TextureLoader.prototype = {
  5320. constructor: THREE.TextureLoader,
  5321. load: function ( url ) {
  5322. var scope = this;
  5323. var image = new Image();
  5324. image.addEventListener( 'load', function () {
  5325. var texture = new THREE.Texture( image );
  5326. texture.needsUpdate = true;
  5327. scope.dispatchEvent( { type: 'load', content: texture } );
  5328. }, false );
  5329. image.addEventListener( 'error', function () {
  5330. scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
  5331. }, false );
  5332. if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
  5333. image.src = url;
  5334. }
  5335. }
  5336. /**
  5337. * @author mr.doob / http://mrdoob.com/
  5338. * @author alteredq / http://alteredqualia.com/
  5339. */
  5340. THREE.Material = function ( parameters ) {
  5341. parameters = parameters || {};
  5342. this.id = THREE.MaterialCount ++;
  5343. this.name = '';
  5344. this.opacity = parameters.opacity !== undefined ? parameters.opacity : 1;
  5345. this.transparent = parameters.transparent !== undefined ? parameters.transparent : false;
  5346. this.blending = parameters.blending !== undefined ? parameters.blending : THREE.NormalBlending;
  5347. this.blendSrc = parameters.blendSrc !== undefined ? parameters.blendSrc : THREE.SrcAlphaFactor;
  5348. this.blendDst = parameters.blendDst !== undefined ? parameters.blendDst : THREE.OneMinusSrcAlphaFactor;
  5349. this.blendEquation = parameters.blendEquation !== undefined ? parameters.blendEquation : THREE.AddEquation;
  5350. this.depthTest = parameters.depthTest !== undefined ? parameters.depthTest : true;
  5351. this.depthWrite = parameters.depthWrite !== undefined ? parameters.depthWrite : true;
  5352. this.polygonOffset = parameters.polygonOffset !== undefined ? parameters.polygonOffset : false;
  5353. this.polygonOffsetFactor = parameters.polygonOffsetFactor !== undefined ? parameters.polygonOffsetFactor : 0;
  5354. this.polygonOffsetUnits = parameters.polygonOffsetUnits !== undefined ? parameters.polygonOffsetUnits : 0;
  5355. this.alphaTest = parameters.alphaTest !== undefined ? parameters.alphaTest : 0;
  5356. this.overdraw = parameters.overdraw !== undefined ? parameters.overdraw : false; // Boolean for fixing antialiasing gaps in CanvasRenderer
  5357. this.visible = true;
  5358. this.needsUpdate = true;
  5359. }
  5360. THREE.MaterialCount = 0;
  5361. /**
  5362. * @author mr.doob / http://mrdoob.com/
  5363. * @author alteredq / http://alteredqualia.com/
  5364. *
  5365. * parameters = {
  5366. * color: <hex>,
  5367. * opacity: <float>,
  5368. *
  5369. * blending: THREE.NormalBlending,
  5370. * depthTest: <bool>,
  5371. *
  5372. * linewidth: <float>,
  5373. * linecap: "round",
  5374. * linejoin: "round",
  5375. *
  5376. * vertexColors: <bool>
  5377. *
  5378. * fog: <bool>
  5379. * }
  5380. */
  5381. THREE.LineBasicMaterial = function ( parameters ) {
  5382. THREE.Material.call( this, parameters );
  5383. parameters = parameters || {};
  5384. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5385. this.linewidth = parameters.linewidth !== undefined ? parameters.linewidth : 1;
  5386. this.linecap = parameters.linecap !== undefined ? parameters.linecap : 'round';
  5387. this.linejoin = parameters.linejoin !== undefined ? parameters.linejoin : 'round';
  5388. this.vertexColors = parameters.vertexColors ? parameters.vertexColors : false;
  5389. this.fog = parameters.fog !== undefined ? parameters.fog : true;
  5390. };
  5391. THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype );
  5392. /**
  5393. * @author mr.doob / http://mrdoob.com/
  5394. * @author alteredq / http://alteredqualia.com/
  5395. *
  5396. * parameters = {
  5397. * color: <hex>,
  5398. * opacity: <float>,
  5399. * map: new THREE.Texture( <Image> ),
  5400. *
  5401. * lightMap: new THREE.Texture( <Image> ),
  5402. *
  5403. * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  5404. * combine: THREE.Multiply,
  5405. * reflectivity: <float>,
  5406. * refractionRatio: <float>,
  5407. *
  5408. * shading: THREE.SmoothShading,
  5409. * blending: THREE.NormalBlending,
  5410. * depthTest: <bool>,
  5411. *
  5412. * wireframe: <boolean>,
  5413. * wireframeLinewidth: <float>,
  5414. *
  5415. * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
  5416. *
  5417. * skinning: <bool>,
  5418. * morphTargets: <bool>,
  5419. *
  5420. * fog: <bool>
  5421. * }
  5422. */
  5423. THREE.MeshBasicMaterial = function ( parameters ) {
  5424. THREE.Material.call( this, parameters );
  5425. parameters = parameters || {};
  5426. // color property represents emissive for MeshBasicMaterial
  5427. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5428. this.map = parameters.map !== undefined ? parameters.map : null;
  5429. this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null;
  5430. this.envMap = parameters.envMap !== undefined ? parameters.envMap : null;
  5431. this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation;
  5432. this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1;
  5433. this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98;
  5434. this.fog = parameters.fog !== undefined ? parameters.fog : true;
  5435. this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading;
  5436. this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false;
  5437. this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1;
  5438. this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round';
  5439. this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round';
  5440. this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : THREE.NoColors;
  5441. this.skinning = parameters.skinning !== undefined ? parameters.skinning : false;
  5442. this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false;
  5443. };
  5444. THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype );
  5445. /**
  5446. * @author mr.doob / http://mrdoob.com/
  5447. * @author alteredq / http://alteredqualia.com/
  5448. *
  5449. * parameters = {
  5450. * color: <hex>,
  5451. * ambient: <hex>,
  5452. * emissive: <hex>,
  5453. * opacity: <float>,
  5454. *
  5455. * map: new THREE.Texture( <Image> ),
  5456. *
  5457. * lightMap: new THREE.Texture( <Image> ),
  5458. *
  5459. * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  5460. * combine: THREE.Multiply,
  5461. * reflectivity: <float>,
  5462. * refractionRatio: <float>,
  5463. *
  5464. * shading: THREE.SmoothShading,
  5465. * blending: THREE.NormalBlending,
  5466. * depthTest: <bool>,
  5467. *
  5468. * wireframe: <boolean>,
  5469. * wireframeLinewidth: <float>,
  5470. *
  5471. * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
  5472. *
  5473. * skinning: <bool>,
  5474. * morphTargets: <bool>,
  5475. * morphNormals: <bool>,
  5476. *
  5477. * fog: <bool>
  5478. * }
  5479. */
  5480. THREE.MeshLambertMaterial = function ( parameters ) {
  5481. THREE.Material.call( this, parameters );
  5482. parameters = parameters || {};
  5483. // color property represents diffuse for MeshLambertMaterial
  5484. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5485. this.ambient = parameters.ambient !== undefined ? new THREE.Color( parameters.ambient ) : new THREE.Color( 0xffffff );
  5486. this.emissive = parameters.emissive !== undefined ? new THREE.Color( parameters.emissive ) : new THREE.Color( 0x000000 );
  5487. this.wrapAround = parameters.wrapAround !== undefined ? parameters.wrapAround: false;
  5488. this.wrapRGB = new THREE.Vector3( 1, 1, 1 );
  5489. this.map = parameters.map !== undefined ? parameters.map : null;
  5490. this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null;
  5491. this.envMap = parameters.envMap !== undefined ? parameters.envMap : null;
  5492. this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation;
  5493. this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1;
  5494. this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98;
  5495. this.fog = parameters.fog !== undefined ? parameters.fog : true;
  5496. this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading;
  5497. this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false;
  5498. this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1;
  5499. this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round';
  5500. this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round';
  5501. this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : THREE.NoColors;
  5502. this.skinning = parameters.skinning !== undefined ? parameters.skinning : false;
  5503. this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false;
  5504. this.morphNormals = parameters.morphNormals !== undefined ? parameters.morphNormals : false;
  5505. };
  5506. THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype );
  5507. /**
  5508. * @author mr.doob / http://mrdoob.com/
  5509. * @author alteredq / http://alteredqualia.com/
  5510. *
  5511. * parameters = {
  5512. * color: <hex>,
  5513. * ambient: <hex>,
  5514. * emissive: <hex>,
  5515. * specular: <hex>,
  5516. * shininess: <float>,
  5517. * opacity: <float>,
  5518. *
  5519. * map: new THREE.Texture( <Image> ),
  5520. *
  5521. * lightMap: new THREE.Texture( <Image> ),
  5522. *
  5523. * envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  5524. * combine: THREE.Multiply,
  5525. * reflectivity: <float>,
  5526. * refractionRatio: <float>,
  5527. *
  5528. * shading: THREE.SmoothShading,
  5529. * blending: THREE.NormalBlending,
  5530. * depthTest: <bool>,
  5531. *
  5532. * wireframe: <boolean>,
  5533. * wireframeLinewidth: <float>,
  5534. *
  5535. * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
  5536. *
  5537. * skinning: <bool>,
  5538. * morphTargets: <bool>,
  5539. * morphNormals: <bool>,
  5540. *
  5541. * fog: <bool>
  5542. * }
  5543. */
  5544. THREE.MeshPhongMaterial = function ( parameters ) {
  5545. THREE.Material.call( this, parameters );
  5546. parameters = parameters || {};
  5547. // color property represents diffuse for MeshPhongMaterial
  5548. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5549. this.ambient = parameters.ambient !== undefined ? new THREE.Color( parameters.ambient ) : new THREE.Color( 0xffffff );
  5550. this.emissive = parameters.emissive !== undefined ? new THREE.Color( parameters.emissive ) : new THREE.Color( 0x000000 );
  5551. this.specular = parameters.specular !== undefined ? new THREE.Color( parameters.specular ) : new THREE.Color( 0x111111 );
  5552. this.shininess = parameters.shininess !== undefined ? parameters.shininess : 30;
  5553. this.metal = parameters.metal !== undefined ? parameters.metal : false;
  5554. this.perPixel = parameters.perPixel !== undefined ? parameters.perPixel : false;
  5555. this.wrapAround = parameters.wrapAround !== undefined ? parameters.wrapAround: false;
  5556. this.wrapRGB = new THREE.Vector3( 1, 1, 1 );
  5557. this.map = parameters.map !== undefined ? parameters.map : null;
  5558. this.lightMap = parameters.lightMap !== undefined ? parameters.lightMap : null;
  5559. this.envMap = parameters.envMap !== undefined ? parameters.envMap : null;
  5560. this.combine = parameters.combine !== undefined ? parameters.combine : THREE.MultiplyOperation;
  5561. this.reflectivity = parameters.reflectivity !== undefined ? parameters.reflectivity : 1;
  5562. this.refractionRatio = parameters.refractionRatio !== undefined ? parameters.refractionRatio : 0.98;
  5563. this.fog = parameters.fog !== undefined ? parameters.fog : true;
  5564. this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading;
  5565. this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false;
  5566. this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1;
  5567. this.wireframeLinecap = parameters.wireframeLinecap !== undefined ? parameters.wireframeLinecap : 'round';
  5568. this.wireframeLinejoin = parameters.wireframeLinejoin !== undefined ? parameters.wireframeLinejoin : 'round';
  5569. this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : THREE.NoColors;
  5570. this.skinning = parameters.skinning !== undefined ? parameters.skinning : false;
  5571. this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false;
  5572. this.morphNormals = parameters.morphNormals !== undefined ? parameters.morphNormals : false;
  5573. };
  5574. THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype );
  5575. /**
  5576. * @author mr.doob / http://mrdoob.com/
  5577. * @author alteredq / http://alteredqualia.com/
  5578. *
  5579. * parameters = {
  5580. * opacity: <float>,
  5581. * blending: THREE.NormalBlending,
  5582. * depthTest: <bool>,
  5583. * wireframe: <boolean>,
  5584. * wireframeLinewidth: <float>
  5585. * }
  5586. */
  5587. THREE.MeshDepthMaterial = function ( parameters ) {
  5588. THREE.Material.call( this, parameters );
  5589. parameters = parameters || {};
  5590. this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading; // doesn't really apply here, normals are not used
  5591. this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false;
  5592. this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1;
  5593. };
  5594. THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype );
  5595. /**
  5596. * @author mr.doob / http://mrdoob.com/
  5597. *
  5598. * parameters = {
  5599. * opacity: <float>,
  5600. * shading: THREE.FlatShading,
  5601. * blending: THREE.NormalBlending,
  5602. * depthTest: <bool>,
  5603. * wireframe: <boolean>,
  5604. * wireframeLinewidth: <float>
  5605. * }
  5606. */
  5607. THREE.MeshNormalMaterial = function ( parameters ) {
  5608. THREE.Material.call( this, parameters );
  5609. parameters = parameters || {};
  5610. this.shading = parameters.shading ? parameters.shading : THREE.FlatShading;
  5611. this.wireframe = parameters.wireframe ? parameters.wireframe : false;
  5612. this.wireframeLinewidth = parameters.wireframeLinewidth ? parameters.wireframeLinewidth : 1;
  5613. };
  5614. THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype );
  5615. /**
  5616. * @author mr.doob / http://mrdoob.com/
  5617. */
  5618. THREE.MeshFaceMaterial = function () {};
  5619. /**
  5620. * @author mr.doob / http://mrdoob.com/
  5621. * @author alteredq / http://alteredqualia.com/
  5622. *
  5623. * parameters = {
  5624. * color: <hex>,
  5625. * opacity: <float>,
  5626. * map: new THREE.Texture( <Image> ),
  5627. *
  5628. * size: <float>,
  5629. *
  5630. * blending: THREE.NormalBlending,
  5631. * depthTest: <bool>,
  5632. *
  5633. * vertexColors: <bool>,
  5634. *
  5635. * fog: <bool>
  5636. * }
  5637. */
  5638. THREE.ParticleBasicMaterial = function ( parameters ) {
  5639. THREE.Material.call( this, parameters );
  5640. parameters = parameters || {};
  5641. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5642. this.map = parameters.map !== undefined ? parameters.map : null;
  5643. this.size = parameters.size !== undefined ? parameters.size : 1;
  5644. this.sizeAttenuation = parameters.sizeAttenuation !== undefined ? parameters.sizeAttenuation : true;
  5645. this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : false;
  5646. this.fog = parameters.fog !== undefined ? parameters.fog : true;
  5647. };
  5648. THREE.ParticleBasicMaterial.prototype = Object.create( THREE.Material.prototype );
  5649. /**
  5650. * @author mr.doob / http://mrdoob.com/
  5651. *
  5652. * parameters = {
  5653. * color: <hex>,
  5654. * program: <function>,
  5655. * opacity: <float>,
  5656. * blending: THREE.NormalBlending
  5657. * }
  5658. */
  5659. THREE.ParticleCanvasMaterial = function ( parameters ) {
  5660. THREE.Material.call( this, parameters );
  5661. parameters = parameters || {};
  5662. this.color = parameters.color !== undefined ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  5663. this.program = parameters.program !== undefined ? parameters.program : function ( context, color ) {};
  5664. };
  5665. THREE.ParticleCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
  5666. /**
  5667. * @author mr.doob / http://mrdoob.com/
  5668. */
  5669. THREE.ParticleDOMMaterial = function ( domElement ) {
  5670. THREE.Material.call( this );
  5671. this.domElement = domElement;
  5672. };
  5673. /**
  5674. * @author alteredq / http://alteredqualia.com/
  5675. *
  5676. * parameters = {
  5677. * fragmentShader: <string>,
  5678. * vertexShader: <string>,
  5679. *
  5680. * uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } },
  5681. *
  5682. * shading: THREE.SmoothShading,
  5683. * blending: THREE.NormalBlending,
  5684. * depthTest: <bool>,
  5685. *
  5686. * wireframe: <boolean>,
  5687. * wireframeLinewidth: <float>,
  5688. *
  5689. * lights: <bool>,
  5690. *
  5691. * vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
  5692. *
  5693. * skinning: <bool>,
  5694. * morphTargets: <bool>,
  5695. * morphNormals: <bool>,
  5696. *
  5697. * fog: <bool>
  5698. * }
  5699. */
  5700. THREE.ShaderMaterial = function ( parameters ) {
  5701. THREE.Material.call( this, parameters );
  5702. parameters = parameters || {};
  5703. this.fragmentShader = parameters.fragmentShader !== undefined ? parameters.fragmentShader : "void main() {}";
  5704. this.vertexShader = parameters.vertexShader !== undefined ? parameters.vertexShader : "void main() {}";
  5705. this.uniforms = parameters.uniforms !== undefined ? parameters.uniforms : {};
  5706. this.attributes = parameters.attributes;
  5707. this.shading = parameters.shading !== undefined ? parameters.shading : THREE.SmoothShading;
  5708. this.wireframe = parameters.wireframe !== undefined ? parameters.wireframe : false;
  5709. this.wireframeLinewidth = parameters.wireframeLinewidth !== undefined ? parameters.wireframeLinewidth : 1;
  5710. this.fog = parameters.fog !== undefined ? parameters.fog : false; // set to use scene fog
  5711. this.lights = parameters.lights !== undefined ? parameters.lights : false; // set to use scene lights
  5712. this.vertexColors = parameters.vertexColors !== undefined ? parameters.vertexColors : THREE.NoColors; // set to use "color" attribute stream
  5713. this.skinning = parameters.skinning !== undefined ? parameters.skinning : false; // set to use skinning attribute streams
  5714. this.morphTargets = parameters.morphTargets !== undefined ? parameters.morphTargets : false; // set to use morph targets
  5715. this.morphNormals = parameters.morphNormals !== undefined ? parameters.morphNormals : false; // set to use morph normals
  5716. };
  5717. THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype );
  5718. /**
  5719. * @author mr.doob / http://mrdoob.com/
  5720. * @author alteredq / http://alteredqualia.com/
  5721. * @author szimek / https://github.com/szimek/
  5722. */
  5723. THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
  5724. this.id = THREE.TextureCount ++;
  5725. this.image = image;
  5726. this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping();
  5727. this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
  5728. this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
  5729. this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
  5730. this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
  5731. this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
  5732. this.format = format !== undefined ? format : THREE.RGBAFormat;
  5733. this.type = type !== undefined ? type : THREE.UnsignedByteType;
  5734. this.offset = new THREE.Vector2( 0, 0 );
  5735. this.repeat = new THREE.Vector2( 1, 1 );
  5736. this.generateMipmaps = true;
  5737. this.premultiplyAlpha = false;
  5738. this.flipY = true;
  5739. this.needsUpdate = false;
  5740. this.onUpdate = null;
  5741. };
  5742. THREE.Texture.prototype = {
  5743. constructor: THREE.Texture,
  5744. clone: function () {
  5745. var clonedTexture = new THREE.Texture( this.image, this.mapping, this.wrapS, this.wrapT, this.magFilter, this.minFilter, this.format, this.type );
  5746. clonedTexture.offset.copy( this.offset );
  5747. clonedTexture.repeat.copy( this.repeat );
  5748. return clonedTexture;
  5749. }
  5750. };
  5751. THREE.TextureCount = 0;
  5752. /**
  5753. * @author alteredq / http://alteredqualia.com/
  5754. */
  5755. THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter ) {
  5756. THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type );
  5757. this.image = { data: data, width: width, height: height };
  5758. };
  5759. THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype );
  5760. THREE.DataTexture.prototype.clone = function () {
  5761. var clonedTexture = new THREE.DataTexture( this.image.data, this.image.width, this.image.height, this.format, this.type, this.mapping, this.wrapS, this.wrapT, this.magFilter, this.minFilter );
  5762. clonedTexture.offset.copy( this.offset );
  5763. clonedTexture.repeat.copy( this.repeat );
  5764. return clonedTexture;
  5765. };
  5766. /**
  5767. * @author mr.doob / http://mrdoob.com/
  5768. */
  5769. THREE.Particle = function ( material ) {
  5770. THREE.Object3D.call( this );
  5771. this.material = material;
  5772. };
  5773. THREE.Particle.prototype = Object.create( THREE.Object3D.prototype );
  5774. /**
  5775. * @author alteredq / http://alteredqualia.com/
  5776. */
  5777. THREE.ParticleSystem = function ( geometry, material ) {
  5778. THREE.Object3D.call( this );
  5779. this.geometry = geometry;
  5780. this.material = ( material !== undefined ) ? material : new THREE.ParticleBasicMaterial( { color: Math.random() * 0xffffff } );
  5781. this.sortParticles = false;
  5782. if ( this.geometry ) {
  5783. // calc bound radius
  5784. if( !this.geometry.boundingSphere ) {
  5785. this.geometry.computeBoundingSphere();
  5786. }
  5787. this.boundRadius = geometry.boundingSphere.radius;
  5788. }
  5789. this.frustumCulled = false;
  5790. };
  5791. THREE.ParticleSystem.prototype = Object.create( THREE.Object3D.prototype );
  5792. /**
  5793. * @author mr.doob / http://mrdoob.com/
  5794. */
  5795. THREE.Line = function ( geometry, material, type ) {
  5796. THREE.Object3D.call( this );
  5797. this.geometry = geometry;
  5798. this.material = ( material !== undefined ) ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );
  5799. this.type = ( type !== undefined ) ? type : THREE.LineStrip;
  5800. if ( this.geometry ) {
  5801. if ( ! this.geometry.boundingSphere ) {
  5802. this.geometry.computeBoundingSphere();
  5803. }
  5804. }
  5805. };
  5806. THREE.LineStrip = 0;
  5807. THREE.LinePieces = 1;
  5808. THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
  5809. /**
  5810. * @author mr.doob / http://mrdoob.com/
  5811. * @author alteredq / http://alteredqualia.com/
  5812. * @author mikael emtinger / http://gomo.se/
  5813. */
  5814. THREE.Mesh = function ( geometry, material ) {
  5815. THREE.Object3D.call( this );
  5816. this.geometry = geometry;
  5817. this.material = ( material !== undefined ) ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: true } );
  5818. if ( this.geometry ) {
  5819. // calc bound radius
  5820. if ( ! this.geometry.boundingSphere ) {
  5821. this.geometry.computeBoundingSphere();
  5822. }
  5823. this.boundRadius = geometry.boundingSphere.radius;
  5824. // setup morph targets
  5825. if( this.geometry.morphTargets.length ) {
  5826. this.morphTargetBase = -1;
  5827. this.morphTargetForcedOrder = [];
  5828. this.morphTargetInfluences = [];
  5829. this.morphTargetDictionary = {};
  5830. for( var m = 0; m < this.geometry.morphTargets.length; m ++ ) {
  5831. this.morphTargetInfluences.push( 0 );
  5832. this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m;
  5833. }
  5834. }
  5835. }
  5836. }
  5837. THREE.Mesh.prototype = Object.create( THREE.Object3D.prototype );
  5838. /*
  5839. * Get Morph Target Index by Name
  5840. */
  5841. THREE.Mesh.prototype.getMorphTargetIndexByName = function( name ) {
  5842. if ( this.morphTargetDictionary[ name ] !== undefined ) {
  5843. return this.morphTargetDictionary[ name ];
  5844. }
  5845. console.log( "THREE.Mesh.getMorphTargetIndexByName: morph target " + name + " does not exist. Returning 0." );
  5846. return 0;
  5847. }
  5848. /**
  5849. * @author mikael emtinger / http://gomo.se/
  5850. * @author alteredq / http://alteredqualia.com/
  5851. */
  5852. THREE.Bone = function( belongsToSkin ) {
  5853. THREE.Object3D.call( this );
  5854. this.skin = belongsToSkin;
  5855. this.skinMatrix = new THREE.Matrix4();
  5856. };
  5857. THREE.Bone.prototype = Object.create( THREE.Object3D.prototype );
  5858. THREE.Bone.prototype.update = function( parentSkinMatrix, forceUpdate ) {
  5859. // update local
  5860. if ( this.matrixAutoUpdate ) {
  5861. forceUpdate |= this.updateMatrix();
  5862. }
  5863. // update skin matrix
  5864. if ( forceUpdate || this.matrixWorldNeedsUpdate ) {
  5865. if( parentSkinMatrix ) {
  5866. this.skinMatrix.multiply( parentSkinMatrix, this.matrix );
  5867. } else {
  5868. this.skinMatrix.copy( this.matrix );
  5869. }
  5870. this.matrixWorldNeedsUpdate = false;
  5871. forceUpdate = true;
  5872. }
  5873. // update children
  5874. var child, i, l = this.children.length;
  5875. for ( i = 0; i < l; i ++ ) {
  5876. this.children[ i ].update( this.skinMatrix, forceUpdate );
  5877. }
  5878. };
  5879. /**
  5880. * @author mikael emtinger / http://gomo.se/
  5881. * @author alteredq / http://alteredqualia.com/
  5882. */
  5883. THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
  5884. THREE.Mesh.call( this, geometry, material );
  5885. //
  5886. this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
  5887. // init bones
  5888. this.identityMatrix = new THREE.Matrix4();
  5889. this.bones = [];
  5890. this.boneMatrices = [];
  5891. var b, bone, gbone, p, q, s;
  5892. if ( this.geometry.bones !== undefined ) {
  5893. for ( b = 0; b < this.geometry.bones.length; b ++ ) {
  5894. gbone = this.geometry.bones[ b ];
  5895. p = gbone.pos;
  5896. q = gbone.rotq;
  5897. s = gbone.scl;
  5898. bone = this.addBone();
  5899. bone.name = gbone.name;
  5900. bone.position.set( p[0], p[1], p[2] );
  5901. bone.quaternion.set( q[0], q[1], q[2], q[3] );
  5902. bone.useQuaternion = true;
  5903. if ( s !== undefined ) {
  5904. bone.scale.set( s[0], s[1], s[2] );
  5905. } else {
  5906. bone.scale.set( 1, 1, 1 );
  5907. }
  5908. }
  5909. for ( b = 0; b < this.bones.length; b ++ ) {
  5910. gbone = this.geometry.bones[ b ];
  5911. bone = this.bones[ b ];
  5912. if ( gbone.parent === -1 ) {
  5913. this.add( bone );
  5914. } else {
  5915. this.bones[ gbone.parent ].add( bone );
  5916. }
  5917. }
  5918. //
  5919. var nBones = this.bones.length;
  5920. if ( this.useVertexTexture ) {
  5921. // layout (1 matrix = 4 pixels)
  5922. // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
  5923. // with 8x8 pixel texture max 16 bones (8 * 8 / 4)
  5924. // 16x16 pixel texture max 64 bones (16 * 16 / 4)
  5925. // 32x32 pixel texture max 256 bones (32 * 32 / 4)
  5926. // 64x64 pixel texture max 1024 bones (64 * 64 / 4)
  5927. var size;
  5928. if ( nBones > 256 )
  5929. size = 64;
  5930. else if ( nBones > 64 )
  5931. size = 32;
  5932. else if ( nBones > 16 )
  5933. size = 16;
  5934. else
  5935. size = 8;
  5936. this.boneTextureWidth = size;
  5937. this.boneTextureHeight = size;
  5938. this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
  5939. this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
  5940. this.boneTexture.minFilter = THREE.NearestFilter;
  5941. this.boneTexture.magFilter = THREE.NearestFilter;
  5942. this.boneTexture.generateMipmaps = false;
  5943. this.boneTexture.flipY = false;
  5944. } else {
  5945. this.boneMatrices = new Float32Array( 16 * nBones );
  5946. }
  5947. this.pose();
  5948. }
  5949. };
  5950. THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
  5951. THREE.SkinnedMesh.prototype.addBone = function( bone ) {
  5952. if ( bone === undefined ) {
  5953. bone = new THREE.Bone( this );
  5954. }
  5955. this.bones.push( bone );
  5956. return bone;
  5957. };
  5958. THREE.SkinnedMesh.prototype.updateMatrixWorld = function ( force ) {
  5959. this.matrixAutoUpdate && this.updateMatrix();
  5960. // update matrixWorld
  5961. if ( this.matrixWorldNeedsUpdate || force ) {
  5962. if ( this.parent ) {
  5963. this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
  5964. } else {
  5965. this.matrixWorld.copy( this.matrix );
  5966. }
  5967. this.matrixWorldNeedsUpdate = false;
  5968. force = true;
  5969. }
  5970. // update children
  5971. for ( var i = 0, l = this.children.length; i < l; i ++ ) {
  5972. var child = this.children[ i ];
  5973. if ( child instanceof THREE.Bone ) {
  5974. child.update( this.identityMatrix, false );
  5975. } else {
  5976. child.updateMatrixWorld( true );
  5977. }
  5978. }
  5979. // flatten bone matrices to array
  5980. var b, bl = this.bones.length,
  5981. ba = this.bones,
  5982. bm = this.boneMatrices;
  5983. for ( b = 0; b < bl; b ++ ) {
  5984. ba[ b ].skinMatrix.flattenToArrayOffset( bm, b * 16 );
  5985. }
  5986. if ( this.useVertexTexture ) {
  5987. this.boneTexture.needsUpdate = true;
  5988. }
  5989. };
  5990. /*
  5991. * Pose
  5992. */
  5993. THREE.SkinnedMesh.prototype.pose = function() {
  5994. this.updateMatrixWorld( true );
  5995. var bim, bone, boneInverses = [];
  5996. for ( var b = 0; b < this.bones.length; b ++ ) {
  5997. bone = this.bones[ b ];
  5998. var inverseMatrix = new THREE.Matrix4();
  5999. inverseMatrix.getInverse( bone.skinMatrix );
  6000. boneInverses.push( inverseMatrix );
  6001. bone.skinMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
  6002. }
  6003. // project vertices to local
  6004. if ( this.geometry.skinVerticesA === undefined ) {
  6005. this.geometry.skinVerticesA = [];
  6006. this.geometry.skinVerticesB = [];
  6007. var orgVertex, vertex;
  6008. for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
  6009. orgVertex = this.geometry.vertices[ i ];
  6010. var indexA = this.geometry.skinIndices[ i ].x;
  6011. var indexB = this.geometry.skinIndices[ i ].y;
  6012. vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
  6013. this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ) );
  6014. vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
  6015. this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ) );
  6016. // todo: add more influences
  6017. // normalize weights
  6018. if ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y !== 1 ) {
  6019. var len = ( 1.0 - ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y ) ) * 0.5;
  6020. this.geometry.skinWeights[ i ].x += len;
  6021. this.geometry.skinWeights[ i ].y += len;
  6022. }
  6023. }
  6024. }
  6025. };
  6026. /**
  6027. * @author alteredq / http://alteredqualia.com/
  6028. */
  6029. THREE.MorphAnimMesh = function ( geometry, material ) {
  6030. THREE.Mesh.call( this, geometry, material );
  6031. // API
  6032. this.duration = 1000; // milliseconds
  6033. this.mirroredLoop = false;
  6034. this.time = 0;
  6035. // internals
  6036. this.lastKeyframe = 0;
  6037. this.currentKeyframe = 0;
  6038. this.direction = 1;
  6039. this.directionBackwards = false;
  6040. this.setFrameRange( 0, this.geometry.morphTargets.length - 1 );
  6041. };
  6042. THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
  6043. THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) {
  6044. this.startKeyframe = start;
  6045. this.endKeyframe = end;
  6046. this.length = this.endKeyframe - this.startKeyframe + 1;
  6047. };
  6048. THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
  6049. this.direction = 1;
  6050. this.directionBackwards = false;
  6051. };
  6052. THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
  6053. this.direction = -1;
  6054. this.directionBackwards = true;
  6055. };
  6056. THREE.MorphAnimMesh.prototype.parseAnimations = function () {
  6057. var geometry = this.geometry;
  6058. if ( ! geometry.animations ) geometry.animations = {};
  6059. var firstAnimation, animations = geometry.animations;
  6060. var pattern = /([a-z]+)(\d+)/;
  6061. for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
  6062. var morph = geometry.morphTargets[ i ];
  6063. var parts = morph.name.match( pattern );
  6064. if ( parts && parts.length > 1 ) {
  6065. var label = parts[ 1 ];
  6066. var num = parts[ 2 ];
  6067. if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: -Infinity };
  6068. var animation = animations[ label ];
  6069. if ( i < animation.start ) animation.start = i;
  6070. if ( i > animation.end ) animation.end = i;
  6071. if ( ! firstAnimation ) firstAnimation = label;
  6072. }
  6073. }
  6074. geometry.firstAnimation = firstAnimation;
  6075. };
  6076. THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) {
  6077. if ( ! this.geometry.animations ) this.geometry.animations = {};
  6078. this.geometry.animations[ label ] = { start: start, end: end };
  6079. };
  6080. THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
  6081. var animation = this.geometry.animations[ label ];
  6082. if ( animation ) {
  6083. this.setFrameRange( animation.start, animation.end );
  6084. this.duration = 1000 * ( ( animation.end - animation.start ) / fps );
  6085. this.time = 0;
  6086. } else {
  6087. console.warn( "animation[" + label + "] undefined" );
  6088. }
  6089. };
  6090. THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
  6091. var frameTime = this.duration / this.length;
  6092. this.time += this.direction * delta;
  6093. if ( this.mirroredLoop ) {
  6094. if ( this.time > this.duration || this.time < 0 ) {
  6095. this.direction *= -1;
  6096. if ( this.time > this.duration ) {
  6097. this.time = this.duration;
  6098. this.directionBackwards = true;
  6099. }
  6100. if ( this.time < 0 ) {
  6101. this.time = 0;
  6102. this.directionBackwards = false;
  6103. }
  6104. }
  6105. } else {
  6106. this.time = this.time % this.duration;
  6107. if ( this.time < 0 ) this.time += this.duration;
  6108. }
  6109. var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 );
  6110. if ( keyframe !== this.currentKeyframe ) {
  6111. this.morphTargetInfluences[ this.lastKeyframe ] = 0;
  6112. this.morphTargetInfluences[ this.currentKeyframe ] = 1;
  6113. this.morphTargetInfluences[ keyframe ] = 0;
  6114. this.lastKeyframe = this.currentKeyframe;
  6115. this.currentKeyframe = keyframe;
  6116. }
  6117. var mix = ( this.time % frameTime ) / frameTime;
  6118. if ( this.directionBackwards ) {
  6119. mix = 1 - mix;
  6120. }
  6121. this.morphTargetInfluences[ this.currentKeyframe ] = mix;
  6122. this.morphTargetInfluences[ this.lastKeyframe ] = 1 - mix;
  6123. };
  6124. /**
  6125. * @author alteredq / http://alteredqualia.com/
  6126. */
  6127. THREE.Ribbon = function ( geometry, material ) {
  6128. THREE.Object3D.call( this );
  6129. this.geometry = geometry;
  6130. this.material = material;
  6131. };
  6132. THREE.Ribbon.prototype = Object.create( THREE.Object3D.prototype );
  6133. /**
  6134. * @author mikael emtinger / http://gomo.se/
  6135. * @author alteredq / http://alteredqualia.com/
  6136. * @author mr.doob / http://mrdoob.com/
  6137. */
  6138. THREE.LOD = function () {
  6139. THREE.Object3D.call( this );
  6140. this.LODs = [];
  6141. };
  6142. THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
  6143. THREE.LOD.prototype.addLevel = function ( object3D, visibleAtDistance ) {
  6144. if ( visibleAtDistance === undefined ) {
  6145. visibleAtDistance = 0;
  6146. }
  6147. visibleAtDistance = Math.abs( visibleAtDistance );
  6148. for ( var l = 0; l < this.LODs.length; l ++ ) {
  6149. if ( visibleAtDistance < this.LODs[ l ].visibleAtDistance ) {
  6150. break;
  6151. }
  6152. }
  6153. this.LODs.splice( l, 0, { visibleAtDistance: visibleAtDistance, object3D: object3D } );
  6154. this.add( object3D );
  6155. };
  6156. THREE.LOD.prototype.update = function ( camera ) {
  6157. if ( this.LODs.length > 1 ) {
  6158. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  6159. var inverse = camera.matrixWorldInverse;
  6160. var distance = -( inverse.elements[2] * this.matrixWorld.elements[12] + inverse.elements[6] * this.matrixWorld.elements[13] + inverse.elements[10] * this.matrixWorld.elements[14] + inverse.elements[14] );
  6161. this.LODs[ 0 ].object3D.visible = true;
  6162. for ( var l = 1; l < this.LODs.length; l ++ ) {
  6163. if( distance >= this.LODs[ l ].visibleAtDistance ) {
  6164. this.LODs[ l - 1 ].object3D.visible = false;
  6165. this.LODs[ l ].object3D.visible = true;
  6166. } else {
  6167. break;
  6168. }
  6169. }
  6170. for( ; l < this.LODs.length; l ++ ) {
  6171. this.LODs[ l ].object3D.visible = false;
  6172. }
  6173. }
  6174. };
  6175. /**
  6176. * @author mikael emtinger / http://gomo.se/
  6177. */
  6178. THREE.Sprite = function ( parameters ) {
  6179. THREE.Object3D.call( this );
  6180. this.color = ( parameters.color !== undefined ) ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
  6181. this.map = ( parameters.map !== undefined ) ? parameters.map : new THREE.Texture();
  6182. this.blending = ( parameters.blending !== undefined ) ? parameters.blending : THREE.NormalBlending;
  6183. this.blendSrc = parameters.blendSrc !== undefined ? parameters.blendSrc : THREE.SrcAlphaFactor;
  6184. this.blendDst = parameters.blendDst !== undefined ? parameters.blendDst : THREE.OneMinusSrcAlphaFactor;
  6185. this.blendEquation = parameters.blendEquation !== undefined ? parameters.blendEquation : THREE.AddEquation;
  6186. this.useScreenCoordinates = ( parameters.useScreenCoordinates !== undefined ) ? parameters.useScreenCoordinates : true;
  6187. this.mergeWith3D = ( parameters.mergeWith3D !== undefined ) ? parameters.mergeWith3D : !this.useScreenCoordinates;
  6188. this.affectedByDistance = ( parameters.affectedByDistance !== undefined ) ? parameters.affectedByDistance : !this.useScreenCoordinates;
  6189. this.scaleByViewport = ( parameters.scaleByViewport !== undefined ) ? parameters.scaleByViewport : !this.affectedByDistance;
  6190. this.alignment = ( parameters.alignment instanceof THREE.Vector2 ) ? parameters.alignment : THREE.SpriteAlignment.center;
  6191. this.rotation3d = this.rotation;
  6192. this.rotation = 0;
  6193. this.opacity = 1;
  6194. this.uvOffset = new THREE.Vector2( 0, 0 );
  6195. this.uvScale = new THREE.Vector2( 1, 1 );
  6196. };
  6197. THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype );
  6198. /*
  6199. * Custom update matrix
  6200. */
  6201. THREE.Sprite.prototype.updateMatrix = function () {
  6202. this.matrix.setPosition( this.position );
  6203. this.rotation3d.set( 0, 0, this.rotation );
  6204. this.matrix.setRotationFromEuler( this.rotation3d );
  6205. if ( this.scale.x !== 1 || this.scale.y !== 1 ) {
  6206. this.matrix.scale( this.scale );
  6207. this.boundRadiusScale = Math.max( this.scale.x, this.scale.y );
  6208. }
  6209. this.matrixWorldNeedsUpdate = true;
  6210. };
  6211. /*
  6212. * Alignment
  6213. */
  6214. THREE.SpriteAlignment = {};
  6215. THREE.SpriteAlignment.topLeft = new THREE.Vector2( 1, -1 );
  6216. THREE.SpriteAlignment.topCenter = new THREE.Vector2( 0, -1 );
  6217. THREE.SpriteAlignment.topRight = new THREE.Vector2( -1, -1 );
  6218. THREE.SpriteAlignment.centerLeft = new THREE.Vector2( 1, 0 );
  6219. THREE.SpriteAlignment.center = new THREE.Vector2( 0, 0 );
  6220. THREE.SpriteAlignment.centerRight = new THREE.Vector2( -1, 0 );
  6221. THREE.SpriteAlignment.bottomLeft = new THREE.Vector2( 1, 1 );
  6222. THREE.SpriteAlignment.bottomCenter = new THREE.Vector2( 0, 1 );
  6223. THREE.SpriteAlignment.bottomRight = new THREE.Vector2( -1, 1 );
  6224. /**
  6225. * @author mr.doob / http://mrdoob.com/
  6226. */
  6227. THREE.Scene = function () {
  6228. THREE.Object3D.call( this );
  6229. this.fog = null;
  6230. this.overrideMaterial = null;
  6231. this.matrixAutoUpdate = false;
  6232. this.__objects = [];
  6233. this.__lights = [];
  6234. this.__objectsAdded = [];
  6235. this.__objectsRemoved = [];
  6236. };
  6237. THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
  6238. THREE.Scene.prototype.__addObject = function ( object ) {
  6239. if ( object instanceof THREE.Light ) {
  6240. if ( this.__lights.indexOf( object ) === - 1 ) {
  6241. this.__lights.push( object );
  6242. }
  6243. } else if ( !( object instanceof THREE.Camera || object instanceof THREE.Bone ) ) {
  6244. if ( this.__objects.indexOf( object ) === - 1 ) {
  6245. this.__objects.push( object );
  6246. this.__objectsAdded.push( object );
  6247. // check if previously removed
  6248. var i = this.__objectsRemoved.indexOf( object );
  6249. if ( i !== -1 ) {
  6250. this.__objectsRemoved.splice( i, 1 );
  6251. }
  6252. }
  6253. }
  6254. for ( var c = 0; c < object.children.length; c ++ ) {
  6255. this.__addObject( object.children[ c ] );
  6256. }
  6257. };
  6258. THREE.Scene.prototype.__removeObject = function ( object ) {
  6259. if ( object instanceof THREE.Light ) {
  6260. var i = this.__lights.indexOf( object );
  6261. if ( i !== -1 ) {
  6262. this.__lights.splice( i, 1 );
  6263. }
  6264. } else if ( !( object instanceof THREE.Camera ) ) {
  6265. var i = this.__objects.indexOf( object );
  6266. if( i !== -1 ) {
  6267. this.__objects.splice( i, 1 );
  6268. this.__objectsRemoved.push( object );
  6269. // check if previously added
  6270. var ai = this.__objectsAdded.indexOf( object );
  6271. if ( ai !== -1 ) {
  6272. this.__objectsAdded.splice( ai, 1 );
  6273. }
  6274. }
  6275. }
  6276. for ( var c = 0; c < object.children.length; c ++ ) {
  6277. this.__removeObject( object.children[ c ] );
  6278. }
  6279. };
  6280. /**
  6281. * @author mr.doob / http://mrdoob.com/
  6282. * @author alteredq / http://alteredqualia.com/
  6283. */
  6284. THREE.Fog = function ( hex, near, far ) {
  6285. this.color = new THREE.Color( hex );
  6286. this.near = ( near !== undefined ) ? near : 1;
  6287. this.far = ( far !== undefined ) ? far : 1000;
  6288. };
  6289. /**
  6290. * @author mr.doob / http://mrdoob.com/
  6291. * @author alteredq / http://alteredqualia.com/
  6292. */
  6293. THREE.FogExp2 = function ( hex, density ) {
  6294. this.color = new THREE.Color( hex );
  6295. this.density = ( density !== undefined ) ? density : 0.00025;
  6296. };
  6297. /**
  6298. * @author mr.doob / http://mrdoob.com/
  6299. */
  6300. THREE.CanvasRenderer = function ( parameters ) {
  6301. console.log( 'THREE.CanvasRenderer', THREE.REVISION );
  6302. parameters = parameters || {};
  6303. var _this = this,
  6304. _renderData, _elements, _lights,
  6305. _projector = new THREE.Projector(),
  6306. _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
  6307. _canvasWidth, _canvasHeight, _canvasWidthHalf, _canvasHeightHalf,
  6308. _context = _canvas.getContext( '2d' ),
  6309. _clearColor = new THREE.Color( 0x000000 ),
  6310. _clearOpacity = 0,
  6311. _contextGlobalAlpha = 1,
  6312. _contextGlobalCompositeOperation = 0,
  6313. _contextStrokeStyle = null,
  6314. _contextFillStyle = null,
  6315. _contextLineWidth = null,
  6316. _contextLineCap = null,
  6317. _contextLineJoin = null,
  6318. _v1, _v2, _v3, _v4,
  6319. _v5 = new THREE.RenderableVertex(),
  6320. _v6 = new THREE.RenderableVertex(),
  6321. _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
  6322. _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
  6323. _color = new THREE.Color(),
  6324. _color1 = new THREE.Color(),
  6325. _color2 = new THREE.Color(),
  6326. _color3 = new THREE.Color(),
  6327. _color4 = new THREE.Color(),
  6328. _patterns = [], _imagedatas = [],
  6329. _near, _far,
  6330. _image, _uvs,
  6331. _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
  6332. _clipRect = new THREE.Rectangle(),
  6333. _clearRect = new THREE.Rectangle(),
  6334. _bboxRect = new THREE.Rectangle(),
  6335. _enableLighting = false,
  6336. _ambientLight = new THREE.Color(),
  6337. _directionalLights = new THREE.Color(),
  6338. _pointLights = new THREE.Color(),
  6339. _pi2 = Math.PI * 2,
  6340. _vector3 = new THREE.Vector3(), // Needed for PointLight
  6341. _pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData,
  6342. _gradientMap, _gradientMapContext, _gradientMapQuality = 16;
  6343. _pixelMap = document.createElement( 'canvas' );
  6344. _pixelMap.width = _pixelMap.height = 2;
  6345. _pixelMapContext = _pixelMap.getContext( '2d' );
  6346. _pixelMapContext.fillStyle = 'rgba(0,0,0,1)';
  6347. _pixelMapContext.fillRect( 0, 0, 2, 2 );
  6348. _pixelMapImage = _pixelMapContext.getImageData( 0, 0, 2, 2 );
  6349. _pixelMapData = _pixelMapImage.data;
  6350. _gradientMap = document.createElement( 'canvas' );
  6351. _gradientMap.width = _gradientMap.height = _gradientMapQuality;
  6352. _gradientMapContext = _gradientMap.getContext( '2d' );
  6353. _gradientMapContext.translate( - _gradientMapQuality / 2, - _gradientMapQuality / 2 );
  6354. _gradientMapContext.scale( _gradientMapQuality, _gradientMapQuality );
  6355. _gradientMapQuality --; // Fix UVs
  6356. this.domElement = _canvas;
  6357. this.autoClear = true;
  6358. this.sortObjects = true;
  6359. this.sortElements = true;
  6360. this.info = {
  6361. render: {
  6362. vertices: 0,
  6363. faces: 0
  6364. }
  6365. }
  6366. this.setSize = function ( width, height ) {
  6367. _canvasWidth = width;
  6368. _canvasHeight = height;
  6369. _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
  6370. _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
  6371. _canvas.width = _canvasWidth;
  6372. _canvas.height = _canvasHeight;
  6373. _clipRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
  6374. _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
  6375. _contextGlobalAlpha = 1;
  6376. _contextGlobalCompositeOperation = 0;
  6377. _contextStrokeStyle = null;
  6378. _contextFillStyle = null;
  6379. _contextLineWidth = null;
  6380. _contextLineCap = null;
  6381. _contextLineJoin = null;
  6382. };
  6383. this.setClearColor = function ( color, opacity ) {
  6384. _clearColor.copy( color );
  6385. _clearOpacity = opacity !== undefined ? opacity : 1;
  6386. _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
  6387. };
  6388. this.setClearColorHex = function ( hex, opacity ) {
  6389. _clearColor.setHex( hex );
  6390. _clearOpacity = opacity !== undefined ? opacity : 1;
  6391. _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
  6392. };
  6393. this.clear = function () {
  6394. _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
  6395. if ( _clearRect.isEmpty() === false ) {
  6396. _clearRect.minSelf( _clipRect );
  6397. _clearRect.inflate( 2 );
  6398. if ( _clearOpacity < 1 ) {
  6399. _context.clearRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
  6400. }
  6401. if ( _clearOpacity > 0 ) {
  6402. setBlending( THREE.NormalBlending );
  6403. setOpacity( 1 );
  6404. setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearOpacity + ')' );
  6405. _context.fillRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
  6406. }
  6407. _clearRect.empty();
  6408. }
  6409. };
  6410. this.render = function ( scene, camera ) {
  6411. var e, el, element, material;
  6412. this.autoClear === true ? this.clear() : _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
  6413. _this.info.render.vertices = 0;
  6414. _this.info.render.faces = 0;
  6415. _renderData = _projector.projectScene( scene, camera, this.sortElements );
  6416. _elements = _renderData.elements;
  6417. _lights = _renderData.lights;
  6418. /* DEBUG
  6419. _context.fillStyle = 'rgba( 0, 255, 255, 0.5 )';
  6420. _context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() );
  6421. */
  6422. _enableLighting = _lights.length > 0;
  6423. if ( _enableLighting === true ) {
  6424. calculateLights( _lights );
  6425. }
  6426. for ( e = 0, el = _elements.length; e < el; e++ ) {
  6427. element = _elements[ e ];
  6428. material = element.material;
  6429. material = material instanceof THREE.MeshFaceMaterial ? element.faceMaterial : material;
  6430. if ( material === undefined || material.visible === false ) continue;
  6431. _bboxRect.empty();
  6432. if ( element instanceof THREE.RenderableParticle ) {
  6433. _v1 = element;
  6434. _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
  6435. renderParticle( _v1, element, material, scene );
  6436. } else if ( element instanceof THREE.RenderableLine ) {
  6437. _v1 = element.v1; _v2 = element.v2;
  6438. _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
  6439. _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
  6440. _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
  6441. _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
  6442. if ( _clipRect.intersects( _bboxRect ) === true ) {
  6443. renderLine( _v1, _v2, element, material, scene );
  6444. }
  6445. } else if ( element instanceof THREE.RenderableFace3 ) {
  6446. _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
  6447. _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
  6448. _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
  6449. _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
  6450. if ( material.overdraw === true ) {
  6451. expand( _v1.positionScreen, _v2.positionScreen );
  6452. expand( _v2.positionScreen, _v3.positionScreen );
  6453. expand( _v3.positionScreen, _v1.positionScreen );
  6454. }
  6455. _bboxRect.add3Points( _v1.positionScreen.x, _v1.positionScreen.y,
  6456. _v2.positionScreen.x, _v2.positionScreen.y,
  6457. _v3.positionScreen.x, _v3.positionScreen.y );
  6458. if ( _clipRect.intersects( _bboxRect ) === true ) {
  6459. renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material, scene );
  6460. }
  6461. } else if ( element instanceof THREE.RenderableFace4 ) {
  6462. _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; _v4 = element.v4;
  6463. _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
  6464. _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
  6465. _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
  6466. _v4.positionScreen.x *= _canvasWidthHalf; _v4.positionScreen.y *= _canvasHeightHalf;
  6467. _v5.positionScreen.copy( _v2.positionScreen );
  6468. _v6.positionScreen.copy( _v4.positionScreen );
  6469. if ( material.overdraw === true ) {
  6470. expand( _v1.positionScreen, _v2.positionScreen );
  6471. expand( _v2.positionScreen, _v4.positionScreen );
  6472. expand( _v4.positionScreen, _v1.positionScreen );
  6473. expand( _v3.positionScreen, _v5.positionScreen );
  6474. expand( _v3.positionScreen, _v6.positionScreen );
  6475. }
  6476. _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
  6477. _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
  6478. _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y );
  6479. _bboxRect.addPoint( _v4.positionScreen.x, _v4.positionScreen.y );
  6480. if ( _clipRect.intersects( _bboxRect ) === true ) {
  6481. renderFace4( _v1, _v2, _v3, _v4, _v5, _v6, element, material, scene );
  6482. }
  6483. }
  6484. /*
  6485. _context.lineWidth = 1;
  6486. _context.strokeStyle = 'rgba( 0, 255, 0, 0.5 )';
  6487. _context.strokeRect( _bboxRect.getX(), _bboxRect.getY(), _bboxRect.getWidth(), _bboxRect.getHeight() );
  6488. */
  6489. _clearRect.addRectangle( _bboxRect );
  6490. }
  6491. /* DEBUG
  6492. _context.lineWidth = 1;
  6493. _context.strokeStyle = 'rgba( 255, 0, 0, 0.5 )';
  6494. _context.strokeRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
  6495. */
  6496. _context.setTransform( 1, 0, 0, 1, 0, 0 );
  6497. //
  6498. function calculateLights( lights ) {
  6499. var l, ll, light, lightColor;
  6500. _ambientLight.setRGB( 0, 0, 0 );
  6501. _directionalLights.setRGB( 0, 0, 0 );
  6502. _pointLights.setRGB( 0, 0, 0 );
  6503. for ( l = 0, ll = lights.length; l < ll; l ++ ) {
  6504. light = lights[ l ];
  6505. lightColor = light.color;
  6506. if ( light instanceof THREE.AmbientLight ) {
  6507. _ambientLight.r += lightColor.r;
  6508. _ambientLight.g += lightColor.g;
  6509. _ambientLight.b += lightColor.b;
  6510. } else if ( light instanceof THREE.DirectionalLight ) {
  6511. // for particles
  6512. _directionalLights.r += lightColor.r;
  6513. _directionalLights.g += lightColor.g;
  6514. _directionalLights.b += lightColor.b;
  6515. } else if ( light instanceof THREE.PointLight ) {
  6516. // for particles
  6517. _pointLights.r += lightColor.r;
  6518. _pointLights.g += lightColor.g;
  6519. _pointLights.b += lightColor.b;
  6520. }
  6521. }
  6522. }
  6523. function calculateLight( lights, position, normal, color ) {
  6524. var l, ll, light, lightColor, lightPosition, amount;
  6525. for ( l = 0, ll = lights.length; l < ll; l ++ ) {
  6526. light = lights[ l ];
  6527. lightColor = light.color;
  6528. if ( light instanceof THREE.DirectionalLight ) {
  6529. lightPosition = light.matrixWorld.getPosition();
  6530. amount = normal.dot( lightPosition );
  6531. if ( amount <= 0 ) continue;
  6532. amount *= light.intensity;
  6533. color.r += lightColor.r * amount;
  6534. color.g += lightColor.g * amount;
  6535. color.b += lightColor.b * amount;
  6536. } else if ( light instanceof THREE.PointLight ) {
  6537. lightPosition = light.matrixWorld.getPosition();
  6538. amount = normal.dot( _vector3.sub( lightPosition, position ).normalize() );
  6539. if ( amount <= 0 ) continue;
  6540. amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
  6541. if ( amount == 0 ) continue;
  6542. amount *= light.intensity;
  6543. color.r += lightColor.r * amount;
  6544. color.g += lightColor.g * amount;
  6545. color.b += lightColor.b * amount;
  6546. }
  6547. }
  6548. }
  6549. function renderParticle( v1, element, material, scene ) {
  6550. setOpacity( material.opacity );
  6551. setBlending( material.blending );
  6552. var width, height, scaleX, scaleY,
  6553. bitmap, bitmapWidth, bitmapHeight;
  6554. if ( material instanceof THREE.ParticleBasicMaterial ) {
  6555. if ( material.map !== null ) {
  6556. bitmap = material.map.image;
  6557. bitmapWidth = bitmap.width >> 1;
  6558. bitmapHeight = bitmap.height >> 1;
  6559. scaleX = element.scale.x * _canvasWidthHalf;
  6560. scaleY = element.scale.y * _canvasHeightHalf;
  6561. width = scaleX * bitmapWidth;
  6562. height = scaleY * bitmapHeight;
  6563. // TODO: Rotations break this...
  6564. _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height );
  6565. if ( _clipRect.intersects( _bboxRect ) === false ) {
  6566. return;
  6567. }
  6568. _context.save();
  6569. _context.translate( v1.x, v1.y );
  6570. _context.rotate( - element.rotation );
  6571. _context.scale( scaleX, - scaleY );
  6572. _context.translate( - bitmapWidth, - bitmapHeight );
  6573. _context.drawImage( bitmap, 0, 0 );
  6574. _context.restore();
  6575. }
  6576. /* DEBUG
  6577. _context.beginPath();
  6578. _context.moveTo( v1.x - 10, v1.y );
  6579. _context.lineTo( v1.x + 10, v1.y );
  6580. _context.moveTo( v1.x, v1.y - 10 );
  6581. _context.lineTo( v1.x, v1.y + 10 );
  6582. _context.closePath();
  6583. _context.strokeStyle = 'rgb(255,255,0)';
  6584. _context.stroke();
  6585. */
  6586. } else if ( material instanceof THREE.ParticleCanvasMaterial ) {
  6587. width = element.scale.x * _canvasWidthHalf;
  6588. height = element.scale.y * _canvasHeightHalf;
  6589. _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height );
  6590. if ( _clipRect.intersects( _bboxRect ) === false ) {
  6591. return;
  6592. }
  6593. setStrokeStyle( material.color.getContextStyle() );
  6594. setFillStyle( material.color.getContextStyle() );
  6595. _context.save();
  6596. _context.translate( v1.x, v1.y );
  6597. _context.rotate( - element.rotation );
  6598. _context.scale( width, height );
  6599. material.program( _context );
  6600. _context.restore();
  6601. }
  6602. }
  6603. function renderLine( v1, v2, element, material, scene ) {
  6604. setOpacity( material.opacity );
  6605. setBlending( material.blending );
  6606. _context.beginPath();
  6607. _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
  6608. _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
  6609. _context.closePath();
  6610. if ( material instanceof THREE.LineBasicMaterial ) {
  6611. setLineWidth( material.linewidth );
  6612. setLineCap( material.linecap );
  6613. setLineJoin( material.linejoin );
  6614. setStrokeStyle( material.color.getContextStyle() );
  6615. _context.stroke();
  6616. _bboxRect.inflate( material.linewidth * 2 );
  6617. }
  6618. }
  6619. function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material, scene ) {
  6620. _this.info.render.vertices += 3;
  6621. _this.info.render.faces ++;
  6622. setOpacity( material.opacity );
  6623. setBlending( material.blending );
  6624. _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
  6625. _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
  6626. _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
  6627. drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
  6628. if ( material instanceof THREE.MeshBasicMaterial ) {
  6629. if ( material.map !== null ) {
  6630. if ( material.map.mapping instanceof THREE.UVMapping ) {
  6631. _uvs = element.uvs[ 0 ];
  6632. patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].u, _uvs[ uv1 ].v, _uvs[ uv2 ].u, _uvs[ uv2 ].v, _uvs[ uv3 ].u, _uvs[ uv3 ].v, material.map );
  6633. }
  6634. } else if ( material.envMap !== null ) {
  6635. if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
  6636. var cameraMatrix = camera.matrixWorldInverse;
  6637. _vector3.copy( element.vertexNormalsWorld[ uv1 ] );
  6638. _uv1x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
  6639. _uv1y = - ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
  6640. _vector3.copy( element.vertexNormalsWorld[ uv2 ] );
  6641. _uv2x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
  6642. _uv2y = - ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
  6643. _vector3.copy( element.vertexNormalsWorld[ uv3 ] );
  6644. _uv3x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
  6645. _uv3y = - ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
  6646. patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
  6647. }/* else if ( material.envMap.mapping == THREE.SphericalRefractionMapping ) {
  6648. }*/
  6649. } else {
  6650. material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
  6651. }
  6652. } else if ( material instanceof THREE.MeshLambertMaterial ) {
  6653. if ( _enableLighting === true ) {
  6654. if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsWorld.length == 3 ) {
  6655. _color1.r = _color2.r = _color3.r = _ambientLight.r;
  6656. _color1.g = _color2.g = _color3.g = _ambientLight.g;
  6657. _color1.b = _color2.b = _color3.b = _ambientLight.b;
  6658. calculateLight( _lights, element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
  6659. calculateLight( _lights, element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
  6660. calculateLight( _lights, element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 );
  6661. _color1.r = Math.max( 0, Math.min( material.color.r * _color1.r, 1 ) );
  6662. _color1.g = Math.max( 0, Math.min( material.color.g * _color1.g, 1 ) );
  6663. _color1.b = Math.max( 0, Math.min( material.color.b * _color1.b, 1 ) );
  6664. _color2.r = Math.max( 0, Math.min( material.color.r * _color2.r, 1 ) );
  6665. _color2.g = Math.max( 0, Math.min( material.color.g * _color2.g, 1 ) );
  6666. _color2.b = Math.max( 0, Math.min( material.color.b * _color2.b, 1 ) );
  6667. _color3.r = Math.max( 0, Math.min( material.color.r * _color3.r, 1 ) );
  6668. _color3.g = Math.max( 0, Math.min( material.color.g * _color3.g, 1 ) );
  6669. _color3.b = Math.max( 0, Math.min( material.color.b * _color3.b, 1 ) );
  6670. _color4.r = ( _color2.r + _color3.r ) * 0.5;
  6671. _color4.g = ( _color2.g + _color3.g ) * 0.5;
  6672. _color4.b = ( _color2.b + _color3.b ) * 0.5;
  6673. _image = getGradientTexture( _color1, _color2, _color3, _color4 );
  6674. clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
  6675. } else {
  6676. _color.r = _ambientLight.r;
  6677. _color.g = _ambientLight.g;
  6678. _color.b = _ambientLight.b;
  6679. calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
  6680. _color.r = Math.max( 0, Math.min( material.color.r * _color.r, 1 ) );
  6681. _color.g = Math.max( 0, Math.min( material.color.g * _color.g, 1 ) );
  6682. _color.b = Math.max( 0, Math.min( material.color.b * _color.b, 1 ) );
  6683. material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
  6684. }
  6685. } else {
  6686. material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
  6687. }
  6688. } else if ( material instanceof THREE.MeshDepthMaterial ) {
  6689. _near = camera.near;
  6690. _far = camera.far;
  6691. _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
  6692. _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
  6693. _color3.r = _color3.g = _color3.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
  6694. _color4.r = ( _color2.r + _color3.r ) * 0.5;
  6695. _color4.g = ( _color2.g + _color3.g ) * 0.5;
  6696. _color4.b = ( _color2.b + _color3.b ) * 0.5;
  6697. _image = getGradientTexture( _color1, _color2, _color3, _color4 );
  6698. clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
  6699. } else if ( material instanceof THREE.MeshNormalMaterial ) {
  6700. _color.r = normalToComponent( element.normalWorld.x );
  6701. _color.g = normalToComponent( element.normalWorld.y );
  6702. _color.b = normalToComponent( element.normalWorld.z );
  6703. material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
  6704. }
  6705. }
  6706. function renderFace4( v1, v2, v3, v4, v5, v6, element, material, scene ) {
  6707. _this.info.render.vertices += 4;
  6708. _this.info.render.faces ++;
  6709. setOpacity( material.opacity );
  6710. setBlending( material.blending );
  6711. if ( material.map !== null || material.envMap !== null ) {
  6712. // Let renderFace3() handle this
  6713. renderFace3( v1, v2, v4, 0, 1, 3, element, material, scene );
  6714. renderFace3( v5, v3, v6, 1, 2, 3, element, material, scene );
  6715. return;
  6716. }
  6717. _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
  6718. _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
  6719. _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
  6720. _v4x = v4.positionScreen.x; _v4y = v4.positionScreen.y;
  6721. _v5x = v5.positionScreen.x; _v5y = v5.positionScreen.y;
  6722. _v6x = v6.positionScreen.x; _v6y = v6.positionScreen.y;
  6723. if ( material instanceof THREE.MeshBasicMaterial ) {
  6724. drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
  6725. material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
  6726. } else if ( material instanceof THREE.MeshLambertMaterial ) {
  6727. if ( _enableLighting === true ) {
  6728. if ( !material.wireframe && material.shading == THREE.SmoothShading && element.vertexNormalsWorld.length == 4 ) {
  6729. _color1.r = _color2.r = _color3.r = _color4.r = _ambientLight.r;
  6730. _color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g;
  6731. _color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b;
  6732. calculateLight( _lights, element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
  6733. calculateLight( _lights, element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
  6734. calculateLight( _lights, element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 );
  6735. calculateLight( _lights, element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 );
  6736. _color1.r = Math.max( 0, Math.min( material.color.r * _color1.r, 1 ) );
  6737. _color1.g = Math.max( 0, Math.min( material.color.g * _color1.g, 1 ) );
  6738. _color1.b = Math.max( 0, Math.min( material.color.b * _color1.b, 1 ) );
  6739. _color2.r = Math.max( 0, Math.min( material.color.r * _color2.r, 1 ) );
  6740. _color2.g = Math.max( 0, Math.min( material.color.g * _color2.g, 1 ) );
  6741. _color2.b = Math.max( 0, Math.min( material.color.b * _color2.b, 1 ) );
  6742. _color3.r = Math.max( 0, Math.min( material.color.r * _color3.r, 1 ) );
  6743. _color3.g = Math.max( 0, Math.min( material.color.g * _color3.g, 1 ) );
  6744. _color3.b = Math.max( 0, Math.min( material.color.b * _color3.b, 1 ) );
  6745. _color4.r = Math.max( 0, Math.min( material.color.r * _color4.r, 1 ) );
  6746. _color4.g = Math.max( 0, Math.min( material.color.g * _color4.g, 1 ) );
  6747. _color4.b = Math.max( 0, Math.min( material.color.b * _color4.b, 1 ) );
  6748. _image = getGradientTexture( _color1, _color2, _color3, _color4 );
  6749. // TODO: UVs are incorrect, v4->v3?
  6750. drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
  6751. clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
  6752. drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
  6753. clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
  6754. } else {
  6755. _color.r = _ambientLight.r;
  6756. _color.g = _ambientLight.g;
  6757. _color.b = _ambientLight.b;
  6758. calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
  6759. _color.r = Math.max( 0, Math.min( material.color.r * _color.r, 1 ) );
  6760. _color.g = Math.max( 0, Math.min( material.color.g * _color.g, 1 ) );
  6761. _color.b = Math.max( 0, Math.min( material.color.b * _color.b, 1 ) );
  6762. drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
  6763. material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
  6764. }
  6765. } else {
  6766. drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
  6767. material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
  6768. }
  6769. } else if ( material instanceof THREE.MeshNormalMaterial ) {
  6770. _color.r = normalToComponent( element.normalWorld.x );
  6771. _color.g = normalToComponent( element.normalWorld.y );
  6772. _color.b = normalToComponent( element.normalWorld.z );
  6773. drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
  6774. material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
  6775. } else if ( material instanceof THREE.MeshDepthMaterial ) {
  6776. _near = camera.near;
  6777. _far = camera.far;
  6778. _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
  6779. _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
  6780. _color3.r = _color3.g = _color3.b = 1 - smoothstep( v4.positionScreen.z, _near, _far );
  6781. _color4.r = _color4.g = _color4.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
  6782. _image = getGradientTexture( _color1, _color2, _color3, _color4 );
  6783. // TODO: UVs are incorrect, v4->v3?
  6784. drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
  6785. clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
  6786. drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
  6787. clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
  6788. }
  6789. }
  6790. //
  6791. function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
  6792. _context.beginPath();
  6793. _context.moveTo( x0, y0 );
  6794. _context.lineTo( x1, y1 );
  6795. _context.lineTo( x2, y2 );
  6796. _context.lineTo( x0, y0 );
  6797. }
  6798. function drawQuad( x0, y0, x1, y1, x2, y2, x3, y3 ) {
  6799. _context.beginPath();
  6800. _context.moveTo( x0, y0 );
  6801. _context.lineTo( x1, y1 );
  6802. _context.lineTo( x2, y2 );
  6803. _context.lineTo( x3, y3 );
  6804. _context.lineTo( x0, y0 );
  6805. }
  6806. function strokePath( color, linewidth, linecap, linejoin ) {
  6807. setLineWidth( linewidth );
  6808. setLineCap( linecap );
  6809. setLineJoin( linejoin );
  6810. setStrokeStyle( color.getContextStyle() );
  6811. _context.stroke();
  6812. _bboxRect.inflate( linewidth * 2 );
  6813. }
  6814. function fillPath( color ) {
  6815. setFillStyle( color.getContextStyle() );
  6816. _context.fill();
  6817. }
  6818. function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
  6819. if ( texture.image === undefined || texture.image.width === 0 ) return;
  6820. if ( texture.needsUpdate === true || _patterns[ texture.id ] === undefined ) {
  6821. var repeatX = texture.wrapS == THREE.RepeatWrapping;
  6822. var repeatY = texture.wrapT == THREE.RepeatWrapping;
  6823. _patterns[ texture.id ] = _context.createPattern( texture.image, repeatX === true && repeatY === true ? 'repeat' : repeatX === true && repeatY === false ? 'repeat-x' : repeatX === false && repeatY === true ? 'repeat-y' : 'no-repeat' );
  6824. texture.needsUpdate = false;
  6825. }
  6826. setFillStyle( _patterns[ texture.id ] );
  6827. // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
  6828. var a, b, c, d, e, f, det, idet,
  6829. offsetX = texture.offset.x / texture.repeat.x,
  6830. offsetY = texture.offset.y / texture.repeat.y,
  6831. width = texture.image.width * texture.repeat.x,
  6832. height = texture.image.height * texture.repeat.y;
  6833. u0 = ( u0 + offsetX ) * width;
  6834. v0 = ( v0 + offsetY ) * height;
  6835. u1 = ( u1 + offsetX ) * width;
  6836. v1 = ( v1 + offsetY ) * height;
  6837. u2 = ( u2 + offsetX ) * width;
  6838. v2 = ( v2 + offsetY ) * height;
  6839. x1 -= x0; y1 -= y0;
  6840. x2 -= x0; y2 -= y0;
  6841. u1 -= u0; v1 -= v0;
  6842. u2 -= u0; v2 -= v0;
  6843. det = u1 * v2 - u2 * v1;
  6844. if ( det === 0 ) {
  6845. if ( _imagedatas[ texture.id ] === undefined ) {
  6846. var canvas = document.createElement( 'canvas' )
  6847. canvas.width = texture.image.width;
  6848. canvas.height = texture.image.height;
  6849. var context = canvas.getContext( '2d' );
  6850. context.drawImage( texture.image, 0, 0 );
  6851. _imagedatas[ texture.id ] = context.getImageData( 0, 0, texture.image.width, texture.image.height ).data;
  6852. // variables cannot be deleted in ES5 strict mode
  6853. //delete canvas;
  6854. }
  6855. var data = _imagedatas[ texture.id ];
  6856. var index = ( Math.floor( u0 ) + Math.floor( v0 ) * texture.image.width ) * 4;
  6857. _color.setRGB( data[ index ] / 255, data[ index + 1 ] / 255, data[ index + 2 ] / 255 );
  6858. fillPath( _color );
  6859. return;
  6860. }
  6861. idet = 1 / det;
  6862. a = ( v2 * x1 - v1 * x2 ) * idet;
  6863. b = ( v2 * y1 - v1 * y2 ) * idet;
  6864. c = ( u1 * x2 - u2 * x1 ) * idet;
  6865. d = ( u1 * y2 - u2 * y1 ) * idet;
  6866. e = x0 - a * u0 - c * v0;
  6867. f = y0 - b * u0 - d * v0;
  6868. _context.save();
  6869. _context.transform( a, b, c, d, e, f );
  6870. _context.fill();
  6871. _context.restore();
  6872. }
  6873. function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
  6874. // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
  6875. var a, b, c, d, e, f, det, idet,
  6876. width = image.width - 1,
  6877. height = image.height - 1;
  6878. u0 *= width; v0 *= height;
  6879. u1 *= width; v1 *= height;
  6880. u2 *= width; v2 *= height;
  6881. x1 -= x0; y1 -= y0;
  6882. x2 -= x0; y2 -= y0;
  6883. u1 -= u0; v1 -= v0;
  6884. u2 -= u0; v2 -= v0;
  6885. det = u1 * v2 - u2 * v1;
  6886. idet = 1 / det;
  6887. a = ( v2 * x1 - v1 * x2 ) * idet;
  6888. b = ( v2 * y1 - v1 * y2 ) * idet;
  6889. c = ( u1 * x2 - u2 * x1 ) * idet;
  6890. d = ( u1 * y2 - u2 * y1 ) * idet;
  6891. e = x0 - a * u0 - c * v0;
  6892. f = y0 - b * u0 - d * v0;
  6893. _context.save();
  6894. _context.transform( a, b, c, d, e, f );
  6895. _context.clip();
  6896. _context.drawImage( image, 0, 0 );
  6897. _context.restore();
  6898. }
  6899. function getGradientTexture( color1, color2, color3, color4 ) {
  6900. // http://mrdoob.com/blog/post/710
  6901. var c1r = ~~ ( color1.r * 255 ), c1g = ~~ ( color1.g * 255 ), c1b = ~~ ( color1.b * 255 ),
  6902. c2r = ~~ ( color2.r * 255 ), c2g = ~~ ( color2.g * 255 ), c2b = ~~ ( color2.b * 255 ),
  6903. c3r = ~~ ( color3.r * 255 ), c3g = ~~ ( color3.g * 255 ), c3b = ~~ ( color3.b * 255 ),
  6904. c4r = ~~ ( color4.r * 255 ), c4g = ~~ ( color4.g * 255 ), c4b = ~~ ( color4.b * 255 );
  6905. _pixelMapData[ 0 ] = c1r < 0 ? 0 : c1r > 255 ? 255 : c1r;
  6906. _pixelMapData[ 1 ] = c1g < 0 ? 0 : c1g > 255 ? 255 : c1g;
  6907. _pixelMapData[ 2 ] = c1b < 0 ? 0 : c1b > 255 ? 255 : c1b;
  6908. _pixelMapData[ 4 ] = c2r < 0 ? 0 : c2r > 255 ? 255 : c2r;
  6909. _pixelMapData[ 5 ] = c2g < 0 ? 0 : c2g > 255 ? 255 : c2g;
  6910. _pixelMapData[ 6 ] = c2b < 0 ? 0 : c2b > 255 ? 255 : c2b;
  6911. _pixelMapData[ 8 ] = c3r < 0 ? 0 : c3r > 255 ? 255 : c3r;
  6912. _pixelMapData[ 9 ] = c3g < 0 ? 0 : c3g > 255 ? 255 : c3g;
  6913. _pixelMapData[ 10 ] = c3b < 0 ? 0 : c3b > 255 ? 255 : c3b;
  6914. _pixelMapData[ 12 ] = c4r < 0 ? 0 : c4r > 255 ? 255 : c4r;
  6915. _pixelMapData[ 13 ] = c4g < 0 ? 0 : c4g > 255 ? 255 : c4g;
  6916. _pixelMapData[ 14 ] = c4b < 0 ? 0 : c4b > 255 ? 255 : c4b;
  6917. _pixelMapContext.putImageData( _pixelMapImage, 0, 0 );
  6918. _gradientMapContext.drawImage( _pixelMap, 0, 0 );
  6919. return _gradientMap;
  6920. }
  6921. function smoothstep( value, min, max ) {
  6922. var x = ( value - min ) / ( max - min );
  6923. return x * x * ( 3 - 2 * x );
  6924. }
  6925. function normalToComponent( normal ) {
  6926. var component = ( normal + 1 ) * 0.5;
  6927. return component < 0 ? 0 : ( component > 1 ? 1 : component );
  6928. }
  6929. // Hide anti-alias gaps
  6930. function expand( v1, v2 ) {
  6931. var x = v2.x - v1.x, y = v2.y - v1.y,
  6932. det = x * x + y * y, idet;
  6933. if ( det === 0 ) return;
  6934. idet = 1 / Math.sqrt( det );
  6935. x *= idet; y *= idet;
  6936. v2.x += x; v2.y += y;
  6937. v1.x -= x; v1.y -= y;
  6938. }
  6939. };
  6940. // Context cached methods.
  6941. function setOpacity( value ) {
  6942. if ( _contextGlobalAlpha !== value ) {
  6943. _context.globalAlpha = value;
  6944. _contextGlobalAlpha = value;
  6945. }
  6946. }
  6947. function setBlending( value ) {
  6948. if ( _contextGlobalCompositeOperation !== value ) {
  6949. if ( value === THREE.NormalBlending ) {
  6950. _context.globalCompositeOperation = 'source-over';
  6951. } else if ( value === THREE.AdditiveBlending ) {
  6952. _context.globalCompositeOperation = 'lighter';
  6953. } else if ( value === THREE.SubtractiveBlending ) {
  6954. _context.globalCompositeOperation = 'darker';
  6955. }
  6956. _contextGlobalCompositeOperation = value;
  6957. }
  6958. }
  6959. function setLineWidth( value ) {
  6960. if ( _contextLineWidth !== value ) {
  6961. _context.lineWidth = value;
  6962. _contextLineWidth = value;
  6963. }
  6964. }
  6965. function setLineCap( value ) {
  6966. // "butt", "round", "square"
  6967. if ( _contextLineCap !== value ) {
  6968. _context.lineCap = value;
  6969. _contextLineCap = value;
  6970. }
  6971. }
  6972. function setLineJoin( value ) {
  6973. // "round", "bevel", "miter"
  6974. if ( _contextLineJoin !== value ) {
  6975. _context.lineJoin = value;
  6976. _contextLineJoin = value;
  6977. }
  6978. }
  6979. function setStrokeStyle( value ) {
  6980. if ( _contextStrokeStyle !== value ) {
  6981. _context.strokeStyle = value;
  6982. _contextStrokeStyle = value;
  6983. }
  6984. }
  6985. function setFillStyle( value ) {
  6986. if ( _contextFillStyle !== value ) {
  6987. _context.fillStyle = value;
  6988. _contextFillStyle = value;
  6989. }
  6990. }
  6991. };
  6992. /**
  6993. * @author alteredq / http://alteredqualia.com/
  6994. * @author mrdoob / http://mrdoob.com/
  6995. * @author mikael emtinger / http://gomo.se/
  6996. */
  6997. THREE.ShaderChunk = {
  6998. // FOG
  6999. fog_pars_fragment: [
  7000. "#ifdef USE_FOG",
  7001. "uniform vec3 fogColor;",
  7002. "#ifdef FOG_EXP2",
  7003. "uniform float fogDensity;",
  7004. "#else",
  7005. "uniform float fogNear;",
  7006. "uniform float fogFar;",
  7007. "#endif",
  7008. "#endif"
  7009. ].join("\n"),
  7010. fog_fragment: [
  7011. "#ifdef USE_FOG",
  7012. "float depth = gl_FragCoord.z / gl_FragCoord.w;",
  7013. "#ifdef FOG_EXP2",
  7014. "const float LOG2 = 1.442695;",
  7015. "float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );",
  7016. "fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );",
  7017. "#else",
  7018. "float fogFactor = smoothstep( fogNear, fogFar, depth );",
  7019. "#endif",
  7020. "gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );",
  7021. "#endif"
  7022. ].join("\n"),
  7023. // ENVIRONMENT MAP
  7024. envmap_pars_fragment: [
  7025. "#ifdef USE_ENVMAP",
  7026. "varying vec3 vReflect;",
  7027. "uniform float reflectivity;",
  7028. "uniform samplerCube envMap;",
  7029. "uniform float flipEnvMap;",
  7030. "uniform int combine;",
  7031. "#endif"
  7032. ].join("\n"),
  7033. envmap_fragment: [
  7034. "#ifdef USE_ENVMAP",
  7035. "#ifdef DOUBLE_SIDED",
  7036. "float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
  7037. "vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * vReflect.x, vReflect.yz ) );",
  7038. "#else",
  7039. "vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * vReflect.x, vReflect.yz ) );",
  7040. "#endif",
  7041. "#ifdef GAMMA_INPUT",
  7042. "cubeColor.xyz *= cubeColor.xyz;",
  7043. "#endif",
  7044. "if ( combine == 1 ) {",
  7045. "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, reflectivity );",
  7046. "} else {",
  7047. "gl_FragColor.xyz = gl_FragColor.xyz * cubeColor.xyz;",
  7048. "}",
  7049. "#endif"
  7050. ].join("\n"),
  7051. envmap_pars_vertex: [
  7052. "#ifdef USE_ENVMAP",
  7053. "varying vec3 vReflect;",
  7054. "uniform float refractionRatio;",
  7055. "uniform bool useRefract;",
  7056. "#endif"
  7057. ].join("\n"),
  7058. envmap_vertex : [
  7059. "#ifdef USE_ENVMAP",
  7060. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  7061. "vec3 nWorld = mat3( objectMatrix[ 0 ].xyz, objectMatrix[ 1 ].xyz, objectMatrix[ 2 ].xyz ) * normal;",
  7062. "if ( useRefract ) {",
  7063. "vReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refractionRatio );",
  7064. "} else {",
  7065. "vReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );",
  7066. "}",
  7067. "#endif"
  7068. ].join("\n"),
  7069. // COLOR MAP (particles)
  7070. map_particle_pars_fragment: [
  7071. "#ifdef USE_MAP",
  7072. "uniform sampler2D map;",
  7073. "#endif"
  7074. ].join("\n"),
  7075. map_particle_fragment: [
  7076. "#ifdef USE_MAP",
  7077. "gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );",
  7078. "#endif"
  7079. ].join("\n"),
  7080. // COLOR MAP (triangles)
  7081. map_pars_vertex: [
  7082. "#ifdef USE_MAP",
  7083. "varying vec2 vUv;",
  7084. "uniform vec4 offsetRepeat;",
  7085. "#endif"
  7086. ].join("\n"),
  7087. map_pars_fragment: [
  7088. "#ifdef USE_MAP",
  7089. "varying vec2 vUv;",
  7090. "uniform sampler2D map;",
  7091. "#endif"
  7092. ].join("\n"),
  7093. map_vertex: [
  7094. "#ifdef USE_MAP",
  7095. "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
  7096. "#endif"
  7097. ].join("\n"),
  7098. map_fragment: [
  7099. "#ifdef USE_MAP",
  7100. "#ifdef GAMMA_INPUT",
  7101. "vec4 texelColor = texture2D( map, vUv );",
  7102. "texelColor.xyz *= texelColor.xyz;",
  7103. "gl_FragColor = gl_FragColor * texelColor;",
  7104. "#else",
  7105. "gl_FragColor = gl_FragColor * texture2D( map, vUv );",
  7106. "#endif",
  7107. "#endif"
  7108. ].join("\n"),
  7109. // LIGHT MAP
  7110. lightmap_pars_fragment: [
  7111. "#ifdef USE_LIGHTMAP",
  7112. "varying vec2 vUv2;",
  7113. "uniform sampler2D lightMap;",
  7114. "#endif"
  7115. ].join("\n"),
  7116. lightmap_pars_vertex: [
  7117. "#ifdef USE_LIGHTMAP",
  7118. "varying vec2 vUv2;",
  7119. "#endif"
  7120. ].join("\n"),
  7121. lightmap_fragment: [
  7122. "#ifdef USE_LIGHTMAP",
  7123. "gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );",
  7124. "#endif"
  7125. ].join("\n"),
  7126. lightmap_vertex: [
  7127. "#ifdef USE_LIGHTMAP",
  7128. "vUv2 = uv2;",
  7129. "#endif"
  7130. ].join("\n"),
  7131. // LIGHTS LAMBERT
  7132. lights_lambert_pars_vertex: [
  7133. "uniform vec3 ambient;",
  7134. "uniform vec3 diffuse;",
  7135. "uniform vec3 emissive;",
  7136. "uniform vec3 ambientLightColor;",
  7137. "#if MAX_DIR_LIGHTS > 0",
  7138. "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
  7139. "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
  7140. "#endif",
  7141. "#if MAX_POINT_LIGHTS > 0",
  7142. "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
  7143. "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
  7144. "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
  7145. "#endif",
  7146. "#if MAX_SPOT_LIGHTS > 0",
  7147. "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
  7148. "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
  7149. "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
  7150. "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
  7151. "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
  7152. "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
  7153. "#endif",
  7154. "#ifdef WRAP_AROUND",
  7155. "uniform vec3 wrapRGB;",
  7156. "#endif"
  7157. ].join("\n"),
  7158. lights_lambert_vertex: [
  7159. "vLightFront = vec3( 0.0 );",
  7160. "#ifdef DOUBLE_SIDED",
  7161. "vLightBack = vec3( 0.0 );",
  7162. "#endif",
  7163. "transformedNormal = normalize( transformedNormal );",
  7164. "#if MAX_DIR_LIGHTS > 0",
  7165. "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
  7166. "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
  7167. "vec3 dirVector = normalize( lDirection.xyz );",
  7168. "float dotProduct = dot( transformedNormal, dirVector );",
  7169. "vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );",
  7170. "#ifdef DOUBLE_SIDED",
  7171. "vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
  7172. "#ifdef WRAP_AROUND",
  7173. "vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
  7174. "#endif",
  7175. "#endif",
  7176. "#ifdef WRAP_AROUND",
  7177. "vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
  7178. "directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );",
  7179. "#ifdef DOUBLE_SIDED",
  7180. "directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );",
  7181. "#endif",
  7182. "#endif",
  7183. "vLightFront += directionalLightColor[ i ] * directionalLightWeighting;",
  7184. "#ifdef DOUBLE_SIDED",
  7185. "vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;",
  7186. "#endif",
  7187. "}",
  7188. "#endif",
  7189. "#if MAX_POINT_LIGHTS > 0",
  7190. "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
  7191. "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
  7192. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  7193. "float lDistance = 1.0;",
  7194. "if ( pointLightDistance[ i ] > 0.0 )",
  7195. "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
  7196. "lVector = normalize( lVector );",
  7197. "float dotProduct = dot( transformedNormal, lVector );",
  7198. "vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );",
  7199. "#ifdef DOUBLE_SIDED",
  7200. "vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
  7201. "#ifdef WRAP_AROUND",
  7202. "vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
  7203. "#endif",
  7204. "#endif",
  7205. "#ifdef WRAP_AROUND",
  7206. "vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
  7207. "pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );",
  7208. "#ifdef DOUBLE_SIDED",
  7209. "pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );",
  7210. "#endif",
  7211. "#endif",
  7212. "vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;",
  7213. "#ifdef DOUBLE_SIDED",
  7214. "vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;",
  7215. "#endif",
  7216. "}",
  7217. "#endif",
  7218. "#if MAX_SPOT_LIGHTS > 0",
  7219. "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
  7220. "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
  7221. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  7222. "lVector = normalize( lVector );",
  7223. "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );",
  7224. "if ( spotEffect > spotLightAngle[ i ] ) {",
  7225. "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
  7226. "float lDistance = 1.0;",
  7227. "if ( spotLightDistance[ i ] > 0.0 )",
  7228. "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
  7229. "float dotProduct = dot( transformedNormal, lVector );",
  7230. "vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );",
  7231. "#ifdef DOUBLE_SIDED",
  7232. "vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
  7233. "#ifdef WRAP_AROUND",
  7234. "vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
  7235. "#endif",
  7236. "#endif",
  7237. "#ifdef WRAP_AROUND",
  7238. "vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
  7239. "spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );",
  7240. "#ifdef DOUBLE_SIDED",
  7241. "spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );",
  7242. "#endif",
  7243. "#endif",
  7244. "vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;",
  7245. "#ifdef DOUBLE_SIDED",
  7246. "vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;",
  7247. "#endif",
  7248. "}",
  7249. "}",
  7250. "#endif",
  7251. "vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;",
  7252. "#ifdef DOUBLE_SIDED",
  7253. "vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;",
  7254. "#endif"
  7255. ].join("\n"),
  7256. // LIGHTS PHONG
  7257. lights_phong_pars_vertex: [
  7258. "#ifndef PHONG_PER_PIXEL",
  7259. "#if MAX_POINT_LIGHTS > 0",
  7260. "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
  7261. "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
  7262. "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
  7263. "#endif",
  7264. "#if MAX_SPOT_LIGHTS > 0",
  7265. "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
  7266. "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
  7267. "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
  7268. "#endif",
  7269. "#endif",
  7270. "#if MAX_SPOT_LIGHTS > 0",
  7271. "varying vec3 vWorldPosition;",
  7272. "#endif"
  7273. ].join("\n"),
  7274. lights_phong_vertex: [
  7275. "#ifndef PHONG_PER_PIXEL",
  7276. "#if MAX_POINT_LIGHTS > 0",
  7277. "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
  7278. "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
  7279. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  7280. "float lDistance = 1.0;",
  7281. "if ( pointLightDistance[ i ] > 0.0 )",
  7282. "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
  7283. "vPointLight[ i ] = vec4( lVector, lDistance );",
  7284. "}",
  7285. "#endif",
  7286. "#if MAX_SPOT_LIGHTS > 0",
  7287. "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
  7288. "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
  7289. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  7290. "float lDistance = 1.0;",
  7291. "if ( spotLightDistance[ i ] > 0.0 )",
  7292. "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
  7293. "vSpotLight[ i ] = vec4( lVector, lDistance );",
  7294. "}",
  7295. "#endif",
  7296. "#endif",
  7297. "#if MAX_SPOT_LIGHTS > 0",
  7298. "vWorldPosition = mPosition.xyz;",
  7299. "#endif"
  7300. ].join("\n"),
  7301. lights_phong_pars_fragment: [
  7302. "uniform vec3 ambientLightColor;",
  7303. "#if MAX_DIR_LIGHTS > 0",
  7304. "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
  7305. "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
  7306. "#endif",
  7307. "#if MAX_POINT_LIGHTS > 0",
  7308. "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
  7309. "#ifdef PHONG_PER_PIXEL",
  7310. "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
  7311. "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
  7312. "#else",
  7313. "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
  7314. "#endif",
  7315. "#endif",
  7316. "#if MAX_SPOT_LIGHTS > 0",
  7317. "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
  7318. "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
  7319. "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
  7320. "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
  7321. "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
  7322. "#ifdef PHONG_PER_PIXEL",
  7323. "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
  7324. "#else",
  7325. "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
  7326. "#endif",
  7327. "varying vec3 vWorldPosition;",
  7328. "#endif",
  7329. "#ifdef WRAP_AROUND",
  7330. "uniform vec3 wrapRGB;",
  7331. "#endif",
  7332. "varying vec3 vViewPosition;",
  7333. "varying vec3 vNormal;"
  7334. ].join("\n"),
  7335. lights_phong_fragment: [
  7336. "vec3 normal = normalize( vNormal );",
  7337. "vec3 viewPosition = normalize( vViewPosition );",
  7338. "#ifdef DOUBLE_SIDED",
  7339. "normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
  7340. "#endif",
  7341. "#if MAX_POINT_LIGHTS > 0",
  7342. "vec3 pointDiffuse = vec3( 0.0 );",
  7343. "vec3 pointSpecular = vec3( 0.0 );",
  7344. "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
  7345. "#ifdef PHONG_PER_PIXEL",
  7346. "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
  7347. "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
  7348. "float lDistance = 1.0;",
  7349. "if ( pointLightDistance[ i ] > 0.0 )",
  7350. "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
  7351. "lVector = normalize( lVector );",
  7352. "#else",
  7353. "vec3 lVector = normalize( vPointLight[ i ].xyz );",
  7354. "float lDistance = vPointLight[ i ].w;",
  7355. "#endif",
  7356. // diffuse
  7357. "float dotProduct = dot( normal, lVector );",
  7358. "#ifdef WRAP_AROUND",
  7359. "float pointDiffuseWeightFull = max( dotProduct, 0.0 );",
  7360. "float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
  7361. "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
  7362. "#else",
  7363. "float pointDiffuseWeight = max( dotProduct, 0.0 );",
  7364. "#endif",
  7365. "pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;",
  7366. // specular
  7367. "vec3 pointHalfVector = normalize( lVector + viewPosition );",
  7368. "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
  7369. "float pointSpecularWeight = max( pow( pointDotNormalHalf, shininess ), 0.0 );",
  7370. "#ifdef PHYSICALLY_BASED_SHADING",
  7371. // 2.0 => 2.0001 is hack to work around ANGLE bug
  7372. "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
  7373. "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );",
  7374. "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;",
  7375. "#else",
  7376. "pointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;",
  7377. "#endif",
  7378. "}",
  7379. "#endif",
  7380. "#if MAX_SPOT_LIGHTS > 0",
  7381. "vec3 spotDiffuse = vec3( 0.0 );",
  7382. "vec3 spotSpecular = vec3( 0.0 );",
  7383. "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
  7384. "#ifdef PHONG_PER_PIXEL",
  7385. "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
  7386. "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
  7387. "float lDistance = 1.0;",
  7388. "if ( spotLightDistance[ i ] > 0.0 )",
  7389. "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
  7390. "lVector = normalize( lVector );",
  7391. "#else",
  7392. "vec3 lVector = normalize( vSpotLight[ i ].xyz );",
  7393. "float lDistance = vSpotLight[ i ].w;",
  7394. "#endif",
  7395. "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
  7396. "if ( spotEffect > spotLightAngle[ i ] ) {",
  7397. "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
  7398. // diffuse
  7399. "float dotProduct = dot( normal, lVector );",
  7400. "#ifdef WRAP_AROUND",
  7401. "float spotDiffuseWeightFull = max( dotProduct, 0.0 );",
  7402. "float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
  7403. "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
  7404. "#else",
  7405. "float spotDiffuseWeight = max( dotProduct, 0.0 );",
  7406. "#endif",
  7407. "spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;",
  7408. // specular
  7409. "vec3 spotHalfVector = normalize( lVector + viewPosition );",
  7410. "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
  7411. "float spotSpecularWeight = max( pow( spotDotNormalHalf, shininess ), 0.0 );",
  7412. "#ifdef PHYSICALLY_BASED_SHADING",
  7413. // 2.0 => 2.0001 is hack to work around ANGLE bug
  7414. "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
  7415. "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );",
  7416. "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;",
  7417. "#else",
  7418. "spotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;",
  7419. "#endif",
  7420. "}",
  7421. "}",
  7422. "#endif",
  7423. "#if MAX_DIR_LIGHTS > 0",
  7424. "vec3 dirDiffuse = vec3( 0.0 );",
  7425. "vec3 dirSpecular = vec3( 0.0 );" ,
  7426. "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
  7427. "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
  7428. "vec3 dirVector = normalize( lDirection.xyz );",
  7429. // diffuse
  7430. "float dotProduct = dot( normal, dirVector );",
  7431. "#ifdef WRAP_AROUND",
  7432. "float dirDiffuseWeightFull = max( dotProduct, 0.0 );",
  7433. "float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
  7434. "vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );",
  7435. "#else",
  7436. "float dirDiffuseWeight = max( dotProduct, 0.0 );",
  7437. "#endif",
  7438. "dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;",
  7439. // specular
  7440. "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
  7441. "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
  7442. "float dirSpecularWeight = max( pow( dirDotNormalHalf, shininess ), 0.0 );",
  7443. "#ifdef PHYSICALLY_BASED_SHADING",
  7444. /*
  7445. // fresnel term from skin shader
  7446. "const float F0 = 0.128;",
  7447. "float base = 1.0 - dot( viewPosition, dirHalfVector );",
  7448. "float exponential = pow( base, 5.0 );",
  7449. "float fresnel = exponential + F0 * ( 1.0 - exponential );",
  7450. */
  7451. /*
  7452. // fresnel term from fresnel shader
  7453. "const float mFresnelBias = 0.08;",
  7454. "const float mFresnelScale = 0.3;",
  7455. "const float mFresnelPower = 5.0;",
  7456. "float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );",
  7457. */
  7458. // 2.0 => 2.0001 is hack to work around ANGLE bug
  7459. "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
  7460. //"dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;",
  7461. "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
  7462. "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
  7463. "#else",
  7464. "dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;",
  7465. "#endif",
  7466. "}",
  7467. "#endif",
  7468. "vec3 totalDiffuse = vec3( 0.0 );",
  7469. "vec3 totalSpecular = vec3( 0.0 );",
  7470. "#if MAX_DIR_LIGHTS > 0",
  7471. "totalDiffuse += dirDiffuse;",
  7472. "totalSpecular += dirSpecular;",
  7473. "#endif",
  7474. "#if MAX_POINT_LIGHTS > 0",
  7475. "totalDiffuse += pointDiffuse;",
  7476. "totalSpecular += pointSpecular;",
  7477. "#endif",
  7478. "#if MAX_SPOT_LIGHTS > 0",
  7479. "totalDiffuse += spotDiffuse;",
  7480. "totalSpecular += spotSpecular;",
  7481. "#endif",
  7482. "#ifdef METAL",
  7483. "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );",
  7484. "#else",
  7485. "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;",
  7486. "#endif"
  7487. ].join("\n"),
  7488. // VERTEX COLORS
  7489. color_pars_fragment: [
  7490. "#ifdef USE_COLOR",
  7491. "varying vec3 vColor;",
  7492. "#endif"
  7493. ].join("\n"),
  7494. color_fragment: [
  7495. "#ifdef USE_COLOR",
  7496. "gl_FragColor = gl_FragColor * vec4( vColor, opacity );",
  7497. "#endif"
  7498. ].join("\n"),
  7499. color_pars_vertex: [
  7500. "#ifdef USE_COLOR",
  7501. "varying vec3 vColor;",
  7502. "#endif"
  7503. ].join("\n"),
  7504. color_vertex: [
  7505. "#ifdef USE_COLOR",
  7506. "#ifdef GAMMA_INPUT",
  7507. "vColor = color * color;",
  7508. "#else",
  7509. "vColor = color;",
  7510. "#endif",
  7511. "#endif"
  7512. ].join("\n"),
  7513. // SKINNING
  7514. skinning_pars_vertex: [
  7515. "#ifdef USE_SKINNING",
  7516. "#ifdef BONE_TEXTURE",
  7517. "uniform sampler2D boneTexture;",
  7518. "mat4 getBoneMatrix( const in float i ) {",
  7519. "float j = i * 4.0;",
  7520. "float x = mod( j, N_BONE_PIXEL_X );",
  7521. "float y = floor( j / N_BONE_PIXEL_X );",
  7522. "const float dx = 1.0 / N_BONE_PIXEL_X;",
  7523. "const float dy = 1.0 / N_BONE_PIXEL_Y;",
  7524. "y = dy * ( y + 0.5 );",
  7525. "vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );",
  7526. "vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );",
  7527. "vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );",
  7528. "vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );",
  7529. "mat4 bone = mat4( v1, v2, v3, v4 );",
  7530. "return bone;",
  7531. "}",
  7532. "#else",
  7533. "uniform mat4 boneGlobalMatrices[ MAX_BONES ];",
  7534. "mat4 getBoneMatrix( const in float i ) {",
  7535. "mat4 bone = boneGlobalMatrices[ int(i) ];",
  7536. "return bone;",
  7537. "}",
  7538. "#endif",
  7539. "#endif"
  7540. ].join("\n"),
  7541. skinbase_vertex: [
  7542. "#ifdef USE_SKINNING",
  7543. "mat4 boneMatX = getBoneMatrix( skinIndex.x );",
  7544. "mat4 boneMatY = getBoneMatrix( skinIndex.y );",
  7545. "#endif"
  7546. ].join("\n"),
  7547. skinning_vertex: [
  7548. "#ifdef USE_SKINNING",
  7549. "vec4 skinned = boneMatX * skinVertexA * skinWeight.x;",
  7550. "skinned += boneMatY * skinVertexB * skinWeight.y;",
  7551. "gl_Position = projectionMatrix * modelViewMatrix * skinned;",
  7552. "#endif"
  7553. ].join("\n"),
  7554. // MORPHING
  7555. morphtarget_pars_vertex: [
  7556. "#ifdef USE_MORPHTARGETS",
  7557. "#ifndef USE_MORPHNORMALS",
  7558. "uniform float morphTargetInfluences[ 8 ];",
  7559. "#else",
  7560. "uniform float morphTargetInfluences[ 4 ];",
  7561. "#endif",
  7562. "#endif"
  7563. ].join("\n"),
  7564. morphtarget_vertex: [
  7565. "#ifdef USE_MORPHTARGETS",
  7566. "vec3 morphed = vec3( 0.0 );",
  7567. "morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];",
  7568. "morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];",
  7569. "morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];",
  7570. "morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];",
  7571. "#ifndef USE_MORPHNORMALS",
  7572. "morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];",
  7573. "morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];",
  7574. "morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];",
  7575. "morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];",
  7576. "#endif",
  7577. "morphed += position;",
  7578. "gl_Position = projectionMatrix * modelViewMatrix * vec4( morphed, 1.0 );",
  7579. "#endif"
  7580. ].join("\n"),
  7581. default_vertex : [
  7582. "#ifndef USE_MORPHTARGETS",
  7583. "#ifndef USE_SKINNING",
  7584. "gl_Position = projectionMatrix * mvPosition;",
  7585. "#endif",
  7586. "#endif"
  7587. ].join("\n"),
  7588. morphnormal_vertex: [
  7589. "#ifdef USE_MORPHNORMALS",
  7590. "vec3 morphedNormal = vec3( 0.0 );",
  7591. "morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];",
  7592. "morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];",
  7593. "morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];",
  7594. "morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];",
  7595. "morphedNormal += normal;",
  7596. "vec3 transformedNormal = normalMatrix * morphedNormal;",
  7597. "#else",
  7598. "vec3 transformedNormal = normalMatrix * normal;",
  7599. "#endif"
  7600. ].join("\n"),
  7601. skinnormal_vertex: [
  7602. "#ifdef USE_SKINNING",
  7603. "mat4 skinMatrix = skinWeight.x * boneMatX;",
  7604. "skinMatrix += skinWeight.y * boneMatY;",
  7605. "vec4 skinnedNormal = skinMatrix * vec4( transformedNormal, 0.0 );",
  7606. "transformedNormal = skinnedNormal.xyz;",
  7607. "#endif"
  7608. ].join("\n"),
  7609. // SHADOW MAP
  7610. // based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
  7611. // http://spidergl.org/example.php?id=6
  7612. // http://fabiensanglard.net/shadowmapping
  7613. shadowmap_pars_fragment: [
  7614. "#ifdef USE_SHADOWMAP",
  7615. "uniform sampler2D shadowMap[ MAX_SHADOWS ];",
  7616. "uniform vec2 shadowMapSize[ MAX_SHADOWS ];",
  7617. "uniform float shadowDarkness[ MAX_SHADOWS ];",
  7618. "uniform float shadowBias[ MAX_SHADOWS ];",
  7619. "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
  7620. "float unpackDepth( const in vec4 rgba_depth ) {",
  7621. "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
  7622. "float depth = dot( rgba_depth, bit_shift );",
  7623. "return depth;",
  7624. "}",
  7625. "#endif"
  7626. ].join("\n"),
  7627. shadowmap_fragment: [
  7628. "#ifdef USE_SHADOWMAP",
  7629. "#ifdef SHADOWMAP_DEBUG",
  7630. "vec3 frustumColors[3];",
  7631. "frustumColors[0] = vec3( 1.0, 0.5, 0.0 );",
  7632. "frustumColors[1] = vec3( 0.0, 1.0, 0.8 );",
  7633. "frustumColors[2] = vec3( 0.0, 0.5, 1.0 );",
  7634. "#endif",
  7635. "#ifdef SHADOWMAP_CASCADE",
  7636. "int inFrustumCount = 0;",
  7637. "#endif",
  7638. "float fDepth;",
  7639. "vec3 shadowColor = vec3( 1.0 );",
  7640. "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
  7641. "vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
  7642. // "if ( something && something )" breaks ATI OpenGL shader compiler
  7643. // "if ( all( something, something ) )" using this instead
  7644. "bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
  7645. "bool inFrustum = all( inFrustumVec );",
  7646. // don't shadow pixels outside of light frustum
  7647. // use just first frustum (for cascades)
  7648. // don't shadow pixels behind far plane of light frustum
  7649. "#ifdef SHADOWMAP_CASCADE",
  7650. "inFrustumCount += int( inFrustum );",
  7651. "bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );",
  7652. "#else",
  7653. "bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );",
  7654. "#endif",
  7655. "bool frustumTest = all( frustumTestVec );",
  7656. "if ( frustumTest ) {",
  7657. "shadowCoord.z += shadowBias[ i ];",
  7658. "#ifdef SHADOWMAP_SOFT",
  7659. // Percentage-close filtering
  7660. // (9 pixel kernel)
  7661. // http://fabiensanglard.net/shadowmappingPCF/
  7662. "float shadow = 0.0;",
  7663. /*
  7664. // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
  7665. // must enroll loop manually
  7666. "for ( float y = -1.25; y <= 1.25; y += 1.25 )",
  7667. "for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
  7668. "vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
  7669. // doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
  7670. //"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
  7671. "float fDepth = unpackDepth( rgbaDepth );",
  7672. "if ( fDepth < shadowCoord.z )",
  7673. "shadow += 1.0;",
  7674. "}",
  7675. "shadow /= 9.0;",
  7676. */
  7677. "const float shadowDelta = 1.0 / 9.0;",
  7678. "float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
  7679. "float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
  7680. "float dx0 = -1.25 * xPixelOffset;",
  7681. "float dy0 = -1.25 * yPixelOffset;",
  7682. "float dx1 = 1.25 * xPixelOffset;",
  7683. "float dy1 = 1.25 * yPixelOffset;",
  7684. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
  7685. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7686. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
  7687. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7688. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
  7689. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7690. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
  7691. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7692. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
  7693. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7694. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
  7695. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7696. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
  7697. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7698. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
  7699. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7700. "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
  7701. "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
  7702. "shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
  7703. "#else",
  7704. "vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
  7705. "float fDepth = unpackDepth( rgbaDepth );",
  7706. "if ( fDepth < shadowCoord.z )",
  7707. // spot with multiple shadows is darker
  7708. "shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
  7709. // spot with multiple shadows has the same color as single shadow spot
  7710. //"shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
  7711. "#endif",
  7712. "}",
  7713. "#ifdef SHADOWMAP_DEBUG",
  7714. "#ifdef SHADOWMAP_CASCADE",
  7715. "if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];",
  7716. "#else",
  7717. "if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];",
  7718. "#endif",
  7719. "#endif",
  7720. "}",
  7721. "#ifdef GAMMA_OUTPUT",
  7722. "shadowColor *= shadowColor;",
  7723. "#endif",
  7724. "gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;",
  7725. "#endif"
  7726. ].join("\n"),
  7727. shadowmap_pars_vertex: [
  7728. "#ifdef USE_SHADOWMAP",
  7729. "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
  7730. "uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
  7731. "#endif"
  7732. ].join("\n"),
  7733. shadowmap_vertex: [
  7734. "#ifdef USE_SHADOWMAP",
  7735. "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
  7736. "#ifdef USE_MORPHTARGETS",
  7737. "vShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( morphed, 1.0 );",
  7738. "#else",
  7739. "#ifdef USE_SKINNING",
  7740. "vShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * skinned;",
  7741. "#else",
  7742. "vShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );",
  7743. "#endif",
  7744. "#endif",
  7745. "}",
  7746. "#endif"
  7747. ].join("\n"),
  7748. // ALPHATEST
  7749. alphatest_fragment: [
  7750. "#ifdef ALPHATEST",
  7751. "if ( gl_FragColor.a < ALPHATEST ) discard;",
  7752. "#endif"
  7753. ].join("\n"),
  7754. // LINEAR SPACE
  7755. linear_to_gamma_fragment: [
  7756. "#ifdef GAMMA_OUTPUT",
  7757. "gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
  7758. "#endif"
  7759. ].join("\n"),
  7760. };
  7761. THREE.UniformsUtils = {
  7762. merge: function ( uniforms ) {
  7763. var u, p, tmp, merged = {};
  7764. for ( u = 0; u < uniforms.length; u++ ) {
  7765. tmp = this.clone( uniforms[ u ] );
  7766. for ( p in tmp ) {
  7767. merged[ p ] = tmp[ p ];
  7768. }
  7769. }
  7770. return merged;
  7771. },
  7772. clone: function ( uniforms_src ) {
  7773. var u, p, parameter, parameter_src, uniforms_dst = {};
  7774. for ( u in uniforms_src ) {
  7775. uniforms_dst[ u ] = {};
  7776. for ( p in uniforms_src[ u ] ) {
  7777. parameter_src = uniforms_src[ u ][ p ];
  7778. if ( parameter_src instanceof THREE.Color ||
  7779. parameter_src instanceof THREE.Vector2 ||
  7780. parameter_src instanceof THREE.Vector3 ||
  7781. parameter_src instanceof THREE.Vector4 ||
  7782. parameter_src instanceof THREE.Matrix4 ||
  7783. parameter_src instanceof THREE.Texture ) {
  7784. uniforms_dst[ u ][ p ] = parameter_src.clone();
  7785. } else if ( parameter_src instanceof Array ) {
  7786. uniforms_dst[ u ][ p ] = parameter_src.slice();
  7787. } else {
  7788. uniforms_dst[ u ][ p ] = parameter_src;
  7789. }
  7790. }
  7791. }
  7792. return uniforms_dst;
  7793. }
  7794. };
  7795. THREE.UniformsLib = {
  7796. common: {
  7797. "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
  7798. "opacity" : { type: "f", value: 1.0 },
  7799. "map" : { type: "t", value: 0, texture: null },
  7800. "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
  7801. "lightMap" : { type: "t", value: 2, texture: null },
  7802. "envMap" : { type: "t", value: 1, texture: null },
  7803. "flipEnvMap" : { type: "f", value: -1 },
  7804. "useRefract" : { type: "i", value: 0 },
  7805. "reflectivity" : { type: "f", value: 1.0 },
  7806. "refractionRatio" : { type: "f", value: 0.98 },
  7807. "combine" : { type: "i", value: 0 },
  7808. "morphTargetInfluences" : { type: "f", value: 0 }
  7809. },
  7810. fog : {
  7811. "fogDensity" : { type: "f", value: 0.00025 },
  7812. "fogNear" : { type: "f", value: 1 },
  7813. "fogFar" : { type: "f", value: 2000 },
  7814. "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
  7815. },
  7816. lights: {
  7817. "ambientLightColor" : { type: "fv", value: [] },
  7818. "directionalLightDirection" : { type: "fv", value: [] },
  7819. "directionalLightColor" : { type: "fv", value: [] },
  7820. "pointLightColor" : { type: "fv", value: [] },
  7821. "pointLightPosition" : { type: "fv", value: [] },
  7822. "pointLightDistance" : { type: "fv1", value: [] },
  7823. "spotLightColor" : { type: "fv", value: [] },
  7824. "spotLightPosition" : { type: "fv", value: [] },
  7825. "spotLightDirection" : { type: "fv", value: [] },
  7826. "spotLightDistance" : { type: "fv1", value: [] },
  7827. "spotLightAngle" : { type: "fv1", value: [] },
  7828. "spotLightExponent" : { type: "fv1", value: [] }
  7829. },
  7830. particle: {
  7831. "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
  7832. "opacity" : { type: "f", value: 1.0 },
  7833. "size" : { type: "f", value: 1.0 },
  7834. "scale" : { type: "f", value: 1.0 },
  7835. "map" : { type: "t", value: 0, texture: null },
  7836. "fogDensity" : { type: "f", value: 0.00025 },
  7837. "fogNear" : { type: "f", value: 1 },
  7838. "fogFar" : { type: "f", value: 2000 },
  7839. "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
  7840. },
  7841. shadowmap: {
  7842. "shadowMap": { type: "tv", value: 6, texture: [] },
  7843. "shadowMapSize": { type: "v2v", value: [] },
  7844. "shadowBias" : { type: "fv1", value: [] },
  7845. "shadowDarkness": { type: "fv1", value: [] },
  7846. "shadowMatrix" : { type: "m4v", value: [] },
  7847. }
  7848. };
  7849. THREE.ShaderLib = {
  7850. 'depth': {
  7851. uniforms: {
  7852. "mNear": { type: "f", value: 1.0 },
  7853. "mFar" : { type: "f", value: 2000.0 },
  7854. "opacity" : { type: "f", value: 1.0 }
  7855. },
  7856. vertexShader: [
  7857. "void main() {",
  7858. "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
  7859. "}"
  7860. ].join("\n"),
  7861. fragmentShader: [
  7862. "uniform float mNear;",
  7863. "uniform float mFar;",
  7864. "uniform float opacity;",
  7865. "void main() {",
  7866. "float depth = gl_FragCoord.z / gl_FragCoord.w;",
  7867. "float color = 1.0 - smoothstep( mNear, mFar, depth );",
  7868. "gl_FragColor = vec4( vec3( color ), opacity );",
  7869. "}"
  7870. ].join("\n")
  7871. },
  7872. 'normal': {
  7873. uniforms: {
  7874. "opacity" : { type: "f", value: 1.0 }
  7875. },
  7876. vertexShader: [
  7877. "varying vec3 vNormal;",
  7878. "void main() {",
  7879. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  7880. "vNormal = normalMatrix * normal;",
  7881. "gl_Position = projectionMatrix * mvPosition;",
  7882. "}"
  7883. ].join("\n"),
  7884. fragmentShader: [
  7885. "uniform float opacity;",
  7886. "varying vec3 vNormal;",
  7887. "void main() {",
  7888. "gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
  7889. "}"
  7890. ].join("\n")
  7891. },
  7892. 'basic': {
  7893. uniforms: THREE.UniformsUtils.merge( [
  7894. THREE.UniformsLib[ "common" ],
  7895. THREE.UniformsLib[ "fog" ],
  7896. THREE.UniformsLib[ "shadowmap" ]
  7897. ] ),
  7898. vertexShader: [
  7899. THREE.ShaderChunk[ "map_pars_vertex" ],
  7900. THREE.ShaderChunk[ "lightmap_pars_vertex" ],
  7901. THREE.ShaderChunk[ "envmap_pars_vertex" ],
  7902. THREE.ShaderChunk[ "color_pars_vertex" ],
  7903. THREE.ShaderChunk[ "skinning_pars_vertex" ],
  7904. THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
  7905. THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
  7906. "void main() {",
  7907. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  7908. THREE.ShaderChunk[ "map_vertex" ],
  7909. THREE.ShaderChunk[ "lightmap_vertex" ],
  7910. THREE.ShaderChunk[ "envmap_vertex" ],
  7911. THREE.ShaderChunk[ "color_vertex" ],
  7912. THREE.ShaderChunk[ "skinbase_vertex" ],
  7913. THREE.ShaderChunk[ "skinning_vertex" ],
  7914. THREE.ShaderChunk[ "morphtarget_vertex" ],
  7915. THREE.ShaderChunk[ "default_vertex" ],
  7916. THREE.ShaderChunk[ "shadowmap_vertex" ],
  7917. "}"
  7918. ].join("\n"),
  7919. fragmentShader: [
  7920. "uniform vec3 diffuse;",
  7921. "uniform float opacity;",
  7922. THREE.ShaderChunk[ "color_pars_fragment" ],
  7923. THREE.ShaderChunk[ "map_pars_fragment" ],
  7924. THREE.ShaderChunk[ "lightmap_pars_fragment" ],
  7925. THREE.ShaderChunk[ "envmap_pars_fragment" ],
  7926. THREE.ShaderChunk[ "fog_pars_fragment" ],
  7927. THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
  7928. "void main() {",
  7929. "gl_FragColor = vec4( diffuse, opacity );",
  7930. THREE.ShaderChunk[ "map_fragment" ],
  7931. THREE.ShaderChunk[ "alphatest_fragment" ],
  7932. THREE.ShaderChunk[ "lightmap_fragment" ],
  7933. THREE.ShaderChunk[ "color_fragment" ],
  7934. THREE.ShaderChunk[ "envmap_fragment" ],
  7935. THREE.ShaderChunk[ "shadowmap_fragment" ],
  7936. THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
  7937. THREE.ShaderChunk[ "fog_fragment" ],
  7938. "}"
  7939. ].join("\n")
  7940. },
  7941. 'lambert': {
  7942. uniforms: THREE.UniformsUtils.merge( [
  7943. THREE.UniformsLib[ "common" ],
  7944. THREE.UniformsLib[ "fog" ],
  7945. THREE.UniformsLib[ "lights" ],
  7946. THREE.UniformsLib[ "shadowmap" ],
  7947. {
  7948. "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
  7949. "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
  7950. "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
  7951. }
  7952. ] ),
  7953. vertexShader: [
  7954. "varying vec3 vLightFront;",
  7955. "#ifdef DOUBLE_SIDED",
  7956. "varying vec3 vLightBack;",
  7957. "#endif",
  7958. THREE.ShaderChunk[ "map_pars_vertex" ],
  7959. THREE.ShaderChunk[ "lightmap_pars_vertex" ],
  7960. THREE.ShaderChunk[ "envmap_pars_vertex" ],
  7961. THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
  7962. THREE.ShaderChunk[ "color_pars_vertex" ],
  7963. THREE.ShaderChunk[ "skinning_pars_vertex" ],
  7964. THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
  7965. THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
  7966. "void main() {",
  7967. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  7968. THREE.ShaderChunk[ "map_vertex" ],
  7969. THREE.ShaderChunk[ "lightmap_vertex" ],
  7970. THREE.ShaderChunk[ "envmap_vertex" ],
  7971. THREE.ShaderChunk[ "color_vertex" ],
  7972. THREE.ShaderChunk[ "morphnormal_vertex" ],
  7973. THREE.ShaderChunk[ "skinbase_vertex" ],
  7974. THREE.ShaderChunk[ "skinnormal_vertex" ],
  7975. "#ifndef USE_ENVMAP",
  7976. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  7977. "#endif",
  7978. THREE.ShaderChunk[ "lights_lambert_vertex" ],
  7979. THREE.ShaderChunk[ "skinning_vertex" ],
  7980. THREE.ShaderChunk[ "morphtarget_vertex" ],
  7981. THREE.ShaderChunk[ "default_vertex" ],
  7982. THREE.ShaderChunk[ "shadowmap_vertex" ],
  7983. "}"
  7984. ].join("\n"),
  7985. fragmentShader: [
  7986. "uniform float opacity;",
  7987. "varying vec3 vLightFront;",
  7988. "#ifdef DOUBLE_SIDED",
  7989. "varying vec3 vLightBack;",
  7990. "#endif",
  7991. THREE.ShaderChunk[ "color_pars_fragment" ],
  7992. THREE.ShaderChunk[ "map_pars_fragment" ],
  7993. THREE.ShaderChunk[ "lightmap_pars_fragment" ],
  7994. THREE.ShaderChunk[ "envmap_pars_fragment" ],
  7995. THREE.ShaderChunk[ "fog_pars_fragment" ],
  7996. THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
  7997. "void main() {",
  7998. "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
  7999. THREE.ShaderChunk[ "map_fragment" ],
  8000. THREE.ShaderChunk[ "alphatest_fragment" ],
  8001. "#ifdef DOUBLE_SIDED",
  8002. //"float isFront = float( gl_FrontFacing );",
  8003. //"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
  8004. "if ( gl_FrontFacing )",
  8005. "gl_FragColor.xyz *= vLightFront;",
  8006. "else",
  8007. "gl_FragColor.xyz *= vLightBack;",
  8008. "#else",
  8009. "gl_FragColor.xyz *= vLightFront;",
  8010. "#endif",
  8011. THREE.ShaderChunk[ "lightmap_fragment" ],
  8012. THREE.ShaderChunk[ "color_fragment" ],
  8013. THREE.ShaderChunk[ "envmap_fragment" ],
  8014. THREE.ShaderChunk[ "shadowmap_fragment" ],
  8015. THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
  8016. THREE.ShaderChunk[ "fog_fragment" ],
  8017. "}"
  8018. ].join("\n")
  8019. },
  8020. 'phong': {
  8021. uniforms: THREE.UniformsUtils.merge( [
  8022. THREE.UniformsLib[ "common" ],
  8023. THREE.UniformsLib[ "fog" ],
  8024. THREE.UniformsLib[ "lights" ],
  8025. THREE.UniformsLib[ "shadowmap" ],
  8026. {
  8027. "ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
  8028. "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
  8029. "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
  8030. "shininess": { type: "f", value: 30 },
  8031. "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
  8032. }
  8033. ] ),
  8034. vertexShader: [
  8035. "varying vec3 vViewPosition;",
  8036. "varying vec3 vNormal;",
  8037. THREE.ShaderChunk[ "map_pars_vertex" ],
  8038. THREE.ShaderChunk[ "lightmap_pars_vertex" ],
  8039. THREE.ShaderChunk[ "envmap_pars_vertex" ],
  8040. THREE.ShaderChunk[ "lights_phong_pars_vertex" ],
  8041. THREE.ShaderChunk[ "color_pars_vertex" ],
  8042. THREE.ShaderChunk[ "skinning_pars_vertex" ],
  8043. THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
  8044. THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
  8045. "void main() {",
  8046. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  8047. THREE.ShaderChunk[ "map_vertex" ],
  8048. THREE.ShaderChunk[ "lightmap_vertex" ],
  8049. THREE.ShaderChunk[ "envmap_vertex" ],
  8050. THREE.ShaderChunk[ "color_vertex" ],
  8051. "#ifndef USE_ENVMAP",
  8052. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  8053. "#endif",
  8054. "vViewPosition = -mvPosition.xyz;",
  8055. THREE.ShaderChunk[ "morphnormal_vertex" ],
  8056. THREE.ShaderChunk[ "skinbase_vertex" ],
  8057. THREE.ShaderChunk[ "skinnormal_vertex" ],
  8058. "vNormal = transformedNormal;",
  8059. THREE.ShaderChunk[ "lights_phong_vertex" ],
  8060. THREE.ShaderChunk[ "skinning_vertex" ],
  8061. THREE.ShaderChunk[ "morphtarget_vertex" ],
  8062. THREE.ShaderChunk[ "default_vertex" ],
  8063. THREE.ShaderChunk[ "shadowmap_vertex" ],
  8064. "}"
  8065. ].join("\n"),
  8066. fragmentShader: [
  8067. "uniform vec3 diffuse;",
  8068. "uniform float opacity;",
  8069. "uniform vec3 ambient;",
  8070. "uniform vec3 emissive;",
  8071. "uniform vec3 specular;",
  8072. "uniform float shininess;",
  8073. THREE.ShaderChunk[ "color_pars_fragment" ],
  8074. THREE.ShaderChunk[ "map_pars_fragment" ],
  8075. THREE.ShaderChunk[ "lightmap_pars_fragment" ],
  8076. THREE.ShaderChunk[ "envmap_pars_fragment" ],
  8077. THREE.ShaderChunk[ "fog_pars_fragment" ],
  8078. THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
  8079. THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
  8080. "void main() {",
  8081. "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
  8082. THREE.ShaderChunk[ "map_fragment" ],
  8083. THREE.ShaderChunk[ "alphatest_fragment" ],
  8084. THREE.ShaderChunk[ "lights_phong_fragment" ],
  8085. THREE.ShaderChunk[ "lightmap_fragment" ],
  8086. THREE.ShaderChunk[ "color_fragment" ],
  8087. THREE.ShaderChunk[ "envmap_fragment" ],
  8088. THREE.ShaderChunk[ "shadowmap_fragment" ],
  8089. THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
  8090. THREE.ShaderChunk[ "fog_fragment" ],
  8091. "}"
  8092. ].join("\n")
  8093. },
  8094. 'particle_basic': {
  8095. uniforms: THREE.UniformsUtils.merge( [
  8096. THREE.UniformsLib[ "particle" ],
  8097. THREE.UniformsLib[ "shadowmap" ]
  8098. ] ),
  8099. vertexShader: [
  8100. "uniform float size;",
  8101. "uniform float scale;",
  8102. THREE.ShaderChunk[ "color_pars_vertex" ],
  8103. THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
  8104. "void main() {",
  8105. THREE.ShaderChunk[ "color_vertex" ],
  8106. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  8107. "#ifdef USE_SIZEATTENUATION",
  8108. "gl_PointSize = size * ( scale / length( mvPosition.xyz ) );",
  8109. "#else",
  8110. "gl_PointSize = size;",
  8111. "#endif",
  8112. "gl_Position = projectionMatrix * mvPosition;",
  8113. THREE.ShaderChunk[ "shadowmap_vertex" ],
  8114. "}"
  8115. ].join("\n"),
  8116. fragmentShader: [
  8117. "uniform vec3 psColor;",
  8118. "uniform float opacity;",
  8119. THREE.ShaderChunk[ "color_pars_fragment" ],
  8120. THREE.ShaderChunk[ "map_particle_pars_fragment" ],
  8121. THREE.ShaderChunk[ "fog_pars_fragment" ],
  8122. THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
  8123. "void main() {",
  8124. "gl_FragColor = vec4( psColor, opacity );",
  8125. THREE.ShaderChunk[ "map_particle_fragment" ],
  8126. THREE.ShaderChunk[ "alphatest_fragment" ],
  8127. THREE.ShaderChunk[ "color_fragment" ],
  8128. THREE.ShaderChunk[ "shadowmap_fragment" ],
  8129. THREE.ShaderChunk[ "fog_fragment" ],
  8130. "}"
  8131. ].join("\n")
  8132. },
  8133. // Depth encoding into RGBA texture
  8134. // based on SpiderGL shadow map example
  8135. // http://spidergl.org/example.php?id=6
  8136. // originally from
  8137. // http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
  8138. // see also here:
  8139. // http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
  8140. 'depthRGBA': {
  8141. uniforms: {},
  8142. vertexShader: [
  8143. THREE.ShaderChunk[ "skinning_pars_vertex" ],
  8144. THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
  8145. "void main() {",
  8146. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  8147. THREE.ShaderChunk[ "skinbase_vertex" ],
  8148. THREE.ShaderChunk[ "skinning_vertex" ],
  8149. THREE.ShaderChunk[ "morphtarget_vertex" ],
  8150. THREE.ShaderChunk[ "default_vertex" ],
  8151. "}"
  8152. ].join("\n"),
  8153. fragmentShader: [
  8154. "vec4 pack_depth( const in float depth ) {",
  8155. "const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
  8156. "const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
  8157. "vec4 res = fract( depth * bit_shift );",
  8158. "res -= res.xxyz * bit_mask;",
  8159. "return res;",
  8160. "}",
  8161. "void main() {",
  8162. "gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
  8163. //"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
  8164. //"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
  8165. //"gl_FragData[ 0 ] = pack_depth( z );",
  8166. //"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
  8167. "}"
  8168. ].join("\n")
  8169. }
  8170. };/**
  8171. * @author supereggbert / http://www.paulbrunt.co.uk/
  8172. * @author mrdoob / http://mrdoob.com/
  8173. * @author alteredq / http://alteredqualia.com/
  8174. * @author szimek / https://github.com/szimek/
  8175. */
  8176. THREE.WebGLRenderer = function ( parameters ) {
  8177. console.log( 'THREE.WebGLRenderer', THREE.REVISION );
  8178. parameters = parameters || {};
  8179. var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
  8180. _precision = parameters.precision !== undefined ? parameters.precision : 'highp',
  8181. _alpha = parameters.alpha !== undefined ? parameters.alpha : true,
  8182. _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
  8183. _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
  8184. _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
  8185. _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
  8186. _clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
  8187. _clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0,
  8188. _maxLights = parameters.maxLights !== undefined ? parameters.maxLights : 4;
  8189. // public properties
  8190. this.domElement = _canvas;
  8191. this.context = null;
  8192. // clearing
  8193. this.autoClear = true;
  8194. this.autoClearColor = true;
  8195. this.autoClearDepth = true;
  8196. this.autoClearStencil = true;
  8197. // scene graph
  8198. this.sortObjects = true;
  8199. this.autoUpdateObjects = true;
  8200. this.autoUpdateScene = true;
  8201. // physically based shading
  8202. this.gammaInput = false;
  8203. this.gammaOutput = false;
  8204. this.physicallyBasedShading = false;
  8205. // shadow map
  8206. this.shadowMapEnabled = false;
  8207. this.shadowMapAutoUpdate = true;
  8208. this.shadowMapSoft = true;
  8209. this.shadowMapCullFrontFaces = true;
  8210. this.shadowMapDebug = false;
  8211. this.shadowMapCascade = false;
  8212. // morphs
  8213. this.maxMorphTargets = 8;
  8214. this.maxMorphNormals = 4;
  8215. // flags
  8216. this.autoScaleCubemaps = true;
  8217. // custom render plugins
  8218. this.renderPluginsPre = [];
  8219. this.renderPluginsPost = [];
  8220. // info
  8221. this.info = {
  8222. memory: {
  8223. programs: 0,
  8224. geometries: 0,
  8225. textures: 0
  8226. },
  8227. render: {
  8228. calls: 0,
  8229. vertices: 0,
  8230. faces: 0,
  8231. points: 0
  8232. }
  8233. };
  8234. // internal properties
  8235. var _this = this,
  8236. _programs = [],
  8237. _programs_counter = 0,
  8238. // internal state cache
  8239. _currentProgram = null,
  8240. _currentFramebuffer = null,
  8241. _currentMaterialId = -1,
  8242. _currentGeometryGroupHash = null,
  8243. _currentCamera = null,
  8244. _geometryGroupCounter = 0,
  8245. // GL state cache
  8246. _oldDoubleSided = -1,
  8247. _oldFlipSided = -1,
  8248. _oldBlending = -1,
  8249. _oldBlendEquation = -1,
  8250. _oldBlendSrc = -1,
  8251. _oldBlendDst = -1,
  8252. _oldDepthTest = -1,
  8253. _oldDepthWrite = -1,
  8254. _oldPolygonOffset = null,
  8255. _oldPolygonOffsetFactor = null,
  8256. _oldPolygonOffsetUnits = null,
  8257. _oldLineWidth = null,
  8258. _viewportX = 0,
  8259. _viewportY = 0,
  8260. _viewportWidth = 0,
  8261. _viewportHeight = 0,
  8262. _currentWidth = 0,
  8263. _currentHeight = 0,
  8264. // frustum
  8265. _frustum = new THREE.Frustum(),
  8266. // camera matrices cache
  8267. _projScreenMatrix = new THREE.Matrix4(),
  8268. _projScreenMatrixPS = new THREE.Matrix4(),
  8269. _vector3 = new THREE.Vector4(),
  8270. // light arrays cache
  8271. _direction = new THREE.Vector3(),
  8272. _lightsNeedUpdate = true,
  8273. _lights = {
  8274. ambient: [ 0, 0, 0 ],
  8275. directional: { length: 0, colors: new Array(), positions: new Array() },
  8276. point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() },
  8277. spot: { length: 0, colors: new Array(), positions: new Array(), distances: new Array(), directions: new Array(), angles: new Array(), exponents: new Array() }
  8278. };
  8279. // initialize
  8280. var _gl;
  8281. var _glExtensionTextureFloat;
  8282. var _glExtensionStandardDerivatives;
  8283. var _glExtensionTextureFilterAnisotropic;
  8284. initGL();
  8285. setDefaultGLState();
  8286. this.context = _gl;
  8287. // GPU capabilities
  8288. var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ),
  8289. _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE ),
  8290. _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
  8291. var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
  8292. var _supportsVertexTextures = ( _maxVertexTextures > 0 );
  8293. var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
  8294. // API
  8295. this.getContext = function () {
  8296. return _gl;
  8297. };
  8298. this.supportsVertexTextures = function () {
  8299. return _supportsVertexTextures;
  8300. };
  8301. this.getMaxAnisotropy = function () {
  8302. return _maxAnisotropy;
  8303. };
  8304. this.setSize = function ( width, height ) {
  8305. _canvas.width = width;
  8306. _canvas.height = height;
  8307. this.setViewport( 0, 0, _canvas.width, _canvas.height );
  8308. };
  8309. this.setViewport = function ( x, y, width, height ) {
  8310. _viewportX = x;
  8311. _viewportY = y;
  8312. _viewportWidth = width;
  8313. _viewportHeight = height;
  8314. _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
  8315. };
  8316. this.setScissor = function ( x, y, width, height ) {
  8317. _gl.scissor( x, y, width, height );
  8318. };
  8319. this.enableScissorTest = function ( enable ) {
  8320. enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
  8321. };
  8322. // Clearing
  8323. this.setClearColorHex = function ( hex, alpha ) {
  8324. _clearColor.setHex( hex );
  8325. _clearAlpha = alpha;
  8326. _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
  8327. };
  8328. this.setClearColor = function ( color, alpha ) {
  8329. _clearColor.copy( color );
  8330. _clearAlpha = alpha;
  8331. _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
  8332. };
  8333. this.getClearColor = function () {
  8334. return _clearColor;
  8335. };
  8336. this.getClearAlpha = function () {
  8337. return _clearAlpha;
  8338. };
  8339. this.clear = function ( color, depth, stencil ) {
  8340. var bits = 0;
  8341. if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
  8342. if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
  8343. if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
  8344. _gl.clear( bits );
  8345. };
  8346. this.clearTarget = function ( renderTarget, color, depth, stencil ) {
  8347. this.setRenderTarget( renderTarget );
  8348. this.clear( color, depth, stencil );
  8349. };
  8350. // Plugins
  8351. this.addPostPlugin = function ( plugin ) {
  8352. plugin.init( this );
  8353. this.renderPluginsPost.push( plugin );
  8354. };
  8355. this.addPrePlugin = function ( plugin ) {
  8356. plugin.init( this );
  8357. this.renderPluginsPre.push( plugin );
  8358. };
  8359. // Deallocation
  8360. this.deallocateObject = function ( object ) {
  8361. if ( ! object.__webglInit ) return;
  8362. object.__webglInit = false;
  8363. delete object._modelViewMatrix;
  8364. delete object._normalMatrix;
  8365. delete object._normalMatrixArray;
  8366. delete object._modelViewMatrixArray;
  8367. delete object._objectMatrixArray;
  8368. if ( object instanceof THREE.Mesh ) {
  8369. for ( var g in object.geometry.geometryGroups ) {
  8370. deleteMeshBuffers( object.geometry.geometryGroups[ g ] );
  8371. }
  8372. } else if ( object instanceof THREE.Ribbon ) {
  8373. deleteRibbonBuffers( object.geometry );
  8374. } else if ( object instanceof THREE.Line ) {
  8375. deleteLineBuffers( object.geometry );
  8376. } else if ( object instanceof THREE.ParticleSystem ) {
  8377. deleteParticleBuffers( object.geometry );
  8378. }
  8379. };
  8380. this.deallocateTexture = function ( texture ) {
  8381. if ( ! texture.__webglInit ) return;
  8382. texture.__webglInit = false;
  8383. _gl.deleteTexture( texture.__webglTexture );
  8384. _this.info.memory.textures --;
  8385. };
  8386. this.deallocateRenderTarget = function ( renderTarget ) {
  8387. if ( !renderTarget || ! renderTarget.__webglTexture ) return;
  8388. _gl.deleteTexture( renderTarget.__webglTexture );
  8389. if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
  8390. for ( var i = 0; i < 6; i ++ ) {
  8391. _gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
  8392. _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
  8393. }
  8394. } else {
  8395. _gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
  8396. _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
  8397. }
  8398. };
  8399. this.deallocateMaterial = function ( material ) {
  8400. var program = material.program;
  8401. if ( ! program ) return;
  8402. material.program = undefined;
  8403. // only deallocate GL program if this was the last use of shared program
  8404. // assumed there is only single copy of any program in the _programs list
  8405. // (that's how it's constructed)
  8406. var i, il, programInfo;
  8407. var deleteProgram = false;
  8408. for ( i = 0, il = _programs.length; i < il; i ++ ) {
  8409. programInfo = _programs[ i ];
  8410. if ( programInfo.program === program ) {
  8411. programInfo.usedTimes --;
  8412. if ( programInfo.usedTimes === 0 ) {
  8413. deleteProgram = true;
  8414. }
  8415. break;
  8416. }
  8417. }
  8418. if ( deleteProgram ) {
  8419. // avoid using array.splice, this is costlier than creating new array from scratch
  8420. var newPrograms = [];
  8421. for ( i = 0, il = _programs.length; i < il; i ++ ) {
  8422. programInfo = _programs[ i ];
  8423. if ( programInfo.program !== program ) {
  8424. newPrograms.push( programInfo );
  8425. }
  8426. }
  8427. _programs = newPrograms;
  8428. _gl.deleteProgram( program );
  8429. _this.info.memory.programs --;
  8430. }
  8431. };
  8432. // Rendering
  8433. this.updateShadowMap = function ( scene, camera ) {
  8434. _currentProgram = null;
  8435. _oldBlending = -1;
  8436. _oldDepthTest = -1;
  8437. _oldDepthWrite = -1;
  8438. _currentGeometryGroupHash = -1;
  8439. _currentMaterialId = -1;
  8440. _lightsNeedUpdate = true;
  8441. _oldDoubleSided = -1;
  8442. _oldFlipSided = -1;
  8443. this.shadowMapPlugin.update( scene, camera );
  8444. };
  8445. // Internal functions
  8446. // Buffer allocation
  8447. function createParticleBuffers ( geometry ) {
  8448. geometry.__webglVertexBuffer = _gl.createBuffer();
  8449. geometry.__webglColorBuffer = _gl.createBuffer();
  8450. _this.info.geometries ++;
  8451. };
  8452. function createLineBuffers ( geometry ) {
  8453. geometry.__webglVertexBuffer = _gl.createBuffer();
  8454. geometry.__webglColorBuffer = _gl.createBuffer();
  8455. _this.info.memory.geometries ++;
  8456. };
  8457. function createRibbonBuffers ( geometry ) {
  8458. geometry.__webglVertexBuffer = _gl.createBuffer();
  8459. geometry.__webglColorBuffer = _gl.createBuffer();
  8460. _this.info.memory.geometries ++;
  8461. };
  8462. function createMeshBuffers ( geometryGroup ) {
  8463. geometryGroup.__webglVertexBuffer = _gl.createBuffer();
  8464. geometryGroup.__webglNormalBuffer = _gl.createBuffer();
  8465. geometryGroup.__webglTangentBuffer = _gl.createBuffer();
  8466. geometryGroup.__webglColorBuffer = _gl.createBuffer();
  8467. geometryGroup.__webglUVBuffer = _gl.createBuffer();
  8468. geometryGroup.__webglUV2Buffer = _gl.createBuffer();
  8469. geometryGroup.__webglSkinVertexABuffer = _gl.createBuffer();
  8470. geometryGroup.__webglSkinVertexBBuffer = _gl.createBuffer();
  8471. geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
  8472. geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
  8473. geometryGroup.__webglFaceBuffer = _gl.createBuffer();
  8474. geometryGroup.__webglLineBuffer = _gl.createBuffer();
  8475. var m, ml;
  8476. if ( geometryGroup.numMorphTargets ) {
  8477. geometryGroup.__webglMorphTargetsBuffers = [];
  8478. for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
  8479. geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
  8480. }
  8481. }
  8482. if ( geometryGroup.numMorphNormals ) {
  8483. geometryGroup.__webglMorphNormalsBuffers = [];
  8484. for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
  8485. geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
  8486. }
  8487. }
  8488. _this.info.memory.geometries ++;
  8489. };
  8490. // Buffer deallocation
  8491. function deleteParticleBuffers ( geometry ) {
  8492. _gl.deleteBuffer( geometry.__webglVertexBuffer );
  8493. _gl.deleteBuffer( geometry.__webglColorBuffer );
  8494. _this.info.memory.geometries --;
  8495. };
  8496. function deleteLineBuffers ( geometry ) {
  8497. _gl.deleteBuffer( geometry.__webglVertexBuffer );
  8498. _gl.deleteBuffer( geometry.__webglColorBuffer );
  8499. _this.info.memory.geometries --;
  8500. };
  8501. function deleteRibbonBuffers ( geometry ) {
  8502. _gl.deleteBuffer( geometry.__webglVertexBuffer );
  8503. _gl.deleteBuffer( geometry.__webglColorBuffer );
  8504. _this.info.memory.geometries --;
  8505. };
  8506. function deleteMeshBuffers ( geometryGroup ) {
  8507. _gl.deleteBuffer( geometryGroup.__webglVertexBuffer );
  8508. _gl.deleteBuffer( geometryGroup.__webglNormalBuffer );
  8509. _gl.deleteBuffer( geometryGroup.__webglTangentBuffer );
  8510. _gl.deleteBuffer( geometryGroup.__webglColorBuffer );
  8511. _gl.deleteBuffer( geometryGroup.__webglUVBuffer );
  8512. _gl.deleteBuffer( geometryGroup.__webglUV2Buffer );
  8513. _gl.deleteBuffer( geometryGroup.__webglSkinVertexABuffer );
  8514. _gl.deleteBuffer( geometryGroup.__webglSkinVertexBBuffer );
  8515. _gl.deleteBuffer( geometryGroup.__webglSkinIndicesBuffer );
  8516. _gl.deleteBuffer( geometryGroup.__webglSkinWeightsBuffer );
  8517. _gl.deleteBuffer( geometryGroup.__webglFaceBuffer );
  8518. _gl.deleteBuffer( geometryGroup.__webglLineBuffer );
  8519. var m, ml;
  8520. if ( geometryGroup.numMorphTargets ) {
  8521. for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
  8522. _gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
  8523. }
  8524. }
  8525. if ( geometryGroup.numMorphNormals ) {
  8526. for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
  8527. _gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
  8528. }
  8529. }
  8530. if ( geometryGroup.__webglCustomAttributesList ) {
  8531. for ( var id in geometryGroup.__webglCustomAttributesList ) {
  8532. _gl.deleteBuffer( geometryGroup.__webglCustomAttributesList[ id ].buffer );
  8533. }
  8534. }
  8535. _this.info.memory.geometries --;
  8536. };
  8537. // Buffer initialization
  8538. function initCustomAttributes ( geometry, object ) {
  8539. var nvertices = geometry.vertices.length;
  8540. var material = object.material;
  8541. if ( material.attributes ) {
  8542. if ( geometry.__webglCustomAttributesList === undefined ) {
  8543. geometry.__webglCustomAttributesList = [];
  8544. }
  8545. for ( var a in material.attributes ) {
  8546. var attribute = material.attributes[ a ];
  8547. if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
  8548. attribute.__webglInitialized = true;
  8549. var size = 1; // "f" and "i"
  8550. if ( attribute.type === "v2" ) size = 2;
  8551. else if ( attribute.type === "v3" ) size = 3;
  8552. else if ( attribute.type === "v4" ) size = 4;
  8553. else if ( attribute.type === "c" ) size = 3;
  8554. attribute.size = size;
  8555. attribute.array = new Float32Array( nvertices * size );
  8556. attribute.buffer = _gl.createBuffer();
  8557. attribute.buffer.belongsToAttribute = a;
  8558. attribute.needsUpdate = true;
  8559. }
  8560. geometry.__webglCustomAttributesList.push( attribute );
  8561. }
  8562. }
  8563. };
  8564. function initParticleBuffers ( geometry, object ) {
  8565. var nvertices = geometry.vertices.length;
  8566. geometry.__vertexArray = new Float32Array( nvertices * 3 );
  8567. geometry.__colorArray = new Float32Array( nvertices * 3 );
  8568. geometry.__sortArray = [];
  8569. geometry.__webglParticleCount = nvertices;
  8570. initCustomAttributes ( geometry, object );
  8571. };
  8572. function initLineBuffers ( geometry, object ) {
  8573. var nvertices = geometry.vertices.length;
  8574. geometry.__vertexArray = new Float32Array( nvertices * 3 );
  8575. geometry.__colorArray = new Float32Array( nvertices * 3 );
  8576. geometry.__webglLineCount = nvertices;
  8577. initCustomAttributes ( geometry, object );
  8578. };
  8579. function initRibbonBuffers ( geometry ) {
  8580. var nvertices = geometry.vertices.length;
  8581. geometry.__vertexArray = new Float32Array( nvertices * 3 );
  8582. geometry.__colorArray = new Float32Array( nvertices * 3 );
  8583. geometry.__webglVertexCount = nvertices;
  8584. };
  8585. function initMeshBuffers ( geometryGroup, object ) {
  8586. var geometry = object.geometry,
  8587. faces3 = geometryGroup.faces3,
  8588. faces4 = geometryGroup.faces4,
  8589. nvertices = faces3.length * 3 + faces4.length * 4,
  8590. ntris = faces3.length * 1 + faces4.length * 2,
  8591. nlines = faces3.length * 3 + faces4.length * 4,
  8592. material = getBufferMaterial( object, geometryGroup ),
  8593. uvType = bufferGuessUVType( material ),
  8594. normalType = bufferGuessNormalType( material ),
  8595. vertexColorType = bufferGuessVertexColorType( material );
  8596. //console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
  8597. geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
  8598. if ( normalType ) {
  8599. geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
  8600. }
  8601. if ( geometry.hasTangents ) {
  8602. geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
  8603. }
  8604. if ( vertexColorType ) {
  8605. geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
  8606. }
  8607. if ( uvType ) {
  8608. if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
  8609. geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
  8610. }
  8611. if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
  8612. geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
  8613. }
  8614. }
  8615. if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
  8616. geometryGroup.__skinVertexAArray = new Float32Array( nvertices * 4 );
  8617. geometryGroup.__skinVertexBArray = new Float32Array( nvertices * 4 );
  8618. geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
  8619. geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
  8620. }
  8621. geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
  8622. geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
  8623. var m, ml;
  8624. if ( geometryGroup.numMorphTargets ) {
  8625. geometryGroup.__morphTargetsArrays = [];
  8626. for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
  8627. geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
  8628. }
  8629. }
  8630. if ( geometryGroup.numMorphNormals ) {
  8631. geometryGroup.__morphNormalsArrays = [];
  8632. for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
  8633. geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
  8634. }
  8635. }
  8636. geometryGroup.__webglFaceCount = ntris * 3;
  8637. geometryGroup.__webglLineCount = nlines * 2;
  8638. // custom attributes
  8639. if ( material.attributes ) {
  8640. if ( geometryGroup.__webglCustomAttributesList === undefined ) {
  8641. geometryGroup.__webglCustomAttributesList = [];
  8642. }
  8643. for ( var a in material.attributes ) {
  8644. // Do a shallow copy of the attribute object so different geometryGroup chunks use different
  8645. // attribute buffers which are correctly indexed in the setMeshBuffers function
  8646. var originalAttribute = material.attributes[ a ];
  8647. var attribute = {};
  8648. for ( var property in originalAttribute ) {
  8649. attribute[ property ] = originalAttribute[ property ];
  8650. }
  8651. if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
  8652. attribute.__webglInitialized = true;
  8653. var size = 1; // "f" and "i"
  8654. if( attribute.type === "v2" ) size = 2;
  8655. else if( attribute.type === "v3" ) size = 3;
  8656. else if( attribute.type === "v4" ) size = 4;
  8657. else if( attribute.type === "c" ) size = 3;
  8658. attribute.size = size;
  8659. attribute.array = new Float32Array( nvertices * size );
  8660. attribute.buffer = _gl.createBuffer();
  8661. attribute.buffer.belongsToAttribute = a;
  8662. originalAttribute.needsUpdate = true;
  8663. attribute.__original = originalAttribute;
  8664. }
  8665. geometryGroup.__webglCustomAttributesList.push( attribute );
  8666. }
  8667. }
  8668. geometryGroup.__inittedArrays = true;
  8669. };
  8670. function getBufferMaterial( object, geometryGroup ) {
  8671. if ( object.material && ! ( object.material instanceof THREE.MeshFaceMaterial ) ) {
  8672. return object.material;
  8673. } else if ( geometryGroup.materialIndex >= 0 ) {
  8674. return object.geometry.materials[ geometryGroup.materialIndex ];
  8675. }
  8676. };
  8677. function materialNeedsSmoothNormals ( material ) {
  8678. return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
  8679. };
  8680. function bufferGuessNormalType ( material ) {
  8681. // only MeshBasicMaterial and MeshDepthMaterial don't need normals
  8682. if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
  8683. return false;
  8684. }
  8685. if ( materialNeedsSmoothNormals( material ) ) {
  8686. return THREE.SmoothShading;
  8687. } else {
  8688. return THREE.FlatShading;
  8689. }
  8690. };
  8691. function bufferGuessVertexColorType ( material ) {
  8692. if ( material.vertexColors ) {
  8693. return material.vertexColors;
  8694. }
  8695. return false;
  8696. };
  8697. function bufferGuessUVType ( material ) {
  8698. // material must use some texture to require uvs
  8699. if ( material.map || material.lightMap || material instanceof THREE.ShaderMaterial ) {
  8700. return true;
  8701. }
  8702. return false;
  8703. };
  8704. //
  8705. function initDirectBuffers( geometry ) {
  8706. var a, attribute, type;
  8707. for ( a in geometry.attributes ) {
  8708. if ( a === "index" ) {
  8709. type = _gl.ELEMENT_ARRAY_BUFFER;
  8710. } else {
  8711. type = _gl.ARRAY_BUFFER;
  8712. }
  8713. attribute = geometry.attributes[ a ];
  8714. attribute.buffer = _gl.createBuffer();
  8715. _gl.bindBuffer( type, attribute.buffer );
  8716. _gl.bufferData( type, attribute.array, _gl.STATIC_DRAW );
  8717. }
  8718. };
  8719. // Buffer setting
  8720. function setParticleBuffers ( geometry, hint, object ) {
  8721. var v, c, vertex, offset, index, color,
  8722. vertices = geometry.vertices,
  8723. vl = vertices.length,
  8724. colors = geometry.colors,
  8725. cl = colors.length,
  8726. vertexArray = geometry.__vertexArray,
  8727. colorArray = geometry.__colorArray,
  8728. sortArray = geometry.__sortArray,
  8729. dirtyVertices = geometry.verticesNeedUpdate,
  8730. dirtyElements = geometry.elementsNeedUpdate,
  8731. dirtyColors = geometry.colorsNeedUpdate,
  8732. customAttributes = geometry.__webglCustomAttributesList,
  8733. i, il,
  8734. a, ca, cal, value,
  8735. customAttribute;
  8736. if ( object.sortParticles ) {
  8737. _projScreenMatrixPS.copy( _projScreenMatrix );
  8738. _projScreenMatrixPS.multiplySelf( object.matrixWorld );
  8739. for ( v = 0; v < vl; v ++ ) {
  8740. vertex = vertices[ v ];
  8741. _vector3.copy( vertex );
  8742. _projScreenMatrixPS.multiplyVector3( _vector3 );
  8743. sortArray[ v ] = [ _vector3.z, v ];
  8744. }
  8745. sortArray.sort( function( a, b ) { return b[ 0 ] - a[ 0 ]; } );
  8746. for ( v = 0; v < vl; v ++ ) {
  8747. vertex = vertices[ sortArray[v][1] ];
  8748. offset = v * 3;
  8749. vertexArray[ offset ] = vertex.x;
  8750. vertexArray[ offset + 1 ] = vertex.y;
  8751. vertexArray[ offset + 2 ] = vertex.z;
  8752. }
  8753. for ( c = 0; c < cl; c ++ ) {
  8754. offset = c * 3;
  8755. color = colors[ sortArray[c][1] ];
  8756. colorArray[ offset ] = color.r;
  8757. colorArray[ offset + 1 ] = color.g;
  8758. colorArray[ offset + 2 ] = color.b;
  8759. }
  8760. if ( customAttributes ) {
  8761. for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
  8762. customAttribute = customAttributes[ i ];
  8763. if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
  8764. offset = 0;
  8765. cal = customAttribute.value.length;
  8766. if ( customAttribute.size === 1 ) {
  8767. for ( ca = 0; ca < cal; ca ++ ) {
  8768. index = sortArray[ ca ][ 1 ];
  8769. customAttribute.array[ ca ] = customAttribute.value[ index ];
  8770. }
  8771. } else if ( customAttribute.size === 2 ) {
  8772. for ( ca = 0; ca < cal; ca ++ ) {
  8773. index = sortArray[ ca ][ 1 ];
  8774. value = customAttribute.value[ index ];
  8775. customAttribute.array[ offset ] = value.x;
  8776. customAttribute.array[ offset + 1 ] = value.y;
  8777. offset += 2;
  8778. }
  8779. } else if ( customAttribute.size === 3 ) {
  8780. if ( customAttribute.type === "c" ) {
  8781. for ( ca = 0; ca < cal; ca ++ ) {
  8782. index = sortArray[ ca ][ 1 ];
  8783. value = customAttribute.value[ index ];
  8784. customAttribute.array[ offset ] = value.r;
  8785. customAttribute.array[ offset + 1 ] = value.g;
  8786. customAttribute.array[ offset + 2 ] = value.b;
  8787. offset += 3;
  8788. }
  8789. } else {
  8790. for ( ca = 0; ca < cal; ca ++ ) {
  8791. index = sortArray[ ca ][ 1 ];
  8792. value = customAttribute.value[ index ];
  8793. customAttribute.array[ offset ] = value.x;
  8794. customAttribute.array[ offset + 1 ] = value.y;
  8795. customAttribute.array[ offset + 2 ] = value.z;
  8796. offset += 3;
  8797. }
  8798. }
  8799. } else if ( customAttribute.size === 4 ) {
  8800. for ( ca = 0; ca < cal; ca ++ ) {
  8801. index = sortArray[ ca ][ 1 ];
  8802. value = customAttribute.value[ index ];
  8803. customAttribute.array[ offset ] = value.x;
  8804. customAttribute.array[ offset + 1 ] = value.y;
  8805. customAttribute.array[ offset + 2 ] = value.z;
  8806. customAttribute.array[ offset + 3 ] = value.w;
  8807. offset += 4;
  8808. }
  8809. }
  8810. }
  8811. }
  8812. } else {
  8813. if ( dirtyVertices ) {
  8814. for ( v = 0; v < vl; v ++ ) {
  8815. vertex = vertices[ v ];
  8816. offset = v * 3;
  8817. vertexArray[ offset ] = vertex.x;
  8818. vertexArray[ offset + 1 ] = vertex.y;
  8819. vertexArray[ offset + 2 ] = vertex.z;
  8820. }
  8821. }
  8822. if ( dirtyColors ) {
  8823. for ( c = 0; c < cl; c ++ ) {
  8824. color = colors[ c ];
  8825. offset = c * 3;
  8826. colorArray[ offset ] = color.r;
  8827. colorArray[ offset + 1 ] = color.g;
  8828. colorArray[ offset + 2 ] = color.b;
  8829. }
  8830. }
  8831. if ( customAttributes ) {
  8832. for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
  8833. customAttribute = customAttributes[ i ];
  8834. if ( customAttribute.needsUpdate &&
  8835. ( customAttribute.boundTo === undefined ||
  8836. customAttribute.boundTo === "vertices") ) {
  8837. cal = customAttribute.value.length;
  8838. offset = 0;
  8839. if ( customAttribute.size === 1 ) {
  8840. for ( ca = 0; ca < cal; ca ++ ) {
  8841. customAttribute.array[ ca ] = customAttribute.value[ ca ];
  8842. }
  8843. } else if ( customAttribute.size === 2 ) {
  8844. for ( ca = 0; ca < cal; ca ++ ) {
  8845. value = customAttribute.value[ ca ];
  8846. customAttribute.array[ offset ] = value.x;
  8847. customAttribute.array[ offset + 1 ] = value.y;
  8848. offset += 2;
  8849. }
  8850. } else if ( customAttribute.size === 3 ) {
  8851. if ( customAttribute.type === "c" ) {
  8852. for ( ca = 0; ca < cal; ca ++ ) {
  8853. value = customAttribute.value[ ca ];
  8854. customAttribute.array[ offset ] = value.r;
  8855. customAttribute.array[ offset + 1 ] = value.g;
  8856. customAttribute.array[ offset + 2 ] = value.b;
  8857. offset += 3;
  8858. }
  8859. } else {
  8860. for ( ca = 0; ca < cal; ca ++ ) {
  8861. value = customAttribute.value[ ca ];
  8862. customAttribute.array[ offset ] = value.x;
  8863. customAttribute.array[ offset + 1 ] = value.y;
  8864. customAttribute.array[ offset + 2 ] = value.z;
  8865. offset += 3;
  8866. }
  8867. }
  8868. } else if ( customAttribute.size === 4 ) {
  8869. for ( ca = 0; ca < cal; ca ++ ) {
  8870. value = customAttribute.value[ ca ];
  8871. customAttribute.array[ offset ] = value.x;
  8872. customAttribute.array[ offset + 1 ] = value.y;
  8873. customAttribute.array[ offset + 2 ] = value.z;
  8874. customAttribute.array[ offset + 3 ] = value.w;
  8875. offset += 4;
  8876. }
  8877. }
  8878. }
  8879. }
  8880. }
  8881. }
  8882. if ( dirtyVertices || object.sortParticles ) {
  8883. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
  8884. _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
  8885. }
  8886. if ( dirtyColors || object.sortParticles ) {
  8887. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
  8888. _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
  8889. }
  8890. if ( customAttributes ) {
  8891. for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
  8892. customAttribute = customAttributes[ i ];
  8893. if ( customAttribute.needsUpdate || object.sortParticles ) {
  8894. _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
  8895. _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
  8896. }
  8897. }
  8898. }
  8899. };
  8900. function setLineBuffers ( geometry, hint ) {
  8901. var v, c, vertex, offset, color,
  8902. vertices = geometry.vertices,
  8903. colors = geometry.colors,
  8904. vl = vertices.length,
  8905. cl = colors.length,
  8906. vertexArray = geometry.__vertexArray,
  8907. colorArray = geometry.__colorArray,
  8908. dirtyVertices = geometry.verticesNeedUpdate,
  8909. dirtyColors = geometry.colorsNeedUpdate,
  8910. customAttributes = geometry.__webglCustomAttributesList,
  8911. i, il,
  8912. a, ca, cal, value,
  8913. customAttribute;
  8914. if ( dirtyVertices ) {
  8915. for ( v = 0; v < vl; v ++ ) {
  8916. vertex = vertices[ v ];
  8917. offset = v * 3;
  8918. vertexArray[ offset ] = vertex.x;
  8919. vertexArray[ offset + 1 ] = vertex.y;
  8920. vertexArray[ offset + 2 ] = vertex.z;
  8921. }
  8922. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
  8923. _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
  8924. }
  8925. if ( dirtyColors ) {
  8926. for ( c = 0; c < cl; c ++ ) {
  8927. color = colors[ c ];
  8928. offset = c * 3;
  8929. colorArray[ offset ] = color.r;
  8930. colorArray[ offset + 1 ] = color.g;
  8931. colorArray[ offset + 2 ] = color.b;
  8932. }
  8933. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
  8934. _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
  8935. }
  8936. if ( customAttributes ) {
  8937. for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
  8938. customAttribute = customAttributes[ i ];
  8939. if ( customAttribute.needsUpdate &&
  8940. ( customAttribute.boundTo === undefined ||
  8941. customAttribute.boundTo === "vertices" ) ) {
  8942. offset = 0;
  8943. cal = customAttribute.value.length;
  8944. if ( customAttribute.size === 1 ) {
  8945. for ( ca = 0; ca < cal; ca ++ ) {
  8946. customAttribute.array[ ca ] = customAttribute.value[ ca ];
  8947. }
  8948. } else if ( customAttribute.size === 2 ) {
  8949. for ( ca = 0; ca < cal; ca ++ ) {
  8950. value = customAttribute.value[ ca ];
  8951. customAttribute.array[ offset ] = value.x;
  8952. customAttribute.array[ offset + 1 ] = value.y;
  8953. offset += 2;
  8954. }
  8955. } else if ( customAttribute.size === 3 ) {
  8956. if ( customAttribute.type === "c" ) {
  8957. for ( ca = 0; ca < cal; ca ++ ) {
  8958. value = customAttribute.value[ ca ];
  8959. customAttribute.array[ offset ] = value.r;
  8960. customAttribute.array[ offset + 1 ] = value.g;
  8961. customAttribute.array[ offset + 2 ] = value.b;
  8962. offset += 3;
  8963. }
  8964. } else {
  8965. for ( ca = 0; ca < cal; ca ++ ) {
  8966. value = customAttribute.value[ ca ];
  8967. customAttribute.array[ offset ] = value.x;
  8968. customAttribute.array[ offset + 1 ] = value.y;
  8969. customAttribute.array[ offset + 2 ] = value.z;
  8970. offset += 3;
  8971. }
  8972. }
  8973. } else if ( customAttribute.size === 4 ) {
  8974. for ( ca = 0; ca < cal; ca ++ ) {
  8975. value = customAttribute.value[ ca ];
  8976. customAttribute.array[ offset ] = value.x;
  8977. customAttribute.array[ offset + 1 ] = value.y;
  8978. customAttribute.array[ offset + 2 ] = value.z;
  8979. customAttribute.array[ offset + 3 ] = value.w;
  8980. offset += 4;
  8981. }
  8982. }
  8983. _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
  8984. _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
  8985. }
  8986. }
  8987. }
  8988. };
  8989. function setRibbonBuffers ( geometry, hint ) {
  8990. var v, c, vertex, offset, color,
  8991. vertices = geometry.vertices,
  8992. colors = geometry.colors,
  8993. vl = vertices.length,
  8994. cl = colors.length,
  8995. vertexArray = geometry.__vertexArray,
  8996. colorArray = geometry.__colorArray,
  8997. dirtyVertices = geometry.verticesNeedUpdate,
  8998. dirtyColors = geometry.colorsNeedUpdate;
  8999. if ( dirtyVertices ) {
  9000. for ( v = 0; v < vl; v ++ ) {
  9001. vertex = vertices[ v ];
  9002. offset = v * 3;
  9003. vertexArray[ offset ] = vertex.x;
  9004. vertexArray[ offset + 1 ] = vertex.y;
  9005. vertexArray[ offset + 2 ] = vertex.z;
  9006. }
  9007. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
  9008. _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
  9009. }
  9010. if ( dirtyColors ) {
  9011. for ( c = 0; c < cl; c ++ ) {
  9012. color = colors[ c ];
  9013. offset = c * 3;
  9014. colorArray[ offset ] = color.r;
  9015. colorArray[ offset + 1 ] = color.g;
  9016. colorArray[ offset + 2 ] = color.b;
  9017. }
  9018. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
  9019. _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
  9020. }
  9021. };
  9022. function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
  9023. if ( ! geometryGroup.__inittedArrays ) {
  9024. // console.log( object );
  9025. return;
  9026. }
  9027. var normalType = bufferGuessNormalType( material ),
  9028. vertexColorType = bufferGuessVertexColorType( material ),
  9029. uvType = bufferGuessUVType( material ),
  9030. needsSmoothNormals = ( normalType === THREE.SmoothShading );
  9031. var f, fl, fi, face,
  9032. vertexNormals, faceNormal, normal,
  9033. vertexColors, faceColor,
  9034. vertexTangents,
  9035. uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
  9036. c1, c2, c3, c4,
  9037. sw1, sw2, sw3, sw4,
  9038. si1, si2, si3, si4,
  9039. sa1, sa2, sa3, sa4,
  9040. sb1, sb2, sb3, sb4,
  9041. m, ml, i, il,
  9042. vn, uvi, uv2i,
  9043. vk, vkl, vka,
  9044. nka, chf, faceVertexNormals,
  9045. a,
  9046. vertexIndex = 0,
  9047. offset = 0,
  9048. offset_uv = 0,
  9049. offset_uv2 = 0,
  9050. offset_face = 0,
  9051. offset_normal = 0,
  9052. offset_tangent = 0,
  9053. offset_line = 0,
  9054. offset_color = 0,
  9055. offset_skin = 0,
  9056. offset_morphTarget = 0,
  9057. offset_custom = 0,
  9058. offset_customSrc = 0,
  9059. value,
  9060. vertexArray = geometryGroup.__vertexArray,
  9061. uvArray = geometryGroup.__uvArray,
  9062. uv2Array = geometryGroup.__uv2Array,
  9063. normalArray = geometryGroup.__normalArray,
  9064. tangentArray = geometryGroup.__tangentArray,
  9065. colorArray = geometryGroup.__colorArray,
  9066. skinVertexAArray = geometryGroup.__skinVertexAArray,
  9067. skinVertexBArray = geometryGroup.__skinVertexBArray,
  9068. skinIndexArray = geometryGroup.__skinIndexArray,
  9069. skinWeightArray = geometryGroup.__skinWeightArray,
  9070. morphTargetsArrays = geometryGroup.__morphTargetsArrays,
  9071. morphNormalsArrays = geometryGroup.__morphNormalsArrays,
  9072. customAttributes = geometryGroup.__webglCustomAttributesList,
  9073. customAttribute,
  9074. faceArray = geometryGroup.__faceArray,
  9075. lineArray = geometryGroup.__lineArray,
  9076. geometry = object.geometry, // this is shared for all chunks
  9077. dirtyVertices = geometry.verticesNeedUpdate,
  9078. dirtyElements = geometry.elementsNeedUpdate,
  9079. dirtyUvs = geometry.uvsNeedUpdate,
  9080. dirtyNormals = geometry.normalsNeedUpdate,
  9081. dirtyTangents = geometry.tangentsNeedUpdate,
  9082. dirtyColors = geometry.colorsNeedUpdate,
  9083. dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
  9084. vertices = geometry.vertices,
  9085. chunk_faces3 = geometryGroup.faces3,
  9086. chunk_faces4 = geometryGroup.faces4,
  9087. obj_faces = geometry.faces,
  9088. obj_uvs = geometry.faceVertexUvs[ 0 ],
  9089. obj_uvs2 = geometry.faceVertexUvs[ 1 ],
  9090. obj_colors = geometry.colors,
  9091. obj_skinVerticesA = geometry.skinVerticesA,
  9092. obj_skinVerticesB = geometry.skinVerticesB,
  9093. obj_skinIndices = geometry.skinIndices,
  9094. obj_skinWeights = geometry.skinWeights,
  9095. morphTargets = geometry.morphTargets,
  9096. morphNormals = geometry.morphNormals;
  9097. if ( dirtyVertices ) {
  9098. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9099. face = obj_faces[ chunk_faces3[ f ] ];
  9100. v1 = vertices[ face.a ];
  9101. v2 = vertices[ face.b ];
  9102. v3 = vertices[ face.c ];
  9103. vertexArray[ offset ] = v1.x;
  9104. vertexArray[ offset + 1 ] = v1.y;
  9105. vertexArray[ offset + 2 ] = v1.z;
  9106. vertexArray[ offset + 3 ] = v2.x;
  9107. vertexArray[ offset + 4 ] = v2.y;
  9108. vertexArray[ offset + 5 ] = v2.z;
  9109. vertexArray[ offset + 6 ] = v3.x;
  9110. vertexArray[ offset + 7 ] = v3.y;
  9111. vertexArray[ offset + 8 ] = v3.z;
  9112. offset += 9;
  9113. }
  9114. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9115. face = obj_faces[ chunk_faces4[ f ] ];
  9116. v1 = vertices[ face.a ];
  9117. v2 = vertices[ face.b ];
  9118. v3 = vertices[ face.c ];
  9119. v4 = vertices[ face.d ];
  9120. vertexArray[ offset ] = v1.x;
  9121. vertexArray[ offset + 1 ] = v1.y;
  9122. vertexArray[ offset + 2 ] = v1.z;
  9123. vertexArray[ offset + 3 ] = v2.x;
  9124. vertexArray[ offset + 4 ] = v2.y;
  9125. vertexArray[ offset + 5 ] = v2.z;
  9126. vertexArray[ offset + 6 ] = v3.x;
  9127. vertexArray[ offset + 7 ] = v3.y;
  9128. vertexArray[ offset + 8 ] = v3.z;
  9129. vertexArray[ offset + 9 ] = v4.x;
  9130. vertexArray[ offset + 10 ] = v4.y;
  9131. vertexArray[ offset + 11 ] = v4.z;
  9132. offset += 12;
  9133. }
  9134. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
  9135. _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
  9136. }
  9137. if ( dirtyMorphTargets ) {
  9138. for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
  9139. offset_morphTarget = 0;
  9140. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9141. chf = chunk_faces3[ f ];
  9142. face = obj_faces[ chf ];
  9143. // morph positions
  9144. v1 = morphTargets[ vk ].vertices[ face.a ];
  9145. v2 = morphTargets[ vk ].vertices[ face.b ];
  9146. v3 = morphTargets[ vk ].vertices[ face.c ];
  9147. vka = morphTargetsArrays[ vk ];
  9148. vka[ offset_morphTarget ] = v1.x;
  9149. vka[ offset_morphTarget + 1 ] = v1.y;
  9150. vka[ offset_morphTarget + 2 ] = v1.z;
  9151. vka[ offset_morphTarget + 3 ] = v2.x;
  9152. vka[ offset_morphTarget + 4 ] = v2.y;
  9153. vka[ offset_morphTarget + 5 ] = v2.z;
  9154. vka[ offset_morphTarget + 6 ] = v3.x;
  9155. vka[ offset_morphTarget + 7 ] = v3.y;
  9156. vka[ offset_morphTarget + 8 ] = v3.z;
  9157. // morph normals
  9158. if ( material.morphNormals ) {
  9159. if ( needsSmoothNormals ) {
  9160. faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
  9161. n1 = faceVertexNormals.a;
  9162. n2 = faceVertexNormals.b;
  9163. n3 = faceVertexNormals.c;
  9164. } else {
  9165. n1 = morphNormals[ vk ].faceNormals[ chf ];
  9166. n2 = n1;
  9167. n3 = n1;
  9168. }
  9169. nka = morphNormalsArrays[ vk ];
  9170. nka[ offset_morphTarget ] = n1.x;
  9171. nka[ offset_morphTarget + 1 ] = n1.y;
  9172. nka[ offset_morphTarget + 2 ] = n1.z;
  9173. nka[ offset_morphTarget + 3 ] = n2.x;
  9174. nka[ offset_morphTarget + 4 ] = n2.y;
  9175. nka[ offset_morphTarget + 5 ] = n2.z;
  9176. nka[ offset_morphTarget + 6 ] = n3.x;
  9177. nka[ offset_morphTarget + 7 ] = n3.y;
  9178. nka[ offset_morphTarget + 8 ] = n3.z;
  9179. }
  9180. //
  9181. offset_morphTarget += 9;
  9182. }
  9183. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9184. chf = chunk_faces4[ f ];
  9185. face = obj_faces[ chf ];
  9186. // morph positions
  9187. v1 = morphTargets[ vk ].vertices[ face.a ];
  9188. v2 = morphTargets[ vk ].vertices[ face.b ];
  9189. v3 = morphTargets[ vk ].vertices[ face.c ];
  9190. v4 = morphTargets[ vk ].vertices[ face.d ];
  9191. vka = morphTargetsArrays[ vk ];
  9192. vka[ offset_morphTarget ] = v1.x;
  9193. vka[ offset_morphTarget + 1 ] = v1.y;
  9194. vka[ offset_morphTarget + 2 ] = v1.z;
  9195. vka[ offset_morphTarget + 3 ] = v2.x;
  9196. vka[ offset_morphTarget + 4 ] = v2.y;
  9197. vka[ offset_morphTarget + 5 ] = v2.z;
  9198. vka[ offset_morphTarget + 6 ] = v3.x;
  9199. vka[ offset_morphTarget + 7 ] = v3.y;
  9200. vka[ offset_morphTarget + 8 ] = v3.z;
  9201. vka[ offset_morphTarget + 9 ] = v4.x;
  9202. vka[ offset_morphTarget + 10 ] = v4.y;
  9203. vka[ offset_morphTarget + 11 ] = v4.z;
  9204. // morph normals
  9205. if ( material.morphNormals ) {
  9206. if ( needsSmoothNormals ) {
  9207. faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
  9208. n1 = faceVertexNormals.a;
  9209. n2 = faceVertexNormals.b;
  9210. n3 = faceVertexNormals.c;
  9211. n4 = faceVertexNormals.d;
  9212. } else {
  9213. n1 = morphNormals[ vk ].faceNormals[ chf ];
  9214. n2 = n1;
  9215. n3 = n1;
  9216. n4 = n1;
  9217. }
  9218. nka = morphNormalsArrays[ vk ];
  9219. nka[ offset_morphTarget ] = n1.x;
  9220. nka[ offset_morphTarget + 1 ] = n1.y;
  9221. nka[ offset_morphTarget + 2 ] = n1.z;
  9222. nka[ offset_morphTarget + 3 ] = n2.x;
  9223. nka[ offset_morphTarget + 4 ] = n2.y;
  9224. nka[ offset_morphTarget + 5 ] = n2.z;
  9225. nka[ offset_morphTarget + 6 ] = n3.x;
  9226. nka[ offset_morphTarget + 7 ] = n3.y;
  9227. nka[ offset_morphTarget + 8 ] = n3.z;
  9228. nka[ offset_morphTarget + 9 ] = n4.x;
  9229. nka[ offset_morphTarget + 10 ] = n4.y;
  9230. nka[ offset_morphTarget + 11 ] = n4.z;
  9231. }
  9232. //
  9233. offset_morphTarget += 12;
  9234. }
  9235. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
  9236. _gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
  9237. if ( material.morphNormals ) {
  9238. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
  9239. _gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
  9240. }
  9241. }
  9242. }
  9243. if ( obj_skinWeights.length ) {
  9244. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9245. face = obj_faces[ chunk_faces3[ f ] ];
  9246. // weights
  9247. sw1 = obj_skinWeights[ face.a ];
  9248. sw2 = obj_skinWeights[ face.b ];
  9249. sw3 = obj_skinWeights[ face.c ];
  9250. skinWeightArray[ offset_skin ] = sw1.x;
  9251. skinWeightArray[ offset_skin + 1 ] = sw1.y;
  9252. skinWeightArray[ offset_skin + 2 ] = sw1.z;
  9253. skinWeightArray[ offset_skin + 3 ] = sw1.w;
  9254. skinWeightArray[ offset_skin + 4 ] = sw2.x;
  9255. skinWeightArray[ offset_skin + 5 ] = sw2.y;
  9256. skinWeightArray[ offset_skin + 6 ] = sw2.z;
  9257. skinWeightArray[ offset_skin + 7 ] = sw2.w;
  9258. skinWeightArray[ offset_skin + 8 ] = sw3.x;
  9259. skinWeightArray[ offset_skin + 9 ] = sw3.y;
  9260. skinWeightArray[ offset_skin + 10 ] = sw3.z;
  9261. skinWeightArray[ offset_skin + 11 ] = sw3.w;
  9262. // indices
  9263. si1 = obj_skinIndices[ face.a ];
  9264. si2 = obj_skinIndices[ face.b ];
  9265. si3 = obj_skinIndices[ face.c ];
  9266. skinIndexArray[ offset_skin ] = si1.x;
  9267. skinIndexArray[ offset_skin + 1 ] = si1.y;
  9268. skinIndexArray[ offset_skin + 2 ] = si1.z;
  9269. skinIndexArray[ offset_skin + 3 ] = si1.w;
  9270. skinIndexArray[ offset_skin + 4 ] = si2.x;
  9271. skinIndexArray[ offset_skin + 5 ] = si2.y;
  9272. skinIndexArray[ offset_skin + 6 ] = si2.z;
  9273. skinIndexArray[ offset_skin + 7 ] = si2.w;
  9274. skinIndexArray[ offset_skin + 8 ] = si3.x;
  9275. skinIndexArray[ offset_skin + 9 ] = si3.y;
  9276. skinIndexArray[ offset_skin + 10 ] = si3.z;
  9277. skinIndexArray[ offset_skin + 11 ] = si3.w;
  9278. // vertices A
  9279. sa1 = obj_skinVerticesA[ face.a ];
  9280. sa2 = obj_skinVerticesA[ face.b ];
  9281. sa3 = obj_skinVerticesA[ face.c ];
  9282. skinVertexAArray[ offset_skin ] = sa1.x;
  9283. skinVertexAArray[ offset_skin + 1 ] = sa1.y;
  9284. skinVertexAArray[ offset_skin + 2 ] = sa1.z;
  9285. skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
  9286. skinVertexAArray[ offset_skin + 4 ] = sa2.x;
  9287. skinVertexAArray[ offset_skin + 5 ] = sa2.y;
  9288. skinVertexAArray[ offset_skin + 6 ] = sa2.z;
  9289. skinVertexAArray[ offset_skin + 7 ] = 1;
  9290. skinVertexAArray[ offset_skin + 8 ] = sa3.x;
  9291. skinVertexAArray[ offset_skin + 9 ] = sa3.y;
  9292. skinVertexAArray[ offset_skin + 10 ] = sa3.z;
  9293. skinVertexAArray[ offset_skin + 11 ] = 1;
  9294. // vertices B
  9295. sb1 = obj_skinVerticesB[ face.a ];
  9296. sb2 = obj_skinVerticesB[ face.b ];
  9297. sb3 = obj_skinVerticesB[ face.c ];
  9298. skinVertexBArray[ offset_skin ] = sb1.x;
  9299. skinVertexBArray[ offset_skin + 1 ] = sb1.y;
  9300. skinVertexBArray[ offset_skin + 2 ] = sb1.z;
  9301. skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
  9302. skinVertexBArray[ offset_skin + 4 ] = sb2.x;
  9303. skinVertexBArray[ offset_skin + 5 ] = sb2.y;
  9304. skinVertexBArray[ offset_skin + 6 ] = sb2.z;
  9305. skinVertexBArray[ offset_skin + 7 ] = 1;
  9306. skinVertexBArray[ offset_skin + 8 ] = sb3.x;
  9307. skinVertexBArray[ offset_skin + 9 ] = sb3.y;
  9308. skinVertexBArray[ offset_skin + 10 ] = sb3.z;
  9309. skinVertexBArray[ offset_skin + 11 ] = 1;
  9310. offset_skin += 12;
  9311. }
  9312. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9313. face = obj_faces[ chunk_faces4[ f ] ];
  9314. // weights
  9315. sw1 = obj_skinWeights[ face.a ];
  9316. sw2 = obj_skinWeights[ face.b ];
  9317. sw3 = obj_skinWeights[ face.c ];
  9318. sw4 = obj_skinWeights[ face.d ];
  9319. skinWeightArray[ offset_skin ] = sw1.x;
  9320. skinWeightArray[ offset_skin + 1 ] = sw1.y;
  9321. skinWeightArray[ offset_skin + 2 ] = sw1.z;
  9322. skinWeightArray[ offset_skin + 3 ] = sw1.w;
  9323. skinWeightArray[ offset_skin + 4 ] = sw2.x;
  9324. skinWeightArray[ offset_skin + 5 ] = sw2.y;
  9325. skinWeightArray[ offset_skin + 6 ] = sw2.z;
  9326. skinWeightArray[ offset_skin + 7 ] = sw2.w;
  9327. skinWeightArray[ offset_skin + 8 ] = sw3.x;
  9328. skinWeightArray[ offset_skin + 9 ] = sw3.y;
  9329. skinWeightArray[ offset_skin + 10 ] = sw3.z;
  9330. skinWeightArray[ offset_skin + 11 ] = sw3.w;
  9331. skinWeightArray[ offset_skin + 12 ] = sw4.x;
  9332. skinWeightArray[ offset_skin + 13 ] = sw4.y;
  9333. skinWeightArray[ offset_skin + 14 ] = sw4.z;
  9334. skinWeightArray[ offset_skin + 15 ] = sw4.w;
  9335. // indices
  9336. si1 = obj_skinIndices[ face.a ];
  9337. si2 = obj_skinIndices[ face.b ];
  9338. si3 = obj_skinIndices[ face.c ];
  9339. si4 = obj_skinIndices[ face.d ];
  9340. skinIndexArray[ offset_skin ] = si1.x;
  9341. skinIndexArray[ offset_skin + 1 ] = si1.y;
  9342. skinIndexArray[ offset_skin + 2 ] = si1.z;
  9343. skinIndexArray[ offset_skin + 3 ] = si1.w;
  9344. skinIndexArray[ offset_skin + 4 ] = si2.x;
  9345. skinIndexArray[ offset_skin + 5 ] = si2.y;
  9346. skinIndexArray[ offset_skin + 6 ] = si2.z;
  9347. skinIndexArray[ offset_skin + 7 ] = si2.w;
  9348. skinIndexArray[ offset_skin + 8 ] = si3.x;
  9349. skinIndexArray[ offset_skin + 9 ] = si3.y;
  9350. skinIndexArray[ offset_skin + 10 ] = si3.z;
  9351. skinIndexArray[ offset_skin + 11 ] = si3.w;
  9352. skinIndexArray[ offset_skin + 12 ] = si4.x;
  9353. skinIndexArray[ offset_skin + 13 ] = si4.y;
  9354. skinIndexArray[ offset_skin + 14 ] = si4.z;
  9355. skinIndexArray[ offset_skin + 15 ] = si4.w;
  9356. // vertices A
  9357. sa1 = obj_skinVerticesA[ face.a ];
  9358. sa2 = obj_skinVerticesA[ face.b ];
  9359. sa3 = obj_skinVerticesA[ face.c ];
  9360. sa4 = obj_skinVerticesA[ face.d ];
  9361. skinVertexAArray[ offset_skin ] = sa1.x;
  9362. skinVertexAArray[ offset_skin + 1 ] = sa1.y;
  9363. skinVertexAArray[ offset_skin + 2 ] = sa1.z;
  9364. skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
  9365. skinVertexAArray[ offset_skin + 4 ] = sa2.x;
  9366. skinVertexAArray[ offset_skin + 5 ] = sa2.y;
  9367. skinVertexAArray[ offset_skin + 6 ] = sa2.z;
  9368. skinVertexAArray[ offset_skin + 7 ] = 1;
  9369. skinVertexAArray[ offset_skin + 8 ] = sa3.x;
  9370. skinVertexAArray[ offset_skin + 9 ] = sa3.y;
  9371. skinVertexAArray[ offset_skin + 10 ] = sa3.z;
  9372. skinVertexAArray[ offset_skin + 11 ] = 1;
  9373. skinVertexAArray[ offset_skin + 12 ] = sa4.x;
  9374. skinVertexAArray[ offset_skin + 13 ] = sa4.y;
  9375. skinVertexAArray[ offset_skin + 14 ] = sa4.z;
  9376. skinVertexAArray[ offset_skin + 15 ] = 1;
  9377. // vertices B
  9378. sb1 = obj_skinVerticesB[ face.a ];
  9379. sb2 = obj_skinVerticesB[ face.b ];
  9380. sb3 = obj_skinVerticesB[ face.c ];
  9381. sb4 = obj_skinVerticesB[ face.d ];
  9382. skinVertexBArray[ offset_skin ] = sb1.x;
  9383. skinVertexBArray[ offset_skin + 1 ] = sb1.y;
  9384. skinVertexBArray[ offset_skin + 2 ] = sb1.z;
  9385. skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader
  9386. skinVertexBArray[ offset_skin + 4 ] = sb2.x;
  9387. skinVertexBArray[ offset_skin + 5 ] = sb2.y;
  9388. skinVertexBArray[ offset_skin + 6 ] = sb2.z;
  9389. skinVertexBArray[ offset_skin + 7 ] = 1;
  9390. skinVertexBArray[ offset_skin + 8 ] = sb3.x;
  9391. skinVertexBArray[ offset_skin + 9 ] = sb3.y;
  9392. skinVertexBArray[ offset_skin + 10 ] = sb3.z;
  9393. skinVertexBArray[ offset_skin + 11 ] = 1;
  9394. skinVertexBArray[ offset_skin + 12 ] = sb4.x;
  9395. skinVertexBArray[ offset_skin + 13 ] = sb4.y;
  9396. skinVertexBArray[ offset_skin + 14 ] = sb4.z;
  9397. skinVertexBArray[ offset_skin + 15 ] = 1;
  9398. offset_skin += 16;
  9399. }
  9400. if ( offset_skin > 0 ) {
  9401. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
  9402. _gl.bufferData( _gl.ARRAY_BUFFER, skinVertexAArray, hint );
  9403. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
  9404. _gl.bufferData( _gl.ARRAY_BUFFER, skinVertexBArray, hint );
  9405. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
  9406. _gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
  9407. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
  9408. _gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
  9409. }
  9410. }
  9411. if ( dirtyColors && vertexColorType ) {
  9412. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9413. face = obj_faces[ chunk_faces3[ f ] ];
  9414. vertexColors = face.vertexColors;
  9415. faceColor = face.color;
  9416. if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
  9417. c1 = vertexColors[ 0 ];
  9418. c2 = vertexColors[ 1 ];
  9419. c3 = vertexColors[ 2 ];
  9420. } else {
  9421. c1 = faceColor;
  9422. c2 = faceColor;
  9423. c3 = faceColor;
  9424. }
  9425. colorArray[ offset_color ] = c1.r;
  9426. colorArray[ offset_color + 1 ] = c1.g;
  9427. colorArray[ offset_color + 2 ] = c1.b;
  9428. colorArray[ offset_color + 3 ] = c2.r;
  9429. colorArray[ offset_color + 4 ] = c2.g;
  9430. colorArray[ offset_color + 5 ] = c2.b;
  9431. colorArray[ offset_color + 6 ] = c3.r;
  9432. colorArray[ offset_color + 7 ] = c3.g;
  9433. colorArray[ offset_color + 8 ] = c3.b;
  9434. offset_color += 9;
  9435. }
  9436. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9437. face = obj_faces[ chunk_faces4[ f ] ];
  9438. vertexColors = face.vertexColors;
  9439. faceColor = face.color;
  9440. if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
  9441. c1 = vertexColors[ 0 ];
  9442. c2 = vertexColors[ 1 ];
  9443. c3 = vertexColors[ 2 ];
  9444. c4 = vertexColors[ 3 ];
  9445. } else {
  9446. c1 = faceColor;
  9447. c2 = faceColor;
  9448. c3 = faceColor;
  9449. c4 = faceColor;
  9450. }
  9451. colorArray[ offset_color ] = c1.r;
  9452. colorArray[ offset_color + 1 ] = c1.g;
  9453. colorArray[ offset_color + 2 ] = c1.b;
  9454. colorArray[ offset_color + 3 ] = c2.r;
  9455. colorArray[ offset_color + 4 ] = c2.g;
  9456. colorArray[ offset_color + 5 ] = c2.b;
  9457. colorArray[ offset_color + 6 ] = c3.r;
  9458. colorArray[ offset_color + 7 ] = c3.g;
  9459. colorArray[ offset_color + 8 ] = c3.b;
  9460. colorArray[ offset_color + 9 ] = c4.r;
  9461. colorArray[ offset_color + 10 ] = c4.g;
  9462. colorArray[ offset_color + 11 ] = c4.b;
  9463. offset_color += 12;
  9464. }
  9465. if ( offset_color > 0 ) {
  9466. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
  9467. _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
  9468. }
  9469. }
  9470. if ( dirtyTangents && geometry.hasTangents ) {
  9471. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9472. face = obj_faces[ chunk_faces3[ f ] ];
  9473. vertexTangents = face.vertexTangents;
  9474. t1 = vertexTangents[ 0 ];
  9475. t2 = vertexTangents[ 1 ];
  9476. t3 = vertexTangents[ 2 ];
  9477. tangentArray[ offset_tangent ] = t1.x;
  9478. tangentArray[ offset_tangent + 1 ] = t1.y;
  9479. tangentArray[ offset_tangent + 2 ] = t1.z;
  9480. tangentArray[ offset_tangent + 3 ] = t1.w;
  9481. tangentArray[ offset_tangent + 4 ] = t2.x;
  9482. tangentArray[ offset_tangent + 5 ] = t2.y;
  9483. tangentArray[ offset_tangent + 6 ] = t2.z;
  9484. tangentArray[ offset_tangent + 7 ] = t2.w;
  9485. tangentArray[ offset_tangent + 8 ] = t3.x;
  9486. tangentArray[ offset_tangent + 9 ] = t3.y;
  9487. tangentArray[ offset_tangent + 10 ] = t3.z;
  9488. tangentArray[ offset_tangent + 11 ] = t3.w;
  9489. offset_tangent += 12;
  9490. }
  9491. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9492. face = obj_faces[ chunk_faces4[ f ] ];
  9493. vertexTangents = face.vertexTangents;
  9494. t1 = vertexTangents[ 0 ];
  9495. t2 = vertexTangents[ 1 ];
  9496. t3 = vertexTangents[ 2 ];
  9497. t4 = vertexTangents[ 3 ];
  9498. tangentArray[ offset_tangent ] = t1.x;
  9499. tangentArray[ offset_tangent + 1 ] = t1.y;
  9500. tangentArray[ offset_tangent + 2 ] = t1.z;
  9501. tangentArray[ offset_tangent + 3 ] = t1.w;
  9502. tangentArray[ offset_tangent + 4 ] = t2.x;
  9503. tangentArray[ offset_tangent + 5 ] = t2.y;
  9504. tangentArray[ offset_tangent + 6 ] = t2.z;
  9505. tangentArray[ offset_tangent + 7 ] = t2.w;
  9506. tangentArray[ offset_tangent + 8 ] = t3.x;
  9507. tangentArray[ offset_tangent + 9 ] = t3.y;
  9508. tangentArray[ offset_tangent + 10 ] = t3.z;
  9509. tangentArray[ offset_tangent + 11 ] = t3.w;
  9510. tangentArray[ offset_tangent + 12 ] = t4.x;
  9511. tangentArray[ offset_tangent + 13 ] = t4.y;
  9512. tangentArray[ offset_tangent + 14 ] = t4.z;
  9513. tangentArray[ offset_tangent + 15 ] = t4.w;
  9514. offset_tangent += 16;
  9515. }
  9516. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
  9517. _gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
  9518. }
  9519. if ( dirtyNormals && normalType ) {
  9520. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9521. face = obj_faces[ chunk_faces3[ f ] ];
  9522. vertexNormals = face.vertexNormals;
  9523. faceNormal = face.normal;
  9524. if ( vertexNormals.length === 3 && needsSmoothNormals ) {
  9525. for ( i = 0; i < 3; i ++ ) {
  9526. vn = vertexNormals[ i ];
  9527. normalArray[ offset_normal ] = vn.x;
  9528. normalArray[ offset_normal + 1 ] = vn.y;
  9529. normalArray[ offset_normal + 2 ] = vn.z;
  9530. offset_normal += 3;
  9531. }
  9532. } else {
  9533. for ( i = 0; i < 3; i ++ ) {
  9534. normalArray[ offset_normal ] = faceNormal.x;
  9535. normalArray[ offset_normal + 1 ] = faceNormal.y;
  9536. normalArray[ offset_normal + 2 ] = faceNormal.z;
  9537. offset_normal += 3;
  9538. }
  9539. }
  9540. }
  9541. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9542. face = obj_faces[ chunk_faces4[ f ] ];
  9543. vertexNormals = face.vertexNormals;
  9544. faceNormal = face.normal;
  9545. if ( vertexNormals.length === 4 && needsSmoothNormals ) {
  9546. for ( i = 0; i < 4; i ++ ) {
  9547. vn = vertexNormals[ i ];
  9548. normalArray[ offset_normal ] = vn.x;
  9549. normalArray[ offset_normal + 1 ] = vn.y;
  9550. normalArray[ offset_normal + 2 ] = vn.z;
  9551. offset_normal += 3;
  9552. }
  9553. } else {
  9554. for ( i = 0; i < 4; i ++ ) {
  9555. normalArray[ offset_normal ] = faceNormal.x;
  9556. normalArray[ offset_normal + 1 ] = faceNormal.y;
  9557. normalArray[ offset_normal + 2 ] = faceNormal.z;
  9558. offset_normal += 3;
  9559. }
  9560. }
  9561. }
  9562. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
  9563. _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
  9564. }
  9565. if ( dirtyUvs && obj_uvs && uvType ) {
  9566. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9567. fi = chunk_faces3[ f ];
  9568. face = obj_faces[ fi ];
  9569. uv = obj_uvs[ fi ];
  9570. if ( uv === undefined ) continue;
  9571. for ( i = 0; i < 3; i ++ ) {
  9572. uvi = uv[ i ];
  9573. uvArray[ offset_uv ] = uvi.u;
  9574. uvArray[ offset_uv + 1 ] = uvi.v;
  9575. offset_uv += 2;
  9576. }
  9577. }
  9578. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9579. fi = chunk_faces4[ f ];
  9580. face = obj_faces[ fi ];
  9581. uv = obj_uvs[ fi ];
  9582. if ( uv === undefined ) continue;
  9583. for ( i = 0; i < 4; i ++ ) {
  9584. uvi = uv[ i ];
  9585. uvArray[ offset_uv ] = uvi.u;
  9586. uvArray[ offset_uv + 1 ] = uvi.v;
  9587. offset_uv += 2;
  9588. }
  9589. }
  9590. if ( offset_uv > 0 ) {
  9591. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
  9592. _gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
  9593. }
  9594. }
  9595. if ( dirtyUvs && obj_uvs2 && uvType ) {
  9596. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9597. fi = chunk_faces3[ f ];
  9598. face = obj_faces[ fi ];
  9599. uv2 = obj_uvs2[ fi ];
  9600. if ( uv2 === undefined ) continue;
  9601. for ( i = 0; i < 3; i ++ ) {
  9602. uv2i = uv2[ i ];
  9603. uv2Array[ offset_uv2 ] = uv2i.u;
  9604. uv2Array[ offset_uv2 + 1 ] = uv2i.v;
  9605. offset_uv2 += 2;
  9606. }
  9607. }
  9608. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9609. fi = chunk_faces4[ f ];
  9610. face = obj_faces[ fi ];
  9611. uv2 = obj_uvs2[ fi ];
  9612. if ( uv2 === undefined ) continue;
  9613. for ( i = 0; i < 4; i ++ ) {
  9614. uv2i = uv2[ i ];
  9615. uv2Array[ offset_uv2 ] = uv2i.u;
  9616. uv2Array[ offset_uv2 + 1 ] = uv2i.v;
  9617. offset_uv2 += 2;
  9618. }
  9619. }
  9620. if ( offset_uv2 > 0 ) {
  9621. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
  9622. _gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
  9623. }
  9624. }
  9625. if ( dirtyElements ) {
  9626. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9627. face = obj_faces[ chunk_faces3[ f ] ];
  9628. faceArray[ offset_face ] = vertexIndex;
  9629. faceArray[ offset_face + 1 ] = vertexIndex + 1;
  9630. faceArray[ offset_face + 2 ] = vertexIndex + 2;
  9631. offset_face += 3;
  9632. lineArray[ offset_line ] = vertexIndex;
  9633. lineArray[ offset_line + 1 ] = vertexIndex + 1;
  9634. lineArray[ offset_line + 2 ] = vertexIndex;
  9635. lineArray[ offset_line + 3 ] = vertexIndex + 2;
  9636. lineArray[ offset_line + 4 ] = vertexIndex + 1;
  9637. lineArray[ offset_line + 5 ] = vertexIndex + 2;
  9638. offset_line += 6;
  9639. vertexIndex += 3;
  9640. }
  9641. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9642. face = obj_faces[ chunk_faces4[ f ] ];
  9643. faceArray[ offset_face ] = vertexIndex;
  9644. faceArray[ offset_face + 1 ] = vertexIndex + 1;
  9645. faceArray[ offset_face + 2 ] = vertexIndex + 3;
  9646. faceArray[ offset_face + 3 ] = vertexIndex + 1;
  9647. faceArray[ offset_face + 4 ] = vertexIndex + 2;
  9648. faceArray[ offset_face + 5 ] = vertexIndex + 3;
  9649. offset_face += 6;
  9650. lineArray[ offset_line ] = vertexIndex;
  9651. lineArray[ offset_line + 1 ] = vertexIndex + 1;
  9652. lineArray[ offset_line + 2 ] = vertexIndex;
  9653. lineArray[ offset_line + 3 ] = vertexIndex + 3;
  9654. lineArray[ offset_line + 4 ] = vertexIndex + 1;
  9655. lineArray[ offset_line + 5 ] = vertexIndex + 2;
  9656. lineArray[ offset_line + 6 ] = vertexIndex + 2;
  9657. lineArray[ offset_line + 7 ] = vertexIndex + 3;
  9658. offset_line += 8;
  9659. vertexIndex += 4;
  9660. }
  9661. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
  9662. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
  9663. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
  9664. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
  9665. }
  9666. if ( customAttributes ) {
  9667. for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
  9668. customAttribute = customAttributes[ i ];
  9669. if ( ! customAttribute.__original.needsUpdate ) continue;
  9670. offset_custom = 0;
  9671. offset_customSrc = 0;
  9672. if ( customAttribute.size === 1 ) {
  9673. if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
  9674. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9675. face = obj_faces[ chunk_faces3[ f ] ];
  9676. customAttribute.array[ offset_custom ] = customAttribute.value[ face.a ];
  9677. customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
  9678. customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
  9679. offset_custom += 3;
  9680. }
  9681. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9682. face = obj_faces[ chunk_faces4[ f ] ];
  9683. customAttribute.array[ offset_custom ] = customAttribute.value[ face.a ];
  9684. customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
  9685. customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
  9686. customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
  9687. offset_custom += 4;
  9688. }
  9689. } else if ( customAttribute.boundTo === "faces" ) {
  9690. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9691. value = customAttribute.value[ chunk_faces3[ f ] ];
  9692. customAttribute.array[ offset_custom ] = value;
  9693. customAttribute.array[ offset_custom + 1 ] = value;
  9694. customAttribute.array[ offset_custom + 2 ] = value;
  9695. offset_custom += 3;
  9696. }
  9697. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9698. value = customAttribute.value[ chunk_faces4[ f ] ];
  9699. customAttribute.array[ offset_custom ] = value;
  9700. customAttribute.array[ offset_custom + 1 ] = value;
  9701. customAttribute.array[ offset_custom + 2 ] = value;
  9702. customAttribute.array[ offset_custom + 3 ] = value;
  9703. offset_custom += 4;
  9704. }
  9705. }
  9706. } else if ( customAttribute.size === 2 ) {
  9707. if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
  9708. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9709. face = obj_faces[ chunk_faces3[ f ] ];
  9710. v1 = customAttribute.value[ face.a ];
  9711. v2 = customAttribute.value[ face.b ];
  9712. v3 = customAttribute.value[ face.c ];
  9713. customAttribute.array[ offset_custom ] = v1.x;
  9714. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9715. customAttribute.array[ offset_custom + 2 ] = v2.x;
  9716. customAttribute.array[ offset_custom + 3 ] = v2.y;
  9717. customAttribute.array[ offset_custom + 4 ] = v3.x;
  9718. customAttribute.array[ offset_custom + 5 ] = v3.y;
  9719. offset_custom += 6;
  9720. }
  9721. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9722. face = obj_faces[ chunk_faces4[ f ] ];
  9723. v1 = customAttribute.value[ face.a ];
  9724. v2 = customAttribute.value[ face.b ];
  9725. v3 = customAttribute.value[ face.c ];
  9726. v4 = customAttribute.value[ face.d ];
  9727. customAttribute.array[ offset_custom ] = v1.x;
  9728. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9729. customAttribute.array[ offset_custom + 2 ] = v2.x;
  9730. customAttribute.array[ offset_custom + 3 ] = v2.y;
  9731. customAttribute.array[ offset_custom + 4 ] = v3.x;
  9732. customAttribute.array[ offset_custom + 5 ] = v3.y;
  9733. customAttribute.array[ offset_custom + 6 ] = v4.x;
  9734. customAttribute.array[ offset_custom + 7 ] = v4.y;
  9735. offset_custom += 8;
  9736. }
  9737. } else if ( customAttribute.boundTo === "faces" ) {
  9738. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9739. value = customAttribute.value[ chunk_faces3[ f ] ];
  9740. v1 = value;
  9741. v2 = value;
  9742. v3 = value;
  9743. customAttribute.array[ offset_custom ] = v1.x;
  9744. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9745. customAttribute.array[ offset_custom + 2 ] = v2.x;
  9746. customAttribute.array[ offset_custom + 3 ] = v2.y;
  9747. customAttribute.array[ offset_custom + 4 ] = v3.x;
  9748. customAttribute.array[ offset_custom + 5 ] = v3.y;
  9749. offset_custom += 6;
  9750. }
  9751. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9752. value = customAttribute.value[ chunk_faces4[ f ] ];
  9753. v1 = value;
  9754. v2 = value;
  9755. v3 = value;
  9756. v4 = value;
  9757. customAttribute.array[ offset_custom ] = v1.x;
  9758. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9759. customAttribute.array[ offset_custom + 2 ] = v2.x;
  9760. customAttribute.array[ offset_custom + 3 ] = v2.y;
  9761. customAttribute.array[ offset_custom + 4 ] = v3.x;
  9762. customAttribute.array[ offset_custom + 5 ] = v3.y;
  9763. customAttribute.array[ offset_custom + 6 ] = v4.x;
  9764. customAttribute.array[ offset_custom + 7 ] = v4.y;
  9765. offset_custom += 8;
  9766. }
  9767. }
  9768. } else if ( customAttribute.size === 3 ) {
  9769. var pp;
  9770. if ( customAttribute.type === "c" ) {
  9771. pp = [ "r", "g", "b" ];
  9772. } else {
  9773. pp = [ "x", "y", "z" ];
  9774. }
  9775. if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
  9776. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9777. face = obj_faces[ chunk_faces3[ f ] ];
  9778. v1 = customAttribute.value[ face.a ];
  9779. v2 = customAttribute.value[ face.b ];
  9780. v3 = customAttribute.value[ face.c ];
  9781. customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
  9782. customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
  9783. customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
  9784. customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
  9785. customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
  9786. customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
  9787. customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
  9788. customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
  9789. customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
  9790. offset_custom += 9;
  9791. }
  9792. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9793. face = obj_faces[ chunk_faces4[ f ] ];
  9794. v1 = customAttribute.value[ face.a ];
  9795. v2 = customAttribute.value[ face.b ];
  9796. v3 = customAttribute.value[ face.c ];
  9797. v4 = customAttribute.value[ face.d ];
  9798. customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
  9799. customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
  9800. customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
  9801. customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
  9802. customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
  9803. customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
  9804. customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
  9805. customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
  9806. customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
  9807. customAttribute.array[ offset_custom + 9 ] = v4[ pp[ 0 ] ];
  9808. customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
  9809. customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
  9810. offset_custom += 12;
  9811. }
  9812. } else if ( customAttribute.boundTo === "faces" ) {
  9813. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9814. value = customAttribute.value[ chunk_faces3[ f ] ];
  9815. v1 = value;
  9816. v2 = value;
  9817. v3 = value;
  9818. customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
  9819. customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
  9820. customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
  9821. customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
  9822. customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
  9823. customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
  9824. customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
  9825. customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
  9826. customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
  9827. offset_custom += 9;
  9828. }
  9829. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9830. value = customAttribute.value[ chunk_faces4[ f ] ];
  9831. v1 = value;
  9832. v2 = value;
  9833. v3 = value;
  9834. v4 = value;
  9835. customAttribute.array[ offset_custom ] = v1[ pp[ 0 ] ];
  9836. customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
  9837. customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
  9838. customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
  9839. customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
  9840. customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
  9841. customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
  9842. customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
  9843. customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
  9844. customAttribute.array[ offset_custom + 9 ] = v4[ pp[ 0 ] ];
  9845. customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
  9846. customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
  9847. offset_custom += 12;
  9848. }
  9849. }
  9850. } else if ( customAttribute.size === 4 ) {
  9851. if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
  9852. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9853. face = obj_faces[ chunk_faces3[ f ] ];
  9854. v1 = customAttribute.value[ face.a ];
  9855. v2 = customAttribute.value[ face.b ];
  9856. v3 = customAttribute.value[ face.c ];
  9857. customAttribute.array[ offset_custom ] = v1.x;
  9858. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9859. customAttribute.array[ offset_custom + 2 ] = v1.z;
  9860. customAttribute.array[ offset_custom + 3 ] = v1.w;
  9861. customAttribute.array[ offset_custom + 4 ] = v2.x;
  9862. customAttribute.array[ offset_custom + 5 ] = v2.y;
  9863. customAttribute.array[ offset_custom + 6 ] = v2.z;
  9864. customAttribute.array[ offset_custom + 7 ] = v2.w;
  9865. customAttribute.array[ offset_custom + 8 ] = v3.x;
  9866. customAttribute.array[ offset_custom + 9 ] = v3.y;
  9867. customAttribute.array[ offset_custom + 10 ] = v3.z;
  9868. customAttribute.array[ offset_custom + 11 ] = v3.w;
  9869. offset_custom += 12;
  9870. }
  9871. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9872. face = obj_faces[ chunk_faces4[ f ] ];
  9873. v1 = customAttribute.value[ face.a ];
  9874. v2 = customAttribute.value[ face.b ];
  9875. v3 = customAttribute.value[ face.c ];
  9876. v4 = customAttribute.value[ face.d ];
  9877. customAttribute.array[ offset_custom ] = v1.x;
  9878. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9879. customAttribute.array[ offset_custom + 2 ] = v1.z;
  9880. customAttribute.array[ offset_custom + 3 ] = v1.w;
  9881. customAttribute.array[ offset_custom + 4 ] = v2.x;
  9882. customAttribute.array[ offset_custom + 5 ] = v2.y;
  9883. customAttribute.array[ offset_custom + 6 ] = v2.z;
  9884. customAttribute.array[ offset_custom + 7 ] = v2.w;
  9885. customAttribute.array[ offset_custom + 8 ] = v3.x;
  9886. customAttribute.array[ offset_custom + 9 ] = v3.y;
  9887. customAttribute.array[ offset_custom + 10 ] = v3.z;
  9888. customAttribute.array[ offset_custom + 11 ] = v3.w;
  9889. customAttribute.array[ offset_custom + 12 ] = v4.x;
  9890. customAttribute.array[ offset_custom + 13 ] = v4.y;
  9891. customAttribute.array[ offset_custom + 14 ] = v4.z;
  9892. customAttribute.array[ offset_custom + 15 ] = v4.w;
  9893. offset_custom += 16;
  9894. }
  9895. } else if ( customAttribute.boundTo === "faces" ) {
  9896. for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
  9897. value = customAttribute.value[ chunk_faces3[ f ] ];
  9898. v1 = value;
  9899. v2 = value;
  9900. v3 = value;
  9901. customAttribute.array[ offset_custom ] = v1.x;
  9902. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9903. customAttribute.array[ offset_custom + 2 ] = v1.z;
  9904. customAttribute.array[ offset_custom + 3 ] = v1.w;
  9905. customAttribute.array[ offset_custom + 4 ] = v2.x;
  9906. customAttribute.array[ offset_custom + 5 ] = v2.y;
  9907. customAttribute.array[ offset_custom + 6 ] = v2.z;
  9908. customAttribute.array[ offset_custom + 7 ] = v2.w;
  9909. customAttribute.array[ offset_custom + 8 ] = v3.x;
  9910. customAttribute.array[ offset_custom + 9 ] = v3.y;
  9911. customAttribute.array[ offset_custom + 10 ] = v3.z;
  9912. customAttribute.array[ offset_custom + 11 ] = v3.w;
  9913. offset_custom += 12;
  9914. }
  9915. for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
  9916. value = customAttribute.value[ chunk_faces4[ f ] ];
  9917. v1 = value;
  9918. v2 = value;
  9919. v3 = value;
  9920. v4 = value;
  9921. customAttribute.array[ offset_custom ] = v1.x;
  9922. customAttribute.array[ offset_custom + 1 ] = v1.y;
  9923. customAttribute.array[ offset_custom + 2 ] = v1.z;
  9924. customAttribute.array[ offset_custom + 3 ] = v1.w;
  9925. customAttribute.array[ offset_custom + 4 ] = v2.x;
  9926. customAttribute.array[ offset_custom + 5 ] = v2.y;
  9927. customAttribute.array[ offset_custom + 6 ] = v2.z;
  9928. customAttribute.array[ offset_custom + 7 ] = v2.w;
  9929. customAttribute.array[ offset_custom + 8 ] = v3.x;
  9930. customAttribute.array[ offset_custom + 9 ] = v3.y;
  9931. customAttribute.array[ offset_custom + 10 ] = v3.z;
  9932. customAttribute.array[ offset_custom + 11 ] = v3.w;
  9933. customAttribute.array[ offset_custom + 12 ] = v4.x;
  9934. customAttribute.array[ offset_custom + 13 ] = v4.y;
  9935. customAttribute.array[ offset_custom + 14 ] = v4.z;
  9936. customAttribute.array[ offset_custom + 15 ] = v4.w;
  9937. offset_custom += 16;
  9938. }
  9939. }
  9940. }
  9941. _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
  9942. _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
  9943. }
  9944. }
  9945. if ( dispose ) {
  9946. delete geometryGroup.__inittedArrays;
  9947. delete geometryGroup.__colorArray;
  9948. delete geometryGroup.__normalArray;
  9949. delete geometryGroup.__tangentArray;
  9950. delete geometryGroup.__uvArray;
  9951. delete geometryGroup.__uv2Array;
  9952. delete geometryGroup.__faceArray;
  9953. delete geometryGroup.__vertexArray;
  9954. delete geometryGroup.__lineArray;
  9955. delete geometryGroup.__skinVertexAArray;
  9956. delete geometryGroup.__skinVertexBArray;
  9957. delete geometryGroup.__skinIndexArray;
  9958. delete geometryGroup.__skinWeightArray;
  9959. }
  9960. };
  9961. function setDirectBuffers ( geometry, hint, dispose ) {
  9962. var attributes = geometry.attributes;
  9963. var index = attributes[ "index" ];
  9964. var position = attributes[ "position" ];
  9965. var normal = attributes[ "normal" ];
  9966. var uv = attributes[ "uv" ];
  9967. var color = attributes[ "color" ];
  9968. var tangent = attributes[ "tangent" ];
  9969. if ( geometry.elementsNeedUpdate && index !== undefined ) {
  9970. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
  9971. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, index.array, hint );
  9972. }
  9973. if ( geometry.verticesNeedUpdate && position !== undefined ) {
  9974. _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
  9975. _gl.bufferData( _gl.ARRAY_BUFFER, position.array, hint );
  9976. }
  9977. if ( geometry.normalsNeedUpdate && normal !== undefined ) {
  9978. _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
  9979. _gl.bufferData( _gl.ARRAY_BUFFER, normal.array, hint );
  9980. }
  9981. if ( geometry.uvsNeedUpdate && uv !== undefined ) {
  9982. _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
  9983. _gl.bufferData( _gl.ARRAY_BUFFER, uv.array, hint );
  9984. }
  9985. if ( geometry.colorsNeedUpdate && color !== undefined ) {
  9986. _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
  9987. _gl.bufferData( _gl.ARRAY_BUFFER, color.array, hint );
  9988. }
  9989. if ( geometry.tangentsNeedUpdate && tangent !== undefined ) {
  9990. _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
  9991. _gl.bufferData( _gl.ARRAY_BUFFER, tangent.array, hint );
  9992. }
  9993. if ( dispose ) {
  9994. for ( var i in geometry.attributes ) {
  9995. delete geometry.attributes[ i ].array;
  9996. }
  9997. }
  9998. };
  9999. // Buffer rendering
  10000. this.renderBufferImmediate = function ( object, program, material ) {
  10001. if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
  10002. if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
  10003. if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
  10004. if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
  10005. if ( object.hasPositions ) {
  10006. _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
  10007. _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
  10008. _gl.enableVertexAttribArray( program.attributes.position );
  10009. _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
  10010. }
  10011. if ( object.hasNormals ) {
  10012. _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
  10013. if ( material.shading === THREE.FlatShading ) {
  10014. var nx, ny, nz,
  10015. nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
  10016. normalArray,
  10017. i, il = object.count * 3;
  10018. for( i = 0; i < il; i += 9 ) {
  10019. normalArray = object.normalArray;
  10020. nax = normalArray[ i ];
  10021. nay = normalArray[ i + 1 ];
  10022. naz = normalArray[ i + 2 ];
  10023. nbx = normalArray[ i + 3 ];
  10024. nby = normalArray[ i + 4 ];
  10025. nbz = normalArray[ i + 5 ];
  10026. ncx = normalArray[ i + 6 ];
  10027. ncy = normalArray[ i + 7 ];
  10028. ncz = normalArray[ i + 8 ];
  10029. nx = ( nax + nbx + ncx ) / 3;
  10030. ny = ( nay + nby + ncy ) / 3;
  10031. nz = ( naz + nbz + ncz ) / 3;
  10032. normalArray[ i ] = nx;
  10033. normalArray[ i + 1 ] = ny;
  10034. normalArray[ i + 2 ] = nz;
  10035. normalArray[ i + 3 ] = nx;
  10036. normalArray[ i + 4 ] = ny;
  10037. normalArray[ i + 5 ] = nz;
  10038. normalArray[ i + 6 ] = nx;
  10039. normalArray[ i + 7 ] = ny;
  10040. normalArray[ i + 8 ] = nz;
  10041. }
  10042. }
  10043. _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
  10044. _gl.enableVertexAttribArray( program.attributes.normal );
  10045. _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
  10046. }
  10047. if ( object.hasUvs && material.map ) {
  10048. _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
  10049. _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
  10050. _gl.enableVertexAttribArray( program.attributes.uv );
  10051. _gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
  10052. }
  10053. if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
  10054. _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
  10055. _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
  10056. _gl.enableVertexAttribArray( program.attributes.color );
  10057. _gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
  10058. }
  10059. _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
  10060. object.count = 0;
  10061. };
  10062. this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
  10063. if ( material.visible === false ) return;
  10064. var program, attributes, linewidth, primitives, a, attribute;
  10065. program = setProgram( camera, lights, fog, material, object );
  10066. attributes = program.attributes;
  10067. var updateBuffers = false,
  10068. wireframeBit = material.wireframe ? 1 : 0,
  10069. geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
  10070. if ( geometryHash !== _currentGeometryGroupHash ) {
  10071. _currentGeometryGroupHash = geometryHash;
  10072. updateBuffers = true;
  10073. }
  10074. // render mesh
  10075. if ( object instanceof THREE.Mesh ) {
  10076. var offsets = geometry.offsets;
  10077. // if there is more than 1 chunk
  10078. // must set attribute pointers to use new offsets for each chunk
  10079. // even if geometry and materials didn't change
  10080. if ( offsets.length > 1 ) updateBuffers = true;
  10081. for ( var i = 0, il = offsets.length; i < il; ++ i ) {
  10082. var startIndex = offsets[ i ].index;
  10083. if ( updateBuffers ) {
  10084. // vertices
  10085. var position = geometry.attributes[ "position" ];
  10086. var positionSize = position.itemSize;
  10087. _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
  10088. _gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, startIndex * positionSize * 4 ); // 4 bytes per Float32
  10089. // normals
  10090. var normal = geometry.attributes[ "normal" ];
  10091. if ( attributes.normal >= 0 && normal ) {
  10092. var normalSize = normal.itemSize;
  10093. _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
  10094. _gl.vertexAttribPointer( attributes.normal, normalSize, _gl.FLOAT, false, 0, startIndex * normalSize * 4 );
  10095. }
  10096. // uvs
  10097. var uv = geometry.attributes[ "uv" ];
  10098. if ( attributes.uv >= 0 && uv ) {
  10099. if ( uv.buffer ) {
  10100. var uvSize = uv.itemSize;
  10101. _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
  10102. _gl.vertexAttribPointer( attributes.uv, uvSize, _gl.FLOAT, false, 0, startIndex * uvSize * 4 );
  10103. _gl.enableVertexAttribArray( attributes.uv );
  10104. } else {
  10105. _gl.disableVertexAttribArray( attributes.uv );
  10106. }
  10107. }
  10108. // colors
  10109. var color = geometry.attributes[ "color" ];
  10110. if ( attributes.color >= 0 && color ) {
  10111. var colorSize = color.itemSize;
  10112. _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
  10113. _gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, startIndex * colorSize * 4 );
  10114. }
  10115. // tangents
  10116. var tangent = geometry.attributes[ "tangent" ];
  10117. if ( attributes.tangent >= 0 && tangent ) {
  10118. var tangentSize = tangent.itemSize;
  10119. _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
  10120. _gl.vertexAttribPointer( attributes.tangent, tangentSize, _gl.FLOAT, false, 0, startIndex * tangentSize * 4 );
  10121. }
  10122. // indices
  10123. var index = geometry.attributes[ "index" ];
  10124. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
  10125. }
  10126. // render indexed triangles
  10127. _gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16
  10128. _this.info.render.calls ++;
  10129. _this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
  10130. _this.info.render.faces += offsets[ i ].count / 3;
  10131. }
  10132. }
  10133. };
  10134. this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
  10135. if ( material.visible === false ) return;
  10136. var program, attributes, linewidth, primitives, a, attribute, i, il;
  10137. program = setProgram( camera, lights, fog, material, object );
  10138. attributes = program.attributes;
  10139. var updateBuffers = false,
  10140. wireframeBit = material.wireframe ? 1 : 0,
  10141. geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
  10142. if ( geometryGroupHash !== _currentGeometryGroupHash ) {
  10143. _currentGeometryGroupHash = geometryGroupHash;
  10144. updateBuffers = true;
  10145. }
  10146. // vertices
  10147. if ( !material.morphTargets && attributes.position >= 0 ) {
  10148. if ( updateBuffers ) {
  10149. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
  10150. _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
  10151. }
  10152. } else {
  10153. if ( object.morphTargetBase ) {
  10154. setupMorphTargets( material, geometryGroup, object );
  10155. }
  10156. }
  10157. if ( updateBuffers ) {
  10158. // custom attributes
  10159. // Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
  10160. if ( geometryGroup.__webglCustomAttributesList ) {
  10161. for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
  10162. attribute = geometryGroup.__webglCustomAttributesList[ i ];
  10163. if( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
  10164. _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
  10165. _gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
  10166. }
  10167. }
  10168. }
  10169. // colors
  10170. if ( attributes.color >= 0 ) {
  10171. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
  10172. _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
  10173. }
  10174. // normals
  10175. if ( attributes.normal >= 0 ) {
  10176. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
  10177. _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
  10178. }
  10179. // tangents
  10180. if ( attributes.tangent >= 0 ) {
  10181. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
  10182. _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
  10183. }
  10184. // uvs
  10185. if ( attributes.uv >= 0 ) {
  10186. if ( geometryGroup.__webglUVBuffer ) {
  10187. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
  10188. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
  10189. _gl.enableVertexAttribArray( attributes.uv );
  10190. } else {
  10191. _gl.disableVertexAttribArray( attributes.uv );
  10192. }
  10193. }
  10194. if ( attributes.uv2 >= 0 ) {
  10195. if ( geometryGroup.__webglUV2Buffer ) {
  10196. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
  10197. _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
  10198. _gl.enableVertexAttribArray( attributes.uv2 );
  10199. } else {
  10200. _gl.disableVertexAttribArray( attributes.uv2 );
  10201. }
  10202. }
  10203. if ( material.skinning &&
  10204. attributes.skinVertexA >= 0 && attributes.skinVertexB >= 0 &&
  10205. attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
  10206. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
  10207. _gl.vertexAttribPointer( attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0 );
  10208. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
  10209. _gl.vertexAttribPointer( attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0 );
  10210. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
  10211. _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
  10212. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
  10213. _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
  10214. }
  10215. }
  10216. // render mesh
  10217. if ( object instanceof THREE.Mesh ) {
  10218. // wireframe
  10219. if ( material.wireframe ) {
  10220. setLineWidth( material.wireframeLinewidth );
  10221. if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
  10222. _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
  10223. // triangles
  10224. } else {
  10225. if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
  10226. _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
  10227. }
  10228. _this.info.render.calls ++;
  10229. _this.info.render.vertices += geometryGroup.__webglFaceCount;
  10230. _this.info.render.faces += geometryGroup.__webglFaceCount / 3;
  10231. // render lines
  10232. } else if ( object instanceof THREE.Line ) {
  10233. primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
  10234. setLineWidth( material.linewidth );
  10235. _gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
  10236. _this.info.render.calls ++;
  10237. // render particles
  10238. } else if ( object instanceof THREE.ParticleSystem ) {
  10239. _gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
  10240. _this.info.render.calls ++;
  10241. _this.info.render.points += geometryGroup.__webglParticleCount;
  10242. // render ribbon
  10243. } else if ( object instanceof THREE.Ribbon ) {
  10244. _gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
  10245. _this.info.render.calls ++;
  10246. }
  10247. };
  10248. function setupMorphTargets ( material, geometryGroup, object ) {
  10249. // set base
  10250. var attributes = material.program.attributes;
  10251. if ( object.morphTargetBase !== -1 ) {
  10252. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
  10253. _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
  10254. } else if ( attributes.position >= 0 ) {
  10255. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
  10256. _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
  10257. }
  10258. if ( object.morphTargetForcedOrder.length ) {
  10259. // set forced order
  10260. var m = 0;
  10261. var order = object.morphTargetForcedOrder;
  10262. var influences = object.morphTargetInfluences;
  10263. while ( m < material.numSupportedMorphTargets && m < order.length ) {
  10264. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
  10265. _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10266. if ( material.morphNormals ) {
  10267. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
  10268. _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10269. }
  10270. object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
  10271. m ++;
  10272. }
  10273. } else {
  10274. // find the most influencing
  10275. var influence, activeInfluenceIndices = [];
  10276. var influences = object.morphTargetInfluences;
  10277. var i, il = influences.length;
  10278. for ( i = 0; i < il; i ++ ) {
  10279. influence = influences[ i ];
  10280. if ( influence > 0 ) {
  10281. activeInfluenceIndices.push( [ i, influence ] );
  10282. }
  10283. }
  10284. if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
  10285. activeInfluenceIndices.sort( numericalSort );
  10286. activeInfluenceIndices.length = material.numSupportedMorphTargets;
  10287. } else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
  10288. activeInfluenceIndices.sort( numericalSort );
  10289. } else if ( activeInfluenceIndices.length === 0 ) {
  10290. activeInfluenceIndices.push( [ 0, 0 ] );
  10291. };
  10292. var influenceIndex, m = 0;
  10293. while ( m < material.numSupportedMorphTargets ) {
  10294. if ( activeInfluenceIndices[ m ] ) {
  10295. influenceIndex = activeInfluenceIndices[ m ][ 0 ];
  10296. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] );
  10297. _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10298. if ( material.morphNormals ) {
  10299. _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] );
  10300. _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10301. }
  10302. object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
  10303. } else {
  10304. _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10305. if ( material.morphNormals ) {
  10306. _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
  10307. }
  10308. object.__webglMorphTargetInfluences[ m ] = 0;
  10309. }
  10310. m ++;
  10311. }
  10312. }
  10313. // load updated influences uniform
  10314. if ( material.program.uniforms.morphTargetInfluences !== null ) {
  10315. _gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
  10316. }
  10317. };
  10318. // Sorting
  10319. function painterSort ( a, b ) {
  10320. return b.z - a.z;
  10321. };
  10322. function numericalSort ( a, b ) {
  10323. return b[ 1 ] - a[ 1 ];
  10324. };
  10325. // Rendering
  10326. this.render = function ( scene, camera, renderTarget, forceClear ) {
  10327. var i, il,
  10328. webglObject, object,
  10329. renderList,
  10330. lights = scene.__lights,
  10331. fog = scene.fog;
  10332. // reset caching for this frame
  10333. _currentMaterialId = -1;
  10334. _lightsNeedUpdate = true;
  10335. // update scene graph
  10336. if ( camera.parent === undefined ) {
  10337. console.warn( 'DEPRECATED: Camera hasn\'t been added to a Scene. Adding it...' );
  10338. scene.add( camera );
  10339. }
  10340. if ( this.autoUpdateScene ) scene.updateMatrixWorld();
  10341. // update camera matrices and frustum
  10342. if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
  10343. if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
  10344. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  10345. camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
  10346. camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
  10347. _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
  10348. _frustum.setFromMatrix( _projScreenMatrix );
  10349. // update WebGL objects
  10350. if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
  10351. // custom render plugins (pre pass)
  10352. renderPlugins( this.renderPluginsPre, scene, camera );
  10353. //
  10354. _this.info.render.calls = 0;
  10355. _this.info.render.vertices = 0;
  10356. _this.info.render.faces = 0;
  10357. _this.info.render.points = 0;
  10358. this.setRenderTarget( renderTarget );
  10359. if ( this.autoClear || forceClear ) {
  10360. this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
  10361. }
  10362. // set matrices for regular objects (frustum culled)
  10363. renderList = scene.__webglObjects;
  10364. for ( i = 0, il = renderList.length; i < il; i ++ ) {
  10365. webglObject = renderList[ i ];
  10366. object = webglObject.object;
  10367. webglObject.render = false;
  10368. if ( object.visible ) {
  10369. if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
  10370. //object.matrixWorld.flattenToArray( object._objectMatrixArray );
  10371. setupMatrices( object, camera );
  10372. unrollBufferMaterial( webglObject );
  10373. webglObject.render = true;
  10374. if ( this.sortObjects ) {
  10375. if ( object.renderDepth ) {
  10376. webglObject.z = object.renderDepth;
  10377. } else {
  10378. _vector3.copy( object.matrixWorld.getPosition() );
  10379. _projScreenMatrix.multiplyVector3( _vector3 );
  10380. webglObject.z = _vector3.z;
  10381. }
  10382. }
  10383. }
  10384. }
  10385. }
  10386. if ( this.sortObjects ) {
  10387. renderList.sort( painterSort );
  10388. }
  10389. // set matrices for immediate objects
  10390. renderList = scene.__webglObjectsImmediate;
  10391. for ( i = 0, il = renderList.length; i < il; i ++ ) {
  10392. webglObject = renderList[ i ];
  10393. object = webglObject.object;
  10394. if ( object.visible ) {
  10395. /*
  10396. if ( object.matrixAutoUpdate ) {
  10397. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  10398. }
  10399. */
  10400. setupMatrices( object, camera );
  10401. unrollImmediateBufferMaterial( webglObject );
  10402. }
  10403. }
  10404. if ( scene.overrideMaterial ) {
  10405. var material = scene.overrideMaterial;
  10406. this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
  10407. this.setDepthTest( material.depthTest );
  10408. this.setDepthWrite( material.depthWrite );
  10409. setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
  10410. renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
  10411. renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
  10412. } else {
  10413. // opaque pass (front-to-back order)
  10414. this.setBlending( THREE.NormalBlending );
  10415. renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false );
  10416. renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false );
  10417. // transparent pass (back-to-front order)
  10418. renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true );
  10419. renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true );
  10420. }
  10421. // custom render plugins (post pass)
  10422. renderPlugins( this.renderPluginsPost, scene, camera );
  10423. // Generate mipmap if we're using any kind of mipmap filtering
  10424. if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
  10425. updateRenderTargetMipmap( renderTarget );
  10426. }
  10427. // Ensure depth buffer writing is enabled so it can be cleared on next render
  10428. this.setDepthTest( true );
  10429. this.setDepthWrite( true );
  10430. // _gl.finish();
  10431. };
  10432. function renderPlugins( plugins, scene, camera ) {
  10433. if ( ! plugins.length ) return;
  10434. for ( var i = 0, il = plugins.length; i < il; i ++ ) {
  10435. // reset state for plugin (to start from clean slate)
  10436. _currentProgram = null;
  10437. _currentCamera = null;
  10438. _oldBlending = -1;
  10439. _oldDepthTest = -1;
  10440. _oldDepthWrite = -1;
  10441. _oldDoubleSided = -1;
  10442. _oldFlipSided = -1;
  10443. _currentGeometryGroupHash = -1;
  10444. _currentMaterialId = -1;
  10445. _lightsNeedUpdate = true;
  10446. plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
  10447. // reset state after plugin (anything could have changed)
  10448. _currentProgram = null;
  10449. _currentCamera = null;
  10450. _oldBlending = -1;
  10451. _oldDepthTest = -1;
  10452. _oldDepthWrite = -1;
  10453. _oldDoubleSided = -1;
  10454. _oldFlipSided = -1;
  10455. _currentGeometryGroupHash = -1;
  10456. _currentMaterialId = -1;
  10457. _lightsNeedUpdate = true;
  10458. }
  10459. };
  10460. function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
  10461. var webglObject, object, buffer, material, start, end, delta;
  10462. if ( reverse ) {
  10463. start = renderList.length - 1;
  10464. end = -1;
  10465. delta = -1;
  10466. } else {
  10467. start = 0;
  10468. end = renderList.length;
  10469. delta = 1;
  10470. }
  10471. for ( var i = start; i !== end; i += delta ) {
  10472. webglObject = renderList[ i ];
  10473. if ( webglObject.render ) {
  10474. object = webglObject.object;
  10475. buffer = webglObject.buffer;
  10476. if ( overrideMaterial ) {
  10477. material = overrideMaterial;
  10478. } else {
  10479. material = webglObject[ materialType ];
  10480. if ( ! material ) continue;
  10481. if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
  10482. _this.setDepthTest( material.depthTest );
  10483. _this.setDepthWrite( material.depthWrite );
  10484. setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
  10485. }
  10486. _this.setObjectFaces( object );
  10487. if ( buffer instanceof THREE.BufferGeometry ) {
  10488. _this.renderBufferDirect( camera, lights, fog, material, buffer, object );
  10489. } else {
  10490. _this.renderBuffer( camera, lights, fog, material, buffer, object );
  10491. }
  10492. }
  10493. }
  10494. };
  10495. function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
  10496. var webglObject, object, material, program;
  10497. for ( var i = 0, il = renderList.length; i < il; i ++ ) {
  10498. webglObject = renderList[ i ];
  10499. object = webglObject.object;
  10500. if ( object.visible ) {
  10501. if ( overrideMaterial ) {
  10502. material = overrideMaterial;
  10503. } else {
  10504. material = webglObject[ materialType ];
  10505. if ( ! material ) continue;
  10506. if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
  10507. _this.setDepthTest( material.depthTest );
  10508. _this.setDepthWrite( material.depthWrite );
  10509. setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
  10510. }
  10511. _this.renderImmediateObject( camera, lights, fog, material, object );
  10512. }
  10513. }
  10514. };
  10515. this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
  10516. var program = setProgram( camera, lights, fog, material, object );
  10517. _currentGeometryGroupHash = -1;
  10518. _this.setObjectFaces( object );
  10519. if ( object.immediateRenderCallback ) {
  10520. object.immediateRenderCallback( program, _gl, _frustum );
  10521. } else {
  10522. object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
  10523. }
  10524. };
  10525. function unrollImmediateBufferMaterial ( globject ) {
  10526. var object = globject.object,
  10527. material = object.material;
  10528. if ( material.transparent ) {
  10529. globject.transparent = material;
  10530. globject.opaque = null;
  10531. } else {
  10532. globject.opaque = material;
  10533. globject.transparent = null;
  10534. }
  10535. };
  10536. function unrollBufferMaterial ( globject ) {
  10537. var object = globject.object,
  10538. buffer = globject.buffer,
  10539. material, materialIndex, meshMaterial;
  10540. meshMaterial = object.material;
  10541. if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
  10542. materialIndex = buffer.materialIndex;
  10543. if ( materialIndex >= 0 ) {
  10544. material = object.geometry.materials[ materialIndex ];
  10545. if ( material.transparent ) {
  10546. globject.transparent = material;
  10547. globject.opaque = null;
  10548. } else {
  10549. globject.opaque = material;
  10550. globject.transparent = null;
  10551. }
  10552. }
  10553. } else {
  10554. material = meshMaterial;
  10555. if ( material ) {
  10556. if ( material.transparent ) {
  10557. globject.transparent = material;
  10558. globject.opaque = null;
  10559. } else {
  10560. globject.opaque = material;
  10561. globject.transparent = null;
  10562. }
  10563. }
  10564. }
  10565. };
  10566. // Geometry splitting
  10567. function sortFacesByMaterial ( geometry ) {
  10568. var f, fl, face, materialIndex, vertices,
  10569. materialHash, groupHash,
  10570. hash_map = {};
  10571. var numMorphTargets = geometry.morphTargets.length;
  10572. var numMorphNormals = geometry.morphNormals.length;
  10573. geometry.geometryGroups = {};
  10574. for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
  10575. face = geometry.faces[ f ];
  10576. materialIndex = face.materialIndex;
  10577. materialHash = ( materialIndex !== undefined ) ? materialIndex : -1;
  10578. if ( hash_map[ materialHash ] === undefined ) {
  10579. hash_map[ materialHash ] = { 'hash': materialHash, 'counter': 0 };
  10580. }
  10581. groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
  10582. if ( geometry.geometryGroups[ groupHash ] === undefined ) {
  10583. geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
  10584. }
  10585. vertices = face instanceof THREE.Face3 ? 3 : 4;
  10586. if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
  10587. hash_map[ materialHash ].counter += 1;
  10588. groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
  10589. if ( geometry.geometryGroups[ groupHash ] === undefined ) {
  10590. geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
  10591. }
  10592. }
  10593. if ( face instanceof THREE.Face3 ) {
  10594. geometry.geometryGroups[ groupHash ].faces3.push( f );
  10595. } else {
  10596. geometry.geometryGroups[ groupHash ].faces4.push( f );
  10597. }
  10598. geometry.geometryGroups[ groupHash ].vertices += vertices;
  10599. }
  10600. geometry.geometryGroupsList = [];
  10601. for ( var g in geometry.geometryGroups ) {
  10602. geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
  10603. geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
  10604. }
  10605. };
  10606. // Objects refresh
  10607. this.initWebGLObjects = function ( scene ) {
  10608. if ( !scene.__webglObjects ) {
  10609. scene.__webglObjects = [];
  10610. scene.__webglObjectsImmediate = [];
  10611. scene.__webglSprites = [];
  10612. scene.__webglFlares = [];
  10613. }
  10614. while ( scene.__objectsAdded.length ) {
  10615. addObject( scene.__objectsAdded[ 0 ], scene );
  10616. scene.__objectsAdded.splice( 0, 1 );
  10617. }
  10618. while ( scene.__objectsRemoved.length ) {
  10619. removeObject( scene.__objectsRemoved[ 0 ], scene );
  10620. scene.__objectsRemoved.splice( 0, 1 );
  10621. }
  10622. // update must be called after objects adding / removal
  10623. for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
  10624. updateObject( scene.__webglObjects[ o ].object );
  10625. }
  10626. };
  10627. // Objects adding
  10628. function addObject ( object, scene ) {
  10629. var g, geometry, geometryGroup;
  10630. if ( ! object.__webglInit ) {
  10631. object.__webglInit = true;
  10632. object._modelViewMatrix = new THREE.Matrix4();
  10633. object._normalMatrix = new THREE.Matrix3();
  10634. if ( object instanceof THREE.Mesh ) {
  10635. geometry = object.geometry;
  10636. if ( geometry instanceof THREE.Geometry ) {
  10637. if ( geometry.geometryGroups === undefined ) {
  10638. sortFacesByMaterial( geometry );
  10639. }
  10640. // create separate VBOs per geometry chunk
  10641. for ( g in geometry.geometryGroups ) {
  10642. geometryGroup = geometry.geometryGroups[ g ];
  10643. // initialise VBO on the first access
  10644. if ( ! geometryGroup.__webglVertexBuffer ) {
  10645. createMeshBuffers( geometryGroup );
  10646. initMeshBuffers( geometryGroup, object );
  10647. geometry.verticesNeedUpdate = true;
  10648. geometry.morphTargetsNeedUpdate = true;
  10649. geometry.elementsNeedUpdate = true;
  10650. geometry.uvsNeedUpdate = true;
  10651. geometry.normalsNeedUpdate = true;
  10652. geometry.tangentsNeedUpdate = true;
  10653. geometry.colorsNeedUpdate = true;
  10654. }
  10655. }
  10656. } else if ( geometry instanceof THREE.BufferGeometry ) {
  10657. initDirectBuffers( geometry );
  10658. }
  10659. } else if ( object instanceof THREE.Ribbon ) {
  10660. geometry = object.geometry;
  10661. if( ! geometry.__webglVertexBuffer ) {
  10662. createRibbonBuffers( geometry );
  10663. initRibbonBuffers( geometry );
  10664. geometry.verticesNeedUpdate = true;
  10665. geometry.colorsNeedUpdate = true;
  10666. }
  10667. } else if ( object instanceof THREE.Line ) {
  10668. geometry = object.geometry;
  10669. if( ! geometry.__webglVertexBuffer ) {
  10670. createLineBuffers( geometry );
  10671. initLineBuffers( geometry, object );
  10672. geometry.verticesNeedUpdate = true;
  10673. geometry.colorsNeedUpdate = true;
  10674. }
  10675. } else if ( object instanceof THREE.ParticleSystem ) {
  10676. geometry = object.geometry;
  10677. if ( ! geometry.__webglVertexBuffer ) {
  10678. createParticleBuffers( geometry );
  10679. initParticleBuffers( geometry, object );
  10680. geometry.verticesNeedUpdate = true;
  10681. geometry.colorsNeedUpdate = true;
  10682. }
  10683. }
  10684. }
  10685. if ( ! object.__webglActive ) {
  10686. if ( object instanceof THREE.Mesh ) {
  10687. geometry = object.geometry;
  10688. if ( geometry instanceof THREE.BufferGeometry ) {
  10689. addBuffer( scene.__webglObjects, geometry, object );
  10690. } else {
  10691. for ( g in geometry.geometryGroups ) {
  10692. geometryGroup = geometry.geometryGroups[ g ];
  10693. addBuffer( scene.__webglObjects, geometryGroup, object );
  10694. }
  10695. }
  10696. } else if ( object instanceof THREE.Ribbon ||
  10697. object instanceof THREE.Line ||
  10698. object instanceof THREE.ParticleSystem ) {
  10699. geometry = object.geometry;
  10700. addBuffer( scene.__webglObjects, geometry, object );
  10701. } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
  10702. addBufferImmediate( scene.__webglObjectsImmediate, object );
  10703. } else if ( object instanceof THREE.Sprite ) {
  10704. scene.__webglSprites.push( object );
  10705. } else if ( object instanceof THREE.LensFlare ) {
  10706. scene.__webglFlares.push( object );
  10707. }
  10708. object.__webglActive = true;
  10709. }
  10710. };
  10711. function addBuffer ( objlist, buffer, object ) {
  10712. objlist.push(
  10713. {
  10714. buffer: buffer,
  10715. object: object,
  10716. opaque: null,
  10717. transparent: null
  10718. }
  10719. );
  10720. };
  10721. function addBufferImmediate ( objlist, object ) {
  10722. objlist.push(
  10723. {
  10724. object: object,
  10725. opaque: null,
  10726. transparent: null
  10727. }
  10728. );
  10729. };
  10730. // Objects updates
  10731. function updateObject ( object ) {
  10732. var geometry = object.geometry,
  10733. geometryGroup, customAttributesDirty, material;
  10734. if ( object instanceof THREE.Mesh ) {
  10735. if ( geometry instanceof THREE.BufferGeometry ) {
  10736. if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
  10737. geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
  10738. geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
  10739. setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
  10740. }
  10741. geometry.verticesNeedUpdate = false;
  10742. geometry.elementsNeedUpdate = false;
  10743. geometry.uvsNeedUpdate = false;
  10744. geometry.normalsNeedUpdate = false;
  10745. geometry.colorsNeedUpdate = false;
  10746. geometry.tangentsNeedUpdate = false;
  10747. } else {
  10748. // check all geometry groups
  10749. for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
  10750. geometryGroup = geometry.geometryGroupsList[ i ];
  10751. material = getBufferMaterial( object, geometryGroup );
  10752. customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
  10753. if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
  10754. geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
  10755. geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
  10756. setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
  10757. }
  10758. }
  10759. geometry.verticesNeedUpdate = false;
  10760. geometry.morphTargetsNeedUpdate = false;
  10761. geometry.elementsNeedUpdate = false;
  10762. geometry.uvsNeedUpdate = false;
  10763. geometry.normalsNeedUpdate = false;
  10764. geometry.colorsNeedUpdate = false;
  10765. geometry.tangentsNeedUpdate = false;
  10766. material.attributes && clearCustomAttributes( material );
  10767. }
  10768. } else if ( object instanceof THREE.Ribbon ) {
  10769. if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
  10770. setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
  10771. }
  10772. geometry.verticesNeedUpdate = false;
  10773. geometry.colorsNeedUpdate = false;
  10774. } else if ( object instanceof THREE.Line ) {
  10775. material = getBufferMaterial( object, geometryGroup );
  10776. customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
  10777. if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || customAttributesDirty ) {
  10778. setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
  10779. }
  10780. geometry.verticesNeedUpdate = false;
  10781. geometry.colorsNeedUpdate = false;
  10782. material.attributes && clearCustomAttributes( material );
  10783. } else if ( object instanceof THREE.ParticleSystem ) {
  10784. material = getBufferMaterial( object, geometryGroup );
  10785. customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
  10786. if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
  10787. setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
  10788. }
  10789. geometry.verticesNeedUpdate = false;
  10790. geometry.colorsNeedUpdate = false;
  10791. material.attributes && clearCustomAttributes( material );
  10792. }
  10793. };
  10794. // Objects updates - custom attributes check
  10795. function areCustomAttributesDirty ( material ) {
  10796. for ( var a in material.attributes ) {
  10797. if ( material.attributes[ a ].needsUpdate ) return true;
  10798. }
  10799. return false;
  10800. };
  10801. function clearCustomAttributes ( material ) {
  10802. for ( var a in material.attributes ) {
  10803. material.attributes[ a ].needsUpdate = false;
  10804. }
  10805. };
  10806. // Objects removal
  10807. function removeObject ( object, scene ) {
  10808. if ( object instanceof THREE.Mesh ||
  10809. object instanceof THREE.ParticleSystem ||
  10810. object instanceof THREE.Ribbon ||
  10811. object instanceof THREE.Line ) {
  10812. removeInstances( scene.__webglObjects, object );
  10813. } else if ( object instanceof THREE.Sprite ) {
  10814. removeInstancesDirect( scene.__webglSprites, object );
  10815. } else if ( object instanceof THREE.LensFlare ) {
  10816. removeInstancesDirect( scene.__webglFlares, object );
  10817. } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
  10818. removeInstances( scene.__webglObjectsImmediate, object );
  10819. }
  10820. object.__webglActive = false;
  10821. };
  10822. function removeInstances ( objlist, object ) {
  10823. for ( var o = objlist.length - 1; o >= 0; o -- ) {
  10824. if ( objlist[ o ].object === object ) {
  10825. objlist.splice( o, 1 );
  10826. }
  10827. }
  10828. };
  10829. function removeInstancesDirect ( objlist, object ) {
  10830. for ( var o = objlist.length - 1; o >= 0; o -- ) {
  10831. if ( objlist[ o ] === object ) {
  10832. objlist.splice( o, 1 );
  10833. }
  10834. }
  10835. };
  10836. // Materials
  10837. this.initMaterial = function ( material, lights, fog, object ) {
  10838. var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
  10839. if ( material instanceof THREE.MeshDepthMaterial ) {
  10840. shaderID = 'depth';
  10841. } else if ( material instanceof THREE.MeshNormalMaterial ) {
  10842. shaderID = 'normal';
  10843. } else if ( material instanceof THREE.MeshBasicMaterial ) {
  10844. shaderID = 'basic';
  10845. } else if ( material instanceof THREE.MeshLambertMaterial ) {
  10846. shaderID = 'lambert';
  10847. } else if ( material instanceof THREE.MeshPhongMaterial ) {
  10848. shaderID = 'phong';
  10849. } else if ( material instanceof THREE.LineBasicMaterial ) {
  10850. shaderID = 'basic';
  10851. } else if ( material instanceof THREE.ParticleBasicMaterial ) {
  10852. shaderID = 'particle_basic';
  10853. }
  10854. if ( shaderID ) {
  10855. setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
  10856. }
  10857. // heuristics to create shader parameters according to lights in the scene
  10858. // (not to blow over maxLights budget)
  10859. maxLightCount = allocateLights( lights );
  10860. maxShadows = allocateShadows( lights );
  10861. maxBones = allocateBones( object );
  10862. parameters = {
  10863. map: !!material.map,
  10864. envMap: !!material.envMap,
  10865. lightMap: !!material.lightMap,
  10866. vertexColors: material.vertexColors,
  10867. fog: fog,
  10868. useFog: material.fog,
  10869. sizeAttenuation: material.sizeAttenuation,
  10870. skinning: material.skinning,
  10871. maxBones: maxBones,
  10872. useVertexTexture: _supportsBoneTextures && object.useVertexTexture,
  10873. boneTextureWidth: object.boneTextureWidth,
  10874. boneTextureHeight: object.boneTextureHeight,
  10875. morphTargets: material.morphTargets,
  10876. morphNormals: material.morphNormals,
  10877. maxMorphTargets: this.maxMorphTargets,
  10878. maxMorphNormals: this.maxMorphNormals,
  10879. maxDirLights: maxLightCount.directional,
  10880. maxPointLights: maxLightCount.point,
  10881. maxSpotLights: maxLightCount.spot,
  10882. maxShadows: maxShadows,
  10883. shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
  10884. shadowMapSoft: this.shadowMapSoft,
  10885. shadowMapDebug: this.shadowMapDebug,
  10886. shadowMapCascade: this.shadowMapCascade,
  10887. alphaTest: material.alphaTest,
  10888. metal: material.metal,
  10889. perPixel: material.perPixel,
  10890. wrapAround: material.wrapAround,
  10891. doubleSided: object && object.doubleSided
  10892. };
  10893. material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters );
  10894. var attributes = material.program.attributes;
  10895. if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position );
  10896. if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color );
  10897. if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal );
  10898. if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent );
  10899. if ( material.skinning &&
  10900. attributes.skinVertexA >=0 && attributes.skinVertexB >= 0 &&
  10901. attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
  10902. _gl.enableVertexAttribArray( attributes.skinVertexA );
  10903. _gl.enableVertexAttribArray( attributes.skinVertexB );
  10904. _gl.enableVertexAttribArray( attributes.skinIndex );
  10905. _gl.enableVertexAttribArray( attributes.skinWeight );
  10906. }
  10907. if ( material.attributes ) {
  10908. for ( a in material.attributes ) {
  10909. if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] );
  10910. }
  10911. }
  10912. if ( material.morphTargets ) {
  10913. material.numSupportedMorphTargets = 0;
  10914. var id, base = "morphTarget";
  10915. for ( i = 0; i < this.maxMorphTargets; i ++ ) {
  10916. id = base + i;
  10917. if ( attributes[ id ] >= 0 ) {
  10918. _gl.enableVertexAttribArray( attributes[ id ] );
  10919. material.numSupportedMorphTargets ++;
  10920. }
  10921. }
  10922. }
  10923. if ( material.morphNormals ) {
  10924. material.numSupportedMorphNormals = 0;
  10925. var id, base = "morphNormal";
  10926. for ( i = 0; i < this.maxMorphNormals; i ++ ) {
  10927. id = base + i;
  10928. if ( attributes[ id ] >= 0 ) {
  10929. _gl.enableVertexAttribArray( attributes[ id ] );
  10930. material.numSupportedMorphNormals ++;
  10931. }
  10932. }
  10933. }
  10934. material.uniformsList = [];
  10935. for ( u in material.uniforms ) {
  10936. material.uniformsList.push( [ material.uniforms[ u ], u ] );
  10937. }
  10938. };
  10939. function setMaterialShaders( material, shaders ) {
  10940. material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
  10941. material.vertexShader = shaders.vertexShader;
  10942. material.fragmentShader = shaders.fragmentShader;
  10943. };
  10944. function setProgram( camera, lights, fog, material, object ) {
  10945. if ( material.needsUpdate ) {
  10946. if ( material.program ) _this.deallocateMaterial( material );
  10947. _this.initMaterial( material, lights, fog, object );
  10948. material.needsUpdate = false;
  10949. }
  10950. if ( material.morphTargets ) {
  10951. if ( ! object.__webglMorphTargetInfluences ) {
  10952. object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
  10953. }
  10954. }
  10955. var refreshMaterial = false;
  10956. var program = material.program,
  10957. p_uniforms = program.uniforms,
  10958. m_uniforms = material.uniforms;
  10959. if ( program !== _currentProgram ) {
  10960. _gl.useProgram( program );
  10961. _currentProgram = program;
  10962. refreshMaterial = true;
  10963. }
  10964. if ( material.id !== _currentMaterialId ) {
  10965. _currentMaterialId = material.id;
  10966. refreshMaterial = true;
  10967. }
  10968. if ( refreshMaterial || camera !== _currentCamera ) {
  10969. _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera._projectionMatrixArray );
  10970. if ( camera !== _currentCamera ) _currentCamera = camera;
  10971. }
  10972. if ( refreshMaterial ) {
  10973. // refresh uniforms common to several materials
  10974. if ( fog && material.fog ) {
  10975. refreshUniformsFog( m_uniforms, fog );
  10976. }
  10977. if ( material instanceof THREE.MeshPhongMaterial ||
  10978. material instanceof THREE.MeshLambertMaterial ||
  10979. material.lights ) {
  10980. if ( _lightsNeedUpdate ) {
  10981. setupLights( program, lights );
  10982. _lightsNeedUpdate = false;
  10983. }
  10984. refreshUniformsLights( m_uniforms, _lights );
  10985. }
  10986. if ( material instanceof THREE.MeshBasicMaterial ||
  10987. material instanceof THREE.MeshLambertMaterial ||
  10988. material instanceof THREE.MeshPhongMaterial ) {
  10989. refreshUniformsCommon( m_uniforms, material );
  10990. }
  10991. // refresh single material specific uniforms
  10992. if ( material instanceof THREE.LineBasicMaterial ) {
  10993. refreshUniformsLine( m_uniforms, material );
  10994. } else if ( material instanceof THREE.ParticleBasicMaterial ) {
  10995. refreshUniformsParticle( m_uniforms, material );
  10996. } else if ( material instanceof THREE.MeshPhongMaterial ) {
  10997. refreshUniformsPhong( m_uniforms, material );
  10998. } else if ( material instanceof THREE.MeshLambertMaterial ) {
  10999. refreshUniformsLambert( m_uniforms, material );
  11000. } else if ( material instanceof THREE.MeshDepthMaterial ) {
  11001. m_uniforms.mNear.value = camera.near;
  11002. m_uniforms.mFar.value = camera.far;
  11003. m_uniforms.opacity.value = material.opacity;
  11004. } else if ( material instanceof THREE.MeshNormalMaterial ) {
  11005. m_uniforms.opacity.value = material.opacity;
  11006. }
  11007. if ( object.receiveShadow && ! material._shadowPass ) {
  11008. refreshUniformsShadow( m_uniforms, lights );
  11009. }
  11010. // load common uniforms
  11011. loadUniformsGeneric( program, material.uniformsList );
  11012. // load material specific uniforms
  11013. // (shader material also gets them for the sake of genericity)
  11014. if ( material instanceof THREE.ShaderMaterial ||
  11015. material instanceof THREE.MeshPhongMaterial ||
  11016. material.envMap ) {
  11017. if ( p_uniforms.cameraPosition !== null ) {
  11018. var position = camera.matrixWorld.getPosition();
  11019. _gl.uniform3f( p_uniforms.cameraPosition, position.x, position.y, position.z );
  11020. }
  11021. }
  11022. if ( material instanceof THREE.MeshPhongMaterial ||
  11023. material instanceof THREE.MeshLambertMaterial ||
  11024. material instanceof THREE.ShaderMaterial ||
  11025. material.skinning ) {
  11026. if ( p_uniforms.viewMatrix !== null ) {
  11027. _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera._viewMatrixArray );
  11028. }
  11029. }
  11030. }
  11031. if ( material.skinning ) {
  11032. if ( _supportsBoneTextures && object.useVertexTexture ) {
  11033. if ( p_uniforms.boneTexture !== null ) {
  11034. // shadowMap texture array starts from 6
  11035. // texture unit 12 should leave space for 6 shadowmaps
  11036. var textureUnit = 12;
  11037. _gl.uniform1i( p_uniforms.boneTexture, textureUnit );
  11038. _this.setTexture( object.boneTexture, textureUnit );
  11039. }
  11040. } else {
  11041. if ( p_uniforms.boneGlobalMatrices !== null ) {
  11042. _gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.boneMatrices );
  11043. }
  11044. }
  11045. }
  11046. loadUniformsMatrices( p_uniforms, object );
  11047. if ( p_uniforms.objectMatrix !== null ) {
  11048. _gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object.matrixWorld.elements );
  11049. }
  11050. return program;
  11051. };
  11052. // Uniforms (refresh uniforms objects)
  11053. function refreshUniformsCommon ( uniforms, material ) {
  11054. uniforms.opacity.value = material.opacity;
  11055. if ( _this.gammaInput ) {
  11056. uniforms.diffuse.value.copyGammaToLinear( material.color );
  11057. } else {
  11058. uniforms.diffuse.value = material.color;
  11059. }
  11060. uniforms.map.texture = material.map;
  11061. if ( material.map ) {
  11062. uniforms.offsetRepeat.value.set( material.map.offset.x, material.map.offset.y, material.map.repeat.x, material.map.repeat.y );
  11063. }
  11064. uniforms.lightMap.texture = material.lightMap;
  11065. uniforms.envMap.texture = material.envMap;
  11066. uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
  11067. if ( _this.gammaInput ) {
  11068. //uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
  11069. uniforms.reflectivity.value = material.reflectivity;
  11070. } else {
  11071. uniforms.reflectivity.value = material.reflectivity;
  11072. }
  11073. uniforms.refractionRatio.value = material.refractionRatio;
  11074. uniforms.combine.value = material.combine;
  11075. uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
  11076. };
  11077. function refreshUniformsLine ( uniforms, material ) {
  11078. uniforms.diffuse.value = material.color;
  11079. uniforms.opacity.value = material.opacity;
  11080. };
  11081. function refreshUniformsParticle ( uniforms, material ) {
  11082. uniforms.psColor.value = material.color;
  11083. uniforms.opacity.value = material.opacity;
  11084. uniforms.size.value = material.size;
  11085. uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
  11086. uniforms.map.texture = material.map;
  11087. };
  11088. function refreshUniformsFog ( uniforms, fog ) {
  11089. uniforms.fogColor.value = fog.color;
  11090. if ( fog instanceof THREE.Fog ) {
  11091. uniforms.fogNear.value = fog.near;
  11092. uniforms.fogFar.value = fog.far;
  11093. } else if ( fog instanceof THREE.FogExp2 ) {
  11094. uniforms.fogDensity.value = fog.density;
  11095. }
  11096. };
  11097. function refreshUniformsPhong ( uniforms, material ) {
  11098. uniforms.shininess.value = material.shininess;
  11099. if ( _this.gammaInput ) {
  11100. uniforms.ambient.value.copyGammaToLinear( material.ambient );
  11101. uniforms.emissive.value.copyGammaToLinear( material.emissive );
  11102. uniforms.specular.value.copyGammaToLinear( material.specular );
  11103. } else {
  11104. uniforms.ambient.value = material.ambient;
  11105. uniforms.emissive.value = material.emissive;
  11106. uniforms.specular.value = material.specular;
  11107. }
  11108. if ( material.wrapAround ) {
  11109. uniforms.wrapRGB.value.copy( material.wrapRGB );
  11110. }
  11111. };
  11112. function refreshUniformsLambert ( uniforms, material ) {
  11113. if ( _this.gammaInput ) {
  11114. uniforms.ambient.value.copyGammaToLinear( material.ambient );
  11115. uniforms.emissive.value.copyGammaToLinear( material.emissive );
  11116. } else {
  11117. uniforms.ambient.value = material.ambient;
  11118. uniforms.emissive.value = material.emissive;
  11119. }
  11120. if ( material.wrapAround ) {
  11121. uniforms.wrapRGB.value.copy( material.wrapRGB );
  11122. }
  11123. };
  11124. function refreshUniformsLights ( uniforms, lights ) {
  11125. uniforms.ambientLightColor.value = lights.ambient;
  11126. uniforms.directionalLightColor.value = lights.directional.colors;
  11127. uniforms.directionalLightDirection.value = lights.directional.positions;
  11128. uniforms.pointLightColor.value = lights.point.colors;
  11129. uniforms.pointLightPosition.value = lights.point.positions;
  11130. uniforms.pointLightDistance.value = lights.point.distances;
  11131. uniforms.spotLightColor.value = lights.spot.colors;
  11132. uniforms.spotLightPosition.value = lights.spot.positions;
  11133. uniforms.spotLightDistance.value = lights.spot.distances;
  11134. uniforms.spotLightDirection.value = lights.spot.directions;
  11135. uniforms.spotLightAngle.value = lights.spot.angles;
  11136. uniforms.spotLightExponent.value = lights.spot.exponents;
  11137. };
  11138. function refreshUniformsShadow ( uniforms, lights ) {
  11139. if ( uniforms.shadowMatrix ) {
  11140. var j = 0;
  11141. for ( var i = 0, il = lights.length; i < il; i ++ ) {
  11142. var light = lights[ i ];
  11143. if ( ! light.castShadow ) continue;
  11144. if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
  11145. uniforms.shadowMap.texture[ j ] = light.shadowMap;
  11146. uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
  11147. uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
  11148. uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
  11149. uniforms.shadowBias.value[ j ] = light.shadowBias;
  11150. j ++;
  11151. }
  11152. }
  11153. }
  11154. };
  11155. // Uniforms (load to GPU)
  11156. function loadUniformsMatrices ( uniforms, object ) {
  11157. _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrix.elements );
  11158. if ( uniforms.normalMatrix ) {
  11159. _gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrix.elements );
  11160. }
  11161. };
  11162. function loadUniformsGeneric ( program, uniforms ) {
  11163. var uniform, value, type, location, texture, i, il, j, jl, offset;
  11164. for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
  11165. location = program.uniforms[ uniforms[ j ][ 1 ] ];
  11166. if ( !location ) continue;
  11167. uniform = uniforms[ j ][ 0 ];
  11168. type = uniform.type;
  11169. value = uniform.value;
  11170. if ( type === "i" ) { // single integer
  11171. _gl.uniform1i( location, value );
  11172. } else if ( type === "f" ) { // single float
  11173. _gl.uniform1f( location, value );
  11174. } else if ( type === "v2" ) { // single THREE.Vector2
  11175. _gl.uniform2f( location, value.x, value.y );
  11176. } else if ( type === "v3" ) { // single THREE.Vector3
  11177. _gl.uniform3f( location, value.x, value.y, value.z );
  11178. } else if ( type === "v4" ) { // single THREE.Vector4
  11179. _gl.uniform4f( location, value.x, value.y, value.z, value.w );
  11180. } else if ( type === "c" ) { // single THREE.Color
  11181. _gl.uniform3f( location, value.r, value.g, value.b );
  11182. } else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
  11183. _gl.uniform1iv( location, value );
  11184. } else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
  11185. _gl.uniform3iv( location, value );
  11186. } else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
  11187. _gl.uniform1fv( location, value );
  11188. } else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
  11189. _gl.uniform3fv( location, value );
  11190. } else if ( type === "v2v" ) { // array of THREE.Vector2
  11191. if ( uniform._array === undefined ) {
  11192. uniform._array = new Float32Array( 2 * value.length );
  11193. }
  11194. for ( i = 0, il = value.length; i < il; i ++ ) {
  11195. offset = i * 2;
  11196. uniform._array[ offset ] = value[ i ].x;
  11197. uniform._array[ offset + 1 ] = value[ i ].y;
  11198. }
  11199. _gl.uniform2fv( location, uniform._array );
  11200. } else if ( type === "v3v" ) { // array of THREE.Vector3
  11201. if ( uniform._array === undefined ) {
  11202. uniform._array = new Float32Array( 3 * value.length );
  11203. }
  11204. for ( i = 0, il = value.length; i < il; i ++ ) {
  11205. offset = i * 3;
  11206. uniform._array[ offset ] = value[ i ].x;
  11207. uniform._array[ offset + 1 ] = value[ i ].y;
  11208. uniform._array[ offset + 2 ] = value[ i ].z;
  11209. }
  11210. _gl.uniform3fv( location, uniform._array );
  11211. } else if ( type === "v4v" ) { // array of THREE.Vector4
  11212. if ( uniform._array === undefined ) {
  11213. uniform._array = new Float32Array( 4 * value.length );
  11214. }
  11215. for ( i = 0, il = value.length; i < il; i ++ ) {
  11216. offset = i * 4;
  11217. uniform._array[ offset ] = value[ i ].x;
  11218. uniform._array[ offset + 1 ] = value[ i ].y;
  11219. uniform._array[ offset + 2 ] = value[ i ].z;
  11220. uniform._array[ offset + 3 ] = value[ i ].w;
  11221. }
  11222. _gl.uniform4fv( location, uniform._array );
  11223. } else if ( type === "m4") { // single THREE.Matrix4
  11224. if ( uniform._array === undefined ) {
  11225. uniform._array = new Float32Array( 16 );
  11226. }
  11227. value.flattenToArray( uniform._array );
  11228. _gl.uniformMatrix4fv( location, false, uniform._array );
  11229. } else if ( type === "m4v" ) { // array of THREE.Matrix4
  11230. if ( uniform._array === undefined ) {
  11231. uniform._array = new Float32Array( 16 * value.length );
  11232. }
  11233. for ( i = 0, il = value.length; i < il; i ++ ) {
  11234. value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
  11235. }
  11236. _gl.uniformMatrix4fv( location, false, uniform._array );
  11237. } else if ( type === "t" ) { // single THREE.Texture (2d or cube)
  11238. _gl.uniform1i( location, value );
  11239. texture = uniform.texture;
  11240. if ( !texture ) continue;
  11241. if ( texture.image instanceof Array && texture.image.length === 6 ) {
  11242. setCubeTexture( texture, value );
  11243. } else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
  11244. setCubeTextureDynamic( texture, value );
  11245. } else {
  11246. _this.setTexture( texture, value );
  11247. }
  11248. } else if ( type === "tv" ) { // array of THREE.Texture (2d)
  11249. if ( uniform._array === undefined ) {
  11250. uniform._array = [];
  11251. for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
  11252. uniform._array[ i ] = value + i;
  11253. }
  11254. }
  11255. _gl.uniform1iv( location, uniform._array );
  11256. for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
  11257. texture = uniform.texture[ i ];
  11258. if ( !texture ) continue;
  11259. _this.setTexture( texture, uniform._array[ i ] );
  11260. }
  11261. }
  11262. }
  11263. };
  11264. function setupMatrices ( object, camera ) {
  11265. object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld);
  11266. object._normalMatrix.getInverse( object._modelViewMatrix );
  11267. object._normalMatrix.transpose();
  11268. };
  11269. function setupLights ( program, lights ) {
  11270. var l, ll, light, n,
  11271. r = 0, g = 0, b = 0,
  11272. color, position, intensity, distance,
  11273. zlights = _lights,
  11274. dcolors = zlights.directional.colors,
  11275. dpositions = zlights.directional.positions,
  11276. pcolors = zlights.point.colors,
  11277. ppositions = zlights.point.positions,
  11278. pdistances = zlights.point.distances,
  11279. scolors = zlights.spot.colors,
  11280. spositions = zlights.spot.positions,
  11281. sdistances = zlights.spot.distances,
  11282. sdirections = zlights.spot.directions,
  11283. sangles = zlights.spot.angles,
  11284. sexponents = zlights.spot.exponents,
  11285. dlength = 0,
  11286. plength = 0,
  11287. slength = 0,
  11288. doffset = 0,
  11289. poffset = 0,
  11290. soffset = 0;
  11291. for ( l = 0, ll = lights.length; l < ll; l ++ ) {
  11292. light = lights[ l ];
  11293. if ( light.onlyShadow || ! light.visible ) continue;
  11294. color = light.color;
  11295. intensity = light.intensity;
  11296. distance = light.distance;
  11297. if ( light instanceof THREE.AmbientLight ) {
  11298. if ( _this.gammaInput ) {
  11299. r += color.r * color.r;
  11300. g += color.g * color.g;
  11301. b += color.b * color.b;
  11302. } else {
  11303. r += color.r;
  11304. g += color.g;
  11305. b += color.b;
  11306. }
  11307. } else if ( light instanceof THREE.DirectionalLight ) {
  11308. doffset = dlength * 3;
  11309. if ( _this.gammaInput ) {
  11310. dcolors[ doffset ] = color.r * color.r * intensity * intensity;
  11311. dcolors[ doffset + 1 ] = color.g * color.g * intensity * intensity;
  11312. dcolors[ doffset + 2 ] = color.b * color.b * intensity * intensity;
  11313. } else {
  11314. dcolors[ doffset ] = color.r * intensity;
  11315. dcolors[ doffset + 1 ] = color.g * intensity;
  11316. dcolors[ doffset + 2 ] = color.b * intensity;
  11317. }
  11318. _direction.copy( light.matrixWorld.getPosition() );
  11319. _direction.subSelf( light.target.matrixWorld.getPosition() );
  11320. _direction.normalize();
  11321. dpositions[ doffset ] = _direction.x;
  11322. dpositions[ doffset + 1 ] = _direction.y;
  11323. dpositions[ doffset + 2 ] = _direction.z;
  11324. dlength += 1;
  11325. } else if( light instanceof THREE.PointLight ) {
  11326. poffset = plength * 3;
  11327. if ( _this.gammaInput ) {
  11328. pcolors[ poffset ] = color.r * color.r * intensity * intensity;
  11329. pcolors[ poffset + 1 ] = color.g * color.g * intensity * intensity;
  11330. pcolors[ poffset + 2 ] = color.b * color.b * intensity * intensity;
  11331. } else {
  11332. pcolors[ poffset ] = color.r * intensity;
  11333. pcolors[ poffset + 1 ] = color.g * intensity;
  11334. pcolors[ poffset + 2 ] = color.b * intensity;
  11335. }
  11336. position = light.matrixWorld.getPosition();
  11337. ppositions[ poffset ] = position.x;
  11338. ppositions[ poffset + 1 ] = position.y;
  11339. ppositions[ poffset + 2 ] = position.z;
  11340. pdistances[ plength ] = distance;
  11341. plength += 1;
  11342. } else if( light instanceof THREE.SpotLight ) {
  11343. soffset = slength * 3;
  11344. if ( _this.gammaInput ) {
  11345. scolors[ soffset ] = color.r * color.r * intensity * intensity;
  11346. scolors[ soffset + 1 ] = color.g * color.g * intensity * intensity;
  11347. scolors[ soffset + 2 ] = color.b * color.b * intensity * intensity;
  11348. } else {
  11349. scolors[ soffset ] = color.r * intensity;
  11350. scolors[ soffset + 1 ] = color.g * intensity;
  11351. scolors[ soffset + 2 ] = color.b * intensity;
  11352. }
  11353. position = light.matrixWorld.getPosition();
  11354. spositions[ soffset ] = position.x;
  11355. spositions[ soffset + 1 ] = position.y;
  11356. spositions[ soffset + 2 ] = position.z;
  11357. sdistances[ slength ] = distance;
  11358. _direction.copy( position );
  11359. _direction.subSelf( light.target.matrixWorld.getPosition() );
  11360. _direction.normalize();
  11361. sdirections[ soffset ] = _direction.x;
  11362. sdirections[ soffset + 1 ] = _direction.y;
  11363. sdirections[ soffset + 2 ] = _direction.z;
  11364. sangles[ slength ] = Math.cos( light.angle );
  11365. sexponents[ slength ] = light.exponent;
  11366. slength += 1;
  11367. }
  11368. }
  11369. // null eventual remains from removed lights
  11370. // (this is to avoid if in shader)
  11371. for ( l = dlength * 3, ll = dcolors.length; l < ll; l ++ ) dcolors[ l ] = 0.0;
  11372. for ( l = plength * 3, ll = pcolors.length; l < ll; l ++ ) pcolors[ l ] = 0.0;
  11373. for ( l = slength * 3, ll = scolors.length; l < ll; l ++ ) scolors[ l ] = 0.0;
  11374. zlights.directional.length = dlength;
  11375. zlights.point.length = plength;
  11376. zlights.spot.length = slength;
  11377. zlights.ambient[ 0 ] = r;
  11378. zlights.ambient[ 1 ] = g;
  11379. zlights.ambient[ 2 ] = b;
  11380. };
  11381. // GL state setting
  11382. this.setFaceCulling = function ( cullFace, frontFace ) {
  11383. if ( cullFace ) {
  11384. if ( !frontFace || frontFace === "ccw" ) {
  11385. _gl.frontFace( _gl.CCW );
  11386. } else {
  11387. _gl.frontFace( _gl.CW );
  11388. }
  11389. if( cullFace === "back" ) {
  11390. _gl.cullFace( _gl.BACK );
  11391. } else if( cullFace === "front" ) {
  11392. _gl.cullFace( _gl.FRONT );
  11393. } else {
  11394. _gl.cullFace( _gl.FRONT_AND_BACK );
  11395. }
  11396. _gl.enable( _gl.CULL_FACE );
  11397. } else {
  11398. _gl.disable( _gl.CULL_FACE );
  11399. }
  11400. };
  11401. this.setObjectFaces = function ( object ) {
  11402. if ( _oldDoubleSided !== object.doubleSided ) {
  11403. if ( object.doubleSided ) {
  11404. _gl.disable( _gl.CULL_FACE );
  11405. } else {
  11406. _gl.enable( _gl.CULL_FACE );
  11407. }
  11408. _oldDoubleSided = object.doubleSided;
  11409. }
  11410. if ( _oldFlipSided !== object.flipSided ) {
  11411. if ( object.flipSided ) {
  11412. _gl.frontFace( _gl.CW );
  11413. } else {
  11414. _gl.frontFace( _gl.CCW );
  11415. }
  11416. _oldFlipSided = object.flipSided;
  11417. }
  11418. };
  11419. this.setDepthTest = function ( depthTest ) {
  11420. if ( _oldDepthTest !== depthTest ) {
  11421. if ( depthTest ) {
  11422. _gl.enable( _gl.DEPTH_TEST );
  11423. } else {
  11424. _gl.disable( _gl.DEPTH_TEST );
  11425. }
  11426. _oldDepthTest = depthTest;
  11427. }
  11428. };
  11429. this.setDepthWrite = function ( depthWrite ) {
  11430. if ( _oldDepthWrite !== depthWrite ) {
  11431. _gl.depthMask( depthWrite );
  11432. _oldDepthWrite = depthWrite;
  11433. }
  11434. };
  11435. function setLineWidth ( width ) {
  11436. if ( width !== _oldLineWidth ) {
  11437. _gl.lineWidth( width );
  11438. _oldLineWidth = width;
  11439. }
  11440. };
  11441. function setPolygonOffset ( polygonoffset, factor, units ) {
  11442. if ( _oldPolygonOffset !== polygonoffset ) {
  11443. if ( polygonoffset ) {
  11444. _gl.enable( _gl.POLYGON_OFFSET_FILL );
  11445. } else {
  11446. _gl.disable( _gl.POLYGON_OFFSET_FILL );
  11447. }
  11448. _oldPolygonOffset = polygonoffset;
  11449. }
  11450. if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
  11451. _gl.polygonOffset( factor, units );
  11452. _oldPolygonOffsetFactor = factor;
  11453. _oldPolygonOffsetUnits = units;
  11454. }
  11455. };
  11456. this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) {
  11457. if ( blending !== _oldBlending ) {
  11458. if ( blending === THREE.NoBlending ) {
  11459. _gl.disable( _gl.BLEND );
  11460. } else if ( blending === THREE.AdditiveBlending ) {
  11461. _gl.enable( _gl.BLEND );
  11462. _gl.blendEquation( _gl.FUNC_ADD );
  11463. _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
  11464. } else if ( blending === THREE.SubtractiveBlending ) {
  11465. // TODO: Find blendFuncSeparate() combination
  11466. _gl.enable( _gl.BLEND );
  11467. _gl.blendEquation( _gl.FUNC_ADD );
  11468. _gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
  11469. } else if ( blending === THREE.MultiplyBlending ) {
  11470. // TODO: Find blendFuncSeparate() combination
  11471. _gl.enable( _gl.BLEND );
  11472. _gl.blendEquation( _gl.FUNC_ADD );
  11473. _gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
  11474. } else if ( blending === THREE.CustomBlending ) {
  11475. _gl.enable( _gl.BLEND );
  11476. } else {
  11477. _gl.enable( _gl.BLEND );
  11478. _gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
  11479. _gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
  11480. }
  11481. _oldBlending = blending;
  11482. }
  11483. if ( blending === THREE.CustomBlending ) {
  11484. if ( blendEquation !== _oldBlendEquation ) {
  11485. _gl.blendEquation( paramThreeToGL( blendEquation ) );
  11486. _oldBlendEquation = blendEquation;
  11487. }
  11488. if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
  11489. _gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
  11490. _oldBlendSrc = blendSrc;
  11491. _oldBlendDst = blendDst;
  11492. }
  11493. } else {
  11494. _oldBlendEquation = null;
  11495. _oldBlendSrc = null;
  11496. _oldBlendDst = null;
  11497. }
  11498. };
  11499. // Shaders
  11500. function buildProgram ( shaderID, fragmentShader, vertexShader, uniforms, attributes, parameters ) {
  11501. var p, pl, program, code;
  11502. var chunks = [];
  11503. // Generate code
  11504. if ( shaderID ) {
  11505. chunks.push( shaderID );
  11506. } else {
  11507. chunks.push( fragmentShader );
  11508. chunks.push( vertexShader );
  11509. }
  11510. for ( p in parameters ) {
  11511. chunks.push( p );
  11512. chunks.push( parameters[ p ] );
  11513. }
  11514. code = chunks.join();
  11515. // Check if code has been already compiled
  11516. for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
  11517. var programInfo = _programs[ p ];
  11518. if ( programInfo.code === code ) {
  11519. // console.log( "Code already compiled." /*: \n\n" + code*/ );
  11520. programInfo.usedTimes ++;
  11521. return programInfo.program;
  11522. }
  11523. }
  11524. //console.log( "building new program " );
  11525. //
  11526. program = _gl.createProgram();
  11527. var prefix_vertex = [
  11528. "precision " + _precision + " float;",
  11529. _supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
  11530. _this.gammaInput ? "#define GAMMA_INPUT" : "",
  11531. _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
  11532. _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
  11533. "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
  11534. "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
  11535. "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
  11536. "#define MAX_SHADOWS " + parameters.maxShadows,
  11537. "#define MAX_BONES " + parameters.maxBones,
  11538. parameters.map ? "#define USE_MAP" : "",
  11539. parameters.envMap ? "#define USE_ENVMAP" : "",
  11540. parameters.lightMap ? "#define USE_LIGHTMAP" : "",
  11541. parameters.vertexColors ? "#define USE_COLOR" : "",
  11542. parameters.skinning ? "#define USE_SKINNING" : "",
  11543. parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
  11544. parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
  11545. parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
  11546. parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
  11547. parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
  11548. parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
  11549. parameters.wrapAround ? "#define WRAP_AROUND" : "",
  11550. parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
  11551. parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
  11552. parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
  11553. parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
  11554. parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
  11555. parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
  11556. "uniform mat4 objectMatrix;",
  11557. "uniform mat4 modelViewMatrix;",
  11558. "uniform mat4 projectionMatrix;",
  11559. "uniform mat4 viewMatrix;",
  11560. "uniform mat3 normalMatrix;",
  11561. "uniform vec3 cameraPosition;",
  11562. "attribute vec3 position;",
  11563. "attribute vec3 normal;",
  11564. "attribute vec2 uv;",
  11565. "attribute vec2 uv2;",
  11566. "#ifdef USE_COLOR",
  11567. "attribute vec3 color;",
  11568. "#endif",
  11569. "#ifdef USE_MORPHTARGETS",
  11570. "attribute vec3 morphTarget0;",
  11571. "attribute vec3 morphTarget1;",
  11572. "attribute vec3 morphTarget2;",
  11573. "attribute vec3 morphTarget3;",
  11574. "#ifdef USE_MORPHNORMALS",
  11575. "attribute vec3 morphNormal0;",
  11576. "attribute vec3 morphNormal1;",
  11577. "attribute vec3 morphNormal2;",
  11578. "attribute vec3 morphNormal3;",
  11579. "#else",
  11580. "attribute vec3 morphTarget4;",
  11581. "attribute vec3 morphTarget5;",
  11582. "attribute vec3 morphTarget6;",
  11583. "attribute vec3 morphTarget7;",
  11584. "#endif",
  11585. "#endif",
  11586. "#ifdef USE_SKINNING",
  11587. "attribute vec4 skinVertexA;",
  11588. "attribute vec4 skinVertexB;",
  11589. "attribute vec4 skinIndex;",
  11590. "attribute vec4 skinWeight;",
  11591. "#endif",
  11592. ""
  11593. ].join("\n");
  11594. var prefix_fragment = [
  11595. "precision " + _precision + " float;",
  11596. "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
  11597. "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
  11598. "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
  11599. "#define MAX_SHADOWS " + parameters.maxShadows,
  11600. parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
  11601. _this.gammaInput ? "#define GAMMA_INPUT" : "",
  11602. _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
  11603. _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
  11604. ( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
  11605. ( parameters.useFog && parameters.fog instanceof THREE.FogExp2 ) ? "#define FOG_EXP2" : "",
  11606. parameters.map ? "#define USE_MAP" : "",
  11607. parameters.envMap ? "#define USE_ENVMAP" : "",
  11608. parameters.lightMap ? "#define USE_LIGHTMAP" : "",
  11609. parameters.vertexColors ? "#define USE_COLOR" : "",
  11610. parameters.metal ? "#define METAL" : "",
  11611. parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
  11612. parameters.wrapAround ? "#define WRAP_AROUND" : "",
  11613. parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
  11614. parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
  11615. parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
  11616. parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
  11617. parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
  11618. "uniform mat4 viewMatrix;",
  11619. "uniform vec3 cameraPosition;",
  11620. ""
  11621. ].join("\n");
  11622. var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
  11623. var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
  11624. _gl.attachShader( program, glVertexShader );
  11625. _gl.attachShader( program, glFragmentShader );
  11626. _gl.linkProgram( program );
  11627. if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
  11628. console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
  11629. }
  11630. // clean up
  11631. _gl.deleteShader( glFragmentShader );
  11632. _gl.deleteShader( glVertexShader );
  11633. //console.log( prefix_fragment + fragmentShader );
  11634. //console.log( prefix_vertex + vertexShader );
  11635. program.uniforms = {};
  11636. program.attributes = {};
  11637. var identifiers, u, a, i;
  11638. // cache uniform locations
  11639. identifiers = [
  11640. 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition',
  11641. 'morphTargetInfluences'
  11642. ];
  11643. if ( parameters.useVertexTexture ) {
  11644. identifiers.push( 'boneTexture' );
  11645. } else {
  11646. identifiers.push( 'boneGlobalMatrices' );
  11647. }
  11648. for ( u in uniforms ) {
  11649. identifiers.push( u );
  11650. }
  11651. cacheUniformLocations( program, identifiers );
  11652. // cache attributes locations
  11653. identifiers = [
  11654. "position", "normal", "uv", "uv2", "tangent", "color",
  11655. "skinVertexA", "skinVertexB", "skinIndex", "skinWeight"
  11656. ];
  11657. for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
  11658. identifiers.push( "morphTarget" + i );
  11659. }
  11660. for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
  11661. identifiers.push( "morphNormal" + i );
  11662. }
  11663. for ( a in attributes ) {
  11664. identifiers.push( a );
  11665. }
  11666. cacheAttributeLocations( program, identifiers );
  11667. program.id = _programs_counter ++;
  11668. _programs.push( { program: program, code: code, usedTimes: 1 } );
  11669. _this.info.memory.programs = _programs.length;
  11670. return program;
  11671. };
  11672. // Shader parameters cache
  11673. function cacheUniformLocations ( program, identifiers ) {
  11674. var i, l, id;
  11675. for( i = 0, l = identifiers.length; i < l; i ++ ) {
  11676. id = identifiers[ i ];
  11677. program.uniforms[ id ] = _gl.getUniformLocation( program, id );
  11678. }
  11679. };
  11680. function cacheAttributeLocations ( program, identifiers ) {
  11681. var i, l, id;
  11682. for( i = 0, l = identifiers.length; i < l; i ++ ) {
  11683. id = identifiers[ i ];
  11684. program.attributes[ id ] = _gl.getAttribLocation( program, id );
  11685. }
  11686. };
  11687. function getShader ( type, string ) {
  11688. var shader;
  11689. if ( type === "fragment" ) {
  11690. shader = _gl.createShader( _gl.FRAGMENT_SHADER );
  11691. } else if ( type === "vertex" ) {
  11692. shader = _gl.createShader( _gl.VERTEX_SHADER );
  11693. }
  11694. _gl.shaderSource( shader, string );
  11695. _gl.compileShader( shader );
  11696. if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
  11697. console.error( _gl.getShaderInfoLog( shader ) );
  11698. console.error( string );
  11699. return null;
  11700. }
  11701. return shader;
  11702. };
  11703. // Textures
  11704. function isPowerOfTwo ( value ) {
  11705. return ( value & ( value - 1 ) ) === 0;
  11706. };
  11707. function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
  11708. if ( isImagePowerOfTwo ) {
  11709. _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
  11710. _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
  11711. _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
  11712. _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
  11713. } else {
  11714. _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
  11715. _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
  11716. _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
  11717. _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
  11718. }
  11719. if ( _glExtensionTextureFilterAnisotropic ) {
  11720. _gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, texture.anisotropy );
  11721. }
  11722. };
  11723. this.setTexture = function ( texture, slot ) {
  11724. if ( texture.needsUpdate ) {
  11725. if ( ! texture.__webglInit ) {
  11726. texture.__webglInit = true;
  11727. texture.__webglTexture = _gl.createTexture();
  11728. _this.info.memory.textures ++;
  11729. }
  11730. _gl.activeTexture( _gl.TEXTURE0 + slot );
  11731. _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
  11732. _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
  11733. _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
  11734. var image = texture.image,
  11735. isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
  11736. glFormat = paramThreeToGL( texture.format ),
  11737. glType = paramThreeToGL( texture.type );
  11738. setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
  11739. if ( texture instanceof THREE.DataTexture ) {
  11740. _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
  11741. } else {
  11742. _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
  11743. }
  11744. if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
  11745. texture.needsUpdate = false;
  11746. if ( texture.onUpdate ) texture.onUpdate();
  11747. } else {
  11748. _gl.activeTexture( _gl.TEXTURE0 + slot );
  11749. _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
  11750. }
  11751. };
  11752. function clampToMaxSize ( image, maxSize ) {
  11753. if ( image.width <= maxSize && image.height <= maxSize ) {
  11754. return image;
  11755. }
  11756. // Warning: Scaling through the canvas will only work with images that use
  11757. // premultiplied alpha.
  11758. var maxDimension = Math.max( image.width, image.height );
  11759. var newWidth = Math.floor( image.width * maxSize / maxDimension );
  11760. var newHeight = Math.floor( image.height * maxSize / maxDimension );
  11761. var canvas = document.createElement( 'canvas' );
  11762. canvas.width = newWidth;
  11763. canvas.height = newHeight;
  11764. var ctx = canvas.getContext( "2d" );
  11765. ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
  11766. return canvas;
  11767. }
  11768. function setCubeTexture ( texture, slot ) {
  11769. if ( texture.image.length === 6 ) {
  11770. if ( texture.needsUpdate ) {
  11771. if ( ! texture.image.__webglTextureCube ) {
  11772. texture.image.__webglTextureCube = _gl.createTexture();
  11773. }
  11774. _gl.activeTexture( _gl.TEXTURE0 + slot );
  11775. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
  11776. _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
  11777. var cubeImage = [];
  11778. for ( var i = 0; i < 6; i ++ ) {
  11779. if ( _this.autoScaleCubemaps ) {
  11780. cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
  11781. } else {
  11782. cubeImage[ i ] = texture.image[ i ];
  11783. }
  11784. }
  11785. var image = cubeImage[ 0 ],
  11786. isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
  11787. glFormat = paramThreeToGL( texture.format ),
  11788. glType = paramThreeToGL( texture.type );
  11789. setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
  11790. for ( var i = 0; i < 6; i ++ ) {
  11791. _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
  11792. }
  11793. if ( texture.generateMipmaps && isImagePowerOfTwo ) {
  11794. _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
  11795. }
  11796. texture.needsUpdate = false;
  11797. if ( texture.onUpdate ) texture.onUpdate();
  11798. } else {
  11799. _gl.activeTexture( _gl.TEXTURE0 + slot );
  11800. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
  11801. }
  11802. }
  11803. };
  11804. function setCubeTextureDynamic ( texture, slot ) {
  11805. _gl.activeTexture( _gl.TEXTURE0 + slot );
  11806. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
  11807. };
  11808. // Render targets
  11809. function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
  11810. _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
  11811. _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
  11812. };
  11813. function setupRenderBuffer ( renderbuffer, renderTarget ) {
  11814. _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
  11815. if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
  11816. _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
  11817. _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
  11818. /* For some reason this is not working. Defaulting to RGBA4.
  11819. } else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
  11820. _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
  11821. _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
  11822. */
  11823. } else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
  11824. _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
  11825. _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
  11826. } else {
  11827. _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
  11828. }
  11829. };
  11830. this.setRenderTarget = function ( renderTarget ) {
  11831. var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
  11832. if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
  11833. if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
  11834. if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
  11835. renderTarget.__webglTexture = _gl.createTexture();
  11836. // Setup texture, create render and frame buffers
  11837. var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
  11838. glFormat = paramThreeToGL( renderTarget.format ),
  11839. glType = paramThreeToGL( renderTarget.type );
  11840. if ( isCube ) {
  11841. renderTarget.__webglFramebuffer = [];
  11842. renderTarget.__webglRenderbuffer = [];
  11843. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
  11844. setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
  11845. for ( var i = 0; i < 6; i ++ ) {
  11846. renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
  11847. renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
  11848. _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
  11849. setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
  11850. setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
  11851. }
  11852. if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
  11853. } else {
  11854. renderTarget.__webglFramebuffer = _gl.createFramebuffer();
  11855. renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
  11856. _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
  11857. setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
  11858. _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
  11859. setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
  11860. setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
  11861. if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
  11862. }
  11863. // Release everything
  11864. if ( isCube ) {
  11865. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
  11866. } else {
  11867. _gl.bindTexture( _gl.TEXTURE_2D, null );
  11868. }
  11869. _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
  11870. _gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
  11871. }
  11872. var framebuffer, width, height, vx, vy;
  11873. if ( renderTarget ) {
  11874. if ( isCube ) {
  11875. framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
  11876. } else {
  11877. framebuffer = renderTarget.__webglFramebuffer;
  11878. }
  11879. width = renderTarget.width;
  11880. height = renderTarget.height;
  11881. vx = 0;
  11882. vy = 0;
  11883. } else {
  11884. framebuffer = null;
  11885. width = _viewportWidth;
  11886. height = _viewportHeight;
  11887. vx = _viewportX;
  11888. vy = _viewportY;
  11889. }
  11890. if ( framebuffer !== _currentFramebuffer ) {
  11891. _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
  11892. _gl.viewport( vx, vy, width, height );
  11893. _currentFramebuffer = framebuffer;
  11894. }
  11895. _currentWidth = width;
  11896. _currentHeight = height;
  11897. };
  11898. function updateRenderTargetMipmap ( renderTarget ) {
  11899. if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
  11900. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
  11901. _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
  11902. _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
  11903. } else {
  11904. _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
  11905. _gl.generateMipmap( _gl.TEXTURE_2D );
  11906. _gl.bindTexture( _gl.TEXTURE_2D, null );
  11907. }
  11908. };
  11909. // Fallback filters for non-power-of-2 textures
  11910. function filterFallback ( f ) {
  11911. if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
  11912. return _gl.NEAREST;
  11913. }
  11914. return _gl.LINEAR;
  11915. };
  11916. // Map three.js constants to WebGL constants
  11917. function paramThreeToGL ( p ) {
  11918. if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
  11919. if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
  11920. if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
  11921. if ( p === THREE.NearestFilter ) return _gl.NEAREST;
  11922. if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
  11923. if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
  11924. if ( p === THREE.LinearFilter ) return _gl.LINEAR;
  11925. if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
  11926. if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
  11927. if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
  11928. if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
  11929. if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
  11930. if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
  11931. if ( p === THREE.ByteType ) return _gl.BYTE;
  11932. if ( p === THREE.ShortType ) return _gl.SHORT;
  11933. if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
  11934. if ( p === THREE.IntType ) return _gl.INT;
  11935. if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
  11936. if ( p === THREE.FloatType ) return _gl.FLOAT;
  11937. if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
  11938. if ( p === THREE.RGBFormat ) return _gl.RGB;
  11939. if ( p === THREE.RGBAFormat ) return _gl.RGBA;
  11940. if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
  11941. if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
  11942. if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
  11943. if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
  11944. if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
  11945. if ( p === THREE.ZeroFactor ) return _gl.ZERO;
  11946. if ( p === THREE.OneFactor ) return _gl.ONE;
  11947. if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
  11948. if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
  11949. if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
  11950. if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
  11951. if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
  11952. if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
  11953. if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
  11954. if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
  11955. if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
  11956. return 0;
  11957. };
  11958. // Allocations
  11959. function allocateBones ( object ) {
  11960. if ( _supportsBoneTextures && object.useVertexTexture ) {
  11961. return 1024;
  11962. } else {
  11963. // default for when object is not specified
  11964. // ( for example when prebuilding shader
  11965. // to be used with multiple objects )
  11966. //
  11967. // - leave some extra space for other uniforms
  11968. // - limit here is ANGLE's 254 max uniform vectors
  11969. // (up to 54 should be safe)
  11970. var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
  11971. var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
  11972. var maxBones = nVertexMatrices;
  11973. if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
  11974. maxBones = Math.min( object.bones.length, maxBones );
  11975. if ( maxBones < object.bones.length ) {
  11976. console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
  11977. }
  11978. }
  11979. return maxBones;
  11980. }
  11981. };
  11982. function allocateLights ( lights ) {
  11983. var l, ll, light, dirLights, pointLights, spotLights, maxDirLights, maxPointLights, maxSpotLights;
  11984. dirLights = pointLights = spotLights = maxDirLights = maxPointLights = maxSpotLights = 0;
  11985. for ( l = 0, ll = lights.length; l < ll; l ++ ) {
  11986. light = lights[ l ];
  11987. if ( light.onlyShadow ) continue;
  11988. if ( light instanceof THREE.DirectionalLight ) dirLights ++;
  11989. if ( light instanceof THREE.PointLight ) pointLights ++;
  11990. if ( light instanceof THREE.SpotLight ) spotLights ++;
  11991. }
  11992. if ( ( pointLights + spotLights + dirLights ) <= _maxLights ) {
  11993. maxDirLights = dirLights;
  11994. maxPointLights = pointLights;
  11995. maxSpotLights = spotLights;
  11996. } else {
  11997. maxDirLights = Math.ceil( _maxLights * dirLights / ( pointLights + dirLights ) );
  11998. maxPointLights = _maxLights - maxDirLights;
  11999. maxSpotLights = maxPointLights; // this is not really correct
  12000. }
  12001. return { 'directional' : maxDirLights, 'point' : maxPointLights, 'spot': maxSpotLights };
  12002. };
  12003. function allocateShadows ( lights ) {
  12004. var l, ll, light, maxShadows = 0;
  12005. for ( l = 0, ll = lights.length; l < ll; l++ ) {
  12006. light = lights[ l ];
  12007. if ( ! light.castShadow ) continue;
  12008. if ( light instanceof THREE.SpotLight ) maxShadows ++;
  12009. if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
  12010. }
  12011. return maxShadows;
  12012. };
  12013. // Initialization
  12014. function initGL () {
  12015. try {
  12016. if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
  12017. throw 'Error creating WebGL context.';
  12018. }
  12019. } catch ( error ) {
  12020. console.error( error );
  12021. }
  12022. _glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
  12023. _glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
  12024. _glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
  12025. _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
  12026. _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
  12027. if ( ! _glExtensionTextureFloat ) {
  12028. console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
  12029. }
  12030. if ( ! _glExtensionStandardDerivatives ) {
  12031. console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
  12032. }
  12033. if ( ! _glExtensionTextureFilterAnisotropic ) {
  12034. console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
  12035. }
  12036. };
  12037. function setDefaultGLState () {
  12038. _gl.clearColor( 0, 0, 0, 1 );
  12039. _gl.clearDepth( 1 );
  12040. _gl.clearStencil( 0 );
  12041. _gl.enable( _gl.DEPTH_TEST );
  12042. _gl.depthFunc( _gl.LEQUAL );
  12043. _gl.frontFace( _gl.CCW );
  12044. _gl.cullFace( _gl.BACK );
  12045. _gl.enable( _gl.CULL_FACE );
  12046. _gl.enable( _gl.BLEND );
  12047. _gl.blendEquation( _gl.FUNC_ADD );
  12048. _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
  12049. _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
  12050. };
  12051. // default plugins (order is important)
  12052. this.shadowMapPlugin = new THREE.ShadowMapPlugin();
  12053. this.addPrePlugin( this.shadowMapPlugin );
  12054. this.addPostPlugin( new THREE.SpritePlugin() );
  12055. this.addPostPlugin( new THREE.LensFlarePlugin() );
  12056. };
  12057. /**
  12058. * @author szimek / https://github.com/szimek/
  12059. */
  12060. THREE.WebGLRenderTarget = function ( width, height, options ) {
  12061. this.width = width;
  12062. this.height = height;
  12063. options = options || {};
  12064. this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping;
  12065. this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping;
  12066. this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter;
  12067. this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter;
  12068. this.offset = new THREE.Vector2( 0, 0 );
  12069. this.repeat = new THREE.Vector2( 1, 1 );
  12070. this.format = options.format !== undefined ? options.format : THREE.RGBAFormat;
  12071. this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType;
  12072. this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
  12073. this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
  12074. this.generateMipmaps = true;
  12075. };
  12076. THREE.WebGLRenderTarget.prototype.clone = function() {
  12077. var tmp = new THREE.WebGLRenderTarget( this.width, this.height );
  12078. tmp.wrapS = this.wrapS;
  12079. tmp.wrapT = this.wrapT;
  12080. tmp.magFilter = this.magFilter;
  12081. tmp.minFilter = this.minFilter;
  12082. tmp.offset.copy( this.offset );
  12083. tmp.repeat.copy( this.repeat );
  12084. tmp.format = this.format;
  12085. tmp.type = this.type;
  12086. tmp.depthBuffer = this.depthBuffer;
  12087. tmp.stencilBuffer = this.stencilBuffer;
  12088. return tmp;
  12089. };
  12090. /**
  12091. * @author alteredq / http://alteredqualia.com
  12092. */
  12093. THREE.WebGLRenderTargetCube = function ( width, height, options ) {
  12094. THREE.WebGLRenderTarget.call( this, width, height, options );
  12095. this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
  12096. };
  12097. THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
  12098. /**
  12099. * @author mr.doob / http://mrdoob.com/
  12100. */
  12101. THREE.RenderableVertex = function () {
  12102. this.positionWorld = new THREE.Vector3();
  12103. this.positionScreen = new THREE.Vector4();
  12104. this.visible = true;
  12105. };
  12106. THREE.RenderableVertex.prototype.copy = function ( vertex ) {
  12107. this.positionWorld.copy( vertex.positionWorld );
  12108. this.positionScreen.copy( vertex.positionScreen );
  12109. }
  12110. /**
  12111. * @author mr.doob / http://mrdoob.com/
  12112. */
  12113. THREE.RenderableFace3 = function () {
  12114. this.v1 = new THREE.RenderableVertex();
  12115. this.v2 = new THREE.RenderableVertex();
  12116. this.v3 = new THREE.RenderableVertex();
  12117. this.centroidWorld = new THREE.Vector3();
  12118. this.centroidScreen = new THREE.Vector3();
  12119. this.normalWorld = new THREE.Vector3();
  12120. this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  12121. this.material = null;
  12122. this.faceMaterial = null;
  12123. this.uvs = [[]];
  12124. this.z = null;
  12125. };
  12126. /**
  12127. * @author mr.doob / http://mrdoob.com/
  12128. */
  12129. THREE.RenderableFace4 = function () {
  12130. this.v1 = new THREE.RenderableVertex();
  12131. this.v2 = new THREE.RenderableVertex();
  12132. this.v3 = new THREE.RenderableVertex();
  12133. this.v4 = new THREE.RenderableVertex();
  12134. this.centroidWorld = new THREE.Vector3();
  12135. this.centroidScreen = new THREE.Vector3();
  12136. this.normalWorld = new THREE.Vector3();
  12137. this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
  12138. this.material = null;
  12139. this.faceMaterial = null;
  12140. this.uvs = [[]];
  12141. this.z = null;
  12142. };
  12143. /**
  12144. * @author mr.doob / http://mrdoob.com/
  12145. */
  12146. THREE.RenderableObject = function () {
  12147. this.object = null;
  12148. this.z = null;
  12149. };
  12150. /**
  12151. * @author mr.doob / http://mrdoob.com/
  12152. */
  12153. THREE.RenderableParticle = function () {
  12154. this.x = null;
  12155. this.y = null;
  12156. this.z = null;
  12157. this.rotation = null;
  12158. this.scale = new THREE.Vector2();
  12159. this.material = null;
  12160. };
  12161. /**
  12162. * @author mr.doob / http://mrdoob.com/
  12163. */
  12164. THREE.RenderableLine = function () {
  12165. this.z = null;
  12166. this.v1 = new THREE.RenderableVertex();
  12167. this.v2 = new THREE.RenderableVertex();
  12168. this.material = null;
  12169. };
  12170. /**
  12171. * @author alteredq / http://alteredqualia.com/
  12172. */
  12173. THREE.ColorUtils = {
  12174. adjustHSV : function ( color, h, s, v ) {
  12175. var hsv = THREE.ColorUtils.__hsv;
  12176. THREE.ColorUtils.rgbToHsv( color, hsv );
  12177. hsv.h = THREE.Math.clamp( hsv.h + h, 0, 1 );
  12178. hsv.s = THREE.Math.clamp( hsv.s + s, 0, 1 );
  12179. hsv.v = THREE.Math.clamp( hsv.v + v, 0, 1 );
  12180. color.setHSV( hsv.h, hsv.s, hsv.v );
  12181. },
  12182. // based on MochiKit implementation by Bob Ippolito
  12183. rgbToHsv : function ( color, hsv ) {
  12184. var r = color.r;
  12185. var g = color.g;
  12186. var b = color.b;
  12187. var max = Math.max( Math.max( r, g ), b );
  12188. var min = Math.min( Math.min( r, g ), b );
  12189. var hue;
  12190. var saturation;
  12191. var value = max;
  12192. if ( min === max ) {
  12193. hue = 0;
  12194. saturation = 0;
  12195. } else {
  12196. var delta = ( max - min );
  12197. saturation = delta / max;
  12198. if ( r === max ) {
  12199. hue = ( g - b ) / delta;
  12200. } else if ( g === max ) {
  12201. hue = 2 + ( ( b - r ) / delta );
  12202. } else {
  12203. hue = 4 + ( ( r - g ) / delta );
  12204. }
  12205. hue /= 6;
  12206. if ( hue < 0 ) {
  12207. hue += 1;
  12208. }
  12209. if ( hue > 1 ) {
  12210. hue -= 1;
  12211. }
  12212. }
  12213. if ( hsv === undefined ) {
  12214. hsv = { h: 0, s: 0, v: 0 };
  12215. }
  12216. hsv.h = hue;
  12217. hsv.s = saturation;
  12218. hsv.v = value;
  12219. return hsv;
  12220. }
  12221. };
  12222. THREE.ColorUtils.__hsv = { h: 0, s: 0, v: 0 };/**
  12223. * @author mrdoob / http://mrdoob.com/
  12224. * @author alteredq / http://alteredqualia.com/
  12225. */
  12226. THREE.GeometryUtils = {
  12227. // Merge two geometries or geometry and geometry from object (using object's transform)
  12228. merge: function ( geometry1, object2 /* mesh | geometry */ ) {
  12229. var matrix, matrixRotation,
  12230. vertexOffset = geometry1.vertices.length,
  12231. uvPosition = geometry1.faceVertexUvs[ 0 ].length,
  12232. geometry2 = object2 instanceof THREE.Mesh ? object2.geometry : object2,
  12233. vertices1 = geometry1.vertices,
  12234. vertices2 = geometry2.vertices,
  12235. faces1 = geometry1.faces,
  12236. faces2 = geometry2.faces,
  12237. uvs1 = geometry1.faceVertexUvs[ 0 ],
  12238. uvs2 = geometry2.faceVertexUvs[ 0 ];
  12239. var geo1MaterialsMap = {};
  12240. for ( var i = 0; i < geometry1.materials.length; i ++ ) {
  12241. var id = geometry1.materials[ i ].id;
  12242. geo1MaterialsMap[ id ] = i;
  12243. }
  12244. if ( object2 instanceof THREE.Mesh ) {
  12245. object2.matrixAutoUpdate && object2.updateMatrix();
  12246. matrix = object2.matrix;
  12247. matrixRotation = new THREE.Matrix4();
  12248. matrixRotation.extractRotation( matrix, object2.scale );
  12249. }
  12250. // vertices
  12251. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  12252. var vertex = vertices2[ i ];
  12253. var vertexCopy = vertex.clone();
  12254. if ( matrix ) matrix.multiplyVector3( vertexCopy );
  12255. vertices1.push( vertexCopy );
  12256. }
  12257. // faces
  12258. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  12259. var face = faces2[ i ], faceCopy, normal, color,
  12260. faceVertexNormals = face.vertexNormals,
  12261. faceVertexColors = face.vertexColors;
  12262. if ( face instanceof THREE.Face3 ) {
  12263. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  12264. } else if ( face instanceof THREE.Face4 ) {
  12265. faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset );
  12266. }
  12267. faceCopy.normal.copy( face.normal );
  12268. if ( matrixRotation ) matrixRotation.multiplyVector3( faceCopy.normal );
  12269. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  12270. normal = faceVertexNormals[ j ].clone();
  12271. if ( matrixRotation ) matrixRotation.multiplyVector3( normal );
  12272. faceCopy.vertexNormals.push( normal );
  12273. }
  12274. faceCopy.color.copy( face.color );
  12275. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  12276. color = faceVertexColors[ j ];
  12277. faceCopy.vertexColors.push( color.clone() );
  12278. }
  12279. if ( face.materialIndex !== undefined ) {
  12280. var material2 = geometry2.materials[ face.materialIndex ];
  12281. var materialId2 = material2.id;
  12282. var materialIndex = geo1MaterialsMap[ materialId2 ];
  12283. if ( materialIndex === undefined ) {
  12284. materialIndex = geometry1.materials.length;
  12285. geo1MaterialsMap[ materialId2 ] = materialIndex;
  12286. geometry1.materials.push( material2 );
  12287. }
  12288. faceCopy.materialIndex = materialIndex;
  12289. }
  12290. faceCopy.centroid.copy( face.centroid );
  12291. if ( matrix ) matrix.multiplyVector3( faceCopy.centroid );
  12292. faces1.push( faceCopy );
  12293. }
  12294. // uvs
  12295. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  12296. var uv = uvs2[ i ], uvCopy = [];
  12297. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  12298. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  12299. }
  12300. uvs1.push( uvCopy );
  12301. }
  12302. },
  12303. clone: function ( geometry ) {
  12304. var cloneGeo = new THREE.Geometry();
  12305. var i, il;
  12306. var vertices = geometry.vertices,
  12307. faces = geometry.faces,
  12308. uvs = geometry.faceVertexUvs[ 0 ];
  12309. // materials
  12310. if ( geometry.materials ) {
  12311. cloneGeo.materials = geometry.materials.slice();
  12312. }
  12313. // vertices
  12314. for ( i = 0, il = vertices.length; i < il; i ++ ) {
  12315. var vertex = vertices[ i ];
  12316. cloneGeo.vertices.push( vertex.clone() );
  12317. }
  12318. // faces
  12319. for ( i = 0, il = faces.length; i < il; i ++ ) {
  12320. var face = faces[ i ];
  12321. cloneGeo.faces.push( face.clone() );
  12322. }
  12323. // uvs
  12324. for ( i = 0, il = uvs.length; i < il; i ++ ) {
  12325. var uv = uvs[ i ], uvCopy = [];
  12326. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  12327. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  12328. }
  12329. cloneGeo.faceVertexUvs[ 0 ].push( uvCopy );
  12330. }
  12331. return cloneGeo;
  12332. },
  12333. // Get random point in triangle (via barycentric coordinates)
  12334. // (uniform distribution)
  12335. // http://www.cgafaq.info/wiki/Random_Point_In_Triangle
  12336. randomPointInTriangle: function ( vectorA, vectorB, vectorC ) {
  12337. var a, b, c,
  12338. point = new THREE.Vector3(),
  12339. tmp = THREE.GeometryUtils.__v1;
  12340. a = THREE.GeometryUtils.random();
  12341. b = THREE.GeometryUtils.random();
  12342. if ( ( a + b ) > 1 ) {
  12343. a = 1 - a;
  12344. b = 1 - b;
  12345. }
  12346. c = 1 - a - b;
  12347. point.copy( vectorA );
  12348. point.multiplyScalar( a );
  12349. tmp.copy( vectorB );
  12350. tmp.multiplyScalar( b );
  12351. point.addSelf( tmp );
  12352. tmp.copy( vectorC );
  12353. tmp.multiplyScalar( c );
  12354. point.addSelf( tmp );
  12355. return point;
  12356. },
  12357. // Get random point in face (triangle / quad)
  12358. // (uniform distribution)
  12359. randomPointInFace: function ( face, geometry, useCachedAreas ) {
  12360. var vA, vB, vC, vD;
  12361. if ( face instanceof THREE.Face3 ) {
  12362. vA = geometry.vertices[ face.a ];
  12363. vB = geometry.vertices[ face.b ];
  12364. vC = geometry.vertices[ face.c ];
  12365. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
  12366. } else if ( face instanceof THREE.Face4 ) {
  12367. vA = geometry.vertices[ face.a ];
  12368. vB = geometry.vertices[ face.b ];
  12369. vC = geometry.vertices[ face.c ];
  12370. vD = geometry.vertices[ face.d ];
  12371. var area1, area2;
  12372. if ( useCachedAreas ) {
  12373. if ( face._area1 && face._area2 ) {
  12374. area1 = face._area1;
  12375. area2 = face._area2;
  12376. } else {
  12377. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  12378. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  12379. face._area1 = area1;
  12380. face._area2 = area2;
  12381. }
  12382. } else {
  12383. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
  12384. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  12385. }
  12386. var r = THREE.GeometryUtils.random() * ( area1 + area2 );
  12387. if ( r < area1 ) {
  12388. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
  12389. } else {
  12390. return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
  12391. }
  12392. }
  12393. },
  12394. // Get uniformly distributed random points in mesh
  12395. // - create array with cumulative sums of face areas
  12396. // - pick random number from 0 to total area
  12397. // - find corresponding place in area array by binary search
  12398. // - get random point in face
  12399. randomPointsInGeometry: function ( geometry, n ) {
  12400. var face, i,
  12401. faces = geometry.faces,
  12402. vertices = geometry.vertices,
  12403. il = faces.length,
  12404. totalArea = 0,
  12405. cumulativeAreas = [],
  12406. vA, vB, vC, vD;
  12407. // precompute face areas
  12408. for ( i = 0; i < il; i ++ ) {
  12409. face = faces[ i ];
  12410. if ( face instanceof THREE.Face3 ) {
  12411. vA = vertices[ face.a ];
  12412. vB = vertices[ face.b ];
  12413. vC = vertices[ face.c ];
  12414. face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
  12415. } else if ( face instanceof THREE.Face4 ) {
  12416. vA = vertices[ face.a ];
  12417. vB = vertices[ face.b ];
  12418. vC = vertices[ face.c ];
  12419. vD = vertices[ face.d ];
  12420. face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  12421. face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  12422. face._area = face._area1 + face._area2;
  12423. }
  12424. totalArea += face._area;
  12425. cumulativeAreas[ i ] = totalArea;
  12426. }
  12427. // binary search cumulative areas array
  12428. function binarySearchIndices( value ) {
  12429. function binarySearch( start, end ) {
  12430. // return closest larger index
  12431. // if exact number is not found
  12432. if ( end < start )
  12433. return start;
  12434. var mid = start + Math.floor( ( end - start ) / 2 );
  12435. if ( cumulativeAreas[ mid ] > value ) {
  12436. return binarySearch( start, mid - 1 );
  12437. } else if ( cumulativeAreas[ mid ] < value ) {
  12438. return binarySearch( mid + 1, end );
  12439. } else {
  12440. return mid;
  12441. }
  12442. }
  12443. var result = binarySearch( 0, cumulativeAreas.length - 1 )
  12444. return result;
  12445. }
  12446. // pick random face weighted by face area
  12447. var r, index,
  12448. result = [];
  12449. var stats = {};
  12450. for ( i = 0; i < n; i ++ ) {
  12451. r = THREE.GeometryUtils.random() * totalArea;
  12452. index = binarySearchIndices( r );
  12453. result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
  12454. if ( ! stats[ index ] ) {
  12455. stats[ index ] = 1;
  12456. } else {
  12457. stats[ index ] += 1;
  12458. }
  12459. }
  12460. return result;
  12461. },
  12462. // Get triangle area (by Heron's formula)
  12463. // http://en.wikipedia.org/wiki/Heron%27s_formula
  12464. triangleArea: function ( vectorA, vectorB, vectorC ) {
  12465. var s, a, b, c,
  12466. tmp = THREE.GeometryUtils.__v1;
  12467. tmp.sub( vectorA, vectorB );
  12468. a = tmp.length();
  12469. tmp.sub( vectorA, vectorC );
  12470. b = tmp.length();
  12471. tmp.sub( vectorB, vectorC );
  12472. c = tmp.length();
  12473. s = 0.5 * ( a + b + c );
  12474. return Math.sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  12475. },
  12476. // Center geometry so that 0,0,0 is in center of bounding box
  12477. center: function ( geometry ) {
  12478. geometry.computeBoundingBox();
  12479. var bb = geometry.boundingBox;
  12480. var offset = new THREE.Vector3();
  12481. offset.add( bb.min, bb.max );
  12482. offset.multiplyScalar( -0.5 );
  12483. geometry.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
  12484. geometry.computeBoundingBox();
  12485. return offset;
  12486. },
  12487. // Normalize UVs to be from <0,1>
  12488. // (for now just the first set of UVs)
  12489. normalizeUVs: function ( geometry ) {
  12490. var uvSet = geometry.faceVertexUvs[ 0 ];
  12491. for ( var i = 0, il = uvSet.length; i < il; i ++ ) {
  12492. var uvs = uvSet[ i ];
  12493. for ( var j = 0, jl = uvs.length; j < jl; j ++ ) {
  12494. // texture repeat
  12495. if( uvs[ j ].u !== 1.0 ) uvs[ j ].u = uvs[ j ].u - Math.floor( uvs[ j ].u );
  12496. if( uvs[ j ].v !== 1.0 ) uvs[ j ].v = uvs[ j ].v - Math.floor( uvs[ j ].v );
  12497. }
  12498. }
  12499. },
  12500. triangulateQuads: function ( geometry ) {
  12501. var i, il, j, jl;
  12502. var faces = [];
  12503. var faceUvs = [];
  12504. var faceVertexUvs = [];
  12505. for ( i = 0, il = geometry.faceUvs.length; i < il; i ++ ) {
  12506. faceUvs[ i ] = [];
  12507. }
  12508. for ( i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
  12509. faceVertexUvs[ i ] = [];
  12510. }
  12511. for ( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  12512. var face = geometry.faces[ i ];
  12513. if ( face instanceof THREE.Face4 ) {
  12514. var a = face.a;
  12515. var b = face.b;
  12516. var c = face.c;
  12517. var d = face.d;
  12518. var triA = new THREE.Face3();
  12519. var triB = new THREE.Face3();
  12520. triA.color.copy( face.color );
  12521. triB.color.copy( face.color );
  12522. triA.materialIndex = face.materialIndex;
  12523. triB.materialIndex = face.materialIndex;
  12524. triA.a = a;
  12525. triA.b = b;
  12526. triA.c = d;
  12527. triB.a = b;
  12528. triB.b = c;
  12529. triB.c = d;
  12530. if ( face.vertexColors.length === 4 ) {
  12531. triA.vertexColors[ 0 ] = face.vertexColors[ 0 ].clone();
  12532. triA.vertexColors[ 1 ] = face.vertexColors[ 1 ].clone();
  12533. triA.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
  12534. triB.vertexColors[ 0 ] = face.vertexColors[ 1 ].clone();
  12535. triB.vertexColors[ 1 ] = face.vertexColors[ 2 ].clone();
  12536. triB.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
  12537. }
  12538. faces.push( triA, triB );
  12539. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12540. if ( geometry.faceVertexUvs[ j ].length ) {
  12541. var uvs = geometry.faceVertexUvs[ j ][ i ];
  12542. var uvA = uvs[ 0 ];
  12543. var uvB = uvs[ 1 ];
  12544. var uvC = uvs[ 2 ];
  12545. var uvD = uvs[ 3 ];
  12546. var uvsTriA = [ uvA.clone(), uvB.clone(), uvD.clone() ];
  12547. var uvsTriB = [ uvB.clone(), uvC.clone(), uvD.clone() ];
  12548. faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
  12549. }
  12550. }
  12551. for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
  12552. if ( geometry.faceUvs[ j ].length ) {
  12553. var faceUv = geometry.faceUvs[ j ][ i ];
  12554. faceUvs[ j ].push( faceUv, faceUv );
  12555. }
  12556. }
  12557. } else {
  12558. faces.push( face );
  12559. for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
  12560. faceUvs[ j ].push( geometry.faceUvs[ j ] );
  12561. }
  12562. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12563. faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ] );
  12564. }
  12565. }
  12566. }
  12567. geometry.faces = faces;
  12568. geometry.faceUvs = faceUvs;
  12569. geometry.faceVertexUvs = faceVertexUvs;
  12570. geometry.computeCentroids();
  12571. geometry.computeFaceNormals();
  12572. geometry.computeVertexNormals();
  12573. if ( geometry.hasTangents ) geometry.computeTangents();
  12574. },
  12575. // Make all faces use unique vertices
  12576. // so that each face can be separated from others
  12577. explode: function( geometry ) {
  12578. var vertices = [];
  12579. for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
  12580. var n = vertices.length;
  12581. var face = geometry.faces[ i ];
  12582. if ( face instanceof THREE.Face4 ) {
  12583. var a = face.a;
  12584. var b = face.b;
  12585. var c = face.c;
  12586. var d = face.d;
  12587. var va = geometry.vertices[ a ];
  12588. var vb = geometry.vertices[ b ];
  12589. var vc = geometry.vertices[ c ];
  12590. var vd = geometry.vertices[ d ];
  12591. vertices.push( va.clone() );
  12592. vertices.push( vb.clone() );
  12593. vertices.push( vc.clone() );
  12594. vertices.push( vd.clone() );
  12595. face.a = n;
  12596. face.b = n + 1;
  12597. face.c = n + 2;
  12598. face.d = n + 3;
  12599. } else {
  12600. var a = face.a;
  12601. var b = face.b;
  12602. var c = face.c;
  12603. var va = geometry.vertices[ a ];
  12604. var vb = geometry.vertices[ b ];
  12605. var vc = geometry.vertices[ c ];
  12606. vertices.push( va.clone() );
  12607. vertices.push( vb.clone() );
  12608. vertices.push( vc.clone() );
  12609. face.a = n;
  12610. face.b = n + 1;
  12611. face.c = n + 2;
  12612. }
  12613. }
  12614. geometry.vertices = vertices;
  12615. delete geometry.__tmpVertices;
  12616. },
  12617. // Break faces with edges longer than maxEdgeLength
  12618. // - not recursive
  12619. tessellate: function ( geometry, maxEdgeLength ) {
  12620. var i, il, face,
  12621. a, b, c, d,
  12622. va, vb, vc, vd,
  12623. dab, dbc, dac, dcd, dad,
  12624. m, m1, m2,
  12625. vm, vm1, vm2,
  12626. vnm, vnm1, vnm2,
  12627. vcm, vcm1, vcm2,
  12628. triA, triB,
  12629. quadA, quadB,
  12630. edge;
  12631. var faces = [];
  12632. var faceVertexUvs = [];
  12633. for ( i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
  12634. faceVertexUvs[ i ] = [];
  12635. }
  12636. for ( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  12637. face = geometry.faces[ i ];
  12638. if ( face instanceof THREE.Face3 ) {
  12639. a = face.a;
  12640. b = face.b;
  12641. c = face.c;
  12642. va = geometry.vertices[ a ];
  12643. vb = geometry.vertices[ b ];
  12644. vc = geometry.vertices[ c ];
  12645. dab = va.distanceTo( vb );
  12646. dbc = vb.distanceTo( vc );
  12647. dac = va.distanceTo( vc );
  12648. if ( dab > maxEdgeLength || dbc > maxEdgeLength || dac > maxEdgeLength ) {
  12649. m = geometry.vertices.length;
  12650. triA = face.clone();
  12651. triB = face.clone();
  12652. if ( dab >= dbc && dab >= dac ) {
  12653. vm = va.clone();
  12654. vm.lerpSelf( vb, 0.5 );
  12655. triA.a = a;
  12656. triA.b = m;
  12657. triA.c = c;
  12658. triB.a = m;
  12659. triB.b = b;
  12660. triB.c = c;
  12661. if ( face.vertexNormals.length === 3 ) {
  12662. vnm = face.vertexNormals[ 0 ].clone();
  12663. vnm.lerpSelf( face.vertexNormals[ 1 ], 0.5 );
  12664. triA.vertexNormals[ 1 ].copy( vnm );
  12665. triB.vertexNormals[ 0 ].copy( vnm );
  12666. }
  12667. if ( face.vertexColors.length === 3 ) {
  12668. vcm = face.vertexColors[ 0 ].clone();
  12669. vcm.lerpSelf( face.vertexColors[ 1 ], 0.5 );
  12670. triA.vertexColors[ 1 ].copy( vcm );
  12671. triB.vertexColors[ 0 ].copy( vcm );
  12672. }
  12673. edge = 0;
  12674. } else if ( dbc >= dab && dbc >= dac ) {
  12675. vm = vb.clone();
  12676. vm.lerpSelf( vc, 0.5 );
  12677. triA.a = a;
  12678. triA.b = b;
  12679. triA.c = m;
  12680. triB.a = m;
  12681. triB.b = c;
  12682. triB.c = a;
  12683. if ( face.vertexNormals.length === 3 ) {
  12684. vnm = face.vertexNormals[ 1 ].clone();
  12685. vnm.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
  12686. triA.vertexNormals[ 2 ].copy( vnm );
  12687. triB.vertexNormals[ 0 ].copy( vnm );
  12688. triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] );
  12689. triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] );
  12690. }
  12691. if ( face.vertexColors.length === 3 ) {
  12692. vcm = face.vertexColors[ 1 ].clone();
  12693. vcm.lerpSelf( face.vertexColors[ 2 ], 0.5 );
  12694. triA.vertexColors[ 2 ].copy( vcm );
  12695. triB.vertexColors[ 0 ].copy( vcm );
  12696. triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] );
  12697. triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] );
  12698. }
  12699. edge = 1;
  12700. } else {
  12701. vm = va.clone();
  12702. vm.lerpSelf( vc, 0.5 );
  12703. triA.a = a;
  12704. triA.b = b;
  12705. triA.c = m;
  12706. triB.a = m;
  12707. triB.b = b;
  12708. triB.c = c;
  12709. if ( face.vertexNormals.length === 3 ) {
  12710. vnm = face.vertexNormals[ 0 ].clone();
  12711. vnm.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
  12712. triA.vertexNormals[ 2 ].copy( vnm );
  12713. triB.vertexNormals[ 0 ].copy( vnm );
  12714. }
  12715. if ( face.vertexColors.length === 3 ) {
  12716. vcm = face.vertexColors[ 0 ].clone();
  12717. vcm.lerpSelf( face.vertexColors[ 2 ], 0.5 );
  12718. triA.vertexColors[ 2 ].copy( vcm );
  12719. triB.vertexColors[ 0 ].copy( vcm );
  12720. }
  12721. edge = 2;
  12722. }
  12723. faces.push( triA, triB );
  12724. geometry.vertices.push( vm );
  12725. var j, jl, uvs, uvA, uvB, uvC, uvM, uvsTriA, uvsTriB;
  12726. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12727. if ( geometry.faceVertexUvs[ j ].length ) {
  12728. uvs = geometry.faceVertexUvs[ j ][ i ];
  12729. uvA = uvs[ 0 ];
  12730. uvB = uvs[ 1 ];
  12731. uvC = uvs[ 2 ];
  12732. // AB
  12733. if ( edge === 0 ) {
  12734. uvM = uvA.clone();
  12735. uvM.lerpSelf( uvB, 0.5 );
  12736. uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
  12737. uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
  12738. // BC
  12739. } else if ( edge === 1 ) {
  12740. uvM = uvB.clone();
  12741. uvM.lerpSelf( uvC, 0.5 );
  12742. uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
  12743. uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
  12744. // AC
  12745. } else {
  12746. uvM = uvA.clone();
  12747. uvM.lerpSelf( uvC, 0.5 );
  12748. uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
  12749. uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
  12750. }
  12751. faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
  12752. }
  12753. }
  12754. } else {
  12755. faces.push( face );
  12756. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12757. faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
  12758. }
  12759. }
  12760. } else {
  12761. a = face.a;
  12762. b = face.b;
  12763. c = face.c;
  12764. d = face.d;
  12765. va = geometry.vertices[ a ];
  12766. vb = geometry.vertices[ b ];
  12767. vc = geometry.vertices[ c ];
  12768. vd = geometry.vertices[ d ];
  12769. dab = va.distanceTo( vb );
  12770. dbc = vb.distanceTo( vc );
  12771. dcd = vc.distanceTo( vd );
  12772. dad = va.distanceTo( vd );
  12773. if ( dab > maxEdgeLength || dbc > maxEdgeLength || dcd > maxEdgeLength || dad > maxEdgeLength ) {
  12774. m1 = geometry.vertices.length;
  12775. m2 = geometry.vertices.length + 1;
  12776. quadA = face.clone();
  12777. quadB = face.clone();
  12778. if ( ( dab >= dbc && dab >= dcd && dab >= dad ) || ( dcd >= dbc && dcd >= dab && dcd >= dad ) ) {
  12779. vm1 = va.clone();
  12780. vm1.lerpSelf( vb, 0.5 );
  12781. vm2 = vc.clone();
  12782. vm2.lerpSelf( vd, 0.5 );
  12783. quadA.a = a;
  12784. quadA.b = m1;
  12785. quadA.c = m2;
  12786. quadA.d = d;
  12787. quadB.a = m1;
  12788. quadB.b = b;
  12789. quadB.c = c;
  12790. quadB.d = m2;
  12791. if ( face.vertexNormals.length === 4 ) {
  12792. vnm1 = face.vertexNormals[ 0 ].clone();
  12793. vnm1.lerpSelf( face.vertexNormals[ 1 ], 0.5 );
  12794. vnm2 = face.vertexNormals[ 2 ].clone();
  12795. vnm2.lerpSelf( face.vertexNormals[ 3 ], 0.5 );
  12796. quadA.vertexNormals[ 1 ].copy( vnm1 );
  12797. quadA.vertexNormals[ 2 ].copy( vnm2 );
  12798. quadB.vertexNormals[ 0 ].copy( vnm1 );
  12799. quadB.vertexNormals[ 3 ].copy( vnm2 );
  12800. }
  12801. if ( face.vertexColors.length === 4 ) {
  12802. vcm1 = face.vertexColors[ 0 ].clone();
  12803. vcm1.lerpSelf( face.vertexColors[ 1 ], 0.5 );
  12804. vcm2 = face.vertexColors[ 2 ].clone();
  12805. vcm2.lerpSelf( face.vertexColors[ 3 ], 0.5 );
  12806. quadA.vertexColors[ 1 ].copy( vcm1 );
  12807. quadA.vertexColors[ 2 ].copy( vcm2 );
  12808. quadB.vertexColors[ 0 ].copy( vcm1 );
  12809. quadB.vertexColors[ 3 ].copy( vcm2 );
  12810. }
  12811. edge = 0;
  12812. } else {
  12813. vm1 = vb.clone();
  12814. vm1.lerpSelf( vc, 0.5 );
  12815. vm2 = vd.clone();
  12816. vm2.lerpSelf( va, 0.5 );
  12817. quadA.a = a;
  12818. quadA.b = b;
  12819. quadA.c = m1;
  12820. quadA.d = m2;
  12821. quadB.a = m2;
  12822. quadB.b = m1;
  12823. quadB.c = c;
  12824. quadB.d = d;
  12825. if ( face.vertexNormals.length === 4 ) {
  12826. vnm1 = face.vertexNormals[ 1 ].clone();
  12827. vnm1.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
  12828. vnm2 = face.vertexNormals[ 3 ].clone();
  12829. vnm2.lerpSelf( face.vertexNormals[ 0 ], 0.5 );
  12830. quadA.vertexNormals[ 2 ].copy( vnm1 );
  12831. quadA.vertexNormals[ 3 ].copy( vnm2 );
  12832. quadB.vertexNormals[ 0 ].copy( vnm2 );
  12833. quadB.vertexNormals[ 1 ].copy( vnm1 );
  12834. }
  12835. if ( face.vertexColors.length === 4 ) {
  12836. vcm1 = face.vertexColors[ 1 ].clone();
  12837. vcm1.lerpSelf( face.vertexColors[ 2 ], 0.5 );
  12838. vcm2 = face.vertexColors[ 3 ].clone();
  12839. vcm2.lerpSelf( face.vertexColors[ 0 ], 0.5 );
  12840. quadA.vertexColors[ 2 ].copy( vcm1 );
  12841. quadA.vertexColors[ 3 ].copy( vcm2 );
  12842. quadB.vertexColors[ 0 ].copy( vcm2 );
  12843. quadB.vertexColors[ 1 ].copy( vcm1 );
  12844. }
  12845. edge = 1;
  12846. }
  12847. faces.push( quadA, quadB );
  12848. geometry.vertices.push( vm1, vm2 );
  12849. var j, jl, uvs, uvA, uvB, uvC, uvD, uvM1, uvM2, uvsQuadA, uvsQuadB;
  12850. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12851. if ( geometry.faceVertexUvs[ j ].length ) {
  12852. uvs = geometry.faceVertexUvs[ j ][ i ];
  12853. uvA = uvs[ 0 ];
  12854. uvB = uvs[ 1 ];
  12855. uvC = uvs[ 2 ];
  12856. uvD = uvs[ 3 ];
  12857. // AB + CD
  12858. if ( edge === 0 ) {
  12859. uvM1 = uvA.clone();
  12860. uvM1.lerpSelf( uvB, 0.5 );
  12861. uvM2 = uvC.clone();
  12862. uvM2.lerpSelf( uvD, 0.5 );
  12863. uvsQuadA = [ uvA.clone(), uvM1.clone(), uvM2.clone(), uvD.clone() ];
  12864. uvsQuadB = [ uvM1.clone(), uvB.clone(), uvC.clone(), uvM2.clone() ];
  12865. // BC + AD
  12866. } else {
  12867. uvM1 = uvB.clone();
  12868. uvM1.lerpSelf( uvC, 0.5 );
  12869. uvM2 = uvD.clone();
  12870. uvM2.lerpSelf( uvA, 0.5 );
  12871. uvsQuadA = [ uvA.clone(), uvB.clone(), uvM1.clone(), uvM2.clone() ];
  12872. uvsQuadB = [ uvM2.clone(), uvM1.clone(), uvC.clone(), uvD.clone() ];
  12873. }
  12874. faceVertexUvs[ j ].push( uvsQuadA, uvsQuadB );
  12875. }
  12876. }
  12877. } else {
  12878. faces.push( face );
  12879. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  12880. faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
  12881. }
  12882. }
  12883. }
  12884. }
  12885. geometry.faces = faces;
  12886. geometry.faceVertexUvs = faceVertexUvs;
  12887. }
  12888. };
  12889. THREE.GeometryUtils.random = THREE.Math.random16;
  12890. THREE.GeometryUtils.__v1 = new THREE.Vector3();
  12891. /**
  12892. * @author alteredq / http://alteredqualia.com/
  12893. * @author mrdoob / http://mrdoob.com/
  12894. */
  12895. THREE.ImageUtils = {
  12896. crossOrigin: 'anonymous',
  12897. loadTexture: function ( url, mapping, onLoad, onError ) {
  12898. var texture = new THREE.Texture( undefined, mapping );
  12899. var loader = new THREE.ImageLoader();
  12900. loader.addEventListener( 'load', function ( event ) {
  12901. texture.image = event.content;
  12902. texture.needsUpdate = true;
  12903. if ( onLoad ) onLoad( texture );
  12904. } );
  12905. loader.addEventListener( 'error', function ( event ) {
  12906. if ( onError ) onError( event.message );
  12907. } );
  12908. loader.crossOrigin = this.crossOrigin;
  12909. loader.load( url );
  12910. return texture;
  12911. },
  12912. loadTextureCube: function ( array, mapping, onLoad ) {
  12913. var i, l, images = [];
  12914. var texture = new THREE.Texture( images, mapping );
  12915. texture.flipY = false;
  12916. images.loadCount = 0;
  12917. for ( i = 0, l = array.length; i < l; ++ i ) {
  12918. images[ i ] = new Image();
  12919. images[ i ].onload = function () {
  12920. images.loadCount += 1;
  12921. if ( images.loadCount === 6 ) {
  12922. texture.needsUpdate = true;
  12923. if ( onLoad ) onLoad();
  12924. }
  12925. };
  12926. images[ i ].crossOrigin = this.crossOrigin;
  12927. images[ i ].src = array[ i ];
  12928. }
  12929. return texture;
  12930. },
  12931. getNormalMap: function ( image, depth ) {
  12932. // Adapted from http://www.paulbrunt.co.uk/lab/heightnormal/
  12933. var cross = function ( a, b ) {
  12934. return [ a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ], a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ], a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ] ];
  12935. }
  12936. var subtract = function ( a, b ) {
  12937. return [ a[ 0 ] - b[ 0 ], a[ 1 ] - b[ 1 ], a[ 2 ] - b[ 2 ] ];
  12938. }
  12939. var normalize = function ( a ) {
  12940. var l = Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] );
  12941. return [ a[ 0 ] / l, a[ 1 ] / l, a[ 2 ] / l ];
  12942. }
  12943. depth = depth | 1;
  12944. var width = image.width;
  12945. var height = image.height;
  12946. var canvas = document.createElement( 'canvas' );
  12947. canvas.width = width;
  12948. canvas.height = height;
  12949. var context = canvas.getContext( '2d' );
  12950. context.drawImage( image, 0, 0 );
  12951. var data = context.getImageData( 0, 0, width, height ).data;
  12952. var imageData = context.createImageData( width, height );
  12953. var output = imageData.data;
  12954. for ( var x = 0; x < width; x ++ ) {
  12955. for ( var y = 0; y < height; y ++ ) {
  12956. var ly = y - 1 < 0 ? 0 : y - 1;
  12957. var uy = y + 1 > height - 1 ? height - 1 : y + 1;
  12958. var lx = x - 1 < 0 ? 0 : x - 1;
  12959. var ux = x + 1 > width - 1 ? width - 1 : x + 1;
  12960. var points = [];
  12961. var origin = [ 0, 0, data[ ( y * width + x ) * 4 ] / 255 * depth ];
  12962. points.push( [ - 1, 0, data[ ( y * width + lx ) * 4 ] / 255 * depth ] );
  12963. points.push( [ - 1, - 1, data[ ( ly * width + lx ) * 4 ] / 255 * depth ] );
  12964. points.push( [ 0, - 1, data[ ( ly * width + x ) * 4 ] / 255 * depth ] );
  12965. points.push( [ 1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] );
  12966. points.push( [ 1, 0, data[ ( y * width + ux ) * 4 ] / 255 * depth ] );
  12967. points.push( [ 1, 1, data[ ( uy * width + ux ) * 4 ] / 255 * depth ] );
  12968. points.push( [ 0, 1, data[ ( uy * width + x ) * 4 ] / 255 * depth ] );
  12969. points.push( [ - 1, 1, data[ ( uy * width + lx ) * 4 ] / 255 * depth ] );
  12970. var normals = [];
  12971. var num_points = points.length;
  12972. for ( var i = 0; i < num_points; i ++ ) {
  12973. var v1 = points[ i ];
  12974. var v2 = points[ ( i + 1 ) % num_points ];
  12975. v1 = subtract( v1, origin );
  12976. v2 = subtract( v2, origin );
  12977. normals.push( normalize( cross( v1, v2 ) ) );
  12978. }
  12979. var normal = [ 0, 0, 0 ];
  12980. for ( var i = 0; i < normals.length; i ++ ) {
  12981. normal[ 0 ] += normals[ i ][ 0 ];
  12982. normal[ 1 ] += normals[ i ][ 1 ];
  12983. normal[ 2 ] += normals[ i ][ 2 ];
  12984. }
  12985. normal[ 0 ] /= normals.length;
  12986. normal[ 1 ] /= normals.length;
  12987. normal[ 2 ] /= normals.length;
  12988. var idx = ( y * width + x ) * 4;
  12989. output[ idx ] = ( ( normal[ 0 ] + 1.0 ) / 2.0 * 255 ) | 0;
  12990. output[ idx + 1 ] = ( ( normal[ 1 ] + 1.0 ) / 2.0 * 255 ) | 0;
  12991. output[ idx + 2 ] = ( normal[ 2 ] * 255 ) | 0;
  12992. output[ idx + 3 ] = 255;
  12993. }
  12994. }
  12995. context.putImageData( imageData, 0, 0 );
  12996. return canvas;
  12997. },
  12998. generateDataTexture: function ( width, height, color ) {
  12999. var size = width * height;
  13000. var data = new Uint8Array( 3 * size );
  13001. var r = Math.floor( color.r * 255 );
  13002. var g = Math.floor( color.g * 255 );
  13003. var b = Math.floor( color.b * 255 );
  13004. for ( var i = 0; i < size; i ++ ) {
  13005. data[ i * 3 ] = r;
  13006. data[ i * 3 + 1 ] = g;
  13007. data[ i * 3 + 2 ] = b;
  13008. }
  13009. var texture = new THREE.DataTexture( data, width, height, THREE.RGBFormat );
  13010. texture.needsUpdate = true;
  13011. return texture;
  13012. }
  13013. };
  13014. /**
  13015. * @author alteredq / http://alteredqualia.com/
  13016. */
  13017. THREE.SceneUtils = {
  13018. showHierarchy : function ( root, visible ) {
  13019. THREE.SceneUtils.traverseHierarchy( root, function( node ) { node.visible = visible; } );
  13020. },
  13021. traverseHierarchy : function ( root, callback ) {
  13022. var n, i, l = root.children.length;
  13023. for ( i = 0; i < l; i ++ ) {
  13024. n = root.children[ i ];
  13025. callback( n );
  13026. THREE.SceneUtils.traverseHierarchy( n, callback );
  13027. }
  13028. },
  13029. createMultiMaterialObject : function ( geometry, materials ) {
  13030. var i, il = materials.length,
  13031. group = new THREE.Object3D();
  13032. for ( i = 0; i < il; i ++ ) {
  13033. var object = new THREE.Mesh( geometry, materials[ i ] );
  13034. group.add( object );
  13035. }
  13036. return group;
  13037. },
  13038. cloneObject: function ( source ) {
  13039. var object;
  13040. // subclass specific properties
  13041. // (must process in order from more specific subclasses to more abstract classes)
  13042. if ( source instanceof THREE.MorphAnimMesh ) {
  13043. object = new THREE.MorphAnimMesh( source.geometry, source.material );
  13044. object.duration = source.duration;
  13045. object.mirroredLoop = source.mirroredLoop;
  13046. object.time = source.time;
  13047. object.lastKeyframe = source.lastKeyframe;
  13048. object.currentKeyframe = source.currentKeyframe;
  13049. object.direction = source.direction;
  13050. object.directionBackwards = source.directionBackwards;
  13051. } else if ( source instanceof THREE.SkinnedMesh ) {
  13052. object = new THREE.SkinnedMesh( source.geometry, source.material );
  13053. } else if ( source instanceof THREE.Mesh ) {
  13054. object = new THREE.Mesh( source.geometry, source.material );
  13055. } else if ( source instanceof THREE.Line ) {
  13056. object = new THREE.Line( source.geometry, source.material, source.type );
  13057. } else if ( source instanceof THREE.Ribbon ) {
  13058. object = new THREE.Ribbon( source.geometry, source.material );
  13059. } else if ( source instanceof THREE.ParticleSystem ) {
  13060. object = new THREE.ParticleSystem( source.geometry, source.material );
  13061. object.sortParticles = source.sortParticles;
  13062. } else if ( source instanceof THREE.Particle ) {
  13063. object = new THREE.Particle( source.material );
  13064. } else if ( source instanceof THREE.Sprite ) {
  13065. object = new THREE.Sprite( {} );
  13066. object.color.copy( source.color );
  13067. object.map = source.map;
  13068. object.blending = source.blending;
  13069. object.useScreenCoordinates = source.useScreenCoordinates;
  13070. object.mergeWith3D = source.mergeWith3D;
  13071. object.affectedByDistance = source.affectedByDistance;
  13072. object.scaleByViewport = source.scaleByViewport;
  13073. object.alignment = source.alignment;
  13074. object.rotation3d.copy( source.rotation3d );
  13075. object.rotation = source.rotation;
  13076. object.opacity = source.opacity;
  13077. object.uvOffset.copy( source.uvOffset );
  13078. object.uvScale.copy( source.uvScale);
  13079. } else if ( source instanceof THREE.LOD ) {
  13080. object = new THREE.LOD();
  13081. /*
  13082. } else if ( source instanceof THREE.MarchingCubes ) {
  13083. object = new THREE.MarchingCubes( source.resolution, source.material );
  13084. object.field.set( source.field );
  13085. object.isolation = source.isolation;
  13086. */
  13087. } else if ( source instanceof THREE.Object3D ) {
  13088. object = new THREE.Object3D();
  13089. }
  13090. // base class properties
  13091. object.name = source.name;
  13092. object.parent = source.parent;
  13093. object.up.copy( source.up );
  13094. object.position.copy( source.position );
  13095. // because of Sprite madness
  13096. if ( object.rotation instanceof THREE.Vector3 )
  13097. object.rotation.copy( source.rotation );
  13098. object.eulerOrder = source.eulerOrder;
  13099. object.scale.copy( source.scale );
  13100. object.dynamic = source.dynamic;
  13101. object.doubleSided = source.doubleSided;
  13102. object.flipSided = source.flipSided;
  13103. object.renderDepth = source.renderDepth;
  13104. object.rotationAutoUpdate = source.rotationAutoUpdate;
  13105. object.matrix.copy( source.matrix );
  13106. object.matrixWorld.copy( source.matrixWorld );
  13107. object.matrixRotationWorld.copy( source.matrixRotationWorld );
  13108. object.matrixAutoUpdate = source.matrixAutoUpdate;
  13109. object.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
  13110. object.quaternion.copy( source.quaternion );
  13111. object.useQuaternion = source.useQuaternion;
  13112. object.boundRadius = source.boundRadius;
  13113. object.boundRadiusScale = source.boundRadiusScale;
  13114. object.visible = source.visible;
  13115. object.castShadow = source.castShadow;
  13116. object.receiveShadow = source.receiveShadow;
  13117. object.frustumCulled = source.frustumCulled;
  13118. // children
  13119. for ( var i = 0; i < source.children.length; i ++ ) {
  13120. var child = THREE.SceneUtils.cloneObject( source.children[ i ] );
  13121. object.children[ i ] = child;
  13122. child.parent = object;
  13123. }
  13124. // LODs need to be patched separately to use cloned children
  13125. if ( source instanceof THREE.LOD ) {
  13126. for ( var i = 0; i < source.LODs.length; i ++ ) {
  13127. var lod = source.LODs[ i ];
  13128. object.LODs[ i ] = { visibleAtDistance: lod.visibleAtDistance, object3D: object.children[ i ] };
  13129. }
  13130. }
  13131. return object;
  13132. },
  13133. detach : function ( child, parent, scene ) {
  13134. child.applyMatrix( parent.matrixWorld );
  13135. parent.remove( child );
  13136. scene.add( child );
  13137. },
  13138. attach: function ( child, scene, parent ) {
  13139. var matrixWorldInverse = new THREE.Matrix4();
  13140. matrixWorldInverse.getInverse( parent.matrixWorld );
  13141. child.applyMatrix( matrixWorldInverse );
  13142. scene.remove( child );
  13143. parent.add( child );
  13144. }
  13145. };
  13146. /**
  13147. * @author alteredq / http://alteredqualia.com/
  13148. * @author mr.doob / http://mrdoob.com/
  13149. *
  13150. * ShaderUtils currently contains:
  13151. *
  13152. * fresnel
  13153. * normal
  13154. * cube
  13155. *
  13156. */
  13157. if ( THREE.WebGLRenderer ) {
  13158. THREE.ShaderUtils = {
  13159. lib: {
  13160. /* -------------------------------------------------------------------------
  13161. // Fresnel shader
  13162. // - based on Nvidia Cg tutorial
  13163. ------------------------------------------------------------------------- */
  13164. 'fresnel': {
  13165. uniforms: {
  13166. "mRefractionRatio": { type: "f", value: 1.02 },
  13167. "mFresnelBias": { type: "f", value: 0.1 },
  13168. "mFresnelPower": { type: "f", value: 2.0 },
  13169. "mFresnelScale": { type: "f", value: 1.0 },
  13170. "tCube": { type: "t", value: 1, texture: null }
  13171. },
  13172. fragmentShader: [
  13173. "uniform samplerCube tCube;",
  13174. "varying vec3 vReflect;",
  13175. "varying vec3 vRefract[3];",
  13176. "varying float vReflectionFactor;",
  13177. "void main() {",
  13178. "vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
  13179. "vec4 refractedColor = vec4( 1.0, 1.0, 1.0, 1.0 );",
  13180. "refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;",
  13181. "refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;",
  13182. "refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;",
  13183. "refractedColor.a = 1.0;",
  13184. "gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );",
  13185. "}"
  13186. ].join("\n"),
  13187. vertexShader: [
  13188. "uniform float mRefractionRatio;",
  13189. "uniform float mFresnelBias;",
  13190. "uniform float mFresnelScale;",
  13191. "uniform float mFresnelPower;",
  13192. "varying vec3 vReflect;",
  13193. "varying vec3 vRefract[3];",
  13194. "varying float vReflectionFactor;",
  13195. "void main() {",
  13196. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  13197. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  13198. "vec3 nWorld = normalize ( mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal );",
  13199. "vec3 I = mPosition.xyz - cameraPosition;",
  13200. "vReflect = reflect( I, nWorld );",
  13201. "vRefract[0] = refract( normalize( I ), nWorld, mRefractionRatio );",
  13202. "vRefract[1] = refract( normalize( I ), nWorld, mRefractionRatio * 0.99 );",
  13203. "vRefract[2] = refract( normalize( I ), nWorld, mRefractionRatio * 0.98 );",
  13204. "vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), nWorld ), mFresnelPower );",
  13205. "gl_Position = projectionMatrix * mvPosition;",
  13206. "}"
  13207. ].join("\n")
  13208. },
  13209. /* -------------------------------------------------------------------------
  13210. // Normal map shader
  13211. // - Blinn-Phong
  13212. // - normal + diffuse + specular + AO + displacement + reflection + shadow maps
  13213. // - point and directional lights (use with "lights: true" material option)
  13214. ------------------------------------------------------------------------- */
  13215. 'normal' : {
  13216. uniforms: THREE.UniformsUtils.merge( [
  13217. THREE.UniformsLib[ "fog" ],
  13218. THREE.UniformsLib[ "lights" ],
  13219. THREE.UniformsLib[ "shadowmap" ],
  13220. {
  13221. "enableAO" : { type: "i", value: 0 },
  13222. "enableDiffuse" : { type: "i", value: 0 },
  13223. "enableSpecular" : { type: "i", value: 0 },
  13224. "enableReflection": { type: "i", value: 0 },
  13225. "tDiffuse" : { type: "t", value: 0, texture: null },
  13226. "tCube" : { type: "t", value: 1, texture: null },
  13227. "tNormal" : { type: "t", value: 2, texture: null },
  13228. "tSpecular" : { type: "t", value: 3, texture: null },
  13229. "tAO" : { type: "t", value: 4, texture: null },
  13230. "tDisplacement": { type: "t", value: 5, texture: null },
  13231. "uNormalScale": { type: "f", value: 1.0 },
  13232. "uDisplacementBias": { type: "f", value: 0.0 },
  13233. "uDisplacementScale": { type: "f", value: 1.0 },
  13234. "uDiffuseColor": { type: "c", value: new THREE.Color( 0xffffff ) },
  13235. "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
  13236. "uAmbientColor": { type: "c", value: new THREE.Color( 0xffffff ) },
  13237. "uShininess": { type: "f", value: 30 },
  13238. "uOpacity": { type: "f", value: 1 },
  13239. "uReflectivity": { type: "f", value: 0.5 },
  13240. "uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) },
  13241. "uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
  13242. "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
  13243. }
  13244. ] ),
  13245. fragmentShader: [
  13246. "uniform vec3 uAmbientColor;",
  13247. "uniform vec3 uDiffuseColor;",
  13248. "uniform vec3 uSpecularColor;",
  13249. "uniform float uShininess;",
  13250. "uniform float uOpacity;",
  13251. "uniform bool enableDiffuse;",
  13252. "uniform bool enableSpecular;",
  13253. "uniform bool enableAO;",
  13254. "uniform bool enableReflection;",
  13255. "uniform sampler2D tDiffuse;",
  13256. "uniform sampler2D tNormal;",
  13257. "uniform sampler2D tSpecular;",
  13258. "uniform sampler2D tAO;",
  13259. "uniform samplerCube tCube;",
  13260. "uniform float uNormalScale;",
  13261. "uniform float uReflectivity;",
  13262. "varying vec3 vTangent;",
  13263. "varying vec3 vBinormal;",
  13264. "varying vec3 vNormal;",
  13265. "varying vec2 vUv;",
  13266. "uniform vec3 ambientLightColor;",
  13267. "#if MAX_DIR_LIGHTS > 0",
  13268. "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
  13269. "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
  13270. "#endif",
  13271. "#if MAX_POINT_LIGHTS > 0",
  13272. "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
  13273. "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
  13274. "#endif",
  13275. "#if MAX_SPOT_LIGHTS > 0",
  13276. "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
  13277. "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
  13278. "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
  13279. "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
  13280. "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
  13281. "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
  13282. "varying vec3 vWorldPosition;",
  13283. "#endif",
  13284. "#ifdef WRAP_AROUND",
  13285. "uniform vec3 wrapRGB;",
  13286. "#endif",
  13287. "varying vec3 vViewPosition;",
  13288. THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
  13289. THREE.ShaderChunk[ "fog_pars_fragment" ],
  13290. "void main() {",
  13291. "gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
  13292. "vec3 specularTex = vec3( 1.0 );",
  13293. "vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
  13294. "normalTex.xy *= uNormalScale;",
  13295. "normalTex = normalize( normalTex );",
  13296. "if( enableDiffuse ) {",
  13297. "#ifdef GAMMA_INPUT",
  13298. "vec4 texelColor = texture2D( tDiffuse, vUv );",
  13299. "texelColor.xyz *= texelColor.xyz;",
  13300. "gl_FragColor = gl_FragColor * texelColor;",
  13301. "#else",
  13302. "gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
  13303. "#endif",
  13304. "}",
  13305. "if( enableAO ) {",
  13306. "#ifdef GAMMA_INPUT",
  13307. "vec4 aoColor = texture2D( tAO, vUv );",
  13308. "aoColor.xyz *= aoColor.xyz;",
  13309. "gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
  13310. "#else",
  13311. "gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
  13312. "#endif",
  13313. "}",
  13314. "if( enableSpecular )",
  13315. "specularTex = texture2D( tSpecular, vUv ).xyz;",
  13316. "mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );",
  13317. "vec3 finalNormal = tsb * normalTex;",
  13318. "vec3 normal = normalize( finalNormal );",
  13319. "vec3 viewPosition = normalize( vViewPosition );",
  13320. // point lights
  13321. "#if MAX_POINT_LIGHTS > 0",
  13322. "vec3 pointDiffuse = vec3( 0.0 );",
  13323. "vec3 pointSpecular = vec3( 0.0 );",
  13324. "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
  13325. "vec3 pointVector = normalize( vPointLight[ i ].xyz );",
  13326. "float pointDistance = vPointLight[ i ].w;",
  13327. // diffuse
  13328. "#ifdef WRAP_AROUND",
  13329. "float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );",
  13330. "float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );",
  13331. "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
  13332. "#else",
  13333. "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
  13334. "#endif",
  13335. "pointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;",
  13336. // specular
  13337. "vec3 pointHalfVector = normalize( pointVector + viewPosition );",
  13338. "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
  13339. "float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );",
  13340. "#ifdef PHYSICALLY_BASED_SHADING",
  13341. // 2.0 => 2.0001 is hack to work around ANGLE bug
  13342. "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
  13343. "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );",
  13344. "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
  13345. "#else",
  13346. "pointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;",
  13347. "#endif",
  13348. "}",
  13349. "#endif",
  13350. // spot lights
  13351. "#if MAX_SPOT_LIGHTS > 0",
  13352. "vec3 spotDiffuse = vec3( 0.0 );",
  13353. "vec3 spotSpecular = vec3( 0.0 );",
  13354. "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
  13355. "vec3 spotVector = normalize( vSpotLight[ i ].xyz );",
  13356. "float spotDistance = vSpotLight[ i ].w;",
  13357. "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
  13358. "if ( spotEffect > spotLightAngle[ i ] ) {",
  13359. "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
  13360. // diffuse
  13361. "#ifdef WRAP_AROUND",
  13362. "float spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );",
  13363. "float spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );",
  13364. "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
  13365. "#else",
  13366. "float spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );",
  13367. "#endif",
  13368. "spotDiffuse += spotDistance * spotLightColor[ i ] * uDiffuseColor * spotDiffuseWeight * spotEffect;",
  13369. // specular
  13370. "vec3 spotHalfVector = normalize( spotVector + viewPosition );",
  13371. "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
  13372. "float spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, uShininess ), 0.0 );",
  13373. "#ifdef PHYSICALLY_BASED_SHADING",
  13374. // 2.0 => 2.0001 is hack to work around ANGLE bug
  13375. "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
  13376. "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( spotVector, spotHalfVector ), 5.0 );",
  13377. "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;",
  13378. "#else",
  13379. "spotSpecular += spotDistance * spotLightColor[ i ] * uSpecularColor * spotSpecularWeight * spotDiffuseWeight * spotEffect;",
  13380. "#endif",
  13381. "}",
  13382. "}",
  13383. "#endif",
  13384. // directional lights
  13385. "#if MAX_DIR_LIGHTS > 0",
  13386. "vec3 dirDiffuse = vec3( 0.0 );",
  13387. "vec3 dirSpecular = vec3( 0.0 );",
  13388. "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
  13389. "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
  13390. "vec3 dirVector = normalize( lDirection.xyz );",
  13391. // diffuse
  13392. "#ifdef WRAP_AROUND",
  13393. "float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );",
  13394. "float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
  13395. "vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );",
  13396. "#else",
  13397. "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
  13398. "#endif",
  13399. "dirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;",
  13400. // specular
  13401. "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
  13402. "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
  13403. "float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );",
  13404. "#ifdef PHYSICALLY_BASED_SHADING",
  13405. // 2.0 => 2.0001 is hack to work around ANGLE bug
  13406. "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
  13407. "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
  13408. "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
  13409. "#else",
  13410. "dirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;",
  13411. "#endif",
  13412. "}",
  13413. "#endif",
  13414. // all lights contribution summation
  13415. "vec3 totalDiffuse = vec3( 0.0 );",
  13416. "vec3 totalSpecular = vec3( 0.0 );",
  13417. "#if MAX_DIR_LIGHTS > 0",
  13418. "totalDiffuse += dirDiffuse;",
  13419. "totalSpecular += dirSpecular;",
  13420. "#endif",
  13421. "#if MAX_POINT_LIGHTS > 0",
  13422. "totalDiffuse += pointDiffuse;",
  13423. "totalSpecular += pointSpecular;",
  13424. "#endif",
  13425. "#if MAX_SPOT_LIGHTS > 0",
  13426. "totalDiffuse += spotDiffuse;",
  13427. "totalSpecular += spotSpecular;",
  13428. "#endif",
  13429. "gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;",
  13430. "if ( enableReflection ) {",
  13431. "vec3 wPos = cameraPosition - vViewPosition;",
  13432. "vec3 vReflect = reflect( normalize( wPos ), normal );",
  13433. "vec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
  13434. "#ifdef GAMMA_INPUT",
  13435. "cubeColor.xyz *= cubeColor.xyz;",
  13436. "#endif",
  13437. "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );",
  13438. "}",
  13439. THREE.ShaderChunk[ "shadowmap_fragment" ],
  13440. THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
  13441. THREE.ShaderChunk[ "fog_fragment" ],
  13442. "}"
  13443. ].join("\n"),
  13444. vertexShader: [
  13445. "attribute vec4 tangent;",
  13446. "uniform vec2 uOffset;",
  13447. "uniform vec2 uRepeat;",
  13448. "#ifdef VERTEX_TEXTURES",
  13449. "uniform sampler2D tDisplacement;",
  13450. "uniform float uDisplacementScale;",
  13451. "uniform float uDisplacementBias;",
  13452. "#endif",
  13453. "varying vec3 vTangent;",
  13454. "varying vec3 vBinormal;",
  13455. "varying vec3 vNormal;",
  13456. "varying vec2 vUv;",
  13457. "#if MAX_POINT_LIGHTS > 0",
  13458. "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
  13459. "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
  13460. "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
  13461. "#endif",
  13462. "#if MAX_SPOT_LIGHTS > 0",
  13463. "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
  13464. "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
  13465. "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
  13466. "varying vec3 vWorldPosition;",
  13467. "#endif",
  13468. "varying vec3 vViewPosition;",
  13469. THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
  13470. "void main() {",
  13471. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  13472. "vViewPosition = -mvPosition.xyz;",
  13473. // normal, tangent and binormal vectors
  13474. "vNormal = normalMatrix * normal;",
  13475. "vTangent = normalMatrix * tangent.xyz;",
  13476. "vBinormal = cross( vNormal, vTangent ) * tangent.w;",
  13477. "vUv = uv * uRepeat + uOffset;",
  13478. // point lights
  13479. "#if MAX_POINT_LIGHTS > 0",
  13480. "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
  13481. "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
  13482. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  13483. "float lDistance = 1.0;",
  13484. "if ( pointLightDistance[ i ] > 0.0 )",
  13485. "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
  13486. "lVector = normalize( lVector );",
  13487. "vPointLight[ i ] = vec4( lVector, lDistance );",
  13488. "}",
  13489. "#endif",
  13490. // spot lights
  13491. "#if MAX_SPOT_LIGHTS > 0",
  13492. "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
  13493. "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
  13494. "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
  13495. "float lDistance = 1.0;",
  13496. "if ( spotLightDistance[ i ] > 0.0 )",
  13497. "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
  13498. "vSpotLight[ i ] = vec4( lVector, lDistance );",
  13499. "}",
  13500. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  13501. "vWorldPosition = mPosition.xyz;",
  13502. "#endif",
  13503. // displacement mapping
  13504. "#ifdef VERTEX_TEXTURES",
  13505. "vec3 dv = texture2D( tDisplacement, uv ).xyz;",
  13506. "float df = uDisplacementScale * dv.x + uDisplacementBias;",
  13507. "vec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;",
  13508. "gl_Position = projectionMatrix * displacedPosition;",
  13509. "#else",
  13510. "gl_Position = projectionMatrix * mvPosition;",
  13511. "#endif",
  13512. THREE.ShaderChunk[ "shadowmap_vertex" ],
  13513. "}"
  13514. ].join("\n")
  13515. },
  13516. /* -------------------------------------------------------------------------
  13517. // Cube map shader
  13518. ------------------------------------------------------------------------- */
  13519. 'cube': {
  13520. uniforms: { "tCube": { type: "t", value: 1, texture: null },
  13521. "tFlip": { type: "f", value: -1 } },
  13522. vertexShader: [
  13523. "varying vec3 vViewPosition;",
  13524. "void main() {",
  13525. "vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
  13526. "vViewPosition = cameraPosition - mPosition.xyz;",
  13527. "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
  13528. "}"
  13529. ].join("\n"),
  13530. fragmentShader: [
  13531. "uniform samplerCube tCube;",
  13532. "uniform float tFlip;",
  13533. "varying vec3 vViewPosition;",
  13534. "void main() {",
  13535. "vec3 wPos = cameraPosition - vViewPosition;",
  13536. "gl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );",
  13537. "}"
  13538. ].join("\n")
  13539. }
  13540. }
  13541. };
  13542. };/**
  13543. * @author zz85 / http://www.lab4games.net/zz85/blog
  13544. * @author alteredq / http://alteredqualia.com/
  13545. *
  13546. * For Text operations in three.js (See TextGeometry)
  13547. *
  13548. * It uses techniques used in:
  13549. *
  13550. * typeface.js and canvastext
  13551. * For converting fonts and rendering with javascript
  13552. * http://typeface.neocracy.org
  13553. *
  13554. * Triangulation ported from AS3
  13555. * Simple Polygon Triangulation
  13556. * http://actionsnippet.com/?p=1462
  13557. *
  13558. * A Method to triangulate shapes with holes
  13559. * http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
  13560. *
  13561. */
  13562. THREE.FontUtils = {
  13563. faces : {},
  13564. // Just for now. face[weight][style]
  13565. face : "helvetiker",
  13566. weight: "normal",
  13567. style : "normal",
  13568. size : 150,
  13569. divisions : 10,
  13570. getFace : function() {
  13571. return this.faces[ this.face ][ this.weight ][ this.style ];
  13572. },
  13573. loadFace : function( data ) {
  13574. var family = data.familyName.toLowerCase();
  13575. var ThreeFont = this;
  13576. ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {};
  13577. ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
  13578. ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  13579. var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
  13580. return data;
  13581. },
  13582. drawText : function( text ) {
  13583. var characterPts = [], allPts = [];
  13584. // RenderText
  13585. var i, p,
  13586. face = this.getFace(),
  13587. scale = this.size / face.resolution,
  13588. offset = 0,
  13589. chars = String( text ).split( '' ),
  13590. length = chars.length;
  13591. var fontPaths = [];
  13592. for ( i = 0; i < length; i ++ ) {
  13593. var path = new THREE.Path();
  13594. var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path );
  13595. offset += ret.offset;
  13596. fontPaths.push( ret.path );
  13597. }
  13598. // get the width
  13599. var width = offset / 2;
  13600. //
  13601. // for ( p = 0; p < allPts.length; p++ ) {
  13602. //
  13603. // allPts[ p ].x -= width;
  13604. //
  13605. // }
  13606. //var extract = this.extractPoints( allPts, characterPts );
  13607. //extract.contour = allPts;
  13608. //extract.paths = fontPaths;
  13609. //extract.offset = width;
  13610. return { paths : fontPaths, offset : width };
  13611. },
  13612. extractGlyphPoints : function( c, face, scale, offset, path ) {
  13613. var pts = [];
  13614. var i, i2, divisions,
  13615. outline, action, length,
  13616. scaleX, scaleY,
  13617. x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
  13618. laste,
  13619. glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
  13620. if ( !glyph ) return;
  13621. if ( glyph.o ) {
  13622. outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
  13623. length = outline.length;
  13624. scaleX = scale;
  13625. scaleY = scale;
  13626. for ( i = 0; i < length; ) {
  13627. action = outline[ i ++ ];
  13628. //console.log( action );
  13629. switch( action ) {
  13630. case 'm':
  13631. // Move To
  13632. x = outline[ i++ ] * scaleX + offset;
  13633. y = outline[ i++ ] * scaleY;
  13634. path.moveTo( x, y );
  13635. break;
  13636. case 'l':
  13637. // Line To
  13638. x = outline[ i++ ] * scaleX + offset;
  13639. y = outline[ i++ ] * scaleY;
  13640. path.lineTo(x,y);
  13641. break;
  13642. case 'q':
  13643. // QuadraticCurveTo
  13644. cpx = outline[ i++ ] * scaleX + offset;
  13645. cpy = outline[ i++ ] * scaleY;
  13646. cpx1 = outline[ i++ ] * scaleX + offset;
  13647. cpy1 = outline[ i++ ] * scaleY;
  13648. path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
  13649. laste = pts[ pts.length - 1 ];
  13650. if ( laste ) {
  13651. cpx0 = laste.x;
  13652. cpy0 = laste.y;
  13653. for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  13654. var t = i2 / divisions;
  13655. var tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
  13656. var ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
  13657. }
  13658. }
  13659. break;
  13660. case 'b':
  13661. // Cubic Bezier Curve
  13662. cpx = outline[ i++ ] * scaleX + offset;
  13663. cpy = outline[ i++ ] * scaleY;
  13664. cpx1 = outline[ i++ ] * scaleX + offset;
  13665. cpy1 = outline[ i++ ] * -scaleY;
  13666. cpx2 = outline[ i++ ] * scaleX + offset;
  13667. cpy2 = outline[ i++ ] * -scaleY;
  13668. path.bezierCurveTo( cpx, cpy, cpx1, cpy1, cpx2, cpy2 );
  13669. laste = pts[ pts.length - 1 ];
  13670. if ( laste ) {
  13671. cpx0 = laste.x;
  13672. cpy0 = laste.y;
  13673. for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
  13674. var t = i2 / divisions;
  13675. var tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
  13676. var ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
  13677. }
  13678. }
  13679. break;
  13680. }
  13681. }
  13682. }
  13683. return { offset: glyph.ha*scale, path:path};
  13684. }
  13685. };
  13686. THREE.FontUtils.generateShapes = function( text, parameters ) {
  13687. // Parameters
  13688. parameters = parameters || {};
  13689. var size = parameters.size !== undefined ? parameters.size : 100;
  13690. var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments: 4;
  13691. var font = parameters.font !== undefined ? parameters.font : "helvetiker";
  13692. var weight = parameters.weight !== undefined ? parameters.weight : "normal";
  13693. var style = parameters.style !== undefined ? parameters.style : "normal";
  13694. THREE.FontUtils.size = size;
  13695. THREE.FontUtils.divisions = curveSegments;
  13696. THREE.FontUtils.face = font;
  13697. THREE.FontUtils.weight = weight;
  13698. THREE.FontUtils.style = style;
  13699. // Get a Font data json object
  13700. var data = THREE.FontUtils.drawText( text );
  13701. var paths = data.paths;
  13702. var shapes = [];
  13703. for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
  13704. Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
  13705. }
  13706. return shapes;
  13707. };
  13708. /**
  13709. * This code is a quick port of code written in C++ which was submitted to
  13710. * flipcode.com by John W. Ratcliff // July 22, 2000
  13711. * See original code and more information here:
  13712. * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
  13713. *
  13714. * ported to actionscript by Zevan Rosser
  13715. * www.actionsnippet.com
  13716. *
  13717. * ported to javascript by Joshua Koo
  13718. * http://www.lab4games.net/zz85/blog
  13719. *
  13720. */
  13721. ( function( namespace ) {
  13722. var EPSILON = 0.0000000001;
  13723. // takes in an contour array and returns
  13724. var process = function( contour, indices ) {
  13725. var n = contour.length;
  13726. if ( n < 3 ) return null;
  13727. var result = [],
  13728. verts = [],
  13729. vertIndices = [];
  13730. /* we want a counter-clockwise polygon in verts */
  13731. var u, v, w;
  13732. if ( area( contour ) > 0.0 ) {
  13733. for ( v = 0; v < n; v++ ) verts[ v ] = v;
  13734. } else {
  13735. for ( v = 0; v < n; v++ ) verts[ v ] = ( n - 1 ) - v;
  13736. }
  13737. var nv = n;
  13738. /* remove nv - 2 vertices, creating 1 triangle every time */
  13739. var count = 2 * nv; /* error detection */
  13740. for( v = nv - 1; nv > 2; ) {
  13741. /* if we loop, it is probably a non-simple polygon */
  13742. if ( ( count-- ) <= 0 ) {
  13743. //** Triangulate: ERROR - probable bad polygon!
  13744. //throw ( "Warning, unable to triangulate polygon!" );
  13745. //return null;
  13746. // Sometimes warning is fine, especially polygons are triangulated in reverse.
  13747. console.log( "Warning, unable to triangulate polygon!" );
  13748. if ( indices ) return vertIndices;
  13749. return result;
  13750. }
  13751. /* three consecutive vertices in current polygon, <u,v,w> */
  13752. u = v; if ( nv <= u ) u = 0; /* previous */
  13753. v = u + 1; if ( nv <= v ) v = 0; /* new v */
  13754. w = v + 1; if ( nv <= w ) w = 0; /* next */
  13755. if ( snip( contour, u, v, w, nv, verts ) ) {
  13756. var a, b, c, s, t;
  13757. /* true names of the vertices */
  13758. a = verts[ u ];
  13759. b = verts[ v ];
  13760. c = verts[ w ];
  13761. /* output Triangle */
  13762. /*
  13763. result.push( contour[ a ] );
  13764. result.push( contour[ b ] );
  13765. result.push( contour[ c ] );
  13766. */
  13767. result.push( [ contour[ a ],
  13768. contour[ b ],
  13769. contour[ c ] ] );
  13770. vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
  13771. /* remove v from the remaining polygon */
  13772. for( s = v, t = v + 1; t < nv; s++, t++ ) {
  13773. verts[ s ] = verts[ t ];
  13774. }
  13775. nv--;
  13776. /* reset error detection counter */
  13777. count = 2 * nv;
  13778. }
  13779. }
  13780. if ( indices ) return vertIndices;
  13781. return result;
  13782. };
  13783. // calculate area of the contour polygon
  13784. var area = function ( contour ) {
  13785. var n = contour.length;
  13786. var a = 0.0;
  13787. for( var p = n - 1, q = 0; q < n; p = q++ ) {
  13788. a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
  13789. }
  13790. return a * 0.5;
  13791. };
  13792. // see if p is inside triangle abc
  13793. var insideTriangle = function( ax, ay,
  13794. bx, by,
  13795. cx, cy,
  13796. px, py ) {
  13797. var aX, aY, bX, bY;
  13798. var cX, cY, apx, apy;
  13799. var bpx, bpy, cpx, cpy;
  13800. var cCROSSap, bCROSScp, aCROSSbp;
  13801. aX = cx - bx; aY = cy - by;
  13802. bX = ax - cx; bY = ay - cy;
  13803. cX = bx - ax; cY = by - ay;
  13804. apx= px -ax; apy= py - ay;
  13805. bpx= px - bx; bpy= py - by;
  13806. cpx= px - cx; cpy= py - cy;
  13807. aCROSSbp = aX*bpy - aY*bpx;
  13808. cCROSSap = cX*apy - cY*apx;
  13809. bCROSScp = bX*cpy - bY*cpx;
  13810. return ( (aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0) );
  13811. };
  13812. var snip = function ( contour, u, v, w, n, verts ) {
  13813. var p;
  13814. var ax, ay, bx, by;
  13815. var cx, cy, px, py;
  13816. ax = contour[ verts[ u ] ].x;
  13817. ay = contour[ verts[ u ] ].y;
  13818. bx = contour[ verts[ v ] ].x;
  13819. by = contour[ verts[ v ] ].y;
  13820. cx = contour[ verts[ w ] ].x;
  13821. cy = contour[ verts[ w ] ].y;
  13822. if ( EPSILON > (((bx-ax)*(cy-ay)) - ((by-ay)*(cx-ax))) ) return false;
  13823. for ( p = 0; p < n; p++ ) {
  13824. if( (p == u) || (p == v) || (p == w) ) continue;
  13825. px = contour[ verts[ p ] ].x
  13826. py = contour[ verts[ p ] ].y
  13827. if ( insideTriangle( ax, ay, bx, by, cx, cy, px, py ) ) return false;
  13828. }
  13829. return true;
  13830. };
  13831. namespace.Triangulate = process;
  13832. namespace.Triangulate.area = area;
  13833. return namespace;
  13834. })(THREE.FontUtils);
  13835. // To use the typeface.js face files, hook up the API
  13836. self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };/**
  13837. * @author alteredq / http://alteredqualia.com/
  13838. */
  13839. THREE.BufferGeometry = function () {
  13840. this.id = THREE.GeometryCount ++;
  13841. // attributes
  13842. this.attributes = {};
  13843. // attributes typed arrays are kept only if dynamic flag is set
  13844. this.dynamic = false;
  13845. // boundings
  13846. this.boundingBox = null;
  13847. this.boundingSphere = null;
  13848. this.hasTangents = false;
  13849. // for compatibility
  13850. this.morphTargets = [];
  13851. };
  13852. THREE.BufferGeometry.prototype = {
  13853. constructor : THREE.BufferGeometry,
  13854. applyMatrix: function ( matrix ) {
  13855. var positionArray;
  13856. var normalArray;
  13857. if ( this.attributes[ "position" ] ) positionArray = this.attributes[ "position" ].array;
  13858. if ( this.attributes[ "normal" ] ) normalArray = this.attributes[ "normal" ].array;
  13859. if ( positionArray !== undefined ) {
  13860. matrix.multiplyVector3Array( positionArray );
  13861. this.verticesNeedUpdate = true;
  13862. }
  13863. if ( normalArray !== undefined ) {
  13864. var matrixRotation = new THREE.Matrix4();
  13865. matrixRotation.extractRotation( matrix );
  13866. matrixRotation.multiplyVector3Array( normalArray );
  13867. this.normalsNeedUpdate = true;
  13868. }
  13869. },
  13870. computeBoundingBox: function () {
  13871. if ( ! this.boundingBox ) {
  13872. this.boundingBox = {
  13873. min: new THREE.Vector3( Infinity, Infinity, Infinity ),
  13874. max: new THREE.Vector3( -Infinity, -Infinity, -Infinity )
  13875. };
  13876. }
  13877. var positions = this.attributes[ "position" ].array;
  13878. if ( positions ) {
  13879. var bb = this.boundingBox;
  13880. var x, y, z;
  13881. for ( var i = 0, il = positions.length; i < il; i += 3 ) {
  13882. x = positions[ i ];
  13883. y = positions[ i + 1 ];
  13884. z = positions[ i + 2 ];
  13885. // bounding box
  13886. if ( x < bb.min.x ) {
  13887. bb.min.x = x;
  13888. } else if ( x > bb.max.x ) {
  13889. bb.max.x = x;
  13890. }
  13891. if ( y < bb.min.y ) {
  13892. bb.min.y = y;
  13893. } else if ( y > bb.max.y ) {
  13894. bb.max.y = y;
  13895. }
  13896. if ( z < bb.min.z ) {
  13897. bb.min.z = z;
  13898. } else if ( z > bb.max.z ) {
  13899. bb.max.z = z;
  13900. }
  13901. }
  13902. }
  13903. if ( positions === undefined || positions.length === 0 ) {
  13904. this.boundingBox.min.set( 0, 0, 0 );
  13905. this.boundingBox.max.set( 0, 0, 0 );
  13906. }
  13907. },
  13908. computeBoundingSphere: function () {
  13909. if ( ! this.boundingSphere ) this.boundingSphere = { radius: 0 };
  13910. var positions = this.attributes[ "position" ].array;
  13911. if ( positions ) {
  13912. var radius, maxRadius = 0;
  13913. var x, y, z;
  13914. for ( var i = 0, il = positions.length; i < il; i += 3 ) {
  13915. x = positions[ i ];
  13916. y = positions[ i + 1 ];
  13917. z = positions[ i + 2 ];
  13918. radius = Math.sqrt( x * x + y * y + z * z );
  13919. if ( radius > maxRadius ) maxRadius = radius;
  13920. }
  13921. this.boundingSphere.radius = maxRadius;
  13922. }
  13923. },
  13924. computeVertexNormals: function () {
  13925. if ( this.attributes[ "position" ] && this.attributes[ "index" ] ) {
  13926. var i, il;
  13927. var j, jl;
  13928. var nVertexElements = this.attributes[ "position" ].array.length;
  13929. if ( this.attributes[ "normal" ] === undefined ) {
  13930. this.attributes[ "normal" ] = {
  13931. itemSize: 3,
  13932. array: new Float32Array( nVertexElements ),
  13933. numItems: nVertexElements
  13934. };
  13935. } else {
  13936. // reset existing normals to zero
  13937. for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
  13938. this.attributes[ "normal" ].array[ i ] = 0;
  13939. }
  13940. }
  13941. var offsets = this.offsets;
  13942. var indices = this.attributes[ "index" ].array;
  13943. var positions = this.attributes[ "position" ].array;
  13944. var normals = this.attributes[ "normal" ].array;
  13945. var vA, vB, vC, x, y, z,
  13946. pA = new THREE.Vector3(),
  13947. pB = new THREE.Vector3(),
  13948. pC = new THREE.Vector3(),
  13949. cb = new THREE.Vector3(),
  13950. ab = new THREE.Vector3();
  13951. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  13952. var start = offsets[ j ].start;
  13953. var count = offsets[ j ].count;
  13954. var index = offsets[ j ].index;
  13955. for ( i = start, il = start + count; i < il; i += 3 ) {
  13956. vA = index + indices[ i ];
  13957. vB = index + indices[ i + 1 ];
  13958. vC = index + indices[ i + 2 ];
  13959. x = positions[ vA * 3 ];
  13960. y = positions[ vA * 3 + 1 ];
  13961. z = positions[ vA * 3 + 2 ];
  13962. pA.set( x, y, z );
  13963. x = positions[ vB * 3 ];
  13964. y = positions[ vB * 3 + 1 ];
  13965. z = positions[ vB * 3 + 2 ];
  13966. pB.set( x, y, z );
  13967. x = positions[ vC * 3 ];
  13968. y = positions[ vC * 3 + 1 ];
  13969. z = positions[ vC * 3 + 2 ];
  13970. pC.set( x, y, z );
  13971. cb.sub( pC, pB );
  13972. ab.sub( pA, pB );
  13973. cb.crossSelf( ab );
  13974. normals[ vA * 3 ] += cb.x;
  13975. normals[ vA * 3 + 1 ] += cb.y;
  13976. normals[ vA * 3 + 2 ] += cb.z;
  13977. normals[ vB * 3 ] += cb.x;
  13978. normals[ vB * 3 + 1 ] += cb.y;
  13979. normals[ vB * 3 + 2 ] += cb.z;
  13980. normals[ vC * 3 ] += cb.x;
  13981. normals[ vC * 3 + 1 ] += cb.y;
  13982. normals[ vC * 3 + 2 ] += cb.z;
  13983. }
  13984. }
  13985. // normalize normals
  13986. for ( i = 0, il = normals.length; i < il; i += 3 ) {
  13987. x = normals[ i ];
  13988. y = normals[ i + 1 ];
  13989. z = normals[ i + 2 ];
  13990. var n = 1.0 / Math.sqrt( x * x + y * y + z * z );
  13991. normals[ i ] *= n;
  13992. normals[ i + 1 ] *= n;
  13993. normals[ i + 2 ] *= n;
  13994. }
  13995. this.normalsNeedUpdate = true;
  13996. }
  13997. },
  13998. computeTangents: function () {
  13999. // based on http://www.terathon.com/code/tangent.html
  14000. // (per vertex tangents)
  14001. if ( this.attributes[ "index" ] === undefined ||
  14002. this.attributes[ "position" ] === undefined ||
  14003. this.attributes[ "normal" ] === undefined ||
  14004. this.attributes[ "uv" ] === undefined ) {
  14005. console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
  14006. return;
  14007. }
  14008. var indices = this.attributes[ "index" ].array;
  14009. var positions = this.attributes[ "position" ].array;
  14010. var normals = this.attributes[ "normal" ].array;
  14011. var uvs = this.attributes[ "uv" ].array;
  14012. var nVertices = positions.length / 3;
  14013. if ( this.attributes[ "tangent" ] === undefined ) {
  14014. var nTangentElements = 4 * nVertices;
  14015. this.attributes[ "tangent" ] = {
  14016. itemSize: 4,
  14017. array: new Float32Array( nTangentElements ),
  14018. numItems: nTangentElements
  14019. };
  14020. }
  14021. var tangents = this.attributes[ "tangent" ].array;
  14022. var tan1 = [], tan2 = [];
  14023. for ( var k = 0; k < nVertices; k ++ ) {
  14024. tan1[ k ] = new THREE.Vector3();
  14025. tan2[ k ] = new THREE.Vector3();
  14026. }
  14027. var xA, yA, zA,
  14028. xB, yB, zB,
  14029. xC, yC, zC,
  14030. uA, vA,
  14031. uB, vB,
  14032. uC, vC,
  14033. x1, x2, y1, y2, z1, z2,
  14034. s1, s2, t1, t2, r;
  14035. var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
  14036. function handleTriangle( a, b, c ) {
  14037. xA = positions[ a * 3 ];
  14038. yA = positions[ a * 3 + 1 ];
  14039. zA = positions[ a * 3 + 2 ];
  14040. xB = positions[ b * 3 ];
  14041. yB = positions[ b * 3 + 1 ];
  14042. zB = positions[ b * 3 + 2 ];
  14043. xC = positions[ c * 3 ];
  14044. yC = positions[ c * 3 + 1 ];
  14045. zC = positions[ c * 3 + 2 ];
  14046. uA = uvs[ a * 2 ];
  14047. vA = uvs[ a * 2 + 1 ];
  14048. uB = uvs[ b * 2 ];
  14049. vB = uvs[ b * 2 + 1 ];
  14050. uC = uvs[ c * 2 ];
  14051. vC = uvs[ c * 2 + 1 ];
  14052. x1 = xB - xA;
  14053. x2 = xC - xA;
  14054. y1 = yB - yA;
  14055. y2 = yC - yA;
  14056. z1 = zB - zA;
  14057. z2 = zC - zA;
  14058. s1 = uB - uA;
  14059. s2 = uC - uA;
  14060. t1 = vB - vA;
  14061. t2 = vC - vA;
  14062. r = 1.0 / ( s1 * t2 - s2 * t1 );
  14063. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  14064. ( t2 * y1 - t1 * y2 ) * r,
  14065. ( t2 * z1 - t1 * z2 ) * r );
  14066. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  14067. ( s1 * y2 - s2 * y1 ) * r,
  14068. ( s1 * z2 - s2 * z1 ) * r );
  14069. tan1[ a ].addSelf( sdir );
  14070. tan1[ b ].addSelf( sdir );
  14071. tan1[ c ].addSelf( sdir );
  14072. tan2[ a ].addSelf( tdir );
  14073. tan2[ b ].addSelf( tdir );
  14074. tan2[ c ].addSelf( tdir );
  14075. }
  14076. var i, il;
  14077. var j, jl;
  14078. var iA, iB, iC;
  14079. var offsets = this.offsets;
  14080. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  14081. var start = offsets[ j ].start;
  14082. var count = offsets[ j ].count;
  14083. var index = offsets[ j ].index;
  14084. for ( i = start, il = start + count; i < il; i += 3 ) {
  14085. iA = index + indices[ i ];
  14086. iB = index + indices[ i + 1 ];
  14087. iC = index + indices[ i + 2 ];
  14088. handleTriangle( iA, iB, iC );
  14089. }
  14090. }
  14091. var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
  14092. var n = new THREE.Vector3(), n2 = new THREE.Vector3();
  14093. var w, t, test;
  14094. var nx, ny, nz;
  14095. function handleVertex( v ) {
  14096. n.x = normals[ v * 3 ];
  14097. n.y = normals[ v * 3 + 1 ];
  14098. n.z = normals[ v * 3 + 2 ];
  14099. n2.copy( n );
  14100. t = tan1[ v ];
  14101. // Gram-Schmidt orthogonalize
  14102. tmp.copy( t );
  14103. tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
  14104. // Calculate handedness
  14105. tmp2.cross( n2, t );
  14106. test = tmp2.dot( tan2[ v ] );
  14107. w = ( test < 0.0 ) ? -1.0 : 1.0;
  14108. tangents[ v * 4 ] = tmp.x;
  14109. tangents[ v * 4 + 1 ] = tmp.y;
  14110. tangents[ v * 4 + 2 ] = tmp.z;
  14111. tangents[ v * 4 + 3 ] = w;
  14112. }
  14113. for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
  14114. var start = offsets[ j ].start;
  14115. var count = offsets[ j ].count;
  14116. var index = offsets[ j ].index;
  14117. for ( i = start, il = start + count; i < il; i += 3 ) {
  14118. iA = index + indices[ i ];
  14119. iB = index + indices[ i + 1 ];
  14120. iC = index + indices[ i + 2 ];
  14121. handleVertex( iA );
  14122. handleVertex( iB );
  14123. handleVertex( iC );
  14124. }
  14125. }
  14126. this.hasTangents = true;
  14127. this.tangentsNeedUpdate = true;
  14128. }
  14129. };
  14130. /**
  14131. * @author zz85 / http://www.lab4games.net/zz85/blog
  14132. * Extensible curve object
  14133. *
  14134. * Some common of Curve methods
  14135. * .getPoint(t), getTangent(t)
  14136. * .getPointAt(u), getTagentAt(u)
  14137. * .getPoints(), .getSpacedPoints()
  14138. * .getLength()
  14139. * .updateArcLengths()
  14140. *
  14141. * This file contains following classes:
  14142. *
  14143. * -- 2d classes --
  14144. * THREE.Curve
  14145. * THREE.LineCurve
  14146. * THREE.QuadraticBezierCurve
  14147. * THREE.CubicBezierCurve
  14148. * THREE.SplineCurve
  14149. * THREE.ArcCurve
  14150. *
  14151. * -- 3d classes --
  14152. * THREE.LineCurve3
  14153. * THREE.QuadraticBezierCurve3
  14154. * THREE.CubicBezierCurve3
  14155. * THREE.SplineCurve3
  14156. * THREE.ClosedSplineCurve3
  14157. *
  14158. * A series of curves can be represented as a THREE.CurvePath
  14159. *
  14160. **/
  14161. /**************************************************************
  14162. * Abstract Curve base class
  14163. **************************************************************/
  14164. THREE.Curve = function () {
  14165. };
  14166. // Virtual base class method to overwrite and implement in subclasses
  14167. // - t [0 .. 1]
  14168. THREE.Curve.prototype.getPoint = function ( t ) {
  14169. console.log( "Warning, getPoint() not implemented!" );
  14170. return null;
  14171. };
  14172. // Get point at relative position in curve according to arc length
  14173. // - u [0 .. 1]
  14174. THREE.Curve.prototype.getPointAt = function ( u ) {
  14175. var t = this.getUtoTmapping( u );
  14176. return this.getPoint( t );
  14177. };
  14178. // Get sequence of points using getPoint( t )
  14179. THREE.Curve.prototype.getPoints = function ( divisions ) {
  14180. if ( !divisions ) divisions = 5;
  14181. var d, pts = [];
  14182. for ( d = 0; d <= divisions; d ++ ) {
  14183. pts.push( this.getPoint( d / divisions ) );
  14184. }
  14185. return pts;
  14186. };
  14187. // Get sequence of points using getPointAt( u )
  14188. THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {
  14189. if ( !divisions ) divisions = 5;
  14190. var d, pts = [];
  14191. for ( d = 0; d <= divisions; d ++ ) {
  14192. pts.push( this.getPointAt( d / divisions ) );
  14193. }
  14194. return pts;
  14195. };
  14196. // Get total curve arc length
  14197. THREE.Curve.prototype.getLength = function () {
  14198. var lengths = this.getLengths();
  14199. return lengths[ lengths.length - 1 ];
  14200. };
  14201. // Get list of cumulative segment lengths
  14202. THREE.Curve.prototype.getLengths = function ( divisions ) {
  14203. if ( !divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200;
  14204. if ( this.cacheArcLengths
  14205. && ( this.cacheArcLengths.length == divisions + 1 )
  14206. && !this.needsUpdate) {
  14207. //console.log( "cached", this.cacheArcLengths );
  14208. return this.cacheArcLengths;
  14209. }
  14210. this.needsUpdate = false;
  14211. var cache = [];
  14212. var current, last = this.getPoint( 0 );
  14213. var p, sum = 0;
  14214. cache.push( 0 );
  14215. for ( p = 1; p <= divisions; p ++ ) {
  14216. current = this.getPoint ( p / divisions );
  14217. sum += current.distanceTo( last );
  14218. cache.push( sum );
  14219. last = current;
  14220. }
  14221. this.cacheArcLengths = cache;
  14222. return cache; // { sums: cache, sum:sum }; Sum is in the last element.
  14223. };
  14224. THREE.Curve.prototype.updateArcLengths = function() {
  14225. this.needsUpdate = true;
  14226. this.getLengths();
  14227. };
  14228. // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
  14229. THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
  14230. var arcLengths = this.getLengths();
  14231. var i = 0, il = arcLengths.length;
  14232. var targetArcLength; // The targeted u distance value to get
  14233. if ( distance ) {
  14234. targetArcLength = distance;
  14235. } else {
  14236. targetArcLength = u * arcLengths[ il - 1 ];
  14237. }
  14238. //var time = Date.now();
  14239. // binary search for the index with largest value smaller than target u distance
  14240. var low = 0, high = il - 1, comparison;
  14241. while ( low <= high ) {
  14242. 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
  14243. comparison = arcLengths[ i ] - targetArcLength;
  14244. if ( comparison < 0 ) {
  14245. low = i + 1;
  14246. continue;
  14247. } else if ( comparison > 0 ) {
  14248. high = i - 1;
  14249. continue;
  14250. } else {
  14251. high = i;
  14252. break;
  14253. // DONE
  14254. }
  14255. }
  14256. i = high;
  14257. //console.log('b' , i, low, high, Date.now()- time);
  14258. if ( arcLengths[ i ] == targetArcLength ) {
  14259. var t = i / ( il - 1 );
  14260. return t;
  14261. }
  14262. // we could get finer grain at lengths, or use simple interpolatation between two points
  14263. var lengthBefore = arcLengths[ i ];
  14264. var lengthAfter = arcLengths[ i + 1 ];
  14265. var segmentLength = lengthAfter - lengthBefore;
  14266. // determine where we are between the 'before' and 'after' points
  14267. var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
  14268. // add that fractional amount to t
  14269. var t = ( i + segmentFraction ) / ( il -1 );
  14270. return t;
  14271. };
  14272. // In 2D space, there are actually 2 normal vectors,
  14273. // and in 3D space, infinte
  14274. // TODO this should be depreciated.
  14275. THREE.Curve.prototype.getNormalVector = function( t ) {
  14276. var vec = this.getTangent( t );
  14277. return new THREE.Vector2( -vec.y , vec.x );
  14278. };
  14279. // Returns a unit vector tangent at t
  14280. // In case any sub curve does not implement its tangent / normal finding,
  14281. // we get 2 points with a small delta and find a gradient of the 2 points
  14282. // which seems to make a reasonable approximation
  14283. THREE.Curve.prototype.getTangent = function( t ) {
  14284. var delta = 0.0001;
  14285. var t1 = t - delta;
  14286. var t2 = t + delta;
  14287. // Capping in case of danger
  14288. if ( t1 < 0 ) t1 = 0;
  14289. if ( t2 > 1 ) t2 = 1;
  14290. var pt1 = this.getPoint( t1 );
  14291. var pt2 = this.getPoint( t2 );
  14292. var vec = pt2.clone().subSelf(pt1);
  14293. return vec.normalize();
  14294. };
  14295. THREE.Curve.prototype.getTangentAt = function ( u ) {
  14296. var t = this.getUtoTmapping( u );
  14297. return this.getTangent( t );
  14298. };
  14299. /**************************************************************
  14300. * Line
  14301. **************************************************************/
  14302. THREE.LineCurve = function ( v1, v2 ) {
  14303. this.v1 = v1;
  14304. this.v2 = v2;
  14305. };
  14306. THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
  14307. THREE.LineCurve.prototype.getPoint = function ( t ) {
  14308. var point = this.v2.clone().subSelf(this.v1);
  14309. point.multiplyScalar( t ).addSelf( this.v1 );
  14310. return point;
  14311. };
  14312. // Line curve is linear, so we can overwrite default getPointAt
  14313. THREE.LineCurve.prototype.getPointAt = function ( u ) {
  14314. return this.getPoint( u );
  14315. };
  14316. THREE.LineCurve.prototype.getTangent = function( t ) {
  14317. var tangent = this.v2.clone().subSelf(this.v1);
  14318. return tangent.normalize();
  14319. };
  14320. /**************************************************************
  14321. * Quadratic Bezier curve
  14322. **************************************************************/
  14323. THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
  14324. this.v0 = v0;
  14325. this.v1 = v1;
  14326. this.v2 = v2;
  14327. };
  14328. THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
  14329. THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
  14330. var tx, ty;
  14331. tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
  14332. ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
  14333. return new THREE.Vector2( tx, ty );
  14334. };
  14335. THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
  14336. var tx, ty;
  14337. tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
  14338. ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
  14339. // returns unit vector
  14340. var tangent = new THREE.Vector2( tx, ty );
  14341. tangent.normalize();
  14342. return tangent;
  14343. };
  14344. /**************************************************************
  14345. * Cubic Bezier curve
  14346. **************************************************************/
  14347. THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
  14348. this.v0 = v0;
  14349. this.v1 = v1;
  14350. this.v2 = v2;
  14351. this.v3 = v3;
  14352. };
  14353. THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
  14354. THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
  14355. var tx, ty;
  14356. tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
  14357. ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
  14358. return new THREE.Vector2( tx, ty );
  14359. };
  14360. THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
  14361. var tx, ty;
  14362. tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
  14363. ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
  14364. var tangent = new THREE.Vector2( tx, ty );
  14365. tangent.normalize();
  14366. return tangent;
  14367. };
  14368. /**************************************************************
  14369. * Spline curve
  14370. **************************************************************/
  14371. THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
  14372. this.points = (points == undefined) ? [] : points;
  14373. };
  14374. THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
  14375. THREE.SplineCurve.prototype.getPoint = function ( t ) {
  14376. var v = new THREE.Vector2();
  14377. var c = [];
  14378. var points = this.points, point, intPoint, weight;
  14379. point = ( points.length - 1 ) * t;
  14380. intPoint = Math.floor( point );
  14381. weight = point - intPoint;
  14382. c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
  14383. c[ 1 ] = intPoint;
  14384. c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1;
  14385. c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2;
  14386. v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
  14387. v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
  14388. return v;
  14389. };
  14390. /**************************************************************
  14391. * Ellipse curve
  14392. **************************************************************/
  14393. THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
  14394. aStartAngle, aEndAngle,
  14395. aClockwise ) {
  14396. this.aX = aX;
  14397. this.aY = aY;
  14398. this.xRadius = xRadius;
  14399. this.yRadius = yRadius;
  14400. this.aStartAngle = aStartAngle;
  14401. this.aEndAngle = aEndAngle;
  14402. this.aClockwise = aClockwise;
  14403. };
  14404. THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
  14405. THREE.EllipseCurve.prototype.getPoint = function ( t ) {
  14406. var deltaAngle = this.aEndAngle - this.aStartAngle;
  14407. if ( !this.aClockwise ) {
  14408. t = 1 - t;
  14409. }
  14410. var angle = this.aStartAngle + t * deltaAngle;
  14411. var tx = this.aX + this.xRadius * Math.cos( angle );
  14412. var ty = this.aY + this.yRadius * Math.sin( angle );
  14413. return new THREE.Vector2( tx, ty );
  14414. };
  14415. /**************************************************************
  14416. * Arc curve
  14417. **************************************************************/
  14418. THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
  14419. THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
  14420. };
  14421. THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
  14422. /**************************************************************
  14423. * Utils
  14424. **************************************************************/
  14425. THREE.Curve.Utils = {
  14426. tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
  14427. return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
  14428. },
  14429. // Puay Bing, thanks for helping with this derivative!
  14430. tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
  14431. return -3 * p0 * (1 - t) * (1 - t) +
  14432. 3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
  14433. 6 * t * p2 * (1-t) - 3 * t * t * p2 +
  14434. 3 * t * t * p3;
  14435. },
  14436. tangentSpline: function ( t, p0, p1, p2, p3 ) {
  14437. // To check if my formulas are correct
  14438. var h00 = 6 * t * t - 6 * t; // derived from 2t^3 − 3t^2 + 1
  14439. var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
  14440. var h01 = -6 * t * t + 6 * t; // − 2t3 + 3t2
  14441. var h11 = 3 * t * t - 2 * t; // t3 − t2
  14442. return h00 + h10 + h01 + h11;
  14443. },
  14444. // Catmull-Rom
  14445. interpolate: function( p0, p1, p2, p3, t ) {
  14446. var v0 = ( p2 - p0 ) * 0.5;
  14447. var v1 = ( p3 - p1 ) * 0.5;
  14448. var t2 = t * t;
  14449. var t3 = t * t2;
  14450. return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
  14451. }
  14452. };
  14453. // TODO: Transformation for Curves?
  14454. /**************************************************************
  14455. * 3D Curves
  14456. **************************************************************/
  14457. // A Factory method for creating new curve subclasses
  14458. THREE.Curve.create = function ( constructor, getPointFunc ) {
  14459. constructor.prototype = Object.create( THREE.Curve.prototype );
  14460. constructor.prototype.getPoint = getPointFunc;
  14461. return constructor;
  14462. };
  14463. /**************************************************************
  14464. * Line3D
  14465. **************************************************************/
  14466. THREE.LineCurve3 = THREE.Curve.create(
  14467. function ( v1, v2 ) {
  14468. this.v1 = v1;
  14469. this.v2 = v2;
  14470. },
  14471. function ( t ) {
  14472. var r = new THREE.Vector3();
  14473. r.sub( this.v2, this.v1 ); // diff
  14474. r.multiplyScalar( t );
  14475. r.addSelf( this.v1 );
  14476. return r;
  14477. }
  14478. );
  14479. /**************************************************************
  14480. * Quadratic Bezier 3D curve
  14481. **************************************************************/
  14482. THREE.QuadraticBezierCurve3 = THREE.Curve.create(
  14483. function ( v0, v1, v2 ) {
  14484. this.v0 = v0;
  14485. this.v1 = v1;
  14486. this.v2 = v2;
  14487. },
  14488. function ( t ) {
  14489. var tx, ty, tz;
  14490. tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
  14491. ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
  14492. tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
  14493. return new THREE.Vector3( tx, ty, tz );
  14494. }
  14495. );
  14496. /**************************************************************
  14497. * Cubic Bezier 3D curve
  14498. **************************************************************/
  14499. THREE.CubicBezierCurve3 = THREE.Curve.create(
  14500. function ( v0, v1, v2, v3 ) {
  14501. this.v0 = v0;
  14502. this.v1 = v1;
  14503. this.v2 = v2;
  14504. this.v3 = v3;
  14505. },
  14506. function ( t ) {
  14507. var tx, ty, tz;
  14508. tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
  14509. ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
  14510. tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
  14511. return new THREE.Vector3( tx, ty, tz );
  14512. }
  14513. );
  14514. /**************************************************************
  14515. * Spline 3D curve
  14516. **************************************************************/
  14517. THREE.SplineCurve3 = THREE.Curve.create(
  14518. function ( points /* array of Vector3 */) {
  14519. this.points = (points == undefined) ? [] : points;
  14520. },
  14521. function ( t ) {
  14522. var v = new THREE.Vector3();
  14523. var c = [];
  14524. var points = this.points, point, intPoint, weight;
  14525. point = ( points.length - 1 ) * t;
  14526. intPoint = Math.floor( point );
  14527. weight = point - intPoint;
  14528. c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
  14529. c[ 1 ] = intPoint;
  14530. c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
  14531. c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
  14532. var pt0 = points[ c[0] ],
  14533. pt1 = points[ c[1] ],
  14534. pt2 = points[ c[2] ],
  14535. pt3 = points[ c[3] ];
  14536. v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
  14537. v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
  14538. v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
  14539. return v;
  14540. }
  14541. );
  14542. // THREE.SplineCurve3.prototype.getTangent = function(t) {
  14543. // var v = new THREE.Vector3();
  14544. // var c = [];
  14545. // var points = this.points, point, intPoint, weight;
  14546. // point = ( points.length - 1 ) * t;
  14547. // intPoint = Math.floor( point );
  14548. // weight = point - intPoint;
  14549. // c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
  14550. // c[ 1 ] = intPoint;
  14551. // c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
  14552. // c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
  14553. // var pt0 = points[ c[0] ],
  14554. // pt1 = points[ c[1] ],
  14555. // pt2 = points[ c[2] ],
  14556. // pt3 = points[ c[3] ];
  14557. // // t = weight;
  14558. // v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
  14559. // v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
  14560. // v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
  14561. // return v;
  14562. // }
  14563. /**************************************************************
  14564. * Closed Spline 3D curve
  14565. **************************************************************/
  14566. THREE.ClosedSplineCurve3 = THREE.Curve.create(
  14567. function ( points /* array of Vector3 */) {
  14568. this.points = (points == undefined) ? [] : points;
  14569. },
  14570. function ( t ) {
  14571. var v = new THREE.Vector3();
  14572. var c = [];
  14573. var points = this.points, point, intPoint, weight;
  14574. point = ( points.length - 0 ) * t;
  14575. // This needs to be from 0-length +1
  14576. intPoint = Math.floor( point );
  14577. weight = point - intPoint;
  14578. intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
  14579. c[ 0 ] = ( intPoint - 1 ) % points.length;
  14580. c[ 1 ] = ( intPoint ) % points.length;
  14581. c[ 2 ] = ( intPoint + 1 ) % points.length;
  14582. c[ 3 ] = ( intPoint + 2 ) % points.length;
  14583. v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
  14584. v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
  14585. v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
  14586. return v;
  14587. }
  14588. );
  14589. /**
  14590. * @author zz85 / http://www.lab4games.net/zz85/blog
  14591. *
  14592. **/
  14593. /**************************************************************
  14594. * Curved Path - a curve path is simply a array of connected
  14595. * curves, but retains the api of a curve
  14596. **************************************************************/
  14597. THREE.CurvePath = function () {
  14598. this.curves = [];
  14599. this.bends = [];
  14600. this.autoClose = false; // Automatically closes the path
  14601. };
  14602. THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
  14603. THREE.CurvePath.prototype.add = function ( curve ) {
  14604. this.curves.push( curve );
  14605. };
  14606. THREE.CurvePath.prototype.checkConnection = function() {
  14607. // TODO
  14608. // If the ending of curve is not connected to the starting
  14609. // or the next curve, then, this is not a real path
  14610. };
  14611. THREE.CurvePath.prototype.closePath = function() {
  14612. // TODO Test
  14613. // and verify for vector3 (needs to implement equals)
  14614. // Add a line curve if start and end of lines are not connected
  14615. var startPoint = this.curves[0].getPoint(0);
  14616. var endPoint = this.curves[this.curves.length-1].getPoint(1);
  14617. if (!startPoint.equals(endPoint)) {
  14618. this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
  14619. }
  14620. };
  14621. // To get accurate point with reference to
  14622. // entire path distance at time t,
  14623. // following has to be done:
  14624. // 1. Length of each sub path have to be known
  14625. // 2. Locate and identify type of curve
  14626. // 3. Get t for the curve
  14627. // 4. Return curve.getPointAt(t')
  14628. THREE.CurvePath.prototype.getPoint = function( t ) {
  14629. var d = t * this.getLength();
  14630. var curveLengths = this.getCurveLengths();
  14631. var i = 0, diff, curve;
  14632. // To think about boundaries points.
  14633. while ( i < curveLengths.length ) {
  14634. if ( curveLengths[ i ] >= d ) {
  14635. diff = curveLengths[ i ] - d;
  14636. curve = this.curves[ i ];
  14637. var u = 1 - diff / curve.getLength();
  14638. return curve.getPointAt( u );
  14639. break;
  14640. }
  14641. i ++;
  14642. }
  14643. return null;
  14644. // loop where sum != 0, sum > d , sum+1 <d
  14645. };
  14646. /*
  14647. THREE.CurvePath.prototype.getTangent = function( t ) {
  14648. };*/
  14649. // We cannot use the default THREE.Curve getPoint() with getLength() because in
  14650. // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
  14651. // getPoint() depends on getLength
  14652. THREE.CurvePath.prototype.getLength = function() {
  14653. var lens = this.getCurveLengths();
  14654. return lens[ lens.length - 1 ];
  14655. };
  14656. // Compute lengths and cache them
  14657. // We cannot overwrite getLengths() because UtoT mapping uses it.
  14658. THREE.CurvePath.prototype.getCurveLengths = function() {
  14659. // We use cache values if curves and cache array are same length
  14660. if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
  14661. return this.cacheLengths;
  14662. };
  14663. // Get length of subsurve
  14664. // Push sums into cached array
  14665. var lengths = [], sums = 0;
  14666. var i, il = this.curves.length;
  14667. for ( i = 0; i < il; i ++ ) {
  14668. sums += this.curves[ i ].getLength();
  14669. lengths.push( sums );
  14670. }
  14671. this.cacheLengths = lengths;
  14672. return lengths;
  14673. };
  14674. // Returns min and max coordinates, as well as centroid
  14675. THREE.CurvePath.prototype.getBoundingBox = function () {
  14676. var points = this.getPoints();
  14677. var maxX, maxY;
  14678. var minX, minY;
  14679. maxX = maxY = Number.NEGATIVE_INFINITY;
  14680. minX = minY = Number.POSITIVE_INFINITY;
  14681. var p, i, il, sum;
  14682. sum = new THREE.Vector2();
  14683. for ( i = 0, il = points.length; i < il; i ++ ) {
  14684. p = points[ i ];
  14685. if ( p.x > maxX ) maxX = p.x;
  14686. else if ( p.x < minX ) minX = p.x;
  14687. if ( p.y > maxY ) maxY = p.y;
  14688. else if ( p.y < minY ) minY = p.y;
  14689. sum.addSelf( p.x, p.y );
  14690. }
  14691. return {
  14692. minX: minX,
  14693. minY: minY,
  14694. maxX: maxX,
  14695. maxY: maxY,
  14696. centroid: sum.divideScalar( il )
  14697. };
  14698. };
  14699. /**************************************************************
  14700. * Create Geometries Helpers
  14701. **************************************************************/
  14702. /// Generate geometry from path points (for Line or ParticleSystem objects)
  14703. THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
  14704. var pts = this.getPoints( divisions, true );
  14705. return this.createGeometry( pts );
  14706. };
  14707. // Generate geometry from equidistance sampling along the path
  14708. THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
  14709. var pts = this.getSpacedPoints( divisions, true );
  14710. return this.createGeometry( pts );
  14711. };
  14712. THREE.CurvePath.prototype.createGeometry = function( points ) {
  14713. var geometry = new THREE.Geometry();
  14714. for ( var i = 0; i < points.length; i ++ ) {
  14715. geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, 0 ) );
  14716. }
  14717. return geometry;
  14718. };
  14719. /**************************************************************
  14720. * Bend / Wrap Helper Methods
  14721. **************************************************************/
  14722. // Wrap path / Bend modifiers?
  14723. THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
  14724. this.bends.push( bendpath );
  14725. };
  14726. THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
  14727. var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
  14728. var i, il;
  14729. if ( !bends ) {
  14730. bends = this.bends;
  14731. }
  14732. for ( i = 0, il = bends.length; i < il; i ++ ) {
  14733. oldPts = this.getWrapPoints( oldPts, bends[ i ] );
  14734. }
  14735. return oldPts;
  14736. };
  14737. THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
  14738. var oldPts = this.getSpacedPoints( segments );
  14739. var i, il;
  14740. if ( !bends ) {
  14741. bends = this.bends;
  14742. }
  14743. for ( i = 0, il = bends.length; i < il; i ++ ) {
  14744. oldPts = this.getWrapPoints( oldPts, bends[ i ] );
  14745. }
  14746. return oldPts;
  14747. };
  14748. // This returns getPoints() bend/wrapped around the contour of a path.
  14749. // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
  14750. THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
  14751. var bounds = this.getBoundingBox();
  14752. var i, il, p, oldX, oldY, xNorm;
  14753. for ( i = 0, il = oldPts.length; i < il; i ++ ) {
  14754. p = oldPts[ i ];
  14755. oldX = p.x;
  14756. oldY = p.y;
  14757. xNorm = oldX / bounds.maxX;
  14758. // If using actual distance, for length > path, requires line extrusions
  14759. //xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
  14760. xNorm = path.getUtoTmapping( xNorm, oldX );
  14761. // check for out of bounds?
  14762. var pathPt = path.getPoint( xNorm );
  14763. var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
  14764. p.x = pathPt.x + normal.x;
  14765. p.y = pathPt.y + normal.y;
  14766. }
  14767. return oldPts;
  14768. };
  14769. /**
  14770. * @author alteredq / http://alteredqualia.com/
  14771. */
  14772. THREE.Gyroscope = function () {
  14773. THREE.Object3D.call( this );
  14774. };
  14775. THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
  14776. THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
  14777. this.matrixAutoUpdate && this.updateMatrix();
  14778. // update matrixWorld
  14779. if ( this.matrixWorldNeedsUpdate || force ) {
  14780. if ( this.parent ) {
  14781. this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
  14782. this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
  14783. this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
  14784. this.matrixWorld.compose( this.translationWorld, this.rotationObject, this.scaleWorld );
  14785. } else {
  14786. this.matrixWorld.copy( this.matrix );
  14787. }
  14788. this.matrixWorldNeedsUpdate = false;
  14789. force = true;
  14790. }
  14791. // update children
  14792. for ( var i = 0, l = this.children.length; i < l; i ++ ) {
  14793. this.children[ i ].updateMatrixWorld( force );
  14794. }
  14795. };
  14796. THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
  14797. THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
  14798. THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
  14799. THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
  14800. THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
  14801. THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
  14802. /**
  14803. * @author zz85 / http://www.lab4games.net/zz85/blog
  14804. * Creates free form 2d path using series of points, lines or curves.
  14805. *
  14806. **/
  14807. THREE.Path = function ( points ) {
  14808. THREE.CurvePath.call(this);
  14809. this.actions = [];
  14810. if ( points ) {
  14811. this.fromPoints( points );
  14812. }
  14813. };
  14814. THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
  14815. THREE.PathActions = {
  14816. MOVE_TO: 'moveTo',
  14817. LINE_TO: 'lineTo',
  14818. QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
  14819. BEZIER_CURVE_TO: 'bezierCurveTo', // Bezier cubic curve
  14820. CSPLINE_THRU: 'splineThru', // Catmull-rom spline
  14821. ARC: 'arc', // Circle
  14822. ELLIPSE: 'ellipse'
  14823. };
  14824. // TODO Clean up PATH API
  14825. // Create path using straight lines to connect all points
  14826. // - vectors: array of Vector2
  14827. THREE.Path.prototype.fromPoints = function ( vectors ) {
  14828. this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
  14829. for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
  14830. this.lineTo( vectors[ v ].x, vectors[ v ].y );
  14831. };
  14832. };
  14833. // startPath() endPath()?
  14834. THREE.Path.prototype.moveTo = function ( x, y ) {
  14835. var args = Array.prototype.slice.call( arguments );
  14836. this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
  14837. };
  14838. THREE.Path.prototype.lineTo = function ( x, y ) {
  14839. var args = Array.prototype.slice.call( arguments );
  14840. var lastargs = this.actions[ this.actions.length - 1 ].args;
  14841. var x0 = lastargs[ lastargs.length - 2 ];
  14842. var y0 = lastargs[ lastargs.length - 1 ];
  14843. var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
  14844. this.curves.push( curve );
  14845. this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
  14846. };
  14847. THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
  14848. var args = Array.prototype.slice.call( arguments );
  14849. var lastargs = this.actions[ this.actions.length - 1 ].args;
  14850. var x0 = lastargs[ lastargs.length - 2 ];
  14851. var y0 = lastargs[ lastargs.length - 1 ];
  14852. var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
  14853. new THREE.Vector2( aCPx, aCPy ),
  14854. new THREE.Vector2( aX, aY ) );
  14855. this.curves.push( curve );
  14856. this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
  14857. };
  14858. THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
  14859. aCP2x, aCP2y,
  14860. aX, aY ) {
  14861. var args = Array.prototype.slice.call( arguments );
  14862. var lastargs = this.actions[ this.actions.length - 1 ].args;
  14863. var x0 = lastargs[ lastargs.length - 2 ];
  14864. var y0 = lastargs[ lastargs.length - 1 ];
  14865. var curve = new THREE.CubicBezierCurve( new THREE.Vector2( x0, y0 ),
  14866. new THREE.Vector2( aCP1x, aCP1y ),
  14867. new THREE.Vector2( aCP2x, aCP2y ),
  14868. new THREE.Vector2( aX, aY ) );
  14869. this.curves.push( curve );
  14870. this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
  14871. };
  14872. THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
  14873. var args = Array.prototype.slice.call( arguments );
  14874. var lastargs = this.actions[ this.actions.length - 1 ].args;
  14875. var x0 = lastargs[ lastargs.length - 2 ];
  14876. var y0 = lastargs[ lastargs.length - 1 ];
  14877. //---
  14878. var npts = [ new THREE.Vector2( x0, y0 ) ];
  14879. Array.prototype.push.apply( npts, pts );
  14880. var curve = new THREE.SplineCurve( npts );
  14881. this.curves.push( curve );
  14882. this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
  14883. };
  14884. // FUTURE: Change the API or follow canvas API?
  14885. THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
  14886. aStartAngle, aEndAngle, aClockwise ) {
  14887. var laste = this.actions[ this.actions.length - 1];
  14888. this.absellipse(laste.x + aX, laste.y + aY, xRadius, yRadius,
  14889. aStartAngle, aEndAngle, aClockwise );
  14890. };
  14891. THREE.Path.prototype.arc = function ( aX, aY, aRadius,
  14892. aStartAngle, aEndAngle, aClockwise ) {
  14893. var laste = this.actions[ this.actions.length - 1];
  14894. this.absarc(laste.x + aX, laste.y + aY, aRadius,
  14895. aStartAngle, aEndAngle, aClockwise );
  14896. };
  14897. THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
  14898. aStartAngle, aEndAngle, aClockwise ) {
  14899. var args = Array.prototype.slice.call( arguments );
  14900. var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
  14901. aStartAngle, aEndAngle, aClockwise );
  14902. this.curves.push( curve );
  14903. // All of the other actions look to the last two elements in the list to
  14904. // find the ending point, so we need to append them.
  14905. var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
  14906. args.push(lastPoint.x);
  14907. args.push(lastPoint.y);
  14908. this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
  14909. };
  14910. THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
  14911. aStartAngle, aEndAngle, aClockwise ) {
  14912. this.absellipse(aX, aY, aRadius, aRadius,
  14913. aStartAngle, aEndAngle, aClockwise);
  14914. };
  14915. THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
  14916. if ( ! divisions ) divisions = 40;
  14917. var points = [];
  14918. for ( var i = 0; i < divisions; i ++ ) {
  14919. points.push( this.getPoint( i / divisions ) );
  14920. //if( !this.getPoint( i / divisions ) ) throw "DIE";
  14921. }
  14922. // if ( closedPath ) {
  14923. //
  14924. // points.push( points[ 0 ] );
  14925. //
  14926. // }
  14927. return points;
  14928. };
  14929. /* Return an array of vectors based on contour of the path */
  14930. THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
  14931. if (this.useSpacedPoints) {
  14932. console.log('tata');
  14933. return this.getSpacedPoints( divisions, closedPath );
  14934. }
  14935. divisions = divisions || 12;
  14936. var points = [];
  14937. var i, il, item, action, args;
  14938. var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
  14939. laste, j,
  14940. t, tx, ty;
  14941. for ( i = 0, il = this.actions.length; i < il; i ++ ) {
  14942. item = this.actions[ i ];
  14943. action = item.action;
  14944. args = item.args;
  14945. switch( action ) {
  14946. case THREE.PathActions.MOVE_TO:
  14947. points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
  14948. break;
  14949. case THREE.PathActions.LINE_TO:
  14950. points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
  14951. break;
  14952. case THREE.PathActions.QUADRATIC_CURVE_TO:
  14953. cpx = args[ 2 ];
  14954. cpy = args[ 3 ];
  14955. cpx1 = args[ 0 ];
  14956. cpy1 = args[ 1 ];
  14957. if ( points.length > 0 ) {
  14958. laste = points[ points.length - 1 ];
  14959. cpx0 = laste.x;
  14960. cpy0 = laste.y;
  14961. } else {
  14962. laste = this.actions[ i - 1 ].args;
  14963. cpx0 = laste[ laste.length - 2 ];
  14964. cpy0 = laste[ laste.length - 1 ];
  14965. }
  14966. for ( j = 1; j <= divisions; j ++ ) {
  14967. t = j / divisions;
  14968. tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
  14969. ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
  14970. points.push( new THREE.Vector2( tx, ty ) );
  14971. }
  14972. break;
  14973. case THREE.PathActions.BEZIER_CURVE_TO:
  14974. cpx = args[ 4 ];
  14975. cpy = args[ 5 ];
  14976. cpx1 = args[ 0 ];
  14977. cpy1 = args[ 1 ];
  14978. cpx2 = args[ 2 ];
  14979. cpy2 = args[ 3 ];
  14980. if ( points.length > 0 ) {
  14981. laste = points[ points.length - 1 ];
  14982. cpx0 = laste.x;
  14983. cpy0 = laste.y;
  14984. } else {
  14985. laste = this.actions[ i - 1 ].args;
  14986. cpx0 = laste[ laste.length - 2 ];
  14987. cpy0 = laste[ laste.length - 1 ];
  14988. }
  14989. for ( j = 1; j <= divisions; j ++ ) {
  14990. t = j / divisions;
  14991. tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
  14992. ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
  14993. points.push( new THREE.Vector2( tx, ty ) );
  14994. }
  14995. break;
  14996. case THREE.PathActions.CSPLINE_THRU:
  14997. laste = this.actions[ i - 1 ].args;
  14998. var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
  14999. var spts = [ last ];
  15000. var n = divisions * args[ 0 ].length;
  15001. spts = spts.concat( args[ 0 ] );
  15002. var spline = new THREE.SplineCurve( spts );
  15003. for ( j = 1; j <= n; j ++ ) {
  15004. points.push( spline.getPointAt( j / n ) ) ;
  15005. }
  15006. break;
  15007. case THREE.PathActions.ARC:
  15008. var aX = args[ 0 ], aY = args[ 1 ],
  15009. aRadius = args[ 2 ],
  15010. aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
  15011. aClockwise = !!args[ 5 ];
  15012. var deltaAngle = aEndAngle - aStartAngle;
  15013. var angle;
  15014. var tdivisions = divisions * 2;
  15015. for ( j = 1; j <= tdivisions; j ++ ) {
  15016. t = j / tdivisions;
  15017. if ( ! aClockwise ) {
  15018. t = 1 - t;
  15019. }
  15020. angle = aStartAngle + t * deltaAngle;
  15021. tx = aX + aRadius * Math.cos( angle );
  15022. ty = aY + aRadius * Math.sin( angle );
  15023. //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
  15024. points.push( new THREE.Vector2( tx, ty ) );
  15025. }
  15026. //console.log(points);
  15027. break;
  15028. case THREE.PathActions.ELLIPSE:
  15029. var aX = args[ 0 ], aY = args[ 1 ],
  15030. xRadius = args[ 2 ],
  15031. yRadius = args[3]
  15032. aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
  15033. aClockwise = !!args[ 6 ];
  15034. var deltaAngle = aEndAngle - aStartAngle;
  15035. var angle;
  15036. var tdivisions = divisions * 2;
  15037. for ( j = 1; j <= tdivisions; j ++ ) {
  15038. t = j / tdivisions;
  15039. if ( ! aClockwise ) {
  15040. t = 1 - t;
  15041. }
  15042. angle = aStartAngle + t * deltaAngle;
  15043. tx = aX + xRadius * Math.cos( angle );
  15044. ty = aY + yRadius * Math.sin( angle );
  15045. //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
  15046. points.push( new THREE.Vector2( tx, ty ) );
  15047. }
  15048. //console.log(points);
  15049. break;
  15050. } // end switch
  15051. }
  15052. // Normalize to remove the closing point by default.
  15053. var lastPoint = points[ points.length - 1];
  15054. var EPSILON = 0.0000000001;
  15055. if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
  15056. Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
  15057. points.splice( points.length - 1, 1);
  15058. if ( closedPath ) {
  15059. points.push( points[ 0 ] );
  15060. }
  15061. return points;
  15062. };
  15063. // Breaks path into shapes
  15064. THREE.Path.prototype.toShapes = function() {
  15065. var i, il, item, action, args;
  15066. var subPaths = [], lastPath = new THREE.Path();
  15067. for ( i = 0, il = this.actions.length; i < il; i ++ ) {
  15068. item = this.actions[ i ];
  15069. args = item.args;
  15070. action = item.action;
  15071. if ( action == THREE.PathActions.MOVE_TO ) {
  15072. if ( lastPath.actions.length != 0 ) {
  15073. subPaths.push( lastPath );
  15074. lastPath = new THREE.Path();
  15075. }
  15076. }
  15077. lastPath[ action ].apply( lastPath, args );
  15078. }
  15079. if ( lastPath.actions.length != 0 ) {
  15080. subPaths.push( lastPath );
  15081. }
  15082. // console.log(subPaths);
  15083. if ( subPaths.length == 0 ) return [];
  15084. var tmpPath, tmpShape, shapes = [];
  15085. var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
  15086. // console.log("Holes first", holesFirst);
  15087. if ( subPaths.length == 1) {
  15088. tmpPath = subPaths[0];
  15089. tmpShape = new THREE.Shape();
  15090. tmpShape.actions = tmpPath.actions;
  15091. tmpShape.curves = tmpPath.curves;
  15092. shapes.push( tmpShape );
  15093. return shapes;
  15094. };
  15095. if ( holesFirst ) {
  15096. tmpShape = new THREE.Shape();
  15097. for ( i = 0, il = subPaths.length; i < il; i ++ ) {
  15098. tmpPath = subPaths[ i ];
  15099. if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
  15100. tmpShape.actions = tmpPath.actions;
  15101. tmpShape.curves = tmpPath.curves;
  15102. shapes.push( tmpShape );
  15103. tmpShape = new THREE.Shape();
  15104. //console.log('cw', i);
  15105. } else {
  15106. tmpShape.holes.push( tmpPath );
  15107. //console.log('ccw', i);
  15108. }
  15109. }
  15110. } else {
  15111. // Shapes first
  15112. for ( i = 0, il = subPaths.length; i < il; i ++ ) {
  15113. tmpPath = subPaths[ i ];
  15114. if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
  15115. if ( tmpShape ) shapes.push( tmpShape );
  15116. tmpShape = new THREE.Shape();
  15117. tmpShape.actions = tmpPath.actions;
  15118. tmpShape.curves = tmpPath.curves;
  15119. } else {
  15120. tmpShape.holes.push( tmpPath );
  15121. }
  15122. }
  15123. shapes.push( tmpShape );
  15124. }
  15125. //console.log("shape", shapes);
  15126. return shapes;
  15127. };
  15128. /**
  15129. * @author zz85 / http://www.lab4games.net/zz85/blog
  15130. * Defines a 2d shape plane using paths.
  15131. **/
  15132. // STEP 1 Create a path.
  15133. // STEP 2 Turn path into shape.
  15134. // STEP 3 ExtrudeGeometry takes in Shape/Shapes
  15135. // STEP 3a - Extract points from each shape, turn to vertices
  15136. // STEP 3b - Triangulate each shape, add faces.
  15137. THREE.Shape = function ( ) {
  15138. THREE.Path.apply( this, arguments );
  15139. this.holes = [];
  15140. };
  15141. THREE.Shape.prototype = Object.create( THREE.Path.prototype );
  15142. // Convenience method to return ExtrudeGeometry
  15143. THREE.Shape.prototype.extrude = function ( options ) {
  15144. var extruded = new THREE.ExtrudeGeometry( this, options );
  15145. return extruded;
  15146. };
  15147. // Get points of holes
  15148. THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
  15149. var i, il = this.holes.length, holesPts = [];
  15150. for ( i = 0; i < il; i ++ ) {
  15151. holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
  15152. }
  15153. return holesPts;
  15154. };
  15155. // Get points of holes (spaced by regular distance)
  15156. THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
  15157. var i, il = this.holes.length, holesPts = [];
  15158. for ( i = 0; i < il; i ++ ) {
  15159. holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
  15160. }
  15161. return holesPts;
  15162. };
  15163. // Get points of shape and holes (keypoints based on segments parameter)
  15164. THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
  15165. return {
  15166. shape: this.getTransformedPoints( divisions ),
  15167. holes: this.getPointsHoles( divisions )
  15168. };
  15169. };
  15170. THREE.Shape.prototype.extractPoints = function ( divisions ) {
  15171. if (this.useSpacedPoints) {
  15172. return this.extractAllSpacedPoints(divisions);
  15173. }
  15174. return this.extractAllPoints(divisions);
  15175. };
  15176. //
  15177. // THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
  15178. //
  15179. // return {
  15180. //
  15181. // shape: this.transform( bend, divisions ),
  15182. // holes: this.getPointsHoles( divisions, bend )
  15183. //
  15184. // };
  15185. //
  15186. // };
  15187. // Get points of shape and holes (spaced by regular distance)
  15188. THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
  15189. return {
  15190. shape: this.getTransformedSpacedPoints( divisions ),
  15191. holes: this.getSpacedPointsHoles( divisions )
  15192. };
  15193. };
  15194. /**************************************************************
  15195. * Utils
  15196. **************************************************************/
  15197. THREE.Shape.Utils = {
  15198. /*
  15199. contour - array of vector2 for contour
  15200. holes - array of array of vector2
  15201. */
  15202. removeHoles: function ( contour, holes ) {
  15203. var shape = contour.concat(); // work on this shape
  15204. var allpoints = shape.concat();
  15205. /* For each isolated shape, find the closest points and break to the hole to allow triangulation */
  15206. var prevShapeVert, nextShapeVert,
  15207. prevHoleVert, nextHoleVert,
  15208. holeIndex, shapeIndex,
  15209. shapeId, shapeGroup,
  15210. h, h2,
  15211. hole, shortest, d,
  15212. p, pts1, pts2,
  15213. tmpShape1, tmpShape2,
  15214. tmpHole1, tmpHole2,
  15215. verts = [];
  15216. for ( h = 0; h < holes.length; h ++ ) {
  15217. hole = holes[ h ];
  15218. /*
  15219. shapeholes[ h ].concat(); // preserves original
  15220. holes.push( hole );
  15221. */
  15222. Array.prototype.push.apply( allpoints, hole );
  15223. shortest = Number.POSITIVE_INFINITY;
  15224. // Find the shortest pair of pts between shape and hole
  15225. // Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n)
  15226. // Using distanceToSquared() intead of distanceTo() should speed a little
  15227. // since running square roots operations are reduced.
  15228. for ( h2 = 0; h2 < hole.length; h2 ++ ) {
  15229. pts1 = hole[ h2 ];
  15230. var dist = [];
  15231. for ( p = 0; p < shape.length; p++ ) {
  15232. pts2 = shape[ p ];
  15233. d = pts1.distanceToSquared( pts2 );
  15234. dist.push( d );
  15235. if ( d < shortest ) {
  15236. shortest = d;
  15237. holeIndex = h2;
  15238. shapeIndex = p;
  15239. }
  15240. }
  15241. }
  15242. //console.log("shortest", shortest, dist);
  15243. prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
  15244. prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
  15245. var areaapts = [
  15246. hole[ holeIndex ],
  15247. shape[ shapeIndex ],
  15248. shape[ prevShapeVert ]
  15249. ];
  15250. var areaa = THREE.FontUtils.Triangulate.area( areaapts );
  15251. var areabpts = [
  15252. hole[ holeIndex ],
  15253. hole[ prevHoleVert ],
  15254. shape[ shapeIndex ]
  15255. ];
  15256. var areab = THREE.FontUtils.Triangulate.area( areabpts );
  15257. var shapeOffset = 1;
  15258. var holeOffset = -1;
  15259. var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
  15260. shapeIndex += shapeOffset;
  15261. holeIndex += holeOffset;
  15262. if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
  15263. shapeIndex %= shape.length;
  15264. if ( holeIndex < 0 ) { holeIndex += hole.length; }
  15265. holeIndex %= hole.length;
  15266. prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
  15267. prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
  15268. areaapts = [
  15269. hole[ holeIndex ],
  15270. shape[ shapeIndex ],
  15271. shape[ prevShapeVert ]
  15272. ];
  15273. var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
  15274. areabpts = [
  15275. hole[ holeIndex ],
  15276. hole[ prevHoleVert ],
  15277. shape[ shapeIndex ]
  15278. ];
  15279. var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
  15280. //console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ), ( areaa2 + areab2 ));
  15281. if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
  15282. // In case areas are not correct.
  15283. //console.log("USE THIS");
  15284. shapeIndex = oldShapeIndex;
  15285. holeIndex = oldHoleIndex ;
  15286. if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
  15287. shapeIndex %= shape.length;
  15288. if ( holeIndex < 0 ) { holeIndex += hole.length; }
  15289. holeIndex %= hole.length;
  15290. prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
  15291. prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
  15292. } else {
  15293. //console.log("USE THAT ")
  15294. }
  15295. tmpShape1 = shape.slice( 0, shapeIndex );
  15296. tmpShape2 = shape.slice( shapeIndex );
  15297. tmpHole1 = hole.slice( holeIndex );
  15298. tmpHole2 = hole.slice( 0, holeIndex );
  15299. // Should check orders here again?
  15300. var trianglea = [
  15301. hole[ holeIndex ],
  15302. shape[ shapeIndex ],
  15303. shape[ prevShapeVert ]
  15304. ];
  15305. var triangleb = [
  15306. hole[ holeIndex ] ,
  15307. hole[ prevHoleVert ],
  15308. shape[ shapeIndex ]
  15309. ];
  15310. verts.push( trianglea );
  15311. verts.push( triangleb );
  15312. shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
  15313. }
  15314. return {
  15315. shape:shape, /* shape with no holes */
  15316. isolatedPts: verts, /* isolated faces */
  15317. allpoints: allpoints
  15318. }
  15319. },
  15320. triangulateShape: function ( contour, holes ) {
  15321. var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
  15322. var shape = shapeWithoutHoles.shape,
  15323. allpoints = shapeWithoutHoles.allpoints,
  15324. isolatedPts = shapeWithoutHoles.isolatedPts;
  15325. var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
  15326. // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
  15327. //console.log( "triangles",triangles, triangles.length );
  15328. //console.log( "allpoints",allpoints, allpoints.length );
  15329. var i, il, f, face,
  15330. key, index,
  15331. allPointsMap = {},
  15332. isolatedPointsMap = {};
  15333. // prepare all points map
  15334. for ( i = 0, il = allpoints.length; i < il; i ++ ) {
  15335. key = allpoints[ i ].x + ":" + allpoints[ i ].y;
  15336. if ( allPointsMap[ key ] !== undefined ) {
  15337. console.log( "Duplicate point", key );
  15338. }
  15339. allPointsMap[ key ] = i;
  15340. }
  15341. // check all face vertices against all points map
  15342. for ( i = 0, il = triangles.length; i < il; i ++ ) {
  15343. face = triangles[ i ];
  15344. for ( f = 0; f < 3; f ++ ) {
  15345. key = face[ f ].x + ":" + face[ f ].y;
  15346. index = allPointsMap[ key ];
  15347. if ( index !== undefined ) {
  15348. face[ f ] = index;
  15349. }
  15350. }
  15351. }
  15352. // check isolated points vertices against all points map
  15353. for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
  15354. face = isolatedPts[ i ];
  15355. for ( f = 0; f < 3; f ++ ) {
  15356. key = face[ f ].x + ":" + face[ f ].y;
  15357. index = allPointsMap[ key ];
  15358. if ( index !== undefined ) {
  15359. face[ f ] = index;
  15360. }
  15361. }
  15362. }
  15363. return triangles.concat( isolatedPts );
  15364. }, // end triangulate shapes
  15365. /*
  15366. triangulate2 : function( pts, holes ) {
  15367. // For use with Poly2Tri.js
  15368. var allpts = pts.concat();
  15369. var shape = [];
  15370. for (var p in pts) {
  15371. shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
  15372. }
  15373. var swctx = new js.poly2tri.SweepContext(shape);
  15374. for (var h in holes) {
  15375. var aHole = holes[h];
  15376. var newHole = []
  15377. for (i in aHole) {
  15378. newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
  15379. allpts.push(aHole[i]);
  15380. }
  15381. swctx.AddHole(newHole);
  15382. }
  15383. var find;
  15384. var findIndexForPt = function (pt) {
  15385. find = new THREE.Vector2(pt.x, pt.y);
  15386. var p;
  15387. for (p=0, pl = allpts.length; p<pl; p++) {
  15388. if (allpts[p].equals(find)) return p;
  15389. }
  15390. return -1;
  15391. };
  15392. // triangulate
  15393. js.poly2tri.sweep.Triangulate(swctx);
  15394. var triangles = swctx.GetTriangles();
  15395. var tr ;
  15396. var facesPts = [];
  15397. for (var t in triangles) {
  15398. tr = triangles[t];
  15399. facesPts.push([
  15400. findIndexForPt(tr.GetPoint(0)),
  15401. findIndexForPt(tr.GetPoint(1)),
  15402. findIndexForPt(tr.GetPoint(2))
  15403. ]);
  15404. }
  15405. // console.log(facesPts);
  15406. // console.log("triangles", triangles.length, triangles);
  15407. // Returns array of faces with 3 element each
  15408. return facesPts;
  15409. },
  15410. */
  15411. isClockWise: function ( pts ) {
  15412. return THREE.FontUtils.Triangulate.area( pts ) < 0;
  15413. },
  15414. // Bezier Curves formulas obtained from
  15415. // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
  15416. // Quad Bezier Functions
  15417. b2p0: function ( t, p ) {
  15418. var k = 1 - t;
  15419. return k * k * p;
  15420. },
  15421. b2p1: function ( t, p ) {
  15422. return 2 * ( 1 - t ) * t * p;
  15423. },
  15424. b2p2: function ( t, p ) {
  15425. return t * t * p;
  15426. },
  15427. b2: function ( t, p0, p1, p2 ) {
  15428. return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
  15429. },
  15430. // Cubic Bezier Functions
  15431. b3p0: function ( t, p ) {
  15432. var k = 1 - t;
  15433. return k * k * k * p;
  15434. },
  15435. b3p1: function ( t, p ) {
  15436. var k = 1 - t;
  15437. return 3 * k * k * t * p;
  15438. },
  15439. b3p2: function ( t, p ) {
  15440. var k = 1 - t;
  15441. return 3 * k * t * t * p;
  15442. },
  15443. b3p3: function ( t, p ) {
  15444. return t * t * t * p;
  15445. },
  15446. b3: function ( t, p0, p1, p2, p3 ) {
  15447. return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) + this.b3p3( t, p3 );
  15448. }
  15449. };
  15450. /**
  15451. * @author mikael emtinger / http://gomo.se/
  15452. */
  15453. THREE.AnimationHandler = (function() {
  15454. var playing = [];
  15455. var library = {};
  15456. var that = {};
  15457. //--- update ---
  15458. that.update = function( deltaTimeMS ) {
  15459. for( var i = 0; i < playing.length; i ++ )
  15460. playing[ i ].update( deltaTimeMS );
  15461. };
  15462. //--- add ---
  15463. that.addToUpdate = function( animation ) {
  15464. if ( playing.indexOf( animation ) === -1 )
  15465. playing.push( animation );
  15466. };
  15467. //--- remove ---
  15468. that.removeFromUpdate = function( animation ) {
  15469. var index = playing.indexOf( animation );
  15470. if( index !== -1 )
  15471. playing.splice( index, 1 );
  15472. };
  15473. //--- add ---
  15474. that.add = function( data ) {
  15475. if ( library[ data.name ] !== undefined )
  15476. console.log( "THREE.AnimationHandler.add: Warning! " + data.name + " already exists in library. Overwriting." );
  15477. library[ data.name ] = data;
  15478. initData( data );
  15479. };
  15480. //--- get ---
  15481. that.get = function( name ) {
  15482. if ( typeof name === "string" ) {
  15483. if ( library[ name ] ) {
  15484. return library[ name ];
  15485. } else {
  15486. console.log( "THREE.AnimationHandler.get: Couldn't find animation " + name );
  15487. return null;
  15488. }
  15489. } else {
  15490. // todo: add simple tween library
  15491. }
  15492. };
  15493. //--- parse ---
  15494. that.parse = function( root ) {
  15495. // setup hierarchy
  15496. var hierarchy = [];
  15497. if ( root instanceof THREE.SkinnedMesh ) {
  15498. for( var b = 0; b < root.bones.length; b++ ) {
  15499. hierarchy.push( root.bones[ b ] );
  15500. }
  15501. } else {
  15502. parseRecurseHierarchy( root, hierarchy );
  15503. }
  15504. return hierarchy;
  15505. };
  15506. var parseRecurseHierarchy = function( root, hierarchy ) {
  15507. hierarchy.push( root );
  15508. for( var c = 0; c < root.children.length; c++ )
  15509. parseRecurseHierarchy( root.children[ c ], hierarchy );
  15510. }
  15511. //--- init data ---
  15512. var initData = function( data ) {
  15513. if( data.initialized === true )
  15514. return;
  15515. // loop through all keys
  15516. for( var h = 0; h < data.hierarchy.length; h ++ ) {
  15517. for( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
  15518. // remove minus times
  15519. if( data.hierarchy[ h ].keys[ k ].time < 0 )
  15520. data.hierarchy[ h ].keys[ k ].time = 0;
  15521. // create quaternions
  15522. if( data.hierarchy[ h ].keys[ k ].rot !== undefined &&
  15523. !( data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion ) ) {
  15524. var quat = data.hierarchy[ h ].keys[ k ].rot;
  15525. data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion( quat[0], quat[1], quat[2], quat[3] );
  15526. }
  15527. }
  15528. // prepare morph target keys
  15529. if( data.hierarchy[ h ].keys.length && data.hierarchy[ h ].keys[ 0 ].morphTargets !== undefined ) {
  15530. // get all used
  15531. var usedMorphTargets = {};
  15532. for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
  15533. for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
  15534. var morphTargetName = data.hierarchy[ h ].keys[ k ].morphTargets[ m ];
  15535. usedMorphTargets[ morphTargetName ] = -1;
  15536. }
  15537. }
  15538. data.hierarchy[ h ].usedMorphTargets = usedMorphTargets;
  15539. // set all used on all frames
  15540. for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
  15541. var influences = {};
  15542. for ( var morphTargetName in usedMorphTargets ) {
  15543. for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
  15544. if ( data.hierarchy[ h ].keys[ k ].morphTargets[ m ] === morphTargetName ) {
  15545. influences[ morphTargetName ] = data.hierarchy[ h ].keys[ k ].morphTargetsInfluences[ m ];
  15546. break;
  15547. }
  15548. }
  15549. if ( m === data.hierarchy[ h ].keys[ k ].morphTargets.length ) {
  15550. influences[ morphTargetName ] = 0;
  15551. }
  15552. }
  15553. data.hierarchy[ h ].keys[ k ].morphTargetsInfluences = influences;
  15554. }
  15555. }
  15556. // remove all keys that are on the same time
  15557. for ( var k = 1; k < data.hierarchy[ h ].keys.length; k ++ ) {
  15558. if ( data.hierarchy[ h ].keys[ k ].time === data.hierarchy[ h ].keys[ k - 1 ].time ) {
  15559. data.hierarchy[ h ].keys.splice( k, 1 );
  15560. k --;
  15561. }
  15562. }
  15563. // set index
  15564. for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
  15565. data.hierarchy[ h ].keys[ k ].index = k;
  15566. }
  15567. }
  15568. // JIT
  15569. var lengthInFrames = parseInt( data.length * data.fps, 10 );
  15570. data.JIT = {};
  15571. data.JIT.hierarchy = [];
  15572. for( var h = 0; h < data.hierarchy.length; h ++ )
  15573. data.JIT.hierarchy.push( new Array( lengthInFrames ) );
  15574. // done
  15575. data.initialized = true;
  15576. };
  15577. // interpolation types
  15578. that.LINEAR = 0;
  15579. that.CATMULLROM = 1;
  15580. that.CATMULLROM_FORWARD = 2;
  15581. return that;
  15582. }());
  15583. /**
  15584. * @author mikael emtinger / http://gomo.se/
  15585. * @author mrdoob / http://mrdoob.com/
  15586. * @author alteredq / http://alteredqualia.com/
  15587. */
  15588. THREE.Animation = function ( root, name, interpolationType ) {
  15589. this.root = root;
  15590. this.data = THREE.AnimationHandler.get( name );
  15591. this.hierarchy = THREE.AnimationHandler.parse( root );
  15592. this.currentTime = 0;
  15593. this.timeScale = 1;
  15594. this.isPlaying = false;
  15595. this.isPaused = true;
  15596. this.loop = true;
  15597. this.interpolationType = interpolationType !== undefined ? interpolationType : THREE.AnimationHandler.LINEAR;
  15598. this.points = [];
  15599. this.target = new THREE.Vector3();
  15600. };
  15601. THREE.Animation.prototype.play = function ( loop, startTimeMS ) {
  15602. if ( this.isPlaying === false ) {
  15603. this.isPlaying = true;
  15604. this.loop = loop !== undefined ? loop : true;
  15605. this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
  15606. // reset key cache
  15607. var h, hl = this.hierarchy.length,
  15608. object;
  15609. for ( h = 0; h < hl; h ++ ) {
  15610. object = this.hierarchy[ h ];
  15611. if ( this.interpolationType !== THREE.AnimationHandler.CATMULLROM_FORWARD ) {
  15612. object.useQuaternion = true;
  15613. }
  15614. object.matrixAutoUpdate = true;
  15615. if ( object.animationCache === undefined ) {
  15616. object.animationCache = {};
  15617. object.animationCache.prevKey = { pos: 0, rot: 0, scl: 0 };
  15618. object.animationCache.nextKey = { pos: 0, rot: 0, scl: 0 };
  15619. object.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
  15620. }
  15621. var prevKey = object.animationCache.prevKey;
  15622. var nextKey = object.animationCache.nextKey;
  15623. prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ];
  15624. prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ];
  15625. prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ];
  15626. nextKey.pos = this.getNextKeyWith( "pos", h, 1 );
  15627. nextKey.rot = this.getNextKeyWith( "rot", h, 1 );
  15628. nextKey.scl = this.getNextKeyWith( "scl", h, 1 );
  15629. }
  15630. this.update( 0 );
  15631. }
  15632. this.isPaused = false;
  15633. THREE.AnimationHandler.addToUpdate( this );
  15634. };
  15635. THREE.Animation.prototype.pause = function() {
  15636. if ( this.isPaused === true ) {
  15637. THREE.AnimationHandler.addToUpdate( this );
  15638. } else {
  15639. THREE.AnimationHandler.removeFromUpdate( this );
  15640. }
  15641. this.isPaused = !this.isPaused;
  15642. };
  15643. THREE.Animation.prototype.stop = function() {
  15644. this.isPlaying = false;
  15645. this.isPaused = false;
  15646. THREE.AnimationHandler.removeFromUpdate( this );
  15647. };
  15648. THREE.Animation.prototype.update = function ( deltaTimeMS ) {
  15649. // early out
  15650. if ( this.isPlaying === false ) return;
  15651. // vars
  15652. var types = [ "pos", "rot", "scl" ];
  15653. var type;
  15654. var scale;
  15655. var vector;
  15656. var prevXYZ, nextXYZ;
  15657. var prevKey, nextKey;
  15658. var object;
  15659. var animationCache;
  15660. var frame;
  15661. var JIThierarchy = this.data.JIT.hierarchy;
  15662. var currentTime, unloopedCurrentTime;
  15663. var currentPoint, forwardPoint, angle;
  15664. this.currentTime += deltaTimeMS * this.timeScale;
  15665. unloopedCurrentTime = this.currentTime;
  15666. currentTime = this.currentTime = this.currentTime % this.data.length;
  15667. frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
  15668. for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
  15669. object = this.hierarchy[ h ];
  15670. animationCache = object.animationCache;
  15671. // loop through pos/rot/scl
  15672. for ( var t = 0; t < 3; t ++ ) {
  15673. // get keys
  15674. type = types[ t ];
  15675. prevKey = animationCache.prevKey[ type ];
  15676. nextKey = animationCache.nextKey[ type ];
  15677. // switch keys?
  15678. if ( nextKey.time <= unloopedCurrentTime ) {
  15679. // did we loop?
  15680. if ( currentTime < unloopedCurrentTime ) {
  15681. if ( this.loop ) {
  15682. prevKey = this.data.hierarchy[ h ].keys[ 0 ];
  15683. nextKey = this.getNextKeyWith( type, h, 1 );
  15684. while( nextKey.time < currentTime ) {
  15685. prevKey = nextKey;
  15686. nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
  15687. }
  15688. } else {
  15689. this.stop();
  15690. return;
  15691. }
  15692. } else {
  15693. do {
  15694. prevKey = nextKey;
  15695. nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
  15696. } while( nextKey.time < currentTime )
  15697. }
  15698. animationCache.prevKey[ type ] = prevKey;
  15699. animationCache.nextKey[ type ] = nextKey;
  15700. }
  15701. object.matrixAutoUpdate = true;
  15702. object.matrixWorldNeedsUpdate = true;
  15703. scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
  15704. prevXYZ = prevKey[ type ];
  15705. nextXYZ = nextKey[ type ];
  15706. // check scale error
  15707. if ( scale < 0 || scale > 1 ) {
  15708. console.log( "THREE.Animation.update: Warning! Scale out of bounds:" + scale + " on bone " + h );
  15709. scale = scale < 0 ? 0 : 1;
  15710. }
  15711. // interpolate
  15712. if ( type === "pos" ) {
  15713. vector = object.position;
  15714. if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
  15715. vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
  15716. vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
  15717. vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
  15718. } else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
  15719. this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
  15720. this.points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
  15721. this.points[ 1 ] = prevXYZ;
  15722. this.points[ 2 ] = nextXYZ;
  15723. this.points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
  15724. scale = scale * 0.33 + 0.33;
  15725. currentPoint = this.interpolateCatmullRom( this.points, scale );
  15726. vector.x = currentPoint[ 0 ];
  15727. vector.y = currentPoint[ 1 ];
  15728. vector.z = currentPoint[ 2 ];
  15729. if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
  15730. forwardPoint = this.interpolateCatmullRom( this.points, scale * 1.01 );
  15731. this.target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
  15732. this.target.subSelf( vector );
  15733. this.target.y = 0;
  15734. this.target.normalize();
  15735. angle = Math.atan2( this.target.x, this.target.z );
  15736. object.rotation.set( 0, angle, 0 );
  15737. }
  15738. }
  15739. } else if ( type === "rot" ) {
  15740. THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale );
  15741. } else if ( type === "scl" ) {
  15742. vector = object.scale;
  15743. vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
  15744. vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
  15745. vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
  15746. }
  15747. }
  15748. }
  15749. };
  15750. // Catmull-Rom spline
  15751. THREE.Animation.prototype.interpolateCatmullRom = function ( points, scale ) {
  15752. var c = [], v3 = [],
  15753. point, intPoint, weight, w2, w3,
  15754. pa, pb, pc, pd;
  15755. point = ( points.length - 1 ) * scale;
  15756. intPoint = Math.floor( point );
  15757. weight = point - intPoint;
  15758. c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
  15759. c[ 1 ] = intPoint;
  15760. c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
  15761. c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
  15762. pa = points[ c[ 0 ] ];
  15763. pb = points[ c[ 1 ] ];
  15764. pc = points[ c[ 2 ] ];
  15765. pd = points[ c[ 3 ] ];
  15766. w2 = weight * weight;
  15767. w3 = weight * w2;
  15768. v3[ 0 ] = this.interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
  15769. v3[ 1 ] = this.interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
  15770. v3[ 2 ] = this.interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
  15771. return v3;
  15772. };
  15773. THREE.Animation.prototype.interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
  15774. var v0 = ( p2 - p0 ) * 0.5,
  15775. v1 = ( p3 - p1 ) * 0.5;
  15776. return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
  15777. };
  15778. // Get next key with
  15779. THREE.Animation.prototype.getNextKeyWith = function ( type, h, key ) {
  15780. var keys = this.data.hierarchy[ h ].keys;
  15781. if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
  15782. this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
  15783. key = key < keys.length - 1 ? key : keys.length - 1;
  15784. } else {
  15785. key = key % keys.length;
  15786. }
  15787. for ( ; key < keys.length; key++ ) {
  15788. if ( keys[ key ][ type ] !== undefined ) {
  15789. return keys[ key ];
  15790. }
  15791. }
  15792. return this.data.hierarchy[ h ].keys[ 0 ];
  15793. };
  15794. // Get previous key with
  15795. THREE.Animation.prototype.getPrevKeyWith = function ( type, h, key ) {
  15796. var keys = this.data.hierarchy[ h ].keys;
  15797. if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
  15798. this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
  15799. key = key > 0 ? key : 0;
  15800. } else {
  15801. key = key >= 0 ? key : key + keys.length;
  15802. }
  15803. for ( ; key >= 0; key -- ) {
  15804. if ( keys[ key ][ type ] !== undefined ) {
  15805. return keys[ key ];
  15806. }
  15807. }
  15808. return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
  15809. };
  15810. /**
  15811. * @author mikael emtinger / http://gomo.se/
  15812. * @author mrdoob / http://mrdoob.com/
  15813. * @author alteredq / http://alteredqualia.com/
  15814. * @author khang duong
  15815. * @author erik kitson
  15816. */
  15817. THREE.KeyFrameAnimation = function( root, data, JITCompile ) {
  15818. this.root = root;
  15819. this.data = THREE.AnimationHandler.get( data );
  15820. this.hierarchy = THREE.AnimationHandler.parse( root );
  15821. this.currentTime = 0;
  15822. this.timeScale = 0.001;
  15823. this.isPlaying = false;
  15824. this.isPaused = true;
  15825. this.loop = true;
  15826. this.JITCompile = JITCompile !== undefined ? JITCompile : true;
  15827. // initialize to first keyframes
  15828. for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
  15829. var keys = this.data.hierarchy[h].keys,
  15830. sids = this.data.hierarchy[h].sids,
  15831. obj = this.hierarchy[h];
  15832. if ( keys.length && sids ) {
  15833. for ( var s = 0; s < sids.length; s++ ) {
  15834. var sid = sids[ s ],
  15835. next = this.getNextKeyWith( sid, h, 0 );
  15836. if ( next ) {
  15837. next.apply( sid );
  15838. }
  15839. }
  15840. obj.matrixAutoUpdate = false;
  15841. this.data.hierarchy[h].node.updateMatrix();
  15842. obj.matrixWorldNeedsUpdate = true;
  15843. }
  15844. }
  15845. };
  15846. // Play
  15847. THREE.KeyFrameAnimation.prototype.play = function( loop, startTimeMS ) {
  15848. if( !this.isPlaying ) {
  15849. this.isPlaying = true;
  15850. this.loop = loop !== undefined ? loop : true;
  15851. this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
  15852. this.startTimeMs = startTimeMS;
  15853. this.startTime = 10000000;
  15854. this.endTime = -this.startTime;
  15855. // reset key cache
  15856. var h, hl = this.hierarchy.length,
  15857. object,
  15858. node;
  15859. for ( h = 0; h < hl; h++ ) {
  15860. object = this.hierarchy[ h ];
  15861. node = this.data.hierarchy[ h ];
  15862. object.useQuaternion = true;
  15863. if ( node.animationCache === undefined ) {
  15864. node.animationCache = {};
  15865. node.animationCache.prevKey = null;
  15866. node.animationCache.nextKey = null;
  15867. node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
  15868. }
  15869. var keys = this.data.hierarchy[h].keys;
  15870. if (keys.length) {
  15871. node.animationCache.prevKey = keys[ 0 ];
  15872. node.animationCache.nextKey = keys[ 1 ];
  15873. this.startTime = Math.min( keys[0].time, this.startTime );
  15874. this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
  15875. }
  15876. }
  15877. this.update( 0 );
  15878. }
  15879. this.isPaused = false;
  15880. THREE.AnimationHandler.addToUpdate( this );
  15881. };
  15882. // Pause
  15883. THREE.KeyFrameAnimation.prototype.pause = function() {
  15884. if( this.isPaused ) {
  15885. THREE.AnimationHandler.addToUpdate( this );
  15886. } else {
  15887. THREE.AnimationHandler.removeFromUpdate( this );
  15888. }
  15889. this.isPaused = !this.isPaused;
  15890. };
  15891. // Stop
  15892. THREE.KeyFrameAnimation.prototype.stop = function() {
  15893. this.isPlaying = false;
  15894. this.isPaused = false;
  15895. THREE.AnimationHandler.removeFromUpdate( this );
  15896. // reset JIT matrix and remove cache
  15897. for ( var h = 0; h < this.data.hierarchy.length; h++ ) {
  15898. var obj = this.hierarchy[ h ];
  15899. var node = this.data.hierarchy[ h ];
  15900. if ( node.animationCache !== undefined ) {
  15901. var original = node.animationCache.originalMatrix;
  15902. if( obj instanceof THREE.Bone ) {
  15903. original.copy( obj.skinMatrix );
  15904. obj.skinMatrix = original;
  15905. } else {
  15906. original.copy( obj.matrix );
  15907. obj.matrix = original;
  15908. }
  15909. delete node.animationCache;
  15910. }
  15911. }
  15912. };
  15913. // Update
  15914. THREE.KeyFrameAnimation.prototype.update = function( deltaTimeMS ) {
  15915. // early out
  15916. if( !this.isPlaying ) return;
  15917. // vars
  15918. var prevKey, nextKey;
  15919. var object;
  15920. var node;
  15921. var frame;
  15922. var JIThierarchy = this.data.JIT.hierarchy;
  15923. var currentTime, unloopedCurrentTime;
  15924. var looped;
  15925. // update
  15926. this.currentTime += deltaTimeMS * this.timeScale;
  15927. unloopedCurrentTime = this.currentTime;
  15928. currentTime = this.currentTime = this.currentTime % this.data.length;
  15929. // if looped around, the current time should be based on the startTime
  15930. if ( currentTime < this.startTimeMs ) {
  15931. currentTime = this.currentTime = this.startTimeMs + currentTime;
  15932. }
  15933. frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
  15934. looped = currentTime < unloopedCurrentTime;
  15935. if ( looped && !this.loop ) {
  15936. // Set the animation to the last keyframes and stop
  15937. for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
  15938. var keys = this.data.hierarchy[h].keys,
  15939. sids = this.data.hierarchy[h].sids,
  15940. end = keys.length-1,
  15941. obj = this.hierarchy[h];
  15942. if ( keys.length ) {
  15943. for ( var s = 0; s < sids.length; s++ ) {
  15944. var sid = sids[ s ],
  15945. prev = this.getPrevKeyWith( sid, h, end );
  15946. if ( prev ) {
  15947. prev.apply( sid );
  15948. }
  15949. }
  15950. this.data.hierarchy[h].node.updateMatrix();
  15951. obj.matrixWorldNeedsUpdate = true;
  15952. }
  15953. }
  15954. this.stop();
  15955. return;
  15956. }
  15957. // check pre-infinity
  15958. if ( currentTime < this.startTime ) {
  15959. return;
  15960. }
  15961. // update
  15962. for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
  15963. object = this.hierarchy[ h ];
  15964. node = this.data.hierarchy[ h ];
  15965. var keys = node.keys,
  15966. animationCache = node.animationCache;
  15967. // use JIT?
  15968. if ( this.JITCompile && JIThierarchy[ h ][ frame ] !== undefined ) {
  15969. if( object instanceof THREE.Bone ) {
  15970. object.skinMatrix = JIThierarchy[ h ][ frame ];
  15971. object.matrixWorldNeedsUpdate = false;
  15972. } else {
  15973. object.matrix = JIThierarchy[ h ][ frame ];
  15974. object.matrixWorldNeedsUpdate = true;
  15975. }
  15976. // use interpolation
  15977. } else if ( keys.length ) {
  15978. // make sure so original matrix and not JIT matrix is set
  15979. if ( this.JITCompile && animationCache ) {
  15980. if( object instanceof THREE.Bone ) {
  15981. object.skinMatrix = animationCache.originalMatrix;
  15982. } else {
  15983. object.matrix = animationCache.originalMatrix;
  15984. }
  15985. }
  15986. prevKey = animationCache.prevKey;
  15987. nextKey = animationCache.nextKey;
  15988. if ( prevKey && nextKey ) {
  15989. // switch keys?
  15990. if ( nextKey.time <= unloopedCurrentTime ) {
  15991. // did we loop?
  15992. if ( looped && this.loop ) {
  15993. prevKey = keys[ 0 ];
  15994. nextKey = keys[ 1 ];
  15995. while ( nextKey.time < currentTime ) {
  15996. prevKey = nextKey;
  15997. nextKey = keys[ prevKey.index + 1 ];
  15998. }
  15999. } else if ( !looped ) {
  16000. var lastIndex = keys.length - 1;
  16001. while ( nextKey.time < currentTime && nextKey.index !== lastIndex ) {
  16002. prevKey = nextKey;
  16003. nextKey = keys[ prevKey.index + 1 ];
  16004. }
  16005. }
  16006. animationCache.prevKey = prevKey;
  16007. animationCache.nextKey = nextKey;
  16008. }
  16009. if(nextKey.time >= currentTime)
  16010. prevKey.interpolate( nextKey, currentTime );
  16011. else
  16012. prevKey.interpolate( nextKey, nextKey.time);
  16013. }
  16014. this.data.hierarchy[h].node.updateMatrix();
  16015. object.matrixWorldNeedsUpdate = true;
  16016. }
  16017. }
  16018. // update JIT?
  16019. if ( this.JITCompile ) {
  16020. if ( JIThierarchy[ 0 ][ frame ] === undefined ) {
  16021. this.hierarchy[ 0 ].updateMatrixWorld( true );
  16022. for ( var h = 0; h < this.hierarchy.length; h++ ) {
  16023. if( this.hierarchy[ h ] instanceof THREE.Bone ) {
  16024. JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
  16025. } else {
  16026. JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].matrix.clone();
  16027. }
  16028. }
  16029. }
  16030. }
  16031. };
  16032. // Get next key with
  16033. THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
  16034. var keys = this.data.hierarchy[ h ].keys;
  16035. key = key % keys.length;
  16036. for ( ; key < keys.length; key++ ) {
  16037. if ( keys[ key ].hasTarget( sid ) ) {
  16038. return keys[ key ];
  16039. }
  16040. }
  16041. return keys[ 0 ];
  16042. };
  16043. // Get previous key with
  16044. THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
  16045. var keys = this.data.hierarchy[ h ].keys;
  16046. key = key >= 0 ? key : key + keys.length;
  16047. for ( ; key >= 0; key-- ) {
  16048. if ( keys[ key ].hasTarget( sid ) ) {
  16049. return keys[ key ];
  16050. }
  16051. }
  16052. return keys[ keys.length - 1 ];
  16053. };
  16054. /**
  16055. * Camera for rendering cube maps
  16056. * - renders scene into axis-aligned cube
  16057. *
  16058. * @author alteredq / http://alteredqualia.com/
  16059. */
  16060. THREE.CubeCamera = function ( near, far, cubeResolution ) {
  16061. THREE.Object3D.call( this );
  16062. var fov = 90, aspect = 1;
  16063. var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16064. cameraPX.up.set( 0, -1, 0 );
  16065. cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
  16066. this.add( cameraPX );
  16067. var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16068. cameraNX.up.set( 0, -1, 0 );
  16069. cameraNX.lookAt( new THREE.Vector3( -1, 0, 0 ) );
  16070. this.add( cameraNX );
  16071. var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16072. cameraPY.up.set( 0, 0, 1 );
  16073. cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
  16074. this.add( cameraPY );
  16075. var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16076. cameraNY.up.set( 0, 0, -1 );
  16077. cameraNY.lookAt( new THREE.Vector3( 0, -1, 0 ) );
  16078. this.add( cameraNY );
  16079. var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16080. cameraPZ.up.set( 0, -1, 0 );
  16081. cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
  16082. this.add( cameraPZ );
  16083. var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
  16084. cameraNZ.up.set( 0, -1, 0 );
  16085. cameraNZ.lookAt( new THREE.Vector3( 0, 0, -1 ) );
  16086. this.add( cameraNZ );
  16087. this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
  16088. this.updateCubeMap = function ( renderer, scene ) {
  16089. var renderTarget = this.renderTarget;
  16090. var generateMipmaps = renderTarget.generateMipmaps;
  16091. renderTarget.generateMipmaps = false;
  16092. renderTarget.activeCubeFace = 0;
  16093. renderer.render( scene, cameraPX, renderTarget );
  16094. renderTarget.activeCubeFace = 1;
  16095. renderer.render( scene, cameraNX, renderTarget );
  16096. renderTarget.activeCubeFace = 2;
  16097. renderer.render( scene, cameraPY, renderTarget );
  16098. renderTarget.activeCubeFace = 3;
  16099. renderer.render( scene, cameraNY, renderTarget );
  16100. renderTarget.activeCubeFace = 4;
  16101. renderer.render( scene, cameraPZ, renderTarget );
  16102. renderTarget.generateMipmaps = generateMipmaps;
  16103. renderTarget.activeCubeFace = 5;
  16104. renderer.render( scene, cameraNZ, renderTarget );
  16105. };
  16106. };
  16107. THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
  16108. /*
  16109. * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
  16110. *
  16111. * A general perpose camera, for setting FOV, Lens Focal Length,
  16112. * and switching between perspective and orthographic views easily.
  16113. * Use this only if you do not wish to manage
  16114. * both a Orthographic and Perspective Camera
  16115. *
  16116. */
  16117. THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
  16118. THREE.Camera.call( this );
  16119. this.fov = fov;
  16120. this.left = -width / 2;
  16121. this.right = width / 2
  16122. this.top = height / 2;
  16123. this.bottom = -height / 2;
  16124. // We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
  16125. this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, orthoNear, orthoFar );
  16126. this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
  16127. this.zoom = 1;
  16128. this.toPerspective();
  16129. var aspect = width/height;
  16130. };
  16131. THREE.CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
  16132. THREE.CombinedCamera.prototype.toPerspective = function () {
  16133. // Switches to the Perspective Camera
  16134. this.near = this.cameraP.near;
  16135. this.far = this.cameraP.far;
  16136. this.cameraP.fov = this.fov / this.zoom ;
  16137. this.cameraP.updateProjectionMatrix();
  16138. this.projectionMatrix = this.cameraP.projectionMatrix;
  16139. this.inPerspectiveMode = true;
  16140. this.inOrthographicMode = false;
  16141. };
  16142. THREE.CombinedCamera.prototype.toOrthographic = function () {
  16143. // Switches to the Orthographic camera estimating viewport from Perspective
  16144. var fov = this.fov;
  16145. var aspect = this.cameraP.aspect;
  16146. var near = this.cameraP.near;
  16147. var far = this.cameraP.far;
  16148. // The size that we set is the mid plane of the viewing frustum
  16149. var hyperfocus = ( near + far ) / 2;
  16150. var halfHeight = Math.tan( fov / 2 ) * hyperfocus;
  16151. var planeHeight = 2 * halfHeight;
  16152. var planeWidth = planeHeight * aspect;
  16153. var halfWidth = planeWidth / 2;
  16154. halfHeight /= this.zoom;
  16155. halfWidth /= this.zoom;
  16156. this.cameraO.left = -halfWidth;
  16157. this.cameraO.right = halfWidth;
  16158. this.cameraO.top = halfHeight;
  16159. this.cameraO.bottom = -halfHeight;
  16160. // this.cameraO.left = -farHalfWidth;
  16161. // this.cameraO.right = farHalfWidth;
  16162. // this.cameraO.top = farHalfHeight;
  16163. // this.cameraO.bottom = -farHalfHeight;
  16164. // this.cameraO.left = this.left / this.zoom;
  16165. // this.cameraO.right = this.right / this.zoom;
  16166. // this.cameraO.top = this.top / this.zoom;
  16167. // this.cameraO.bottom = this.bottom / this.zoom;
  16168. this.cameraO.updateProjectionMatrix();
  16169. this.near = this.cameraO.near;
  16170. this.far = this.cameraO.far;
  16171. this.projectionMatrix = this.cameraO.projectionMatrix;
  16172. this.inPerspectiveMode = false;
  16173. this.inOrthographicMode = true;
  16174. };
  16175. THREE.CombinedCamera.prototype.setSize = function( width, height ) {
  16176. this.cameraP.aspect = width / height;
  16177. this.left = -width / 2;
  16178. this.right = width / 2
  16179. this.top = height / 2;
  16180. this.bottom = -height / 2;
  16181. };
  16182. THREE.CombinedCamera.prototype.setFov = function( fov ) {
  16183. this.fov = fov;
  16184. if ( this.inPerspectiveMode ) {
  16185. this.toPerspective();
  16186. } else {
  16187. this.toOrthographic();
  16188. }
  16189. };
  16190. // For mantaining similar API with PerspectiveCamera
  16191. THREE.CombinedCamera.prototype.updateProjectionMatrix = function() {
  16192. if ( this.inPerspectiveMode ) {
  16193. this.toPerspective();
  16194. } else {
  16195. this.toPerspective();
  16196. this.toOrthographic();
  16197. }
  16198. };
  16199. /*
  16200. * Uses Focal Length (in mm) to estimate and set FOV
  16201. * 35mm (fullframe) camera is used if frame size is not specified;
  16202. * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
  16203. */
  16204. THREE.CombinedCamera.prototype.setLens = function ( focalLength, frameHeight ) {
  16205. frameHeight = frameHeight !== undefined ? frameHeight : 24;
  16206. var fov = 2 * Math.atan( frameHeight / ( focalLength * 2 ) ) * ( 180 / Math.PI );
  16207. this.setFov( fov );
  16208. return fov;
  16209. };
  16210. THREE.CombinedCamera.prototype.setZoom = function( zoom ) {
  16211. this.zoom = zoom;
  16212. if ( this.inPerspectiveMode ) {
  16213. this.toPerspective();
  16214. } else {
  16215. this.toOrthographic();
  16216. }
  16217. };
  16218. THREE.CombinedCamera.prototype.toFrontView = function() {
  16219. this.rotation.x = 0;
  16220. this.rotation.y = 0;
  16221. this.rotation.z = 0;
  16222. // should we be modifing the matrix instead?
  16223. this.rotationAutoUpdate = false;
  16224. };
  16225. THREE.CombinedCamera.prototype.toBackView = function() {
  16226. this.rotation.x = 0;
  16227. this.rotation.y = Math.PI;
  16228. this.rotation.z = 0;
  16229. this.rotationAutoUpdate = false;
  16230. };
  16231. THREE.CombinedCamera.prototype.toLeftView = function() {
  16232. this.rotation.x = 0;
  16233. this.rotation.y = - Math.PI / 2;
  16234. this.rotation.z = 0;
  16235. this.rotationAutoUpdate = false;
  16236. };
  16237. THREE.CombinedCamera.prototype.toRightView = function() {
  16238. this.rotation.x = 0;
  16239. this.rotation.y = Math.PI / 2;
  16240. this.rotation.z = 0;
  16241. this.rotationAutoUpdate = false;
  16242. };
  16243. THREE.CombinedCamera.prototype.toTopView = function() {
  16244. this.rotation.x = - Math.PI / 2;
  16245. this.rotation.y = 0;
  16246. this.rotation.z = 0;
  16247. this.rotationAutoUpdate = false;
  16248. };
  16249. THREE.CombinedCamera.prototype.toBottomView = function() {
  16250. this.rotation.x = Math.PI / 2;
  16251. this.rotation.y = 0;
  16252. this.rotation.z = 0;
  16253. this.rotationAutoUpdate = false;
  16254. };
  16255. /**
  16256. * @author mrdoob / http://mrdoob.com/
  16257. * @author alteredq / http://alteredqualia.com/
  16258. * @author paulirish / http://paulirish.com/
  16259. */
  16260. THREE.FirstPersonControls = function ( object, domElement ) {
  16261. this.object = object;
  16262. this.target = new THREE.Vector3( 0, 0, 0 );
  16263. this.domElement = ( domElement !== undefined ) ? domElement : document;
  16264. this.movementSpeed = 1.0;
  16265. this.lookSpeed = 0.005;
  16266. this.lookVertical = true;
  16267. this.autoForward = false;
  16268. // this.invertVertical = false;
  16269. this.activeLook = true;
  16270. this.heightSpeed = false;
  16271. this.heightCoef = 1.0;
  16272. this.heightMin = 0.0;
  16273. this.heightMax = 1.0;
  16274. this.constrainVertical = false;
  16275. this.verticalMin = 0;
  16276. this.verticalMax = Math.PI;
  16277. this.autoSpeedFactor = 0.0;
  16278. this.mouseX = 0;
  16279. this.mouseY = 0;
  16280. this.lat = 0;
  16281. this.lon = 0;
  16282. this.phi = 0;
  16283. this.theta = 0;
  16284. this.moveForward = false;
  16285. this.moveBackward = false;
  16286. this.moveLeft = false;
  16287. this.moveRight = false;
  16288. this.freeze = false;
  16289. this.mouseDragOn = false;
  16290. this.viewHalfX = 0;
  16291. this.viewHalfY = 0;
  16292. if ( this.domElement !== document ) {
  16293. this.domElement.setAttribute( 'tabindex', -1 );
  16294. }
  16295. //
  16296. this.handleResize = function () {
  16297. if ( this.domElement === document ) {
  16298. this.viewHalfX = window.innerWidth / 2;
  16299. this.viewHalfY = window.innerHeight / 2;
  16300. } else {
  16301. this.viewHalfX = this.domElement.offsetWidth / 2;
  16302. this.viewHalfY = this.domElement.offsetHeight / 2;
  16303. }
  16304. };
  16305. this.onMouseDown = function ( event ) {
  16306. if ( this.domElement !== document ) {
  16307. this.domElement.focus();
  16308. }
  16309. event.preventDefault();
  16310. event.stopPropagation();
  16311. if ( this.activeLook ) {
  16312. switch ( event.button ) {
  16313. case 0: this.moveForward = true; break;
  16314. case 2: this.moveBackward = true; break;
  16315. }
  16316. }
  16317. this.mouseDragOn = true;
  16318. };
  16319. this.onMouseUp = function ( event ) {
  16320. event.preventDefault();
  16321. event.stopPropagation();
  16322. if ( this.activeLook ) {
  16323. switch ( event.button ) {
  16324. case 0: this.moveForward = false; break;
  16325. case 2: this.moveBackward = false; break;
  16326. }
  16327. }
  16328. this.mouseDragOn = false;
  16329. };
  16330. this.onMouseMove = function ( event ) {
  16331. if ( this.domElement === document ) {
  16332. this.mouseX = event.pageX - this.viewHalfX;
  16333. this.mouseY = event.pageY - this.viewHalfY;
  16334. } else {
  16335. this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
  16336. this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
  16337. }
  16338. };
  16339. this.onKeyDown = function ( event ) {
  16340. //event.preventDefault();
  16341. switch ( event.keyCode ) {
  16342. case 38: /*up*/
  16343. case 87: /*W*/ this.moveForward = true; break;
  16344. case 37: /*left*/
  16345. case 65: /*A*/ this.moveLeft = true; break;
  16346. case 40: /*down*/
  16347. case 83: /*S*/ this.moveBackward = true; break;
  16348. case 39: /*right*/
  16349. case 68: /*D*/ this.moveRight = true; break;
  16350. case 82: /*R*/ this.moveUp = true; break;
  16351. case 70: /*F*/ this.moveDown = true; break;
  16352. case 81: /*Q*/ this.freeze = !this.freeze; break;
  16353. }
  16354. };
  16355. this.onKeyUp = function ( event ) {
  16356. switch( event.keyCode ) {
  16357. case 38: /*up*/
  16358. case 87: /*W*/ this.moveForward = false; break;
  16359. case 37: /*left*/
  16360. case 65: /*A*/ this.moveLeft = false; break;
  16361. case 40: /*down*/
  16362. case 83: /*S*/ this.moveBackward = false; break;
  16363. case 39: /*right*/
  16364. case 68: /*D*/ this.moveRight = false; break;
  16365. case 82: /*R*/ this.moveUp = false; break;
  16366. case 70: /*F*/ this.moveDown = false; break;
  16367. }
  16368. };
  16369. this.update = function( delta ) {
  16370. var actualMoveSpeed = 0;
  16371. if ( this.freeze ) {
  16372. return;
  16373. } else {
  16374. if ( this.heightSpeed ) {
  16375. var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
  16376. var heightDelta = y - this.heightMin;
  16377. this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
  16378. } else {
  16379. this.autoSpeedFactor = 0.0;
  16380. }
  16381. actualMoveSpeed = delta * this.movementSpeed;
  16382. if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
  16383. if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
  16384. if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
  16385. if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
  16386. if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
  16387. if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
  16388. var actualLookSpeed = delta * this.lookSpeed;
  16389. if ( !this.activeLook ) {
  16390. actualLookSpeed = 0;
  16391. }
  16392. this.lon += this.mouseX * actualLookSpeed;
  16393. if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; // * this.invertVertical?-1:1;
  16394. this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
  16395. this.phi = ( 90 - this.lat ) * Math.PI / 180;
  16396. this.theta = this.lon * Math.PI / 180;
  16397. var targetPosition = this.target,
  16398. position = this.object.position;
  16399. targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
  16400. targetPosition.y = position.y + 100 * Math.cos( this.phi );
  16401. targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
  16402. }
  16403. var verticalLookRatio = 1;
  16404. if ( this.constrainVertical ) {
  16405. verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
  16406. }
  16407. this.lon += this.mouseX * actualLookSpeed;
  16408. if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
  16409. this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
  16410. this.phi = ( 90 - this.lat ) * Math.PI / 180;
  16411. this.theta = this.lon * Math.PI / 180;
  16412. if ( this.constrainVertical ) {
  16413. this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
  16414. }
  16415. var targetPosition = this.target,
  16416. position = this.object.position;
  16417. targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
  16418. targetPosition.y = position.y + 100 * Math.cos( this.phi );
  16419. targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
  16420. this.object.lookAt( targetPosition );
  16421. };
  16422. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  16423. this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
  16424. this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false );
  16425. this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false );
  16426. this.domElement.addEventListener( 'keydown', bind( this, this.onKeyDown ), false );
  16427. this.domElement.addEventListener( 'keyup', bind( this, this.onKeyUp ), false );
  16428. function bind( scope, fn ) {
  16429. return function () {
  16430. fn.apply( scope, arguments );
  16431. };
  16432. };
  16433. this.handleResize();
  16434. };
  16435. /**
  16436. * @author alteredq / http://alteredqualia.com/
  16437. */
  16438. THREE.PathControls = function ( object, domElement ) {
  16439. this.object = object;
  16440. this.domElement = ( domElement !== undefined ) ? domElement : document;
  16441. this.id = "PathControls" + THREE.PathControlsIdCounter ++;
  16442. // API
  16443. this.duration = 10 * 1000; // milliseconds
  16444. this.waypoints = [];
  16445. this.useConstantSpeed = true;
  16446. this.resamplingCoef = 50;
  16447. this.debugPath = new THREE.Object3D();
  16448. this.debugDummy = new THREE.Object3D();
  16449. this.animationParent = new THREE.Object3D();
  16450. this.lookSpeed = 0.005;
  16451. this.lookVertical = true;
  16452. this.lookHorizontal = true;
  16453. this.verticalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };
  16454. this.horizontalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };
  16455. // internals
  16456. this.target = new THREE.Object3D();
  16457. this.mouseX = 0;
  16458. this.mouseY = 0;
  16459. this.lat = 0;
  16460. this.lon = 0;
  16461. this.phi = 0;
  16462. this.theta = 0;
  16463. var PI2 = Math.PI * 2,
  16464. PI180 = Math.PI / 180;
  16465. this.viewHalfX = 0;
  16466. this.viewHalfY = 0;
  16467. if ( this.domElement !== document ) {
  16468. this.domElement.setAttribute( 'tabindex', -1 );
  16469. }
  16470. // methods
  16471. this.handleResize = function () {
  16472. if ( this.domElement === document ) {
  16473. this.viewHalfX = window.innerWidth / 2;
  16474. this.viewHalfY = window.innerHeight / 2;
  16475. } else {
  16476. this.viewHalfX = this.domElement.offsetWidth / 2;
  16477. this.viewHalfY = this.domElement.offsetHeight / 2;
  16478. }
  16479. };
  16480. this.update = function ( delta ) {
  16481. var srcRange, dstRange;
  16482. if( this.lookHorizontal ) this.lon += this.mouseX * this.lookSpeed * delta;
  16483. if( this.lookVertical ) this.lat -= this.mouseY * this.lookSpeed * delta;
  16484. this.lon = Math.max( 0, Math.min( 360, this.lon ) );
  16485. this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
  16486. this.phi = ( 90 - this.lat ) * PI180;
  16487. this.theta = this.lon * PI180;
  16488. this.phi = normalize_angle_rad( this.phi );
  16489. // constrain vertical look angle
  16490. srcRange = this.verticalAngleMap.srcRange;
  16491. dstRange = this.verticalAngleMap.dstRange;
  16492. var tmpPhi = THREE.Math.mapLinear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
  16493. var tmpPhiFullRange = dstRange[ 1 ] - dstRange[ 0 ];
  16494. var tmpPhiNormalized = ( tmpPhi - dstRange[ 0 ] ) / tmpPhiFullRange;
  16495. this.phi = QuadraticEaseInOut( tmpPhiNormalized ) * tmpPhiFullRange + dstRange[ 0 ];
  16496. // constrain horizontal look angle
  16497. srcRange = this.horizontalAngleMap.srcRange;
  16498. dstRange = this.horizontalAngleMap.dstRange;
  16499. var tmpTheta = THREE.Math.mapLinear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
  16500. var tmpThetaFullRange = dstRange[ 1 ] - dstRange[ 0 ];
  16501. var tmpThetaNormalized = ( tmpTheta - dstRange[ 0 ] ) / tmpThetaFullRange;
  16502. this.theta = QuadraticEaseInOut( tmpThetaNormalized ) * tmpThetaFullRange + dstRange[ 0 ];
  16503. var targetPosition = this.target.position,
  16504. position = this.object.position;
  16505. targetPosition.x = 100 * Math.sin( this.phi ) * Math.cos( this.theta );
  16506. targetPosition.y = 100 * Math.cos( this.phi );
  16507. targetPosition.z = 100 * Math.sin( this.phi ) * Math.sin( this.theta );
  16508. this.object.lookAt( this.target.position );
  16509. };
  16510. this.onMouseMove = function ( event ) {
  16511. if ( this.domElement === document ) {
  16512. this.mouseX = event.pageX - this.viewHalfX;
  16513. this.mouseY = event.pageY - this.viewHalfY;
  16514. } else {
  16515. this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
  16516. this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
  16517. }
  16518. };
  16519. // utils
  16520. function normalize_angle_rad( a ) {
  16521. var b = a % PI2;
  16522. return b >= 0 ? b : b + PI2;
  16523. };
  16524. function distance( a, b ) {
  16525. var dx = a[ 0 ] - b[ 0 ],
  16526. dy = a[ 1 ] - b[ 1 ],
  16527. dz = a[ 2 ] - b[ 2 ];
  16528. return Math.sqrt( dx * dx + dy * dy + dz * dz );
  16529. };
  16530. function QuadraticEaseInOut ( k ) {
  16531. if ( ( k *= 2 ) < 1 ) return 0.5 * k * k;
  16532. return - 0.5 * ( --k * ( k - 2 ) - 1 );
  16533. };
  16534. function bind( scope, fn ) {
  16535. return function () {
  16536. fn.apply( scope, arguments );
  16537. };
  16538. };
  16539. function initAnimationPath( parent, spline, name, duration ) {
  16540. var animationData = {
  16541. name: name,
  16542. fps: 0.6,
  16543. length: duration,
  16544. hierarchy: []
  16545. };
  16546. var i,
  16547. parentAnimation, childAnimation,
  16548. path = spline.getControlPointsArray(),
  16549. sl = spline.getLength(),
  16550. pl = path.length,
  16551. t = 0,
  16552. first = 0,
  16553. last = pl - 1;
  16554. parentAnimation = { parent: -1, keys: [] };
  16555. parentAnimation.keys[ first ] = { time: 0, pos: path[ first ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };
  16556. parentAnimation.keys[ last ] = { time: duration, pos: path[ last ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };
  16557. for ( i = 1; i < pl - 1; i++ ) {
  16558. // real distance (approximation via linear segments)
  16559. t = duration * sl.chunks[ i ] / sl.total;
  16560. // equal distance
  16561. //t = duration * ( i / pl );
  16562. // linear distance
  16563. //t += duration * distance( path[ i ], path[ i - 1 ] ) / sl.total;
  16564. parentAnimation.keys[ i ] = { time: t, pos: path[ i ] };
  16565. }
  16566. animationData.hierarchy[ 0 ] = parentAnimation;
  16567. THREE.AnimationHandler.add( animationData );
  16568. return new THREE.Animation( parent, name, THREE.AnimationHandler.CATMULLROM_FORWARD, false );
  16569. };
  16570. function createSplineGeometry( spline, n_sub ) {
  16571. var i, index, position,
  16572. geometry = new THREE.Geometry();
  16573. for ( i = 0; i < spline.points.length * n_sub; i ++ ) {
  16574. index = i / ( spline.points.length * n_sub );
  16575. position = spline.getPoint( index );
  16576. geometry.vertices[ i ] = new THREE.Vector3( position.x, position.y, position.z );
  16577. }
  16578. return geometry;
  16579. };
  16580. function createPath( parent, spline ) {
  16581. var lineGeo = createSplineGeometry( spline, 10 ),
  16582. particleGeo = createSplineGeometry( spline, 10 ),
  16583. lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ),
  16584. lineObj = new THREE.Line( lineGeo, lineMat ),
  16585. particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleBasicMaterial( { color: 0xffaa00, size: 3 } ) );
  16586. lineObj.scale.set( 1, 1, 1 );
  16587. parent.add( lineObj );
  16588. particleObj.scale.set( 1, 1, 1 );
  16589. parent.add( particleObj );
  16590. var waypoint,
  16591. geo = new THREE.SphereGeometry( 1, 16, 8 ),
  16592. mat = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
  16593. for ( var i = 0; i < spline.points.length; i ++ ) {
  16594. waypoint = new THREE.Mesh( geo, mat );
  16595. waypoint.position.copy( spline.points[ i ] );
  16596. parent.add( waypoint );
  16597. }
  16598. };
  16599. this.init = function ( ) {
  16600. // constructor
  16601. this.spline = new THREE.Spline();
  16602. this.spline.initFromArray( this.waypoints );
  16603. if ( this.useConstantSpeed ) {
  16604. this.spline.reparametrizeByArcLength( this.resamplingCoef );
  16605. }
  16606. if ( this.createDebugDummy ) {
  16607. var dummyParentMaterial = new THREE.MeshLambertMaterial( { color: 0x0077ff } ),
  16608. dummyChildMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00 } ),
  16609. dummyParentGeo = new THREE.CubeGeometry( 10, 10, 20 ),
  16610. dummyChildGeo = new THREE.CubeGeometry( 2, 2, 10 );
  16611. this.animationParent = new THREE.Mesh( dummyParentGeo, dummyParentMaterial );
  16612. var dummyChild = new THREE.Mesh( dummyChildGeo, dummyChildMaterial );
  16613. dummyChild.position.set( 0, 10, 0 );
  16614. this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );
  16615. this.animationParent.add( this.object );
  16616. this.animationParent.add( this.target );
  16617. this.animationParent.add( dummyChild );
  16618. } else {
  16619. this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );
  16620. this.animationParent.add( this.target );
  16621. this.animationParent.add( this.object );
  16622. }
  16623. if ( this.createDebugPath ) {
  16624. createPath( this.debugPath, this.spline );
  16625. }
  16626. this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
  16627. };
  16628. this.handleResize();
  16629. };
  16630. THREE.PathControlsIdCounter = 0;
  16631. /**
  16632. * @author James Baicoianu / http://www.baicoianu.com/
  16633. */
  16634. THREE.FlyControls = function ( object, domElement ) {
  16635. this.object = object;
  16636. this.domElement = ( domElement !== undefined ) ? domElement : document;
  16637. if ( domElement ) this.domElement.setAttribute( 'tabindex', -1 );
  16638. // API
  16639. this.movementSpeed = 1.0;
  16640. this.rollSpeed = 0.005;
  16641. this.dragToLook = false;
  16642. this.autoForward = false;
  16643. // disable default target object behavior
  16644. this.object.useQuaternion = true;
  16645. // internals
  16646. this.tmpQuaternion = new THREE.Quaternion();
  16647. this.mouseStatus = 0;
  16648. this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 };
  16649. this.moveVector = new THREE.Vector3( 0, 0, 0 );
  16650. this.rotationVector = new THREE.Vector3( 0, 0, 0 );
  16651. this.handleEvent = function ( event ) {
  16652. if ( typeof this[ event.type ] == 'function' ) {
  16653. this[ event.type ]( event );
  16654. }
  16655. };
  16656. this.keydown = function( event ) {
  16657. if ( event.altKey ) {
  16658. return;
  16659. }
  16660. //event.preventDefault();
  16661. switch ( event.keyCode ) {
  16662. case 16: /* shift */ this.movementSpeedMultiplier = .1; break;
  16663. case 87: /*W*/ this.moveState.forward = 1; break;
  16664. case 83: /*S*/ this.moveState.back = 1; break;
  16665. case 65: /*A*/ this.moveState.left = 1; break;
  16666. case 68: /*D*/ this.moveState.right = 1; break;
  16667. case 82: /*R*/ this.moveState.up = 1; break;
  16668. case 70: /*F*/ this.moveState.down = 1; break;
  16669. case 38: /*up*/ this.moveState.pitchUp = 1; break;
  16670. case 40: /*down*/ this.moveState.pitchDown = 1; break;
  16671. case 37: /*left*/ this.moveState.yawLeft = 1; break;
  16672. case 39: /*right*/ this.moveState.yawRight = 1; break;
  16673. case 81: /*Q*/ this.moveState.rollLeft = 1; break;
  16674. case 69: /*E*/ this.moveState.rollRight = 1; break;
  16675. }
  16676. this.updateMovementVector();
  16677. this.updateRotationVector();
  16678. };
  16679. this.keyup = function( event ) {
  16680. switch( event.keyCode ) {
  16681. case 16: /* shift */ this.movementSpeedMultiplier = 1; break;
  16682. case 87: /*W*/ this.moveState.forward = 0; break;
  16683. case 83: /*S*/ this.moveState.back = 0; break;
  16684. case 65: /*A*/ this.moveState.left = 0; break;
  16685. case 68: /*D*/ this.moveState.right = 0; break;
  16686. case 82: /*R*/ this.moveState.up = 0; break;
  16687. case 70: /*F*/ this.moveState.down = 0; break;
  16688. case 38: /*up*/ this.moveState.pitchUp = 0; break;
  16689. case 40: /*down*/ this.moveState.pitchDown = 0; break;
  16690. case 37: /*left*/ this.moveState.yawLeft = 0; break;
  16691. case 39: /*right*/ this.moveState.yawRight = 0; break;
  16692. case 81: /*Q*/ this.moveState.rollLeft = 0; break;
  16693. case 69: /*E*/ this.moveState.rollRight = 0; break;
  16694. }
  16695. this.updateMovementVector();
  16696. this.updateRotationVector();
  16697. };
  16698. this.mousedown = function( event ) {
  16699. if ( this.domElement !== document ) {
  16700. this.domElement.focus();
  16701. }
  16702. event.preventDefault();
  16703. event.stopPropagation();
  16704. if ( this.dragToLook ) {
  16705. this.mouseStatus ++;
  16706. } else {
  16707. switch ( event.button ) {
  16708. case 0: this.object.moveForward = true; break;
  16709. case 2: this.object.moveBackward = true; break;
  16710. }
  16711. }
  16712. };
  16713. this.mousemove = function( event ) {
  16714. if ( !this.dragToLook || this.mouseStatus > 0 ) {
  16715. var container = this.getContainerDimensions();
  16716. var halfWidth = container.size[ 0 ] / 2;
  16717. var halfHeight = container.size[ 1 ] / 2;
  16718. this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth;
  16719. this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight;
  16720. this.updateRotationVector();
  16721. }
  16722. };
  16723. this.mouseup = function( event ) {
  16724. event.preventDefault();
  16725. event.stopPropagation();
  16726. if ( this.dragToLook ) {
  16727. this.mouseStatus --;
  16728. this.moveState.yawLeft = this.moveState.pitchDown = 0;
  16729. } else {
  16730. switch ( event.button ) {
  16731. case 0: this.moveForward = false; break;
  16732. case 2: this.moveBackward = false; break;
  16733. }
  16734. }
  16735. this.updateRotationVector();
  16736. };
  16737. this.update = function( delta ) {
  16738. var moveMult = delta * this.movementSpeed;
  16739. var rotMult = delta * this.rollSpeed;
  16740. this.object.translateX( this.moveVector.x * moveMult );
  16741. this.object.translateY( this.moveVector.y * moveMult );
  16742. this.object.translateZ( this.moveVector.z * moveMult );
  16743. this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();
  16744. this.object.quaternion.multiplySelf( this.tmpQuaternion );
  16745. this.object.matrix.setPosition( this.object.position );
  16746. this.object.matrix.setRotationFromQuaternion( this.object.quaternion );
  16747. this.object.matrixWorldNeedsUpdate = true;
  16748. };
  16749. this.updateMovementVector = function() {
  16750. var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0;
  16751. this.moveVector.x = ( -this.moveState.left + this.moveState.right );
  16752. this.moveVector.y = ( -this.moveState.down + this.moveState.up );
  16753. this.moveVector.z = ( -forward + this.moveState.back );
  16754. //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
  16755. };
  16756. this.updateRotationVector = function() {
  16757. this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp );
  16758. this.rotationVector.y = ( -this.moveState.yawRight + this.moveState.yawLeft );
  16759. this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft );
  16760. //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
  16761. };
  16762. this.getContainerDimensions = function() {
  16763. if ( this.domElement != document ) {
  16764. return {
  16765. size : [ this.domElement.offsetWidth, this.domElement.offsetHeight ],
  16766. offset : [ this.domElement.offsetLeft, this.domElement.offsetTop ]
  16767. };
  16768. } else {
  16769. return {
  16770. size : [ window.innerWidth, window.innerHeight ],
  16771. offset : [ 0, 0 ]
  16772. };
  16773. }
  16774. };
  16775. function bind( scope, fn ) {
  16776. return function () {
  16777. fn.apply( scope, arguments );
  16778. };
  16779. };
  16780. this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
  16781. this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
  16782. this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false );
  16783. this.domElement.addEventListener( 'keydown', bind( this, this.keydown ), false );
  16784. this.domElement.addEventListener( 'keyup', bind( this, this.keyup ), false );
  16785. this.updateMovementVector();
  16786. this.updateRotationVector();
  16787. };
  16788. /**
  16789. * @author mikael emtinger / http://gomo.se/
  16790. * @author alteredq / http://alteredqualia.com/
  16791. */
  16792. THREE.RollControls = function ( object, domElement ) {
  16793. this.object = object;
  16794. this.domElement = ( domElement !== undefined ) ? domElement : document;
  16795. // API
  16796. this.mouseLook = true;
  16797. this.autoForward = false;
  16798. this.lookSpeed = 1;
  16799. this.movementSpeed = 1;
  16800. this.rollSpeed = 1;
  16801. this.constrainVertical = [ -0.9, 0.9 ];
  16802. // disable default target object behavior
  16803. this.object.matrixAutoUpdate = false;
  16804. // internals
  16805. this.forward = new THREE.Vector3( 0, 0, 1 );
  16806. this.roll = 0;
  16807. var xTemp = new THREE.Vector3();
  16808. var yTemp = new THREE.Vector3();
  16809. var zTemp = new THREE.Vector3();
  16810. var rollMatrix = new THREE.Matrix4();
  16811. var doRoll = false, rollDirection = 1, forwardSpeed = 0, sideSpeed = 0, upSpeed = 0;
  16812. var mouseX = 0, mouseY = 0;
  16813. var windowHalfX = 0;
  16814. var windowHalfY = 0;
  16815. //
  16816. this.handleResize = function () {
  16817. windowHalfX = window.innerWidth / 2;
  16818. windowHalfY = window.innerHeight / 2;
  16819. };
  16820. // custom update
  16821. this.update = function ( delta ) {
  16822. if ( this.mouseLook ) {
  16823. var actualLookSpeed = delta * this.lookSpeed;
  16824. this.rotateHorizontally( actualLookSpeed * mouseX );
  16825. this.rotateVertically( actualLookSpeed * mouseY );
  16826. }
  16827. var actualSpeed = delta * this.movementSpeed;
  16828. var forwardOrAuto = ( forwardSpeed > 0 || ( this.autoForward && ! ( forwardSpeed < 0 ) ) ) ? 1 : forwardSpeed;
  16829. this.object.translateZ( -actualSpeed * forwardOrAuto );
  16830. this.object.translateX( actualSpeed * sideSpeed );
  16831. this.object.translateY( actualSpeed * upSpeed );
  16832. if( doRoll ) {
  16833. this.roll += this.rollSpeed * delta * rollDirection;
  16834. }
  16835. // cap forward up / down
  16836. if( this.forward.y > this.constrainVertical[ 1 ] ) {
  16837. this.forward.y = this.constrainVertical[ 1 ];
  16838. this.forward.normalize();
  16839. } else if( this.forward.y < this.constrainVertical[ 0 ] ) {
  16840. this.forward.y = this.constrainVertical[ 0 ];
  16841. this.forward.normalize();
  16842. }
  16843. // construct unrolled camera matrix
  16844. zTemp.copy( this.forward );
  16845. yTemp.set( 0, 1, 0 );
  16846. xTemp.cross( yTemp, zTemp ).normalize();
  16847. yTemp.cross( zTemp, xTemp ).normalize();
  16848. this.object.matrix.elements[0] = xTemp.x; this.object.matrix.elements[4] = yTemp.x; this.object.matrix.elements[8] = zTemp.x;
  16849. this.object.matrix.elements[1] = xTemp.y; this.object.matrix.elements[5] = yTemp.y; this.object.matrix.elements[9] = zTemp.y;
  16850. this.object.matrix.elements[2] = xTemp.z; this.object.matrix.elements[6] = yTemp.z; this.object.matrix.elements[10] = zTemp.z;
  16851. // calculate roll matrix
  16852. rollMatrix.identity();
  16853. rollMatrix.elements[0] = Math.cos( this.roll ); rollMatrix.elements[4] = -Math.sin( this.roll );
  16854. rollMatrix.elements[1] = Math.sin( this.roll ); rollMatrix.elements[5] = Math.cos( this.roll );
  16855. // multiply camera with roll
  16856. this.object.matrix.multiplySelf( rollMatrix );
  16857. this.object.matrixWorldNeedsUpdate = true;
  16858. // set position
  16859. this.object.matrix.elements[12] = this.object.position.x;
  16860. this.object.matrix.elements[13] = this.object.position.y;
  16861. this.object.matrix.elements[14] = this.object.position.z;
  16862. };
  16863. this.translateX = function ( distance ) {
  16864. this.object.position.x += this.object.matrix.elements[0] * distance;
  16865. this.object.position.y += this.object.matrix.elements[1] * distance;
  16866. this.object.position.z += this.object.matrix.elements[2] * distance;
  16867. };
  16868. this.translateY = function ( distance ) {
  16869. this.object.position.x += this.object.matrix.elements[4] * distance;
  16870. this.object.position.y += this.object.matrix.elements[5] * distance;
  16871. this.object.position.z += this.object.matrix.elements[6] * distance;
  16872. };
  16873. this.translateZ = function ( distance ) {
  16874. this.object.position.x -= this.object.matrix.elements[8] * distance;
  16875. this.object.position.y -= this.object.matrix.elements[9] * distance;
  16876. this.object.position.z -= this.object.matrix.elements[10] * distance;
  16877. };
  16878. this.rotateHorizontally = function ( amount ) {
  16879. // please note that the amount is NOT degrees, but a scale value
  16880. xTemp.set( this.object.matrix.elements[0], this.object.matrix.elements[1], this.object.matrix.elements[2] );
  16881. xTemp.multiplyScalar( amount );
  16882. this.forward.subSelf( xTemp );
  16883. this.forward.normalize();
  16884. };
  16885. this.rotateVertically = function ( amount ) {
  16886. // please note that the amount is NOT degrees, but a scale value
  16887. yTemp.set( this.object.matrix.elements[4], this.object.matrix.elements[5], this.object.matrix.elements[6] );
  16888. yTemp.multiplyScalar( amount );
  16889. this.forward.addSelf( yTemp );
  16890. this.forward.normalize();
  16891. };
  16892. function onKeyDown( event ) {
  16893. //event.preventDefault();
  16894. switch ( event.keyCode ) {
  16895. case 38: /*up*/
  16896. case 87: /*W*/ forwardSpeed = 1; break;
  16897. case 37: /*left*/
  16898. case 65: /*A*/ sideSpeed = -1; break;
  16899. case 40: /*down*/
  16900. case 83: /*S*/ forwardSpeed = -1; break;
  16901. case 39: /*right*/
  16902. case 68: /*D*/ sideSpeed = 1; break;
  16903. case 81: /*Q*/ doRoll = true; rollDirection = 1; break;
  16904. case 69: /*E*/ doRoll = true; rollDirection = -1; break;
  16905. case 82: /*R*/ upSpeed = 1; break;
  16906. case 70: /*F*/ upSpeed = -1; break;
  16907. }
  16908. };
  16909. function onKeyUp( event ) {
  16910. switch( event.keyCode ) {
  16911. case 38: /*up*/
  16912. case 87: /*W*/ forwardSpeed = 0; break;
  16913. case 37: /*left*/
  16914. case 65: /*A*/ sideSpeed = 0; break;
  16915. case 40: /*down*/
  16916. case 83: /*S*/ forwardSpeed = 0; break;
  16917. case 39: /*right*/
  16918. case 68: /*D*/ sideSpeed = 0; break;
  16919. case 81: /*Q*/ doRoll = false; break;
  16920. case 69: /*E*/ doRoll = false; break;
  16921. case 82: /*R*/ upSpeed = 0; break;
  16922. case 70: /*F*/ upSpeed = 0; break;
  16923. }
  16924. };
  16925. function onMouseMove( event ) {
  16926. mouseX = ( event.clientX - windowHalfX ) / window.innerWidth;
  16927. mouseY = ( event.clientY - windowHalfY ) / window.innerHeight;
  16928. };
  16929. function onMouseDown ( event ) {
  16930. event.preventDefault();
  16931. event.stopPropagation();
  16932. switch ( event.button ) {
  16933. case 0: forwardSpeed = 1; break;
  16934. case 2: forwardSpeed = -1; break;
  16935. }
  16936. };
  16937. function onMouseUp ( event ) {
  16938. event.preventDefault();
  16939. event.stopPropagation();
  16940. switch ( event.button ) {
  16941. case 0: forwardSpeed = 0; break;
  16942. case 2: forwardSpeed = 0; break;
  16943. }
  16944. };
  16945. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  16946. this.domElement.addEventListener( 'mousemove', onMouseMove, false );
  16947. this.domElement.addEventListener( 'mousedown', onMouseDown, false );
  16948. this.domElement.addEventListener( 'mouseup', onMouseUp, false );
  16949. this.domElement.addEventListener( 'keydown', onKeyDown, false );
  16950. this.domElement.addEventListener( 'keyup', onKeyUp, false );
  16951. this.handleResize();
  16952. };
  16953. /**
  16954. * @author Eberhard Graether / http://egraether.com/
  16955. */
  16956. THREE.TrackballControls = function ( object, domElement ) {
  16957. THREE.EventTarget.call( this );
  16958. var _this = this,
  16959. STATE = { NONE : -1, ROTATE : 0, ZOOM : 1, PAN : 2 };
  16960. this.object = object;
  16961. this.domElement = ( domElement !== undefined ) ? domElement : document;
  16962. // API
  16963. this.enabled = true;
  16964. this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 };
  16965. this.radius = ( this.screen.width + this.screen.height ) / 4;
  16966. this.rotateSpeed = 1.0;
  16967. this.zoomSpeed = 1.2;
  16968. this.panSpeed = 0.3;
  16969. this.noRotate = false;
  16970. this.noZoom = false;
  16971. this.noPan = false;
  16972. this.staticMoving = false;
  16973. this.dynamicDampingFactor = 0.2;
  16974. this.minDistance = 0;
  16975. this.maxDistance = Infinity;
  16976. this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
  16977. // internals
  16978. this.target = new THREE.Vector3();
  16979. var lastPosition = new THREE.Vector3();
  16980. var _keyPressed = false,
  16981. _state = STATE.NONE,
  16982. _eye = new THREE.Vector3(),
  16983. _rotateStart = new THREE.Vector3(),
  16984. _rotateEnd = new THREE.Vector3(),
  16985. _zoomStart = new THREE.Vector2(),
  16986. _zoomEnd = new THREE.Vector2(),
  16987. _panStart = new THREE.Vector2(),
  16988. _panEnd = new THREE.Vector2();
  16989. // events
  16990. var changeEvent = { type: 'change' };
  16991. // methods
  16992. this.handleResize = function () {
  16993. this.screen.width = window.innerWidth;
  16994. this.screen.height = window.innerHeight;
  16995. this.screen.offsetLeft = 0;
  16996. this.screen.offsetTop = 0;
  16997. this.radius = ( this.screen.width + this.screen.height ) / 4;
  16998. };
  16999. this.handleEvent = function ( event ) {
  17000. if ( typeof this[ event.type ] == 'function' ) {
  17001. this[ event.type ]( event );
  17002. }
  17003. };
  17004. this.getMouseOnScreen = function ( clientX, clientY ) {
  17005. return new THREE.Vector2(
  17006. ( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5,
  17007. ( clientY - _this.screen.offsetTop ) / _this.radius * 0.5
  17008. );
  17009. };
  17010. this.getMouseProjectionOnBall = function ( clientX, clientY ) {
  17011. var mouseOnBall = new THREE.Vector3(
  17012. ( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius,
  17013. ( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius,
  17014. 0.0
  17015. );
  17016. var length = mouseOnBall.length();
  17017. if ( length > 1.0 ) {
  17018. mouseOnBall.normalize();
  17019. } else {
  17020. mouseOnBall.z = Math.sqrt( 1.0 - length * length );
  17021. }
  17022. _eye.copy( _this.object.position ).subSelf( _this.target );
  17023. var projection = _this.object.up.clone().setLength( mouseOnBall.y );
  17024. projection.addSelf( _this.object.up.clone().crossSelf( _eye ).setLength( mouseOnBall.x ) );
  17025. projection.addSelf( _eye.setLength( mouseOnBall.z ) );
  17026. return projection;
  17027. };
  17028. this.rotateCamera = function () {
  17029. var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
  17030. if ( angle ) {
  17031. var axis = ( new THREE.Vector3() ).cross( _rotateStart, _rotateEnd ).normalize(),
  17032. quaternion = new THREE.Quaternion();
  17033. angle *= _this.rotateSpeed;
  17034. quaternion.setFromAxisAngle( axis, -angle );
  17035. quaternion.multiplyVector3( _eye );
  17036. quaternion.multiplyVector3( _this.object.up );
  17037. quaternion.multiplyVector3( _rotateEnd );
  17038. if ( _this.staticMoving ) {
  17039. _rotateStart = _rotateEnd;
  17040. } else {
  17041. quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
  17042. quaternion.multiplyVector3( _rotateStart );
  17043. }
  17044. }
  17045. };
  17046. this.zoomCamera = function () {
  17047. var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
  17048. if ( factor !== 1.0 && factor > 0.0 ) {
  17049. _eye.multiplyScalar( factor );
  17050. if ( _this.staticMoving ) {
  17051. _zoomStart = _zoomEnd;
  17052. } else {
  17053. _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
  17054. }
  17055. }
  17056. };
  17057. this.panCamera = function () {
  17058. var mouseChange = _panEnd.clone().subSelf( _panStart );
  17059. if ( mouseChange.lengthSq() ) {
  17060. mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
  17061. var pan = _eye.clone().crossSelf( _this.object.up ).setLength( mouseChange.x );
  17062. pan.addSelf( _this.object.up.clone().setLength( mouseChange.y ) );
  17063. _this.object.position.addSelf( pan );
  17064. _this.target.addSelf( pan );
  17065. if ( _this.staticMoving ) {
  17066. _panStart = _panEnd;
  17067. } else {
  17068. _panStart.addSelf( mouseChange.sub( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
  17069. }
  17070. }
  17071. };
  17072. this.checkDistances = function () {
  17073. if ( !_this.noZoom || !_this.noPan ) {
  17074. if ( _this.object.position.lengthSq() > _this.maxDistance * _this.maxDistance ) {
  17075. _this.object.position.setLength( _this.maxDistance );
  17076. }
  17077. if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
  17078. _this.object.position.add( _this.target, _eye.setLength( _this.minDistance ) );
  17079. }
  17080. }
  17081. };
  17082. this.update = function () {
  17083. _eye.copy( _this.object.position ).subSelf( _this.target );
  17084. if ( !_this.noRotate ) {
  17085. _this.rotateCamera();
  17086. }
  17087. if ( !_this.noZoom ) {
  17088. _this.zoomCamera();
  17089. }
  17090. if ( !_this.noPan ) {
  17091. _this.panCamera();
  17092. }
  17093. _this.object.position.add( _this.target, _eye );
  17094. _this.checkDistances();
  17095. _this.object.lookAt( _this.target );
  17096. if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) {
  17097. _this.dispatchEvent( changeEvent );
  17098. lastPosition.copy( _this.object.position );
  17099. }
  17100. };
  17101. // listeners
  17102. function keydown( event ) {
  17103. if ( ! _this.enabled ) return;
  17104. //event.preventDefault();
  17105. if ( _state !== STATE.NONE ) {
  17106. return;
  17107. } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
  17108. _state = STATE.ROTATE;
  17109. } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
  17110. _state = STATE.ZOOM;
  17111. } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
  17112. _state = STATE.PAN;
  17113. }
  17114. if ( _state !== STATE.NONE ) {
  17115. _keyPressed = true;
  17116. }
  17117. }
  17118. function keyup( event ) {
  17119. if ( ! _this.enabled ) return;
  17120. if ( _state !== STATE.NONE ) {
  17121. _state = STATE.NONE;
  17122. }
  17123. }
  17124. function mousedown( event ) {
  17125. if ( ! _this.enabled ) return;
  17126. event.preventDefault();
  17127. event.stopPropagation();
  17128. if ( _state === STATE.NONE ) {
  17129. _state = event.button;
  17130. if ( _state === STATE.ROTATE && !_this.noRotate ) {
  17131. _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
  17132. } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
  17133. _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17134. } else if ( !this.noPan ) {
  17135. _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17136. }
  17137. }
  17138. }
  17139. function mousemove( event ) {
  17140. if ( ! _this.enabled ) return;
  17141. if ( _keyPressed ) {
  17142. _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
  17143. _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17144. _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17145. _keyPressed = false;
  17146. }
  17147. if ( _state === STATE.NONE ) {
  17148. return;
  17149. } else if ( _state === STATE.ROTATE && !_this.noRotate ) {
  17150. _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
  17151. } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
  17152. _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17153. } else if ( _state === STATE.PAN && !_this.noPan ) {
  17154. _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  17155. }
  17156. }
  17157. function mouseup( event ) {
  17158. if ( ! _this.enabled ) return;
  17159. event.preventDefault();
  17160. event.stopPropagation();
  17161. _state = STATE.NONE;
  17162. }
  17163. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  17164. this.domElement.addEventListener( 'mousemove', mousemove, false );
  17165. this.domElement.addEventListener( 'mousedown', mousedown, false );
  17166. this.domElement.addEventListener( 'mouseup', mouseup, false );
  17167. // this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false );
  17168. // this.domElement.addEventListener( 'mousewheel', mousewheel, false );
  17169. window.addEventListener( 'keydown', keydown, false );
  17170. window.addEventListener( 'keyup', keyup, false );
  17171. this.handleResize();
  17172. };
  17173. /**
  17174. * @author qiao / https://github.com/qiao
  17175. * @author mrdoob / http://mrdoob.com
  17176. * @author alteredq / http://alteredqualia.com/
  17177. */
  17178. THREE.OrbitControls = function ( object, domElement ) {
  17179. THREE.EventTarget.call( this );
  17180. this.object = object;
  17181. this.domElement = ( domElement !== undefined ) ? domElement : document;
  17182. // API
  17183. this.center = new THREE.Vector3();
  17184. this.userZoom = true;
  17185. this.userZoomSpeed = 1.0;
  17186. this.userRotate = true;
  17187. this.userRotateSpeed = 1.0;
  17188. this.autoRotate = false;
  17189. this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
  17190. // internals
  17191. var scope = this;
  17192. var EPS = 0.000001;
  17193. var PIXELS_PER_ROUND = 1800;
  17194. var rotateStart = new THREE.Vector2();
  17195. var rotateEnd = new THREE.Vector2();
  17196. var rotateDelta = new THREE.Vector2();
  17197. var zoomStart = new THREE.Vector2();
  17198. var zoomEnd = new THREE.Vector2();
  17199. var zoomDelta = new THREE.Vector2();
  17200. var phiDelta = 0;
  17201. var thetaDelta = 0;
  17202. var scale = 1;
  17203. var lastPosition = new THREE.Vector3();
  17204. var STATE = { NONE : -1, ROTATE : 0, ZOOM : 1 };
  17205. var state = STATE.NONE;
  17206. // events
  17207. var changeEvent = { type: 'change' };
  17208. this.rotateLeft = function ( angle ) {
  17209. if ( angle === undefined ) {
  17210. angle = getAutoRotationAngle();
  17211. }
  17212. thetaDelta -= angle;
  17213. };
  17214. this.rotateRight = function ( angle ) {
  17215. if ( angle === undefined ) {
  17216. angle = getAutoRotationAngle();
  17217. }
  17218. thetaDelta += angle;
  17219. };
  17220. this.rotateUp = function ( angle ) {
  17221. if ( angle === undefined ) {
  17222. angle = getAutoRotationAngle();
  17223. }
  17224. phiDelta -= angle;
  17225. };
  17226. this.rotateDown = function ( angle ) {
  17227. if ( angle === undefined ) {
  17228. angle = getAutoRotationAngle();
  17229. }
  17230. phiDelta += angle;
  17231. };
  17232. this.zoomIn = function ( zoomScale ) {
  17233. if ( zoomScale === undefined ) {
  17234. zoomScale = getZoomScale();
  17235. }
  17236. scale /= zoomScale;
  17237. };
  17238. this.zoomOut = function ( zoomScale ) {
  17239. if ( zoomScale === undefined ) {
  17240. zoomScale = getZoomScale();
  17241. }
  17242. scale *= zoomScale;
  17243. };
  17244. this.update = function () {
  17245. var position = this.object.position;
  17246. var offset = position.clone().subSelf( this.center )
  17247. // angle from z-axis around y-axis
  17248. var theta = Math.atan2( offset.x, offset.z );
  17249. // angle from y-axis
  17250. var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
  17251. if ( this.autoRotate ) {
  17252. this.rotateLeft( getAutoRotationAngle() );
  17253. }
  17254. theta += thetaDelta;
  17255. phi += phiDelta;
  17256. // restrict phi to be betwee EPS and PI-EPS
  17257. phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
  17258. var radius = offset.length();
  17259. offset.x = radius * Math.sin( phi ) * Math.sin( theta );
  17260. offset.y = radius * Math.cos( phi );
  17261. offset.z = radius * Math.sin( phi ) * Math.cos( theta );
  17262. offset.multiplyScalar( scale );
  17263. position.copy( this.center ).addSelf( offset );
  17264. this.object.lookAt( this.center );
  17265. thetaDelta = 0;
  17266. phiDelta = 0;
  17267. scale = 1;
  17268. if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
  17269. this.dispatchEvent( changeEvent );
  17270. lastPosition.copy( this.object.position );
  17271. }
  17272. };
  17273. function getAutoRotationAngle() {
  17274. return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
  17275. }
  17276. function getZoomScale() {
  17277. return Math.pow( 0.95, scope.userZoomSpeed );
  17278. }
  17279. function onMouseDown( event ) {
  17280. if ( !scope.userRotate ) return;
  17281. event.preventDefault();
  17282. if ( event.button === 0 || event.button === 2 ) {
  17283. state = STATE.ROTATE;
  17284. rotateStart.set( event.clientX, event.clientY );
  17285. } else if ( event.button === 1 ) {
  17286. state = STATE.ZOOM;
  17287. zoomStart.set( event.clientX, event.clientY );
  17288. }
  17289. document.addEventListener( 'mousemove', onMouseMove, false );
  17290. document.addEventListener( 'mouseup', onMouseUp, false );
  17291. }
  17292. function onMouseMove( event ) {
  17293. event.preventDefault();
  17294. if ( state === STATE.ROTATE ) {
  17295. rotateEnd.set( event.clientX, event.clientY );
  17296. rotateDelta.sub( rotateEnd, rotateStart );
  17297. scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
  17298. scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
  17299. rotateStart.copy( rotateEnd );
  17300. } else if ( state === STATE.ZOOM ) {
  17301. zoomEnd.set( event.clientX, event.clientY );
  17302. zoomDelta.sub( zoomEnd, zoomStart );
  17303. if ( zoomDelta.y > 0 ) {
  17304. scope.zoomIn();
  17305. } else {
  17306. scope.zoomOut();
  17307. }
  17308. zoomStart.copy( zoomEnd );
  17309. }
  17310. }
  17311. function onMouseUp( event ) {
  17312. if ( ! scope.userRotate ) return;
  17313. document.removeEventListener( 'mousemove', onMouseMove, false );
  17314. document.removeEventListener( 'mouseup', onMouseUp, false );
  17315. state = STATE.NONE;
  17316. }
  17317. function onMouseWheel( event ) {
  17318. if ( ! scope.userZoom ) return;
  17319. if ( event.wheelDelta > 0 ) {
  17320. scope.zoomOut();
  17321. } else {
  17322. scope.zoomIn();
  17323. }
  17324. }
  17325. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  17326. this.domElement.addEventListener( 'mousedown', onMouseDown, false );
  17327. this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
  17328. };
  17329. /**
  17330. * @author mr.doob / http://mrdoob.com/
  17331. * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as
  17332. */
  17333. THREE.CubeGeometry = function ( width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides ) {
  17334. THREE.Geometry.call( this );
  17335. var scope = this,
  17336. width_half = width / 2,
  17337. height_half = height / 2,
  17338. depth_half = depth / 2;
  17339. var mpx, mpy, mpz, mnx, mny, mnz;
  17340. if ( materials !== undefined ) {
  17341. if ( materials instanceof Array ) {
  17342. this.materials = materials;
  17343. } else {
  17344. this.materials = [];
  17345. for ( var i = 0; i < 6; i ++ ) {
  17346. this.materials.push( materials );
  17347. }
  17348. }
  17349. mpx = 0; mnx = 1; mpy = 2; mny = 3; mpz = 4; mnz = 5;
  17350. } else {
  17351. this.materials = [];
  17352. }
  17353. this.sides = { px: true, nx: true, py: true, ny: true, pz: true, nz: true };
  17354. if ( sides != undefined ) {
  17355. for ( var s in sides ) {
  17356. if ( this.sides[ s ] !== undefined ) {
  17357. this.sides[ s ] = sides[ s ];
  17358. }
  17359. }
  17360. }
  17361. this.sides.px && buildPlane( 'z', 'y', - 1, - 1, depth, height, width_half, mpx ); // px
  17362. this.sides.nx && buildPlane( 'z', 'y', 1, - 1, depth, height, - width_half, mnx ); // nx
  17363. this.sides.py && buildPlane( 'x', 'z', 1, 1, width, depth, height_half, mpy ); // py
  17364. this.sides.ny && buildPlane( 'x', 'z', 1, - 1, width, depth, - height_half, mny ); // ny
  17365. this.sides.pz && buildPlane( 'x', 'y', 1, - 1, width, height, depth_half, mpz ); // pz
  17366. this.sides.nz && buildPlane( 'x', 'y', - 1, - 1, width, height, - depth_half, mnz ); // nz
  17367. function buildPlane( u, v, udir, vdir, width, height, depth, material ) {
  17368. var w, ix, iy,
  17369. gridX = segmentsWidth || 1,
  17370. gridY = segmentsHeight || 1,
  17371. width_half = width / 2,
  17372. height_half = height / 2,
  17373. offset = scope.vertices.length;
  17374. if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {
  17375. w = 'z';
  17376. } else if ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {
  17377. w = 'y';
  17378. gridY = segmentsDepth || 1;
  17379. } else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {
  17380. w = 'x';
  17381. gridX = segmentsDepth || 1;
  17382. }
  17383. var gridX1 = gridX + 1,
  17384. gridY1 = gridY + 1,
  17385. segment_width = width / gridX,
  17386. segment_height = height / gridY,
  17387. normal = new THREE.Vector3();
  17388. normal[ w ] = depth > 0 ? 1 : - 1;
  17389. for ( iy = 0; iy < gridY1; iy ++ ) {
  17390. for ( ix = 0; ix < gridX1; ix ++ ) {
  17391. var vector = new THREE.Vector3();
  17392. vector[ u ] = ( ix * segment_width - width_half ) * udir;
  17393. vector[ v ] = ( iy * segment_height - height_half ) * vdir;
  17394. vector[ w ] = depth;
  17395. scope.vertices.push( vector );
  17396. }
  17397. }
  17398. for ( iy = 0; iy < gridY; iy++ ) {
  17399. for ( ix = 0; ix < gridX; ix++ ) {
  17400. var a = ix + gridX1 * iy;
  17401. var b = ix + gridX1 * ( iy + 1 );
  17402. var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
  17403. var d = ( ix + 1 ) + gridX1 * iy;
  17404. var face = new THREE.Face4( a + offset, b + offset, c + offset, d + offset );
  17405. face.normal.copy( normal );
  17406. face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );
  17407. face.materialIndex = material;
  17408. scope.faces.push( face );
  17409. scope.faceVertexUvs[ 0 ].push( [
  17410. new THREE.UV( ix / gridX, 1 - iy / gridY ),
  17411. new THREE.UV( ix / gridX, 1 - ( iy + 1 ) / gridY ),
  17412. new THREE.UV( ( ix + 1 ) / gridX, 1- ( iy + 1 ) / gridY ),
  17413. new THREE.UV( ( ix + 1 ) / gridX, 1 - iy / gridY )
  17414. ] );
  17415. }
  17416. }
  17417. }
  17418. this.computeCentroids();
  17419. this.mergeVertices();
  17420. };
  17421. THREE.CubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
  17422. /**
  17423. * @author mr.doob / http://mrdoob.com/
  17424. */
  17425. THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, segmentsRadius, segmentsHeight, openEnded ) {
  17426. THREE.Geometry.call( this );
  17427. radiusTop = radiusTop !== undefined ? radiusTop : 20;
  17428. radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
  17429. height = height !== undefined ? height : 100;
  17430. var heightHalf = height / 2;
  17431. var segmentsX = segmentsRadius || 8;
  17432. var segmentsY = segmentsHeight || 1;
  17433. var x, y, vertices = [], uvs = [];
  17434. for ( y = 0; y <= segmentsY; y ++ ) {
  17435. var verticesRow = [];
  17436. var uvsRow = [];
  17437. var v = y / segmentsY;
  17438. var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
  17439. for ( x = 0; x <= segmentsX; x ++ ) {
  17440. var u = x / segmentsX;
  17441. var vertex = new THREE.Vector3();
  17442. vertex.x = radius * Math.sin( u * Math.PI * 2 );
  17443. vertex.y = - v * height + heightHalf;
  17444. vertex.z = radius * Math.cos( u * Math.PI * 2 );
  17445. this.vertices.push( vertex );
  17446. verticesRow.push( this.vertices.length - 1 );
  17447. uvsRow.push( new THREE.UV( u, v ) );
  17448. }
  17449. vertices.push( verticesRow );
  17450. uvs.push( uvsRow );
  17451. }
  17452. var tanTheta = ( radiusBottom - radiusTop ) / height;
  17453. var na, nb;
  17454. for ( x = 0; x < segmentsX; x ++ ) {
  17455. if ( radiusTop !== 0 ) {
  17456. na = this.vertices[ vertices[ 0 ][ x ] ].clone();
  17457. nb = this.vertices[ vertices[ 0 ][ x + 1 ] ].clone();
  17458. } else {
  17459. na = this.vertices[ vertices[ 1 ][ x ] ].clone();
  17460. nb = this.vertices[ vertices[ 1 ][ x + 1 ] ].clone();
  17461. }
  17462. na.setY( Math.sqrt( na.x * na.x + na.z * na.z ) * tanTheta ).normalize();
  17463. nb.setY( Math.sqrt( nb.x * nb.x + nb.z * nb.z ) * tanTheta ).normalize();
  17464. for ( y = 0; y < segmentsY; y ++ ) {
  17465. var v1 = vertices[ y ][ x ];
  17466. var v2 = vertices[ y + 1 ][ x ];
  17467. var v3 = vertices[ y + 1 ][ x + 1 ];
  17468. var v4 = vertices[ y ][ x + 1 ];
  17469. var n1 = na.clone();
  17470. var n2 = na.clone();
  17471. var n3 = nb.clone();
  17472. var n4 = nb.clone();
  17473. var uv1 = uvs[ y ][ x ].clone();
  17474. var uv2 = uvs[ y + 1 ][ x ].clone();
  17475. var uv3 = uvs[ y + 1 ][ x + 1 ].clone();
  17476. var uv4 = uvs[ y ][ x + 1 ].clone();
  17477. this.faces.push( new THREE.Face4( v1, v2, v3, v4, [ n1, n2, n3, n4 ] ) );
  17478. this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3, uv4 ] );
  17479. }
  17480. }
  17481. // top cap
  17482. if ( !openEnded && radiusTop > 0 ) {
  17483. this.vertices.push( new THREE.Vector3( 0, heightHalf, 0 ) );
  17484. for ( x = 0; x < segmentsX; x ++ ) {
  17485. var v1 = vertices[ 0 ][ x ];
  17486. var v2 = vertices[ 0 ][ x + 1 ];
  17487. var v3 = this.vertices.length - 1;
  17488. var n1 = new THREE.Vector3( 0, 1, 0 );
  17489. var n2 = new THREE.Vector3( 0, 1, 0 );
  17490. var n3 = new THREE.Vector3( 0, 1, 0 );
  17491. var uv1 = uvs[ 0 ][ x ].clone();
  17492. var uv2 = uvs[ 0 ][ x + 1 ].clone();
  17493. var uv3 = new THREE.UV( uv2.u, 0 );
  17494. this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
  17495. this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
  17496. }
  17497. }
  17498. // bottom cap
  17499. if ( !openEnded && radiusBottom > 0 ) {
  17500. this.vertices.push( new THREE.Vector3( 0, - heightHalf, 0 ) );
  17501. for ( x = 0; x < segmentsX; x ++ ) {
  17502. var v1 = vertices[ y ][ x + 1 ];
  17503. var v2 = vertices[ y ][ x ];
  17504. var v3 = this.vertices.length - 1;
  17505. var n1 = new THREE.Vector3( 0, - 1, 0 );
  17506. var n2 = new THREE.Vector3( 0, - 1, 0 );
  17507. var n3 = new THREE.Vector3( 0, - 1, 0 );
  17508. var uv1 = uvs[ y ][ x + 1 ].clone();
  17509. var uv2 = uvs[ y ][ x ].clone();
  17510. var uv3 = new THREE.UV( uv2.u, 1 );
  17511. this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
  17512. this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
  17513. }
  17514. }
  17515. this.computeCentroids();
  17516. this.computeFaceNormals();
  17517. }
  17518. THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype );
  17519. /**
  17520. * @author zz85 / http://www.lab4games.net/zz85/blog
  17521. *
  17522. * Creates extruded geometry from a path shape.
  17523. *
  17524. * parameters = {
  17525. *
  17526. * size: <float>, // size of the text
  17527. * height: <float>, // thickness to extrude text
  17528. * curveSegments: <int>, // number of points on the curves
  17529. * steps: <int>, // number of points for z-side extrusions / used for subdividing segements of extrude spline too
  17530. amount: <int>, // Amount
  17531. *
  17532. * bevelEnabled: <bool>, // turn on bevel
  17533. * bevelThickness: <float>, // how deep into text bevel goes
  17534. * bevelSize: <float>, // how far from text outline is bevel
  17535. * bevelSegments: <int>, // number of bevel layers
  17536. *
  17537. * extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
  17538. * frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
  17539. * bendPath: <THREE.CurvePath> // 2d path for bend the shape around x/y plane
  17540. *
  17541. * material: <int> // material index for front and back faces
  17542. * extrudeMaterial: <int> // material index for extrusion and beveled faces
  17543. * uvGenerator: <Object> // object that provides UV generator functions
  17544. *
  17545. * }
  17546. **/
  17547. THREE.ExtrudeGeometry = function( shapes, options ) {
  17548. if ( typeof( shapes ) === "undefined" ) {
  17549. shapes = [];
  17550. return;
  17551. }
  17552. THREE.Geometry.call( this );
  17553. shapes = shapes instanceof Array ? shapes : [ shapes ];
  17554. this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
  17555. this.addShapeList( shapes, options );
  17556. this.computeCentroids();
  17557. this.computeFaceNormals();
  17558. // can't really use automatic vertex normals
  17559. // as then front and back sides get smoothed too
  17560. // should do separate smoothing just for sides
  17561. //this.computeVertexNormals();
  17562. //console.log( "took", ( Date.now() - startTime ) );
  17563. };
  17564. THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
  17565. THREE.ExtrudeGeometry.prototype.addShapeList = function(shapes, options) {
  17566. var sl = shapes.length;
  17567. for ( var s = 0; s < sl; s ++ ) {
  17568. var shape = shapes[ s ];
  17569. this.addShape( shape, options );
  17570. }
  17571. };
  17572. THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
  17573. var amount = options.amount !== undefined ? options.amount : 100;
  17574. var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
  17575. var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
  17576. var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
  17577. var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
  17578. var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
  17579. var steps = options.steps !== undefined ? options.steps : 1;
  17580. var bendPath = options.bendPath;
  17581. var extrudePath = options.extrudePath;
  17582. var extrudePts, extrudeByPath = false;
  17583. var material = options.material;
  17584. var extrudeMaterial = options.extrudeMaterial;
  17585. // Use default WorldUVGenerator if no UV generators are specified.
  17586. var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
  17587. var shapebb = this.shapebb;
  17588. //shapebb = shape.getBoundingBox();
  17589. var splineTube, binormal, normal, position2;
  17590. if ( extrudePath ) {
  17591. extrudePts = extrudePath.getSpacedPoints( steps );
  17592. extrudeByPath = true;
  17593. bevelEnabled = false; // bevels not supported for path extrusion
  17594. // SETUP TNB variables
  17595. // Reuse TNB from TubeGeomtry for now.
  17596. // TODO1 - have a .isClosed in spline?
  17597. splineTube = options.frames !== undefined ?
  17598. options.frames :
  17599. new THREE.TubeGeometry.FrenetFrames(extrudePath, steps, false);
  17600. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  17601. binormal = new THREE.Vector3();
  17602. normal = new THREE.Vector3();
  17603. position2 = new THREE.Vector3();
  17604. }
  17605. // Safeguards if bevels are not enabled
  17606. if ( ! bevelEnabled ) {
  17607. bevelSegments = 0;
  17608. bevelThickness = 0;
  17609. bevelSize = 0;
  17610. }
  17611. // Variables initalization
  17612. var ahole, h, hl; // looping of holes
  17613. var scope = this;
  17614. var bevelPoints = [];
  17615. var shapesOffset = this.vertices.length;
  17616. if ( bendPath ) {
  17617. shape.addWrapPath( bendPath );
  17618. }
  17619. var shapePoints = shape.extractPoints();
  17620. var vertices = shapePoints.shape;
  17621. var holes = shapePoints.holes;
  17622. var reverse = !THREE.Shape.Utils.isClockWise( vertices ) ;
  17623. if ( reverse ) {
  17624. vertices = vertices.reverse();
  17625. // Maybe we should also check if holes are in the opposite direction, just to be safe ...
  17626. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  17627. ahole = holes[ h ];
  17628. if ( THREE.Shape.Utils.isClockWise( ahole ) ) {
  17629. holes[ h ] = ahole.reverse();
  17630. }
  17631. }
  17632. reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
  17633. }
  17634. var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes );
  17635. //var faces = THREE.Shape.Utils.triangulate2( vertices, holes );
  17636. // Would it be better to move points after triangulation?
  17637. // shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath );
  17638. // vertices = shapePoints.shape;
  17639. // holes = shapePoints.holes;
  17640. //console.log(faces);
  17641. ////
  17642. /// Handle Vertices
  17643. ////
  17644. var contour = vertices; // vertices has all points but contour has only points of circumference
  17645. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  17646. ahole = holes[ h ];
  17647. vertices = vertices.concat( ahole );
  17648. }
  17649. function scalePt2 ( pt, vec, size ) {
  17650. if ( !vec ) console.log( "die" );
  17651. return vec.clone().multiplyScalar( size ).addSelf( pt );
  17652. }
  17653. var b, bs, t, z,
  17654. vert, vlen = vertices.length,
  17655. face, flen = faces.length,
  17656. cont, clen = contour.length;
  17657. //------
  17658. // Find directions for point movement
  17659. //
  17660. var RAD_TO_DEGREES = 180 / Math.PI;
  17661. function getBevelVec( pt_i, pt_j, pt_k ) {
  17662. // Algorithm 2
  17663. return getBevelVec2( pt_i, pt_j, pt_k );
  17664. }
  17665. function getBevelVec1( pt_i, pt_j, pt_k ) {
  17666. var anglea = Math.atan2( pt_j.y - pt_i.y, pt_j.x - pt_i.x );
  17667. var angleb = Math.atan2( pt_k.y - pt_i.y, pt_k.x - pt_i.x );
  17668. if ( anglea > angleb ) {
  17669. angleb += Math.PI * 2;
  17670. }
  17671. var anglec = ( anglea + angleb ) / 2;
  17672. //console.log('angle1', anglea * RAD_TO_DEGREES,'angle2', angleb * RAD_TO_DEGREES, 'anglec', anglec *RAD_TO_DEGREES);
  17673. var x = - Math.cos( anglec );
  17674. var y = - Math.sin( anglec );
  17675. var vec = new THREE.Vector2( x, y ); //.normalize();
  17676. return vec;
  17677. }
  17678. function getBevelVec2( pt_i, pt_j, pt_k ) {
  17679. var a = THREE.ExtrudeGeometry.__v1,
  17680. b = THREE.ExtrudeGeometry.__v2,
  17681. v_hat = THREE.ExtrudeGeometry.__v3,
  17682. w_hat = THREE.ExtrudeGeometry.__v4,
  17683. p = THREE.ExtrudeGeometry.__v5,
  17684. q = THREE.ExtrudeGeometry.__v6,
  17685. v, w,
  17686. v_dot_w_hat, q_sub_p_dot_w_hat,
  17687. s, intersection;
  17688. // good reading for line-line intersection
  17689. // http://sputsoft.com/blog/2010/03/line-line-intersection.html
  17690. // define a as vector j->i
  17691. // define b as vectot k->i
  17692. a.set( pt_i.x - pt_j.x, pt_i.y - pt_j.y );
  17693. b.set( pt_i.x - pt_k.x, pt_i.y - pt_k.y );
  17694. // get unit vectors
  17695. v = a.normalize();
  17696. w = b.normalize();
  17697. // normals from pt i
  17698. v_hat.set( -v.y, v.x );
  17699. w_hat.set( w.y, -w.x );
  17700. // pts from i
  17701. p.copy( pt_i ).addSelf( v_hat );
  17702. q.copy( pt_i ).addSelf( w_hat );
  17703. if ( p.equals( q ) ) {
  17704. //console.log("Warning: lines are straight");
  17705. return w_hat.clone();
  17706. }
  17707. // Points from j, k. helps prevents points cross overover most of the time
  17708. p.copy( pt_j ).addSelf( v_hat );
  17709. q.copy( pt_k ).addSelf( w_hat );
  17710. v_dot_w_hat = v.dot( w_hat );
  17711. q_sub_p_dot_w_hat = q.subSelf( p ).dot( w_hat );
  17712. // We should not reach these conditions
  17713. if ( v_dot_w_hat === 0 ) {
  17714. console.log( "Either infinite or no solutions!" );
  17715. if ( q_sub_p_dot_w_hat === 0 ) {
  17716. console.log( "Its finite solutions." );
  17717. } else {
  17718. console.log( "Too bad, no solutions." );
  17719. }
  17720. }
  17721. s = q_sub_p_dot_w_hat / v_dot_w_hat;
  17722. if ( s < 0 ) {
  17723. // in case of emergecy, revert to algorithm 1.
  17724. return getBevelVec1( pt_i, pt_j, pt_k );
  17725. }
  17726. intersection = v.multiplyScalar( s ).addSelf( p );
  17727. return intersection.subSelf( pt_i ).clone(); // Don't normalize!, otherwise sharp corners become ugly
  17728. }
  17729. var contourMovements = [];
  17730. for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  17731. if ( j === il ) j = 0;
  17732. if ( k === il ) k = 0;
  17733. // (j)---(i)---(k)
  17734. // console.log('i,j,k', i, j , k)
  17735. var pt_i = contour[ i ];
  17736. var pt_j = contour[ j ];
  17737. var pt_k = contour[ k ];
  17738. contourMovements[ i ]= getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
  17739. }
  17740. var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
  17741. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  17742. ahole = holes[ h ];
  17743. oneHoleMovements = [];
  17744. for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  17745. if ( j === il ) j = 0;
  17746. if ( k === il ) k = 0;
  17747. // (j)---(i)---(k)
  17748. oneHoleMovements[ i ]= getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
  17749. }
  17750. holesMovements.push( oneHoleMovements );
  17751. verticesMovements = verticesMovements.concat( oneHoleMovements );
  17752. }
  17753. // Loop bevelSegments, 1 for the front, 1 for the back
  17754. for ( b = 0; b < bevelSegments; b ++ ) {
  17755. //for ( b = bevelSegments; b > 0; b -- ) {
  17756. t = b / bevelSegments;
  17757. z = bevelThickness * ( 1 - t );
  17758. //z = bevelThickness * t;
  17759. bs = bevelSize * ( Math.sin ( t * Math.PI/2 ) ) ; // curved
  17760. //bs = bevelSize * t ; // linear
  17761. // contract shape
  17762. for ( i = 0, il = contour.length; i < il; i ++ ) {
  17763. vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  17764. //vert = scalePt( contour[ i ], contourCentroid, bs, false );
  17765. v( vert.x, vert.y, - z );
  17766. }
  17767. // expand holes
  17768. for ( h = 0, hl = holes.length; h < hl; h++ ) {
  17769. ahole = holes[ h ];
  17770. oneHoleMovements = holesMovements[ h ];
  17771. for ( i = 0, il = ahole.length; i < il; i++ ) {
  17772. vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  17773. //vert = scalePt( ahole[ i ], holesCentroids[ h ], bs, true );
  17774. v( vert.x, vert.y, -z );
  17775. }
  17776. }
  17777. }
  17778. bs = bevelSize;
  17779. // Back facing vertices
  17780. for ( i = 0; i < vlen; i ++ ) {
  17781. vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  17782. if ( !extrudeByPath ) {
  17783. v( vert.x, vert.y, 0 );
  17784. } else {
  17785. // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  17786. normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
  17787. binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
  17788. position2.copy(extrudePts[0]).addSelf(normal).addSelf(binormal);
  17789. v(position2.x, position2.y, position2.z);
  17790. }
  17791. }
  17792. // Add stepped vertices...
  17793. // Including front facing vertices
  17794. var s;
  17795. for ( s = 1; s <= steps; s ++ ) {
  17796. for ( i = 0; i < vlen; i ++ ) {
  17797. vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  17798. if ( !extrudeByPath ) {
  17799. v( vert.x, vert.y, amount / steps * s );
  17800. } else {
  17801. // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  17802. normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
  17803. binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
  17804. position2.copy(extrudePts[s]).addSelf(normal).addSelf(binormal);
  17805. v(position2.x, position2.y, position2.z );
  17806. }
  17807. }
  17808. }
  17809. // Add bevel segments planes
  17810. //for ( b = 1; b <= bevelSegments; b ++ ) {
  17811. for ( b = bevelSegments - 1; b >= 0; b -- ) {
  17812. t = b / bevelSegments;
  17813. z = bevelThickness * ( 1 - t );
  17814. //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
  17815. bs = bevelSize * Math.sin ( t * Math.PI/2 ) ;
  17816. // contract shape
  17817. for ( i = 0, il = contour.length; i < il; i ++ ) {
  17818. vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  17819. v( vert.x, vert.y, amount + z );
  17820. }
  17821. // expand holes
  17822. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  17823. ahole = holes[ h ];
  17824. oneHoleMovements = holesMovements[ h ];
  17825. for ( i = 0, il = ahole.length; i < il; i++ ) {
  17826. vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  17827. if ( !extrudeByPath ) {
  17828. v( vert.x, vert.y, amount + z );
  17829. } else {
  17830. v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
  17831. }
  17832. }
  17833. }
  17834. }
  17835. ////
  17836. /// Handle Faces
  17837. ////
  17838. // Top and bottom faces
  17839. buildLidFaces();
  17840. // Sides faces
  17841. buildSideFaces();
  17842. ///// Internal functions
  17843. function buildLidFaces() {
  17844. if ( bevelEnabled ) {
  17845. var layer = 0 ; // steps + 1
  17846. var offset = vlen * layer;
  17847. // Bottom faces
  17848. for ( i = 0; i < flen; i ++ ) {
  17849. face = faces[ i ];
  17850. f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset, true );
  17851. }
  17852. layer = steps + bevelSegments * 2;
  17853. offset = vlen * layer;
  17854. // Top faces
  17855. for ( i = 0; i < flen; i ++ ) {
  17856. face = faces[ i ];
  17857. f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset, false );
  17858. }
  17859. } else {
  17860. // Bottom faces
  17861. for ( i = 0; i < flen; i++ ) {
  17862. face = faces[ i ];
  17863. f3( face[ 2 ], face[ 1 ], face[ 0 ], true );
  17864. }
  17865. // Top faces
  17866. for ( i = 0; i < flen; i ++ ) {
  17867. face = faces[ i ];
  17868. f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps, false );
  17869. }
  17870. }
  17871. }
  17872. // Create faces for the z-sides of the shape
  17873. function buildSideFaces() {
  17874. var layeroffset = 0;
  17875. sidewalls( contour, layeroffset );
  17876. layeroffset += contour.length;
  17877. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  17878. ahole = holes[ h ];
  17879. sidewalls( ahole, layeroffset );
  17880. //, true
  17881. layeroffset += ahole.length;
  17882. }
  17883. }
  17884. function sidewalls( contour, layeroffset ) {
  17885. var j, k;
  17886. i = contour.length;
  17887. while ( --i >= 0 ) {
  17888. j = i;
  17889. k = i - 1;
  17890. if ( k < 0 ) k = contour.length - 1;
  17891. //console.log('b', i,j, i-1, k,vertices.length);
  17892. var s = 0, sl = steps + bevelSegments * 2;
  17893. for ( s = 0; s < sl; s ++ ) {
  17894. var slen1 = vlen * s;
  17895. var slen2 = vlen * ( s + 1 );
  17896. var a = layeroffset + j + slen1,
  17897. b = layeroffset + k + slen1,
  17898. c = layeroffset + k + slen2,
  17899. d = layeroffset + j + slen2;
  17900. f4( a, b, c, d, contour, s, sl, j, k );
  17901. }
  17902. }
  17903. }
  17904. function v( x, y, z ) {
  17905. scope.vertices.push( new THREE.Vector3( x, y, z ) );
  17906. }
  17907. function f3( a, b, c, isBottom ) {
  17908. a += shapesOffset;
  17909. b += shapesOffset;
  17910. c += shapesOffset;
  17911. // normal, color, material
  17912. scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
  17913. var uvs = isBottom ? uvgen.generateBottomUV( scope, shape, options, a, b, c)
  17914. : uvgen.generateTopUV( scope, shape, options, a, b, c);
  17915. scope.faceVertexUvs[ 0 ].push(uvs);
  17916. }
  17917. function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
  17918. a += shapesOffset;
  17919. b += shapesOffset;
  17920. c += shapesOffset;
  17921. d += shapesOffset;
  17922. scope.faces.push( new THREE.Face4( a, b, c, d, null, null, extrudeMaterial ) );
  17923. var uvs = uvgen.generateSideWallUV( scope, shape, wallContour, options, a, b, c, d,
  17924. stepIndex, stepsLength, contourIndex1, contourIndex2 );
  17925. scope.faceVertexUvs[ 0 ].push(uvs);
  17926. }
  17927. };
  17928. THREE.ExtrudeGeometry.WorldUVGenerator = {
  17929. generateTopUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC) {
  17930. var ax = geometry.vertices[ indexA ].x,
  17931. ay = geometry.vertices[ indexA ].y,
  17932. bx = geometry.vertices[ indexB ].x,
  17933. by = geometry.vertices[ indexB ].y,
  17934. cx = geometry.vertices[ indexC ].x,
  17935. cy = geometry.vertices[ indexC ].y;
  17936. return [
  17937. new THREE.UV( ax, 1 - ay ),
  17938. new THREE.UV( bx, 1 - by ),
  17939. new THREE.UV( cx, 1 - cy )
  17940. ];
  17941. },
  17942. generateBottomUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC) {
  17943. return this.generateTopUV( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC );
  17944. },
  17945. generateSideWallUV: function( geometry, extrudedShape, wallContour, extrudeOptions,
  17946. indexA, indexB, indexC, indexD, stepIndex, stepsLength,
  17947. contourIndex1, contourIndex2 ) {
  17948. var ax = geometry.vertices[ indexA ].x,
  17949. ay = geometry.vertices[ indexA ].y,
  17950. az = geometry.vertices[ indexA ].z,
  17951. bx = geometry.vertices[ indexB ].x,
  17952. by = geometry.vertices[ indexB ].y,
  17953. bz = geometry.vertices[ indexB ].z,
  17954. cx = geometry.vertices[ indexC ].x,
  17955. cy = geometry.vertices[ indexC ].y,
  17956. cz = geometry.vertices[ indexC ].z,
  17957. dx = geometry.vertices[ indexD ].x,
  17958. dy = geometry.vertices[ indexD ].y,
  17959. dz = geometry.vertices[ indexD ].z;
  17960. if ( Math.abs( ay - by ) < 0.01 ) {
  17961. return [
  17962. new THREE.UV( ax, az ),
  17963. new THREE.UV( bx, bz ),
  17964. new THREE.UV( cx, cz ),
  17965. new THREE.UV( dx, dz )
  17966. ];
  17967. } else {
  17968. return [
  17969. new THREE.UV( ay, az ),
  17970. new THREE.UV( by, bz ),
  17971. new THREE.UV( cy, cz ),
  17972. new THREE.UV( dy, dz )
  17973. ];
  17974. }
  17975. }
  17976. };
  17977. THREE.ExtrudeGeometry.__v1 = new THREE.Vector2();
  17978. THREE.ExtrudeGeometry.__v2 = new THREE.Vector2();
  17979. THREE.ExtrudeGeometry.__v3 = new THREE.Vector2();
  17980. THREE.ExtrudeGeometry.__v4 = new THREE.Vector2();
  17981. THREE.ExtrudeGeometry.__v5 = new THREE.Vector2();
  17982. THREE.ExtrudeGeometry.__v6 = new THREE.Vector2();
  17983. /**
  17984. * @author astrodud / http://astrodud.isgreat.org/
  17985. * @author zz85 / https://github.com/zz85
  17986. */
  17987. THREE.LatheGeometry = function ( points, steps, angle ) {
  17988. THREE.Geometry.call( this );
  17989. var _steps = steps || 12;
  17990. var _angle = angle || 2 * Math.PI;
  17991. var _newV = [];
  17992. var _matrix = new THREE.Matrix4().makeRotationZ( _angle / _steps );
  17993. for ( var j = 0; j < points.length; j ++ ) {
  17994. _newV[ j ] = points[ j ].clone();
  17995. this.vertices.push( _newV[ j ] );
  17996. }
  17997. var i, il = _steps + 1;
  17998. for ( i = 0; i < il; i ++ ) {
  17999. for ( var j = 0; j < _newV.length; j ++ ) {
  18000. _newV[ j ] = _matrix.multiplyVector3( _newV[ j ].clone() );
  18001. this.vertices.push( _newV[ j ] );
  18002. }
  18003. }
  18004. for ( i = 0; i < _steps; i ++ ) {
  18005. for ( var k = 0, kl = points.length; k < kl - 1; k ++ ) {
  18006. var a = i * kl + k;
  18007. var b = ( ( i + 1 ) % il ) * kl + k;
  18008. var c = ( ( i + 1 ) % il ) * kl + ( k + 1 ) % kl;
  18009. var d = i * kl + ( k + 1 ) % kl;
  18010. this.faces.push( new THREE.Face4( a, b, c, d ) );
  18011. this.faceVertexUvs[ 0 ].push( [
  18012. new THREE.UV( 1 - i / _steps, k / kl ),
  18013. new THREE.UV( 1 - ( i + 1 ) / _steps, k / kl ),
  18014. new THREE.UV( 1 - ( i + 1 ) / _steps, ( k + 1 ) / kl ),
  18015. new THREE.UV( 1 - i / _steps, ( k + 1 ) / kl )
  18016. ] );
  18017. }
  18018. }
  18019. this.computeCentroids();
  18020. this.computeFaceNormals();
  18021. this.computeVertexNormals();
  18022. };
  18023. THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18024. /**
  18025. * @author mr.doob / http://mrdoob.com/
  18026. * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
  18027. */
  18028. THREE.PlaneGeometry = function ( width, depth, segmentsWidth, segmentsDepth ) {
  18029. THREE.Geometry.call( this );
  18030. var ix, iz,
  18031. width_half = width / 2,
  18032. depth_half = depth / 2,
  18033. gridX = segmentsWidth || 1,
  18034. gridZ = segmentsDepth || 1,
  18035. gridX1 = gridX + 1,
  18036. gridZ1 = gridZ + 1,
  18037. segment_width = width / gridX,
  18038. segment_depth = depth / gridZ,
  18039. normal = new THREE.Vector3( 0, 1, 0 );
  18040. for ( iz = 0; iz < gridZ1; iz ++ ) {
  18041. for ( ix = 0; ix < gridX1; ix ++ ) {
  18042. var x = ix * segment_width - width_half;
  18043. var z = iz * segment_depth - depth_half;
  18044. this.vertices.push( new THREE.Vector3( x, 0, z ) );
  18045. }
  18046. }
  18047. for ( iz = 0; iz < gridZ; iz ++ ) {
  18048. for ( ix = 0; ix < gridX; ix ++ ) {
  18049. var a = ix + gridX1 * iz;
  18050. var b = ix + gridX1 * ( iz + 1 );
  18051. var c = ( ix + 1 ) + gridX1 * ( iz + 1 );
  18052. var d = ( ix + 1 ) + gridX1 * iz;
  18053. var face = new THREE.Face4( a, b, c, d );
  18054. face.normal.copy( normal );
  18055. face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );
  18056. this.faces.push( face );
  18057. this.faceVertexUvs[ 0 ].push( [
  18058. new THREE.UV( ix / gridX, 1 - iz / gridZ ),
  18059. new THREE.UV( ix / gridX, 1 - ( iz + 1 ) / gridZ ),
  18060. new THREE.UV( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ ),
  18061. new THREE.UV( ( ix + 1 ) / gridX, 1 - iz / gridZ )
  18062. ] );
  18063. }
  18064. }
  18065. this.computeCentroids();
  18066. };
  18067. THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18068. /**
  18069. * @author mr.doob / http://mrdoob.com/
  18070. */
  18071. THREE.SphereGeometry = function ( radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength ) {
  18072. THREE.Geometry.call( this );
  18073. radius = radius || 50;
  18074. phiStart = phiStart !== undefined ? phiStart : 0;
  18075. phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
  18076. thetaStart = thetaStart !== undefined ? thetaStart : 0;
  18077. thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
  18078. var segmentsX = Math.max( 3, Math.floor( segmentsWidth ) || 8 );
  18079. var segmentsY = Math.max( 2, Math.floor( segmentsHeight ) || 6 );
  18080. var x, y, vertices = [], uvs = [];
  18081. for ( y = 0; y <= segmentsY; y ++ ) {
  18082. var verticesRow = [];
  18083. var uvsRow = [];
  18084. for ( x = 0; x <= segmentsX; x ++ ) {
  18085. var u = x / segmentsX;
  18086. var v = y / segmentsY;
  18087. var vertex = new THREE.Vector3();
  18088. vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  18089. vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
  18090. vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  18091. this.vertices.push( vertex );
  18092. verticesRow.push( this.vertices.length - 1 );
  18093. uvsRow.push( new THREE.UV( u, 1 - v ) );
  18094. }
  18095. vertices.push( verticesRow );
  18096. uvs.push( uvsRow );
  18097. }
  18098. for ( y = 0; y < segmentsY; y ++ ) {
  18099. for ( x = 0; x < segmentsX; x ++ ) {
  18100. var v1 = vertices[ y ][ x + 1 ];
  18101. var v2 = vertices[ y ][ x ];
  18102. var v3 = vertices[ y + 1 ][ x ];
  18103. var v4 = vertices[ y + 1 ][ x + 1 ];
  18104. var n1 = this.vertices[ v1 ].clone().normalize();
  18105. var n2 = this.vertices[ v2 ].clone().normalize();
  18106. var n3 = this.vertices[ v3 ].clone().normalize();
  18107. var n4 = this.vertices[ v4 ].clone().normalize();
  18108. var uv1 = uvs[ y ][ x + 1 ].clone();
  18109. var uv2 = uvs[ y ][ x ].clone();
  18110. var uv3 = uvs[ y + 1 ][ x ].clone();
  18111. var uv4 = uvs[ y + 1 ][ x + 1 ].clone();
  18112. if ( Math.abs( this.vertices[ v1 ].y ) == radius ) {
  18113. this.faces.push( new THREE.Face3( v1, v3, v4, [ n1, n3, n4 ] ) );
  18114. this.faceVertexUvs[ 0 ].push( [ uv1, uv3, uv4 ] );
  18115. } else if ( Math.abs( this.vertices[ v3 ].y ) == radius ) {
  18116. this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
  18117. this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
  18118. } else {
  18119. this.faces.push( new THREE.Face4( v1, v2, v3, v4, [ n1, n2, n3, n4 ] ) );
  18120. this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3, uv4 ] );
  18121. }
  18122. }
  18123. }
  18124. this.computeCentroids();
  18125. this.computeFaceNormals();
  18126. this.boundingSphere = { radius: radius };
  18127. };
  18128. THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18129. /**
  18130. * @author zz85 / http://www.lab4games.net/zz85/blog
  18131. * @author alteredq / http://alteredqualia.com/
  18132. *
  18133. * For creating 3D text geometry in three.js
  18134. *
  18135. * Text = 3D Text
  18136. *
  18137. * parameters = {
  18138. * size: <float>, // size of the text
  18139. * height: <float>, // thickness to extrude text
  18140. * curveSegments: <int>, // number of points on the curves
  18141. *
  18142. * font: <string>, // font name
  18143. * weight: <string>, // font weight (normal, bold)
  18144. * style: <string>, // font style (normal, italics)
  18145. *
  18146. * bevelEnabled: <bool>, // turn on bevel
  18147. * bevelThickness: <float>, // how deep into text bevel goes
  18148. * bevelSize: <float>, // how far from text outline is bevel
  18149. *
  18150. * bend: <bool> // bend according to hardcoded curve (generates bendPath)
  18151. * bendPath: <curve> // wraps text according to bend Path
  18152. * }
  18153. *
  18154. */
  18155. /* Usage Examples
  18156. // TextGeometry wrapper
  18157. var text3d = new TextGeometry( text, options );
  18158. // Complete manner
  18159. var textShapes = THREE.FontUtils.generateShapes( text, options );
  18160. var text3d = new ExtrudeGeometry( textShapes, options );
  18161. */
  18162. THREE.TextGeometry = function ( text, parameters ) {
  18163. var textShapes = THREE.FontUtils.generateShapes( text, parameters );
  18164. // translate parameters to ExtrudeGeometry API
  18165. parameters.amount = parameters.height !== undefined ? parameters.height : 50;
  18166. // defaults
  18167. if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
  18168. if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
  18169. if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
  18170. if ( parameters.bend ) {
  18171. var b = textShapes[ textShapes.length - 1 ].getBoundingBox();
  18172. var max = b.maxX;
  18173. parameters.bendPath = new THREE.QuadraticBezierCurve(
  18174. new THREE.Vector2( 0, 0 ),
  18175. new THREE.Vector2( max / 2, 120 ),
  18176. new THREE.Vector2( max, 0 )
  18177. );
  18178. }
  18179. THREE.ExtrudeGeometry.call( this, textShapes, parameters );
  18180. };
  18181. THREE.TextGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype );
  18182. /**
  18183. * @author oosmoxiecode
  18184. * @author mr.doob / http://mrdoob.com/
  18185. * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3DLite/src/away3dlite/primitives/Torus.as?r=2888
  18186. */
  18187. THREE.TorusGeometry = function ( radius, tube, segmentsR, segmentsT, arc ) {
  18188. THREE.Geometry.call( this );
  18189. var scope = this;
  18190. this.radius = radius || 100;
  18191. this.tube = tube || 40;
  18192. this.segmentsR = segmentsR || 8;
  18193. this.segmentsT = segmentsT || 6;
  18194. this.arc = arc || Math.PI * 2;
  18195. var center = new THREE.Vector3(), uvs = [], normals = [];
  18196. for ( var j = 0; j <= this.segmentsR; j ++ ) {
  18197. for ( var i = 0; i <= this.segmentsT; i ++ ) {
  18198. var u = i / this.segmentsT * this.arc;
  18199. var v = j / this.segmentsR * Math.PI * 2;
  18200. center.x = this.radius * Math.cos( u );
  18201. center.y = this.radius * Math.sin( u );
  18202. var vertex = new THREE.Vector3();
  18203. vertex.x = ( this.radius + this.tube * Math.cos( v ) ) * Math.cos( u );
  18204. vertex.y = ( this.radius + this.tube * Math.cos( v ) ) * Math.sin( u );
  18205. vertex.z = this.tube * Math.sin( v );
  18206. this.vertices.push( vertex );
  18207. uvs.push( new THREE.UV( i / this.segmentsT, 1 - j / this.segmentsR ) );
  18208. normals.push( vertex.clone().subSelf( center ).normalize() );
  18209. }
  18210. }
  18211. for ( var j = 1; j <= this.segmentsR; j ++ ) {
  18212. for ( var i = 1; i <= this.segmentsT; i ++ ) {
  18213. var a = ( this.segmentsT + 1 ) * j + i - 1;
  18214. var b = ( this.segmentsT + 1 ) * ( j - 1 ) + i - 1;
  18215. var c = ( this.segmentsT + 1 ) * ( j - 1 ) + i;
  18216. var d = ( this.segmentsT + 1 ) * j + i;
  18217. var face = new THREE.Face4( a, b, c, d, [ normals[ a ], normals[ b ], normals[ c ], normals[ d ] ] );
  18218. face.normal.addSelf( normals[ a ] );
  18219. face.normal.addSelf( normals[ b ] );
  18220. face.normal.addSelf( normals[ c ] );
  18221. face.normal.addSelf( normals[ d ] );
  18222. face.normal.normalize();
  18223. this.faces.push( face );
  18224. this.faceVertexUvs[ 0 ].push( [ uvs[ a ].clone(), uvs[ b ].clone(), uvs[ c ].clone(), uvs[ d ].clone() ] );
  18225. }
  18226. }
  18227. this.computeCentroids();
  18228. };
  18229. THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18230. /**
  18231. * @author oosmoxiecode
  18232. * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
  18233. */
  18234. THREE.TorusKnotGeometry = function ( radius, tube, segmentsR, segmentsT, p, q, heightScale ) {
  18235. THREE.Geometry.call( this );
  18236. var scope = this;
  18237. this.radius = radius || 200;
  18238. this.tube = tube || 40;
  18239. this.segmentsR = segmentsR || 64;
  18240. this.segmentsT = segmentsT || 8;
  18241. this.p = p || 2;
  18242. this.q = q || 3;
  18243. this.heightScale = heightScale || 1;
  18244. this.grid = new Array(this.segmentsR);
  18245. var tang = new THREE.Vector3();
  18246. var n = new THREE.Vector3();
  18247. var bitan = new THREE.Vector3();
  18248. for ( var i = 0; i < this.segmentsR; ++ i ) {
  18249. this.grid[ i ] = new Array( this.segmentsT );
  18250. for ( var j = 0; j < this.segmentsT; ++ j ) {
  18251. var u = i / this.segmentsR * 2 * this.p * Math.PI;
  18252. var v = j / this.segmentsT * 2 * Math.PI;
  18253. var p1 = getPos( u, v, this.q, this.p, this.radius, this.heightScale );
  18254. var p2 = getPos( u + 0.01, v, this.q, this.p, this.radius, this.heightScale );
  18255. var cx, cy;
  18256. tang.sub( p2, p1 );
  18257. n.add( p2, p1 );
  18258. bitan.cross( tang, n );
  18259. n.cross( bitan, tang );
  18260. bitan.normalize();
  18261. n.normalize();
  18262. cx = - this.tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
  18263. cy = this.tube * Math.sin( v );
  18264. p1.x += cx * n.x + cy * bitan.x;
  18265. p1.y += cx * n.y + cy * bitan.y;
  18266. p1.z += cx * n.z + cy * bitan.z;
  18267. this.grid[ i ][ j ] = vert( p1.x, p1.y, p1.z );
  18268. }
  18269. }
  18270. for ( var i = 0; i < this.segmentsR; ++ i ) {
  18271. for ( var j = 0; j < this.segmentsT; ++ j ) {
  18272. var ip = ( i + 1 ) % this.segmentsR;
  18273. var jp = ( j + 1 ) % this.segmentsT;
  18274. var a = this.grid[ i ][ j ];
  18275. var b = this.grid[ ip ][ j ];
  18276. var c = this.grid[ ip ][ jp ];
  18277. var d = this.grid[ i ][ jp ];
  18278. var uva = new THREE.UV( i / this.segmentsR, j / this.segmentsT );
  18279. var uvb = new THREE.UV( ( i + 1 ) / this.segmentsR, j / this.segmentsT );
  18280. var uvc = new THREE.UV( ( i + 1 ) / this.segmentsR, ( j + 1 ) / this.segmentsT );
  18281. var uvd = new THREE.UV( i / this.segmentsR, ( j + 1 ) / this.segmentsT );
  18282. this.faces.push( new THREE.Face4( a, b, c, d ) );
  18283. this.faceVertexUvs[ 0 ].push( [ uva,uvb,uvc, uvd ] );
  18284. }
  18285. }
  18286. this.computeCentroids();
  18287. this.computeFaceNormals();
  18288. this.computeVertexNormals();
  18289. function vert( x, y, z ) {
  18290. return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
  18291. }
  18292. function getPos( u, v, in_q, in_p, radius, heightScale ) {
  18293. var cu = Math.cos( u );
  18294. var cv = Math.cos( v );
  18295. var su = Math.sin( u );
  18296. var quOverP = in_q / in_p * u;
  18297. var cs = Math.cos( quOverP );
  18298. var tx = radius * ( 2 + cs ) * 0.5 * cu;
  18299. var ty = radius * ( 2 + cs ) * su * 0.5;
  18300. var tz = heightScale * radius * Math.sin( quOverP ) * 0.5;
  18301. return new THREE.Vector3( tx, ty, tz );
  18302. }
  18303. };
  18304. THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18305. /**
  18306. * @author WestLangley / https://github.com/WestLangley
  18307. * @author zz85 / https://github.com/zz85
  18308. * @author miningold / https://github.com/miningold
  18309. *
  18310. * Modified from the TorusKnotGeometry by @oosmoxiecode
  18311. *
  18312. * Creates a tube which extrudes along a 3d spline
  18313. *
  18314. * Uses parallel transport frames as described in
  18315. * http://www.cs.indiana.edu/pub/techreports/TR425.pdf
  18316. */
  18317. THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, debug ) {
  18318. THREE.Geometry.call( this );
  18319. this.path = path;
  18320. this.segments = segments || 64;
  18321. this.radius = radius || 1;
  18322. this.segmentsRadius = segmentsRadius || 8;
  18323. this.closed = closed || false;
  18324. if ( debug ) this.debug = new THREE.Object3D();
  18325. this.grid = [];
  18326. var scope = this,
  18327. tangent,
  18328. normal,
  18329. binormal,
  18330. numpoints = this.segments + 1,
  18331. x, y, z,
  18332. tx, ty, tz,
  18333. u, v,
  18334. cx, cy,
  18335. pos, pos2 = new THREE.Vector3(),
  18336. i, j,
  18337. ip, jp,
  18338. a, b, c, d,
  18339. uva, uvb, uvc, uvd;
  18340. var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed),
  18341. tangents = frames.tangents,
  18342. normals = frames.normals,
  18343. binormals = frames.binormals;
  18344. // proxy internals
  18345. this.tangents = tangents;
  18346. this.normals = normals;
  18347. this.binormals = binormals;
  18348. function vert( x, y, z ) {
  18349. return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
  18350. }
  18351. // consruct the grid
  18352. for ( i = 0; i < numpoints; i++ ) {
  18353. this.grid[ i ] = [];
  18354. u = i / ( numpoints - 1 );
  18355. pos = path.getPointAt( u );
  18356. tangent = tangents[ i ];
  18357. normal = normals[ i ];
  18358. binormal = binormals[ i ];
  18359. if ( this.debug ) {
  18360. this.debug.add(new THREE.ArrowHelper(tangent, pos, radius, 0x0000ff));
  18361. this.debug.add(new THREE.ArrowHelper(normal, pos, radius, 0xff0000));
  18362. this.debug.add(new THREE.ArrowHelper(binormal, pos, radius, 0x00ff00));
  18363. }
  18364. for ( j = 0; j < this.segmentsRadius; j++ ) {
  18365. v = j / this.segmentsRadius * 2 * Math.PI;
  18366. cx = -this.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
  18367. cy = this.radius * Math.sin( v );
  18368. pos2.copy( pos );
  18369. pos2.x += cx * normal.x + cy * binormal.x;
  18370. pos2.y += cx * normal.y + cy * binormal.y;
  18371. pos2.z += cx * normal.z + cy * binormal.z;
  18372. this.grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
  18373. }
  18374. }
  18375. // construct the mesh
  18376. for ( i = 0; i < this.segments; i++ ) {
  18377. for ( j = 0; j < this.segmentsRadius; j++ ) {
  18378. ip = ( closed ) ? (i + 1) % this.segments : i + 1;
  18379. jp = (j + 1) % this.segmentsRadius;
  18380. a = this.grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! ***
  18381. b = this.grid[ ip ][ j ];
  18382. c = this.grid[ ip ][ jp ];
  18383. d = this.grid[ i ][ jp ];
  18384. uva = new THREE.UV( i / this.segments, j / this.segmentsRadius );
  18385. uvb = new THREE.UV( ( i + 1 ) / this.segments, j / this.segmentsRadius );
  18386. uvc = new THREE.UV( ( i + 1 ) / this.segments, ( j + 1 ) / this.segmentsRadius );
  18387. uvd = new THREE.UV( i / this.segments, ( j + 1 ) / this.segmentsRadius );
  18388. this.faces.push( new THREE.Face4( a, b, c, d ) );
  18389. this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvc, uvd ] );
  18390. }
  18391. }
  18392. this.computeCentroids();
  18393. this.computeFaceNormals();
  18394. this.computeVertexNormals();
  18395. };
  18396. THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18397. // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
  18398. THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
  18399. var
  18400. tangent = new THREE.Vector3(),
  18401. normal = new THREE.Vector3(),
  18402. binormal = new THREE.Vector3(),
  18403. tangents = [],
  18404. normals = [],
  18405. binormals = [],
  18406. vec = new THREE.Vector3(),
  18407. mat = new THREE.Matrix4(),
  18408. numpoints = segments + 1,
  18409. theta,
  18410. epsilon = 0.0001,
  18411. smallest,
  18412. tx, ty, tz,
  18413. i, u, v;
  18414. // expose internals
  18415. this.tangents = tangents;
  18416. this.normals = normals;
  18417. this.binormals = binormals;
  18418. // compute the tangent vectors for each segment on the path
  18419. for ( i = 0; i < numpoints; i++ ) {
  18420. u = i / ( numpoints - 1 );
  18421. tangents[ i ] = path.getTangentAt( u );
  18422. tangents[ i ].normalize();
  18423. }
  18424. initialNormal3();
  18425. function initialNormal1(lastBinormal) {
  18426. // fixed start binormal. Has dangers of 0 vectors
  18427. normals[ 0 ] = new THREE.Vector3();
  18428. binormals[ 0 ] = new THREE.Vector3();
  18429. if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
  18430. normals[ 0 ].cross( lastBinormal, tangents[ 0 ] ).normalize();
  18431. binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] ).normalize();
  18432. }
  18433. function initialNormal2() {
  18434. // This uses the Frenet-Serret formula for deriving binormal
  18435. var t2 = path.getTangentAt( epsilon );
  18436. normals[ 0 ] = new THREE.Vector3().sub( t2, tangents[ 0 ] ).normalize();
  18437. binormals[ 0 ] = new THREE.Vector3().cross( tangents[ 0 ], normals[ 0 ] );
  18438. normals[ 0 ].cross( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
  18439. binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] ).normalize();
  18440. }
  18441. function initialNormal3() {
  18442. // select an initial normal vector perpenicular to the first tangent vector,
  18443. // and in the direction of the smallest tangent xyz component
  18444. normals[ 0 ] = new THREE.Vector3();
  18445. binormals[ 0 ] = new THREE.Vector3();
  18446. smallest = Number.MAX_VALUE;
  18447. tx = Math.abs( tangents[ 0 ].x );
  18448. ty = Math.abs( tangents[ 0 ].y );
  18449. tz = Math.abs( tangents[ 0 ].z );
  18450. if ( tx <= smallest ) {
  18451. smallest = tx;
  18452. normal.set( 1, 0, 0 );
  18453. }
  18454. if ( ty <= smallest ) {
  18455. smallest = ty;
  18456. normal.set( 0, 1, 0 );
  18457. }
  18458. if ( tz <= smallest ) {
  18459. normal.set( 0, 0, 1 );
  18460. }
  18461. vec.cross( tangents[ 0 ], normal ).normalize();
  18462. normals[ 0 ].cross( tangents[ 0 ], vec );
  18463. binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] );
  18464. }
  18465. // compute the slowly-varying normal and binormal vectors for each segment on the path
  18466. for ( i = 1; i < numpoints; i++ ) {
  18467. normals[ i ] = normals[ i-1 ].clone();
  18468. binormals[ i ] = binormals[ i-1 ].clone();
  18469. vec.cross( tangents[ i-1 ], tangents[ i ] );
  18470. if ( vec.length() > epsilon ) {
  18471. vec.normalize();
  18472. theta = Math.acos( tangents[ i-1 ].dot( tangents[ i ] ) );
  18473. mat.makeRotationAxis( vec, theta ).multiplyVector3( normals[ i ] );
  18474. }
  18475. binormals[ i ].cross( tangents[ i ], normals[ i ] );
  18476. }
  18477. // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
  18478. if ( closed ) {
  18479. theta = Math.acos( normals[ 0 ].dot( normals[ numpoints-1 ] ) );
  18480. theta /= ( numpoints - 1 );
  18481. if ( tangents[ 0 ].dot( vec.cross( normals[ 0 ], normals[ numpoints-1 ] ) ) > 0 ) {
  18482. theta = -theta;
  18483. }
  18484. for ( i = 1; i < numpoints; i++ ) {
  18485. // twist a little...
  18486. mat.makeRotationAxis( tangents[ i ], theta * i ).multiplyVector3( normals[ i ] );
  18487. binormals[ i ].cross( tangents[ i ], normals[ i ] );
  18488. }
  18489. }
  18490. };
  18491. /**
  18492. * @author clockworkgeek / https://github.com/clockworkgeek
  18493. * @author timothypratley / https://github.com/timothypratley
  18494. */
  18495. THREE.PolyhedronGeometry = function ( vertices, faces, radius, detail ) {
  18496. THREE.Geometry.call( this );
  18497. radius = radius || 1;
  18498. detail = detail || 0;
  18499. var that = this;
  18500. for ( var i = 0, l = vertices.length; i < l; i ++ ) {
  18501. prepare( new THREE.Vector3( vertices[ i ][ 0 ], vertices[ i ][ 1 ], vertices[ i ][ 2 ] ) );
  18502. }
  18503. var midpoints = [], p = this.vertices;
  18504. for ( var i = 0, l = faces.length; i < l; i ++ ) {
  18505. make( p[ faces[ i ][ 0 ] ], p[ faces[ i ][ 1 ] ], p[ faces[ i ][ 2 ] ], detail );
  18506. }
  18507. this.mergeVertices();
  18508. // Apply radius
  18509. for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
  18510. this.vertices[ i ].multiplyScalar( radius );
  18511. }
  18512. /**
  18513. * Project vector onto sphere's surface
  18514. */
  18515. function prepare( vector ) {
  18516. var vertex = vector.normalize().clone();
  18517. vertex.index = that.vertices.push( vertex ) - 1;
  18518. // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
  18519. var u = azimuth( vector ) / 2 / Math.PI + 0.5;
  18520. var v = inclination( vector ) / Math.PI + 0.5;
  18521. vertex.uv = new THREE.UV( u, v );
  18522. return vertex;
  18523. }
  18524. /**
  18525. * Approximate a curved face with recursively sub-divided triangles.
  18526. */
  18527. function make( v1, v2, v3, detail ) {
  18528. if ( detail < 1 ) {
  18529. var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
  18530. face.centroid.addSelf( v1 ).addSelf( v2 ).addSelf( v3 ).divideScalar( 3 );
  18531. face.normal = face.centroid.clone().normalize();
  18532. that.faces.push( face );
  18533. var azi = azimuth( face.centroid );
  18534. that.faceVertexUvs[ 0 ].push( [
  18535. correctUV( v1.uv, v1, azi ),
  18536. correctUV( v2.uv, v2, azi ),
  18537. correctUV( v3.uv, v3, azi )
  18538. ] );
  18539. }
  18540. else {
  18541. detail -= 1;
  18542. // split triangle into 4 smaller triangles
  18543. make( v1, midpoint( v1, v2 ), midpoint( v1, v3 ), detail ); // top quadrant
  18544. make( midpoint( v1, v2 ), v2, midpoint( v2, v3 ), detail ); // left quadrant
  18545. make( midpoint( v1, v3 ), midpoint( v2, v3 ), v3, detail ); // right quadrant
  18546. make( midpoint( v1, v2 ), midpoint( v2, v3 ), midpoint( v1, v3 ), detail ); // center quadrant
  18547. }
  18548. }
  18549. function midpoint( v1, v2 ) {
  18550. if ( !midpoints[ v1.index ] ) midpoints[ v1.index ] = [];
  18551. if ( !midpoints[ v2.index ] ) midpoints[ v2.index ] = [];
  18552. var mid = midpoints[ v1.index ][ v2.index ];
  18553. if ( mid === undefined ) {
  18554. // generate mean point and project to surface with prepare()
  18555. midpoints[ v1.index ][ v2.index ] = midpoints[ v2.index ][ v1.index ] = mid = prepare(
  18556. new THREE.Vector3().add( v1, v2 ).divideScalar( 2 )
  18557. );
  18558. }
  18559. return mid;
  18560. }
  18561. /**
  18562. * Angle around the Y axis, counter-clockwise when looking from above.
  18563. */
  18564. function azimuth( vector ) {
  18565. return Math.atan2( vector.z, -vector.x );
  18566. }
  18567. /**
  18568. * Angle above the XZ plane.
  18569. */
  18570. function inclination( vector ) {
  18571. return Math.atan2( -vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
  18572. }
  18573. /**
  18574. * Texture fixing helper. Spheres have some odd behaviours.
  18575. */
  18576. function correctUV( uv, vector, azimuth ) {
  18577. if ( (azimuth < 0) && (uv.u === 1) ) uv = new THREE.UV( uv.u - 1, uv.v );
  18578. if ( (vector.x === 0) && (vector.z === 0) ) uv = new THREE.UV( azimuth / 2 / Math.PI + 0.5, uv.v );
  18579. return uv;
  18580. }
  18581. this.computeCentroids();
  18582. this.boundingSphere = { radius: radius };
  18583. };
  18584. THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18585. /**
  18586. * @author timothypratley / https://github.com/timothypratley
  18587. */
  18588. THREE.IcosahedronGeometry = function ( radius, detail ) {
  18589. var t = ( 1 + Math.sqrt( 5 ) ) / 2;
  18590. var vertices = [
  18591. [ -1, t, 0 ], [ 1, t, 0 ], [ -1, -t, 0 ], [ 1, -t, 0 ],
  18592. [ 0, -1, t ], [ 0, 1, t ], [ 0, -1, -t ], [ 0, 1, -t ],
  18593. [ t, 0, -1 ], [ t, 0, 1 ], [ -t, 0, -1 ], [ -t, 0, 1 ]
  18594. ];
  18595. var faces = [
  18596. [ 0, 11, 5 ], [ 0, 5, 1 ], [ 0, 1, 7 ], [ 0, 7, 10 ], [ 0, 10, 11 ],
  18597. [ 1, 5, 9 ], [ 5, 11, 4 ], [ 11, 10, 2 ], [ 10, 7, 6 ], [ 7, 1, 8 ],
  18598. [ 3, 9, 4 ], [ 3, 4, 2 ], [ 3, 2, 6 ], [ 3, 6, 8 ], [ 3, 8, 9 ],
  18599. [ 4, 9, 5 ], [ 2, 4, 11 ], [ 6, 2, 10 ], [ 8, 6, 7 ], [ 9, 8, 1 ]
  18600. ];
  18601. THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
  18602. };
  18603. THREE.IcosahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18604. /**
  18605. * @author timothypratley / https://github.com/timothypratley
  18606. */
  18607. THREE.OctahedronGeometry = function ( radius, detail ) {
  18608. var vertices = [
  18609. [ 1, 0, 0 ], [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ], [ 0, 0, -1 ]
  18610. ];
  18611. var faces = [
  18612. [ 0, 2, 4 ], [ 0, 4, 3 ], [ 0, 3, 5 ], [ 0, 5, 2 ], [ 1, 2, 5 ], [ 1, 5, 3 ], [ 1, 3, 4 ], [ 1, 4, 2 ]
  18613. ];
  18614. THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
  18615. };
  18616. THREE.OctahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18617. /**
  18618. * @author timothypratley / https://github.com/timothypratley
  18619. */
  18620. THREE.TetrahedronGeometry = function ( radius, detail ) {
  18621. var vertices = [
  18622. [ 1, 1, 1 ], [ -1, -1, 1 ], [ -1, 1, -1 ], [ 1, -1, -1 ]
  18623. ];
  18624. var faces = [
  18625. [ 2, 1, 0 ], [ 0, 3, 2 ], [ 1, 3, 0 ], [ 2, 3, 1 ]
  18626. ];
  18627. THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
  18628. };
  18629. THREE.TetrahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18630. /**
  18631. * @author zz85 / https://github.com/zz85
  18632. * Parametric Surfaces Geometry
  18633. * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
  18634. *
  18635. * new THREE.ParametricGeometry( parametricFunction, uSements, ySegements, useTris );
  18636. *
  18637. */
  18638. THREE.ParametricGeometry = function ( func, slices, stacks, useTris ) {
  18639. THREE.Geometry.call( this );
  18640. var verts = this.vertices;
  18641. var faces = this.faces;
  18642. var uvs = this.faceVertexUvs[ 0 ];
  18643. useTris = (useTris === undefined) ? false : useTris;
  18644. var i, il, j, p;
  18645. var u, v;
  18646. var stackCount = stacks + 1;
  18647. var sliceCount = slices + 1;
  18648. for ( i = 0; i <= stacks; i ++ ) {
  18649. v = i / stacks;
  18650. for ( j = 0; j <= slices; j ++ ) {
  18651. u = j / slices;
  18652. p = func( u, v );
  18653. verts.push( p );
  18654. }
  18655. }
  18656. var a, b, c, d;
  18657. var uva, uvb, uvc, uvd;
  18658. for ( i = 0; i < stacks; i ++ ) {
  18659. for ( j = 0; j < slices; j ++ ) {
  18660. a = i * sliceCount + j;
  18661. b = i * sliceCount + j + 1;
  18662. c = (i + 1) * sliceCount + j;
  18663. d = (i + 1) * sliceCount + j + 1;
  18664. uva = new THREE.UV( j / slices, i / stacks );
  18665. uvb = new THREE.UV( ( j + 1 ) / slices, i / stacks );
  18666. uvc = new THREE.UV( j / slices, ( i + 1 ) / stacks );
  18667. uvd = new THREE.UV( ( j + 1 ) / slices, ( i + 1 ) / stacks );
  18668. if ( useTris ) {
  18669. faces.push( new THREE.Face3( a, b, c ) );
  18670. faces.push( new THREE.Face3( b, d, c ) );
  18671. uvs.push( [ uva, uvb, uvc ] );
  18672. uvs.push( [ uvb, uvd, uvc ] );
  18673. } else {
  18674. faces.push( new THREE.Face4( a, b, d, c ) );
  18675. uvs.push( [ uva, uvb, uvd, uvc ] );
  18676. }
  18677. }
  18678. }
  18679. // console.log(this);
  18680. // magic bullet
  18681. // var diff = this.mergeVertices();
  18682. // console.log('removed ', diff, ' vertices by merging');
  18683. this.computeCentroids();
  18684. this.computeFaceNormals();
  18685. this.computeVertexNormals();
  18686. };
  18687. THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18688. /**
  18689. * @author qiao / https://github.com/qiao
  18690. * @fileoverview This is a convex hull generator using the incremental method.
  18691. * The complexity is O(n^2) where n is the number of vertices.
  18692. * O(nlogn) algorithms do exist, but they are much more complicated.
  18693. *
  18694. * Benchmark:
  18695. *
  18696. * Platform: CPU: P7350 @2.00GHz Engine: V8
  18697. *
  18698. * Num Vertices Time(ms)
  18699. *
  18700. * 10 1
  18701. * 20 3
  18702. * 30 19
  18703. * 40 48
  18704. * 50 107
  18705. */
  18706. THREE.ConvexGeometry = function( vertices ) {
  18707. THREE.Geometry.call( this );
  18708. var faces = [ [ 0, 1, 2 ], [ 0, 2, 1 ] ];
  18709. for ( var i = 3; i < vertices.length; i++ ) {
  18710. addPoint( i );
  18711. }
  18712. function addPoint( vertexId ) {
  18713. var vertex = vertices[ vertexId ].clone();
  18714. var mag = vertex.length();
  18715. vertex.x += mag * randomOffset();
  18716. vertex.y += mag * randomOffset();
  18717. vertex.z += mag * randomOffset();
  18718. var hole = [];
  18719. for ( var f = 0; f < faces.length; ) {
  18720. var face = faces[ f ];
  18721. // for each face, if the vertex can see it,
  18722. // then we try to add the face's edges into the hole.
  18723. if ( visible( face, vertex ) ) {
  18724. for ( var e = 0; e < 3; e++ ) {
  18725. var edge = [ face[ e ], face[ ( e + 1 ) % 3 ] ];
  18726. var boundary = true;
  18727. // remove duplicated edges.
  18728. for ( var h = 0; h < hole.length; h++ ) {
  18729. if ( equalEdge( hole[ h ], edge ) ) {
  18730. hole[ h ] = hole[ hole.length - 1 ];
  18731. hole.pop();
  18732. boundary = false;
  18733. break;
  18734. }
  18735. }
  18736. if ( boundary ) {
  18737. hole.push( edge );
  18738. }
  18739. }
  18740. // remove faces[ f ]
  18741. faces[ f ] = faces[ faces.length - 1 ];
  18742. faces.pop();
  18743. } else { // not visible
  18744. f++;
  18745. }
  18746. }
  18747. // construct the new faces formed by the edges of the hole and the vertex
  18748. for ( var h = 0; h < hole.length; h++ ) {
  18749. faces.push( [
  18750. hole[ h ][ 0 ],
  18751. hole[ h ][ 1 ],
  18752. vertexId
  18753. ] );
  18754. }
  18755. }
  18756. /**
  18757. * Whether the face is visible from the vertex
  18758. */
  18759. function visible( face, vertex ) {
  18760. var va = vertices[ face[ 0 ] ];
  18761. var vb = vertices[ face[ 1 ] ];
  18762. var vc = vertices[ face[ 2 ] ];
  18763. var n = normal( va, vb, vc );
  18764. // distance from face to origin
  18765. var dist = n.dot( va );
  18766. return n.dot( vertex ) >= dist;
  18767. }
  18768. /**
  18769. * Face normal
  18770. */
  18771. function normal( va, vb, vc ) {
  18772. var cb = new THREE.Vector3();
  18773. var ab = new THREE.Vector3();
  18774. cb.sub( vc, vb );
  18775. ab.sub( va, vb );
  18776. cb.crossSelf( ab );
  18777. if ( !cb.isZero() ) {
  18778. cb.normalize();
  18779. }
  18780. return cb;
  18781. }
  18782. /**
  18783. * Detect whether two edges are equal.
  18784. * Note that when constructing the convex hull, two same edges can only
  18785. * be of the negative direction.
  18786. */
  18787. function equalEdge( ea, eb ) {
  18788. return ea[ 0 ] === eb[ 1 ] && ea[ 1 ] === eb[ 0 ];
  18789. }
  18790. /**
  18791. * Create a random offset between -1e-6 and 1e-6.
  18792. */
  18793. function randomOffset() {
  18794. return ( Math.random() - 0.5 ) * 2 * 1e-6;
  18795. }
  18796. /**
  18797. * XXX: Not sure if this is the correct approach. Need someone to review.
  18798. */
  18799. function vertexUv( vertex ) {
  18800. var mag = vertex.length();
  18801. return new THREE.UV( vertex.x / mag, vertex.y / mag );
  18802. }
  18803. // Push vertices into `this.vertices`, skipping those inside the hull
  18804. var id = 0;
  18805. var newId = new Array( vertices.length ); // map from old vertex id to new id
  18806. for ( var i = 0; i < faces.length; i++ ) {
  18807. var face = faces[ i ];
  18808. for ( var j = 0; j < 3; j++ ) {
  18809. if ( newId[ face[ j ] ] === undefined ) {
  18810. newId[ face[ j ] ] = id++;
  18811. this.vertices.push( vertices[ face[ j ] ] );
  18812. }
  18813. face[ j ] = newId[ face[ j ] ];
  18814. }
  18815. }
  18816. // Convert faces into instances of THREE.Face3
  18817. for ( var i = 0; i < faces.length; i++ ) {
  18818. this.faces.push( new THREE.Face3(
  18819. faces[ i ][ 0 ],
  18820. faces[ i ][ 1 ],
  18821. faces[ i ][ 2 ]
  18822. ) );
  18823. }
  18824. // Compute UVs
  18825. for ( var i = 0; i < this.faces.length; i++ ) {
  18826. var face = this.faces[ i ];
  18827. this.faceVertexUvs[ 0 ].push( [
  18828. vertexUv( this.vertices[ face.a ] ),
  18829. vertexUv( this.vertices[ face.b ] ),
  18830. vertexUv( this.vertices[ face.c ])
  18831. ] );
  18832. }
  18833. this.computeCentroids();
  18834. this.computeFaceNormals();
  18835. this.computeVertexNormals();
  18836. };
  18837. THREE.ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
  18838. /**
  18839. * @author sroucheray / http://sroucheray.org/
  18840. * @author mr.doob / http://mrdoob.com/
  18841. */
  18842. THREE.AxisHelper = function () {
  18843. THREE.Object3D.call( this );
  18844. var lineGeometry = new THREE.Geometry();
  18845. lineGeometry.vertices.push( new THREE.Vector3() );
  18846. lineGeometry.vertices.push( new THREE.Vector3( 0, 100, 0 ) );
  18847. var coneGeometry = new THREE.CylinderGeometry( 0, 5, 25, 5, 1 );
  18848. var line, cone;
  18849. // x
  18850. line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0xff0000 } ) );
  18851. line.rotation.z = - Math.PI / 2;
  18852. this.add( line );
  18853. cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0xff0000 } ) );
  18854. cone.position.x = 100;
  18855. cone.rotation.z = - Math.PI / 2;
  18856. this.add( cone );
  18857. // y
  18858. line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0x00ff00 } ) );
  18859. this.add( line );
  18860. cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0x00ff00 } ) );
  18861. cone.position.y = 100;
  18862. this.add( cone );
  18863. // z
  18864. line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0x0000ff } ) );
  18865. line.rotation.x = Math.PI / 2;
  18866. this.add( line );
  18867. cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0x0000ff } ) );
  18868. cone.position.z = 100;
  18869. cone.rotation.x = Math.PI / 2;
  18870. this.add( cone );
  18871. };
  18872. THREE.AxisHelper.prototype = Object.create( THREE.Object3D.prototype );
  18873. /**
  18874. * @author WestLangley / http://github.com/WestLangley
  18875. * @author zz85 / https://github.com/zz85
  18876. *
  18877. * Creates an arrow for visualizing directions
  18878. *
  18879. * Parameters:
  18880. * dir - Vector3
  18881. * origin - Vector3
  18882. * length - Number
  18883. * hex - color in hex value
  18884. */
  18885. THREE.ArrowHelper = function ( dir, origin, length, hex ) {
  18886. THREE.Object3D.call( this );
  18887. if ( hex === undefined ) hex = 0xffff00;
  18888. if ( length === undefined ) length = 20;
  18889. var lineGeometry = new THREE.Geometry();
  18890. lineGeometry.vertices.push( new THREE.Vector3( 0, 0, 0 ) );
  18891. lineGeometry.vertices.push( new THREE.Vector3( 0, 1, 0 ) );
  18892. this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color: hex } ) );
  18893. this.add( this.line );
  18894. var coneGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.25, 5, 1 );
  18895. this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: hex } ) );
  18896. this.cone.position.set( 0, 1, 0 );
  18897. this.add( this.cone );
  18898. if ( origin instanceof THREE.Vector3 ) this.position = origin;
  18899. this.setDirection( dir );
  18900. this.setLength( length );
  18901. };
  18902. THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
  18903. THREE.ArrowHelper.prototype.setDirection = function ( dir ) {
  18904. var axis = new THREE.Vector3( 0, 1, 0 ).crossSelf( dir );
  18905. var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( dir.clone().normalize() ) );
  18906. this.matrix = new THREE.Matrix4().makeRotationAxis( axis.normalize(), radians );
  18907. this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
  18908. };
  18909. THREE.ArrowHelper.prototype.setLength = function ( length ) {
  18910. this.scale.set( length, length, length );
  18911. };
  18912. THREE.ArrowHelper.prototype.setColor = function ( hex ) {
  18913. this.line.material.color.setHex( hex );
  18914. this.cone.material.color.setHex( hex );
  18915. };
  18916. /**
  18917. * @author alteredq / http://alteredqualia.com/
  18918. *
  18919. * - shows frustum, line of sight and up of the camera
  18920. * - suitable for fast updates
  18921. * - based on frustum visualization in lightgl.js shadowmap example
  18922. * http://evanw.github.com/lightgl.js/tests/shadowmap.html
  18923. */
  18924. THREE.CameraHelper = function ( camera ) {
  18925. THREE.Object3D.call( this );
  18926. var _this = this;
  18927. this.lineGeometry = new THREE.Geometry();
  18928. this.lineMaterial = new THREE.LineBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );
  18929. this.pointMap = {};
  18930. // colors
  18931. var hexFrustum = 0xffaa00,
  18932. hexCone = 0xff0000,
  18933. hexUp = 0x00aaff,
  18934. hexTarget = 0xffffff,
  18935. hexCross = 0x333333;
  18936. // near
  18937. addLine( "n1", "n2", hexFrustum );
  18938. addLine( "n2", "n4", hexFrustum );
  18939. addLine( "n4", "n3", hexFrustum );
  18940. addLine( "n3", "n1", hexFrustum );
  18941. // far
  18942. addLine( "f1", "f2", hexFrustum );
  18943. addLine( "f2", "f4", hexFrustum );
  18944. addLine( "f4", "f3", hexFrustum );
  18945. addLine( "f3", "f1", hexFrustum );
  18946. // sides
  18947. addLine( "n1", "f1", hexFrustum );
  18948. addLine( "n2", "f2", hexFrustum );
  18949. addLine( "n3", "f3", hexFrustum );
  18950. addLine( "n4", "f4", hexFrustum );
  18951. // cone
  18952. addLine( "p", "n1", hexCone );
  18953. addLine( "p", "n2", hexCone );
  18954. addLine( "p", "n3", hexCone );
  18955. addLine( "p", "n4", hexCone );
  18956. // up
  18957. addLine( "u1", "u2", hexUp );
  18958. addLine( "u2", "u3", hexUp );
  18959. addLine( "u3", "u1", hexUp );
  18960. // target
  18961. addLine( "c", "t", hexTarget );
  18962. addLine( "p", "c", hexCross );
  18963. // cross
  18964. addLine( "cn1", "cn2", hexCross );
  18965. addLine( "cn3", "cn4", hexCross );
  18966. addLine( "cf1", "cf2", hexCross );
  18967. addLine( "cf3", "cf4", hexCross );
  18968. this.camera = camera;
  18969. function addLine( a, b, hex ) {
  18970. addPoint( a, hex );
  18971. addPoint( b, hex );
  18972. }
  18973. function addPoint( id, hex ) {
  18974. _this.lineGeometry.vertices.push( new THREE.Vector3() );
  18975. _this.lineGeometry.colors.push( new THREE.Color( hex ) );
  18976. if ( _this.pointMap[ id ] === undefined ) _this.pointMap[ id ] = [];
  18977. _this.pointMap[ id ].push( _this.lineGeometry.vertices.length - 1 );
  18978. }
  18979. this.update( camera );
  18980. this.lines = new THREE.Line( this.lineGeometry, this.lineMaterial, THREE.LinePieces );
  18981. this.add( this.lines );
  18982. };
  18983. THREE.CameraHelper.prototype = Object.create( THREE.Object3D.prototype );
  18984. THREE.CameraHelper.prototype.update = function () {
  18985. var camera = this.camera;
  18986. var w = 1;
  18987. var h = 1;
  18988. var _this = this;
  18989. // we need just camera projection matrix
  18990. // world matrix must be identity
  18991. THREE.CameraHelper.__c.projectionMatrix.copy( camera.projectionMatrix );
  18992. // center / target
  18993. setPoint( "c", 0, 0, -1 );
  18994. setPoint( "t", 0, 0, 1 );
  18995. // near
  18996. setPoint( "n1", -w, -h, -1 );
  18997. setPoint( "n2", w, -h, -1 );
  18998. setPoint( "n3", -w, h, -1 );
  18999. setPoint( "n4", w, h, -1 );
  19000. // far
  19001. setPoint( "f1", -w, -h, 1 );
  19002. setPoint( "f2", w, -h, 1 );
  19003. setPoint( "f3", -w, h, 1 );
  19004. setPoint( "f4", w, h, 1 );
  19005. // up
  19006. setPoint( "u1", w * 0.7, h * 1.1, -1 );
  19007. setPoint( "u2", -w * 0.7, h * 1.1, -1 );
  19008. setPoint( "u3", 0, h * 2, -1 );
  19009. // cross
  19010. setPoint( "cf1", -w, 0, 1 );
  19011. setPoint( "cf2", w, 0, 1 );
  19012. setPoint( "cf3", 0, -h, 1 );
  19013. setPoint( "cf4", 0, h, 1 );
  19014. setPoint( "cn1", -w, 0, -1 );
  19015. setPoint( "cn2", w, 0, -1 );
  19016. setPoint( "cn3", 0, -h, -1 );
  19017. setPoint( "cn4", 0, h, -1 );
  19018. function setPoint( point, x, y, z ) {
  19019. THREE.CameraHelper.__v.set( x, y, z );
  19020. THREE.CameraHelper.__projector.unprojectVector( THREE.CameraHelper.__v, THREE.CameraHelper.__c );
  19021. var points = _this.pointMap[ point ];
  19022. if ( points !== undefined ) {
  19023. for ( var i = 0, il = points.length; i < il; i ++ ) {
  19024. var j = points[ i ];
  19025. _this.lineGeometry.vertices[ j ].copy( THREE.CameraHelper.__v );
  19026. }
  19027. }
  19028. }
  19029. this.lineGeometry.verticesNeedUpdate = true;
  19030. };
  19031. THREE.CameraHelper.__projector = new THREE.Projector();
  19032. THREE.CameraHelper.__v = new THREE.Vector3();
  19033. THREE.CameraHelper.__c = new THREE.Camera();
  19034. /*
  19035. * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
  19036. *
  19037. * Subdivision Geometry Modifier
  19038. * using Catmull-Clark Subdivision Surfaces
  19039. * for creating smooth geometry meshes
  19040. *
  19041. * Note: a modifier modifies vertices and faces of geometry,
  19042. * so use THREE.GeometryUtils.clone() if orignal geoemtry needs to be retained
  19043. *
  19044. * Readings:
  19045. * http://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
  19046. * http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/
  19047. * http://xrt.wikidot.com/blog:31
  19048. * "Subdivision Surfaces in Character Animation"
  19049. *
  19050. * Supports:
  19051. * Closed and Open geometries.
  19052. *
  19053. * TODO:
  19054. * crease vertex and "semi-sharp" features
  19055. * selective subdivision
  19056. */
  19057. THREE.SubdivisionModifier = function( subdivisions ) {
  19058. this.subdivisions = (subdivisions === undefined ) ? 1 : subdivisions;
  19059. // Settings
  19060. this.useOldVertexColors = false;
  19061. this.supportUVs = true;
  19062. this.debug = false;
  19063. };
  19064. // Applies the "modify" pattern
  19065. THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
  19066. var repeats = this.subdivisions;
  19067. while ( repeats-- > 0 ) {
  19068. this.smooth( geometry );
  19069. }
  19070. };
  19071. // Performs an iteration of Catmull-Clark Subdivision
  19072. THREE.SubdivisionModifier.prototype.smooth = function ( oldGeometry ) {
  19073. //debug( 'running smooth' );
  19074. // New set of vertices, faces and uvs
  19075. var newVertices = [], newFaces = [], newUVs = [];
  19076. function v( x, y, z ) {
  19077. newVertices.push( new THREE.Vector3( x, y, z ) );
  19078. }
  19079. var scope = this;
  19080. function debug() {
  19081. if (scope.debug) console.log.apply(console, arguments);
  19082. }
  19083. function warn() {
  19084. if (console)
  19085. console.log.apply(console, arguments);
  19086. }
  19087. function f4( a, b, c, d, oldFace, orders, facei ) {
  19088. // TODO move vertex selection over here!
  19089. var newFace = new THREE.Face4( a, b, c, d, null, oldFace.color, oldFace.materialIndex );
  19090. if (scope.useOldVertexColors) {
  19091. newFace.vertexColors = [];
  19092. var color, tmpColor, order;
  19093. for (var i=0;i<4;i++) {
  19094. order = orders[i];
  19095. color = new THREE.Color(),
  19096. color.setRGB(0,0,0);
  19097. for (var j=0, jl=0; j<order.length;j++) {
  19098. tmpColor = oldFace.vertexColors[order[j]-1];
  19099. color.r += tmpColor.r;
  19100. color.g += tmpColor.g;
  19101. color.b += tmpColor.b;
  19102. }
  19103. color.r /= order.length;
  19104. color.g /= order.length;
  19105. color.b /= order.length;
  19106. newFace.vertexColors[i] = color;
  19107. }
  19108. }
  19109. newFaces.push( newFace );
  19110. if (scope.supportUVs) {
  19111. var aUv = [
  19112. getUV(a, ''),
  19113. getUV(b, facei),
  19114. getUV(c, facei),
  19115. getUV(d, facei)
  19116. ];
  19117. if (!aUv[0]) debug('a :( ', a+':'+facei);
  19118. else if (!aUv[1]) debug('b :( ', b+':'+facei);
  19119. else if (!aUv[2]) debug('c :( ', c+':'+facei);
  19120. else if (!aUv[3]) debug('d :( ', d+':'+facei);
  19121. else
  19122. newUVs.push( aUv );
  19123. }
  19124. }
  19125. function edge_hash( a, b ) {
  19126. return Math.min( a, b ) + "_" + Math.max( a, b );
  19127. }
  19128. function computeEdgeFaces( geometry ) {
  19129. var i, il, v1, v2, j, k,
  19130. face, faceIndices, faceIndex,
  19131. edge,
  19132. hash,
  19133. edgeFaceMap = {};
  19134. function mapEdgeHash( hash, i ) {
  19135. if ( edgeFaceMap[ hash ] === undefined ) {
  19136. edgeFaceMap[ hash ] = [];
  19137. }
  19138. edgeFaceMap[ hash ].push( i );
  19139. }
  19140. // construct vertex -> face map
  19141. for( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  19142. face = geometry.faces[ i ];
  19143. if ( face instanceof THREE.Face3 ) {
  19144. hash = edge_hash( face.a, face.b );
  19145. mapEdgeHash( hash, i );
  19146. hash = edge_hash( face.b, face.c );
  19147. mapEdgeHash( hash, i );
  19148. hash = edge_hash( face.c, face.a );
  19149. mapEdgeHash( hash, i );
  19150. } else if ( face instanceof THREE.Face4 ) {
  19151. hash = edge_hash( face.a, face.b );
  19152. mapEdgeHash( hash, i );
  19153. hash = edge_hash( face.b, face.c );
  19154. mapEdgeHash( hash, i );
  19155. hash = edge_hash( face.c, face.d );
  19156. mapEdgeHash( hash, i );
  19157. hash = edge_hash( face.d, face.a );
  19158. mapEdgeHash( hash, i );
  19159. }
  19160. }
  19161. // extract faces
  19162. // var edges = [];
  19163. //
  19164. // var numOfEdges = 0;
  19165. // for (i in edgeFaceMap) {
  19166. // numOfEdges++;
  19167. //
  19168. // edge = edgeFaceMap[i];
  19169. // edges.push(edge);
  19170. //
  19171. // }
  19172. //debug('edgeFaceMap', edgeFaceMap, 'geometry.edges',geometry.edges, 'numOfEdges', numOfEdges);
  19173. return edgeFaceMap;
  19174. }
  19175. var originalPoints = oldGeometry.vertices;
  19176. var originalFaces = oldGeometry.faces;
  19177. var newPoints = originalPoints.concat(); // Vertices
  19178. var facePoints = [], edgePoints = {};
  19179. var sharpEdges = {}, sharpVertices = [], sharpFaces = [];
  19180. var uvForVertices = {}; // Stored in {vertex}:{old face} format
  19181. var originalVerticesLength = originalPoints.length;
  19182. function getUV(vertexNo, oldFaceNo) {
  19183. var j,jl;
  19184. var key = vertexNo+':'+oldFaceNo;
  19185. var theUV = uvForVertices[key];
  19186. if (!theUV) {
  19187. if (vertexNo>=originalVerticesLength && vertexNo < (originalVerticesLength + originalFaces.length)) {
  19188. debug('face pt');
  19189. } else {
  19190. debug('edge pt');
  19191. }
  19192. warn('warning, UV not found for', key);
  19193. return null;
  19194. }
  19195. return theUV;
  19196. // Original faces -> Vertex Nos.
  19197. // new Facepoint -> Vertex Nos.
  19198. // edge Points
  19199. }
  19200. function addUV(vertexNo, oldFaceNo, value) {
  19201. var key = vertexNo+':'+oldFaceNo;
  19202. if (!(key in uvForVertices)) {
  19203. uvForVertices[key] = value;
  19204. } else {
  19205. warn('dup vertexNo', vertexNo, 'oldFaceNo', oldFaceNo, 'value', value, 'key', key, uvForVertices[key]);
  19206. }
  19207. }
  19208. // Step 1
  19209. // For each face, add a face point
  19210. // Set each face point to be the centroid of all original points for the respective face.
  19211. // debug(oldGeometry);
  19212. var i, il, j, jl, face;
  19213. // For Uvs
  19214. var uvs = oldGeometry.faceVertexUvs[0];
  19215. var abcd = 'abcd', vertice;
  19216. debug('originalFaces, uvs, originalVerticesLength', originalFaces.length, uvs.length, originalVerticesLength);
  19217. if (scope.supportUVs)
  19218. for (i=0, il = uvs.length; i<il; i++ ) {
  19219. for (j=0,jl=uvs[i].length;j<jl;j++) {
  19220. vertice = originalFaces[i][abcd.charAt(j)];
  19221. addUV(vertice, i, uvs[i][j]);
  19222. }
  19223. }
  19224. if (uvs.length == 0) scope.supportUVs = false;
  19225. // Additional UVs check, if we index original
  19226. var uvCount = 0;
  19227. for (var u in uvForVertices) {
  19228. uvCount++;
  19229. }
  19230. if (!uvCount) {
  19231. scope.supportUVs = false;
  19232. debug('no uvs');
  19233. }
  19234. debug('-- Original Faces + Vertices UVs completed', uvForVertices, 'vs', uvs.length);
  19235. var avgUv ;
  19236. for (i=0, il = originalFaces.length; i<il ;i++) {
  19237. face = originalFaces[ i ];
  19238. facePoints.push( face.centroid );
  19239. newPoints.push( face.centroid );
  19240. if (!scope.supportUVs) continue;
  19241. // Prepare subdivided uv
  19242. avgUv = new THREE.UV();
  19243. if ( face instanceof THREE.Face3 ) {
  19244. avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u;
  19245. avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v;
  19246. avgUv.u /= 3;
  19247. avgUv.v /= 3;
  19248. } else if ( face instanceof THREE.Face4 ) {
  19249. avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u + getUV( face.d, i ).u;
  19250. avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v + getUV( face.d, i ).v;
  19251. avgUv.u /= 4;
  19252. avgUv.v /= 4;
  19253. }
  19254. addUV(originalVerticesLength + i, '', avgUv);
  19255. }
  19256. debug('-- added UVs for new Faces', uvForVertices);
  19257. // Step 2
  19258. // For each edge, add an edge point.
  19259. // Set each edge point to be the average of the two neighbouring face points and its two original endpoints.
  19260. var edgeFaceMap = computeEdgeFaces ( oldGeometry ); // Edge Hash -> Faces Index
  19261. var edge, faceIndexA, faceIndexB, avg;
  19262. // debug('edgeFaceMap', edgeFaceMap);
  19263. var edgeCount = 0;
  19264. var edgeVertex, edgeVertexA, edgeVertexB;
  19265. ////
  19266. var vertexEdgeMap = {}; // Gives edges connecting from each vertex
  19267. var vertexFaceMap = {}; // Gives faces connecting from each vertex
  19268. function addVertexEdgeMap(vertex, edge) {
  19269. if (vertexEdgeMap[vertex]===undefined) {
  19270. vertexEdgeMap[vertex] = [];
  19271. }
  19272. vertexEdgeMap[vertex].push(edge);
  19273. }
  19274. function addVertexFaceMap(vertex, face, edge) {
  19275. if (vertexFaceMap[vertex]===undefined) {
  19276. vertexFaceMap[vertex] = {};
  19277. }
  19278. vertexFaceMap[vertex][face] = edge;
  19279. // vertexFaceMap[vertex][face] = null;
  19280. }
  19281. // Prepares vertexEdgeMap and vertexFaceMap
  19282. for (i in edgeFaceMap) { // This is for every edge
  19283. edge = edgeFaceMap[i];
  19284. edgeVertex = i.split('_');
  19285. edgeVertexA = edgeVertex[0];
  19286. edgeVertexB = edgeVertex[1];
  19287. // Maps an edgeVertex to connecting edges
  19288. addVertexEdgeMap(edgeVertexA, [edgeVertexA, edgeVertexB] );
  19289. addVertexEdgeMap(edgeVertexB, [edgeVertexA, edgeVertexB] );
  19290. for (j=0,jl=edge.length;j<jl;j++) {
  19291. face = edge[j];
  19292. addVertexFaceMap(edgeVertexA, face, i);
  19293. addVertexFaceMap(edgeVertexB, face, i);
  19294. }
  19295. if (edge.length < 2) {
  19296. // edge is "sharp";
  19297. sharpEdges[i] = true;
  19298. sharpVertices[edgeVertexA] = true;
  19299. sharpVertices[edgeVertexB] = true;
  19300. }
  19301. }
  19302. debug('vertexEdgeMap',vertexEdgeMap, 'vertexFaceMap', vertexFaceMap);
  19303. for (i in edgeFaceMap) {
  19304. edge = edgeFaceMap[i];
  19305. faceIndexA = edge[0]; // face index a
  19306. faceIndexB = edge[1]; // face index b
  19307. edgeVertex = i.split('_');
  19308. edgeVertexA = edgeVertex[0];
  19309. edgeVertexB = edgeVertex[1];
  19310. avg = new THREE.Vector3();
  19311. //debug(i, faceIndexB,facePoints[faceIndexB]);
  19312. if (sharpEdges[i]) {
  19313. //debug('warning, ', i, 'edge has only 1 connecting face', edge);
  19314. // For a sharp edge, average the edge end points.
  19315. avg.addSelf(originalPoints[edgeVertexA]);
  19316. avg.addSelf(originalPoints[edgeVertexB]);
  19317. avg.multiplyScalar(0.5);
  19318. sharpVertices[newPoints.length] = true;
  19319. } else {
  19320. avg.addSelf(facePoints[faceIndexA]);
  19321. avg.addSelf(facePoints[faceIndexB]);
  19322. avg.addSelf(originalPoints[edgeVertexA]);
  19323. avg.addSelf(originalPoints[edgeVertexB]);
  19324. avg.multiplyScalar(0.25);
  19325. }
  19326. edgePoints[i] = originalVerticesLength + originalFaces.length + edgeCount;
  19327. newPoints.push( avg );
  19328. edgeCount ++;
  19329. if (!scope.supportUVs) {
  19330. continue;
  19331. }
  19332. // debug('faceIndexAB', faceIndexA, faceIndexB, sharpEdges[i]);
  19333. // Prepare subdivided uv
  19334. avgUv = new THREE.UV();
  19335. avgUv.u = getUV(edgeVertexA, faceIndexA).u + getUV(edgeVertexB, faceIndexA).u;
  19336. avgUv.v = getUV(edgeVertexA, faceIndexA).v + getUV(edgeVertexB, faceIndexA).v;
  19337. avgUv.u /= 2;
  19338. avgUv.v /= 2;
  19339. addUV(edgePoints[i], faceIndexA, avgUv);
  19340. if (!sharpEdges[i]) {
  19341. avgUv = new THREE.UV();
  19342. avgUv.u = getUV(edgeVertexA, faceIndexB).u + getUV(edgeVertexB, faceIndexB).u;
  19343. avgUv.v = getUV(edgeVertexA, faceIndexB).v + getUV(edgeVertexB, faceIndexB).v;
  19344. avgUv.u /= 2;
  19345. avgUv.v /= 2;
  19346. addUV(edgePoints[i], faceIndexB, avgUv);
  19347. }
  19348. }
  19349. debug('-- Step 2 done');
  19350. // Step 3
  19351. // For each face point, add an edge for every edge of the face,
  19352. // connecting the face point to each edge point for the face.
  19353. var facePt, currentVerticeIndex;
  19354. var hashAB, hashBC, hashCD, hashDA, hashCA;
  19355. var abc123 = ['123', '12', '2', '23'];
  19356. var bca123 = ['123', '23', '3', '31'];
  19357. var cab123 = ['123', '31', '1', '12'];
  19358. var abc1234 = ['1234', '12', '2', '23'];
  19359. var bcd1234 = ['1234', '23', '3', '34'];
  19360. var cda1234 = ['1234', '34', '4', '41'];
  19361. var dab1234 = ['1234', '41', '1', '12'];
  19362. for (i=0, il = facePoints.length; i<il ;i++) { // for every face
  19363. facePt = facePoints[i];
  19364. face = originalFaces[i];
  19365. currentVerticeIndex = originalVerticesLength+ i;
  19366. if ( face instanceof THREE.Face3 ) {
  19367. // create 3 face4s
  19368. hashAB = edge_hash( face.a, face.b );
  19369. hashBC = edge_hash( face.b, face.c );
  19370. hashCA = edge_hash( face.c, face.a );
  19371. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc123, i );
  19372. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCA], face, bca123, i );
  19373. f4( currentVerticeIndex, edgePoints[hashCA], face.a, edgePoints[hashAB], face, cab123, i );
  19374. } else if ( face instanceof THREE.Face4 ) {
  19375. // create 4 face4s
  19376. hashAB = edge_hash( face.a, face.b );
  19377. hashBC = edge_hash( face.b, face.c );
  19378. hashCD = edge_hash( face.c, face.d );
  19379. hashDA = edge_hash( face.d, face.a );
  19380. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc1234, i );
  19381. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCD], face, bcd1234, i );
  19382. f4( currentVerticeIndex, edgePoints[hashCD], face.d, edgePoints[hashDA], face, cda1234, i );
  19383. f4( currentVerticeIndex, edgePoints[hashDA], face.a, edgePoints[hashAB], face, dab1234, i );
  19384. } else {
  19385. debug('face should be a face!', face);
  19386. }
  19387. }
  19388. newVertices = newPoints;
  19389. // debug('original ', oldGeometry.vertices.length, oldGeometry.faces.length );
  19390. // debug('new points', newPoints.length, 'faces', newFaces.length );
  19391. // Step 4
  19392. // For each original point P,
  19393. // take the average F of all n face points for faces touching P,
  19394. // and take the average R of all n edge midpoints for edges touching P,
  19395. // where each edge midpoint is the average of its two endpoint vertices.
  19396. // Move each original point to the point
  19397. var F = new THREE.Vector3();
  19398. var R = new THREE.Vector3();
  19399. var n;
  19400. for (i=0, il = originalPoints.length; i<il; i++) {
  19401. // (F + 2R + (n-3)P) / n
  19402. if (vertexEdgeMap[i]===undefined) continue;
  19403. F.set(0,0,0);
  19404. R.set(0,0,0);
  19405. var newPos = new THREE.Vector3(0,0,0);
  19406. var f =0;
  19407. for (j in vertexFaceMap[i]) {
  19408. F.addSelf(facePoints[j]);
  19409. f++;
  19410. }
  19411. var sharpEdgeCount = 0;
  19412. n = vertexEdgeMap[i].length;
  19413. for (j=0;j<n;j++) {
  19414. if (
  19415. sharpEdges[
  19416. edge_hash(vertexEdgeMap[i][j][0],vertexEdgeMap[i][j][1])
  19417. ]) {
  19418. sharpEdgeCount++;
  19419. }
  19420. }
  19421. if ( sharpEdgeCount==2 ) {
  19422. continue;
  19423. // Do not move vertex if there's 2 connecting sharp edges.
  19424. }
  19425. /*
  19426. if (sharpEdgeCount>2) {
  19427. // TODO
  19428. }
  19429. */
  19430. F.divideScalar(f);
  19431. for (j=0; j<n;j++) {
  19432. edge = vertexEdgeMap[i][j];
  19433. var midPt = originalPoints[edge[0]].clone().addSelf(originalPoints[edge[1]]).divideScalar(2);
  19434. R.addSelf(midPt);
  19435. // R.addSelf(originalPoints[edge[0]]);
  19436. // R.addSelf(originalPoints[edge[1]]);
  19437. }
  19438. R.divideScalar(n);
  19439. newPos.addSelf(originalPoints[i]);
  19440. newPos.multiplyScalar(n - 3);
  19441. newPos.addSelf(F);
  19442. newPos.addSelf(R.multiplyScalar(2));
  19443. newPos.divideScalar(n);
  19444. newVertices[i] = newPos;
  19445. }
  19446. var newGeometry = oldGeometry; // Let's pretend the old geometry is now new :P
  19447. newGeometry.vertices = newVertices;
  19448. newGeometry.faces = newFaces;
  19449. newGeometry.faceVertexUvs[ 0 ] = newUVs;
  19450. delete newGeometry.__tmpVertices; // makes __tmpVertices undefined :P
  19451. newGeometry.computeCentroids();
  19452. newGeometry.computeFaceNormals();
  19453. newGeometry.computeVertexNormals();
  19454. };
  19455. /**
  19456. * @author alteredq / http://alteredqualia.com/
  19457. */
  19458. THREE.ImmediateRenderObject = function ( ) {
  19459. THREE.Object3D.call( this );
  19460. this.render = function ( renderCallback ) { };
  19461. };
  19462. THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype );
  19463. /**
  19464. * @author mikael emtinger / http://gomo.se/
  19465. * @author alteredq / http://alteredqualia.com/
  19466. */
  19467. THREE.LensFlare = function ( texture, size, distance, blending, color ) {
  19468. THREE.Object3D.call( this );
  19469. this.lensFlares = [];
  19470. this.positionScreen = new THREE.Vector3();
  19471. this.customUpdateCallback = undefined;
  19472. if( texture !== undefined ) {
  19473. this.add( texture, size, distance, blending, color );
  19474. }
  19475. };
  19476. THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype );
  19477. /*
  19478. * Add: adds another flare
  19479. */
  19480. THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) {
  19481. if( size === undefined ) size = -1;
  19482. if( distance === undefined ) distance = 0;
  19483. if( opacity === undefined ) opacity = 1;
  19484. if( color === undefined ) color = new THREE.Color( 0xffffff );
  19485. if( blending === undefined ) blending = THREE.NormalBlending;
  19486. distance = Math.min( distance, Math.max( 0, distance ) );
  19487. this.lensFlares.push( { texture: texture, // THREE.Texture
  19488. size: size, // size in pixels (-1 = use texture.width)
  19489. distance: distance, // distance (0-1) from light source (0=at light source)
  19490. x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is ontop z = 1 is back
  19491. scale: 1, // scale
  19492. rotation: 1, // rotation
  19493. opacity: opacity, // opacity
  19494. color: color, // color
  19495. blending: blending } ); // blending
  19496. };
  19497. /*
  19498. * Update lens flares update positions on all flares based on the screen position
  19499. * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
  19500. */
  19501. THREE.LensFlare.prototype.updateLensFlares = function () {
  19502. var f, fl = this.lensFlares.length;
  19503. var flare;
  19504. var vecX = -this.positionScreen.x * 2;
  19505. var vecY = -this.positionScreen.y * 2;
  19506. for( f = 0; f < fl; f ++ ) {
  19507. flare = this.lensFlares[ f ];
  19508. flare.x = this.positionScreen.x + vecX * flare.distance;
  19509. flare.y = this.positionScreen.y + vecY * flare.distance;
  19510. flare.wantedRotation = flare.x * Math.PI * 0.25;
  19511. flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
  19512. }
  19513. };
  19514. /**
  19515. * @author alteredq / http://alteredqualia.com/
  19516. */
  19517. THREE.MorphBlendMesh = function( geometry, material ) {
  19518. THREE.Mesh.call( this, geometry, material );
  19519. this.animationsMap = {};
  19520. this.animationsList = [];
  19521. // prepare default animation
  19522. // (all frames played together in 1 second)
  19523. var numFrames = this.geometry.morphTargets.length;
  19524. var name = "__default";
  19525. var startFrame = 0;
  19526. var endFrame = numFrames - 1;
  19527. var fps = numFrames / 1;
  19528. this.createAnimation( name, startFrame, endFrame, fps );
  19529. this.setAnimationWeight( name, 1 );
  19530. };
  19531. THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype );
  19532. THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
  19533. var animation = {
  19534. startFrame: start,
  19535. endFrame: end,
  19536. length: end - start + 1,
  19537. fps: fps,
  19538. duration: ( end - start ) / fps,
  19539. lastFrame: 0,
  19540. currentFrame: 0,
  19541. active: false,
  19542. time: 0,
  19543. direction: 1,
  19544. weight: 1,
  19545. directionBackwards: false,
  19546. mirroredLoop: false
  19547. };
  19548. this.animationsMap[ name ] = animation;
  19549. this.animationsList.push( animation );
  19550. };
  19551. THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
  19552. var pattern = /([a-z]+)(\d+)/;
  19553. var firstAnimation, frameRanges = {};
  19554. var geometry = this.geometry;
  19555. for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
  19556. var morph = geometry.morphTargets[ i ];
  19557. var chunks = morph.name.match( pattern );
  19558. if ( chunks && chunks.length > 1 ) {
  19559. var name = chunks[ 1 ];
  19560. var num = chunks[ 2 ];
  19561. if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: -Infinity };
  19562. var range = frameRanges[ name ];
  19563. if ( i < range.start ) range.start = i;
  19564. if ( i > range.end ) range.end = i;
  19565. if ( ! firstAnimation ) firstAnimation = name;
  19566. }
  19567. }
  19568. for ( var name in frameRanges ) {
  19569. var range = frameRanges[ name ];
  19570. this.createAnimation( name, range.start, range.end, fps );
  19571. }
  19572. this.firstAnimation = firstAnimation;
  19573. };
  19574. THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
  19575. var animation = this.animationsMap[ name ];
  19576. if ( animation ) {
  19577. animation.direction = 1;
  19578. animation.directionBackwards = false;
  19579. }
  19580. };
  19581. THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
  19582. var animation = this.animationsMap[ name ];
  19583. if ( animation ) {
  19584. animation.direction = -1;
  19585. animation.directionBackwards = true;
  19586. }
  19587. };
  19588. THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
  19589. var animation = this.animationsMap[ name ];
  19590. if ( animation ) {
  19591. animation.fps = fps;
  19592. animation.duration = ( animation.end - animation.start ) / animation.fps;
  19593. }
  19594. };
  19595. THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
  19596. var animation = this.animationsMap[ name ];
  19597. if ( animation ) {
  19598. animation.duration = duration;
  19599. animation.fps = ( animation.end - animation.start ) / animation.duration;
  19600. }
  19601. };
  19602. THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
  19603. var animation = this.animationsMap[ name ];
  19604. if ( animation ) {
  19605. animation.weight = weight;
  19606. }
  19607. };
  19608. THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
  19609. var animation = this.animationsMap[ name ];
  19610. if ( animation ) {
  19611. animation.time = time;
  19612. }
  19613. };
  19614. THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
  19615. var time = 0;
  19616. var animation = this.animationsMap[ name ];
  19617. if ( animation ) {
  19618. time = animation.time;
  19619. }
  19620. return time;
  19621. };
  19622. THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
  19623. var duration = -1;
  19624. var animation = this.animationsMap[ name ];
  19625. if ( animation ) {
  19626. duration = animation.duration;
  19627. }
  19628. return duration;
  19629. };
  19630. THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
  19631. var animation = this.animationsMap[ name ];
  19632. if ( animation ) {
  19633. animation.time = 0;
  19634. animation.active = true;
  19635. } else {
  19636. console.warn( "animation[" + name + "] undefined" );
  19637. }
  19638. };
  19639. THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
  19640. var animation = this.animationsMap[ name ];
  19641. if ( animation ) {
  19642. animation.active = false;
  19643. }
  19644. };
  19645. THREE.MorphBlendMesh.prototype.update = function ( delta ) {
  19646. for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
  19647. var animation = this.animationsList[ i ];
  19648. if ( ! animation.active ) continue;
  19649. var frameTime = animation.duration / animation.length;
  19650. animation.time += animation.direction * delta;
  19651. if ( animation.mirroredLoop ) {
  19652. if ( animation.time > animation.duration || animation.time < 0 ) {
  19653. animation.direction *= -1;
  19654. if ( animation.time > animation.duration ) {
  19655. animation.time = animation.duration;
  19656. animation.directionBackwards = true;
  19657. }
  19658. if ( animation.time < 0 ) {
  19659. animation.time = 0;
  19660. animation.directionBackwards = false;
  19661. }
  19662. }
  19663. } else {
  19664. animation.time = animation.time % animation.duration;
  19665. if ( animation.time < 0 ) animation.time += animation.duration;
  19666. }
  19667. var keyframe = animation.startFrame + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
  19668. var weight = animation.weight;
  19669. if ( keyframe !== animation.currentFrame ) {
  19670. this.morphTargetInfluences[ animation.lastFrame ] = 0;
  19671. this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
  19672. this.morphTargetInfluences[ keyframe ] = 0;
  19673. animation.lastFrame = animation.currentFrame;
  19674. animation.currentFrame = keyframe;
  19675. }
  19676. var mix = ( animation.time % frameTime ) / frameTime;
  19677. if ( animation.directionBackwards ) mix = 1 - mix;
  19678. this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
  19679. this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
  19680. }
  19681. };
  19682. /**
  19683. * @author mikael emtinger / http://gomo.se/
  19684. * @author alteredq / http://alteredqualia.com/
  19685. */
  19686. THREE.LensFlarePlugin = function ( ) {
  19687. var _gl, _renderer, _lensFlare = {};
  19688. this.init = function ( renderer ) {
  19689. _gl = renderer.context;
  19690. _renderer = renderer;
  19691. _lensFlare.vertices = new Float32Array( 8 + 8 );
  19692. _lensFlare.faces = new Uint16Array( 6 );
  19693. var i = 0;
  19694. _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = -1; // vertex
  19695. _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 0; // uv... etc.
  19696. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = -1;
  19697. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 0;
  19698. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
  19699. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
  19700. _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = 1;
  19701. _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 1;
  19702. i = 0;
  19703. _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 1; _lensFlare.faces[ i++ ] = 2;
  19704. _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 2; _lensFlare.faces[ i++ ] = 3;
  19705. // buffers
  19706. _lensFlare.vertexBuffer = _gl.createBuffer();
  19707. _lensFlare.elementBuffer = _gl.createBuffer();
  19708. _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
  19709. _gl.bufferData( _gl.ARRAY_BUFFER, _lensFlare.vertices, _gl.STATIC_DRAW );
  19710. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
  19711. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.faces, _gl.STATIC_DRAW );
  19712. // textures
  19713. _lensFlare.tempTexture = _gl.createTexture();
  19714. _lensFlare.occlusionTexture = _gl.createTexture();
  19715. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  19716. _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, 16, 16, 0, _gl.RGB, _gl.UNSIGNED_BYTE, null );
  19717. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
  19718. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
  19719. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
  19720. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
  19721. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
  19722. _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, 16, 16, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null );
  19723. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
  19724. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
  19725. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
  19726. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
  19727. if ( _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) <= 0 ) {
  19728. _lensFlare.hasVertexTexture = false;
  19729. _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlare" ] );
  19730. } else {
  19731. _lensFlare.hasVertexTexture = true;
  19732. _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlareVertexTexture" ] );
  19733. }
  19734. _lensFlare.attributes = {};
  19735. _lensFlare.uniforms = {};
  19736. _lensFlare.attributes.vertex = _gl.getAttribLocation ( _lensFlare.program, "position" );
  19737. _lensFlare.attributes.uv = _gl.getAttribLocation ( _lensFlare.program, "uv" );
  19738. _lensFlare.uniforms.renderType = _gl.getUniformLocation( _lensFlare.program, "renderType" );
  19739. _lensFlare.uniforms.map = _gl.getUniformLocation( _lensFlare.program, "map" );
  19740. _lensFlare.uniforms.occlusionMap = _gl.getUniformLocation( _lensFlare.program, "occlusionMap" );
  19741. _lensFlare.uniforms.opacity = _gl.getUniformLocation( _lensFlare.program, "opacity" );
  19742. _lensFlare.uniforms.color = _gl.getUniformLocation( _lensFlare.program, "color" );
  19743. _lensFlare.uniforms.scale = _gl.getUniformLocation( _lensFlare.program, "scale" );
  19744. _lensFlare.uniforms.rotation = _gl.getUniformLocation( _lensFlare.program, "rotation" );
  19745. _lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" );
  19746. _lensFlare.attributesEnabled = false;
  19747. };
  19748. /*
  19749. * Render lens flares
  19750. * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
  19751. * reads these back and calculates occlusion.
  19752. * Then _lensFlare.update_lensFlares() is called to re-position and
  19753. * update transparency of flares. Then they are rendered.
  19754. *
  19755. */
  19756. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  19757. var flares = scene.__webglFlares,
  19758. nFlares = flares.length;
  19759. if ( ! nFlares ) return;
  19760. var tempPosition = new THREE.Vector3();
  19761. var invAspect = viewportHeight / viewportWidth,
  19762. halfViewportWidth = viewportWidth * 0.5,
  19763. halfViewportHeight = viewportHeight * 0.5;
  19764. var size = 16 / viewportHeight,
  19765. scale = new THREE.Vector2( size * invAspect, size );
  19766. var screenPosition = new THREE.Vector3( 1, 1, 0 ),
  19767. screenPositionPixels = new THREE.Vector2( 1, 1 );
  19768. var uniforms = _lensFlare.uniforms,
  19769. attributes = _lensFlare.attributes;
  19770. // set _lensFlare program and reset blending
  19771. _gl.useProgram( _lensFlare.program );
  19772. if ( ! _lensFlare.attributesEnabled ) {
  19773. _gl.enableVertexAttribArray( _lensFlare.attributes.vertex );
  19774. _gl.enableVertexAttribArray( _lensFlare.attributes.uv );
  19775. _lensFlare.attributesEnabled = true;
  19776. }
  19777. // loop through all lens flares to update their occlusion and positions
  19778. // setup gl and common used attribs/unforms
  19779. _gl.uniform1i( uniforms.occlusionMap, 0 );
  19780. _gl.uniform1i( uniforms.map, 1 );
  19781. _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
  19782. _gl.vertexAttribPointer( attributes.vertex, 2, _gl.FLOAT, false, 2 * 8, 0 );
  19783. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
  19784. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
  19785. _gl.disable( _gl.CULL_FACE );
  19786. _gl.depthMask( false );
  19787. var i, j, jl, flare, sprite;
  19788. for ( i = 0; i < nFlares; i ++ ) {
  19789. size = 16 / viewportHeight;
  19790. scale.set( size * invAspect, size );
  19791. // calc object screen position
  19792. flare = flares[ i ];
  19793. tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
  19794. camera.matrixWorldInverse.multiplyVector3( tempPosition );
  19795. camera.projectionMatrix.multiplyVector3( tempPosition );
  19796. // setup arrays for gl programs
  19797. screenPosition.copy( tempPosition )
  19798. screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
  19799. screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
  19800. // screen cull
  19801. if ( _lensFlare.hasVertexTexture || (
  19802. screenPositionPixels.x > 0 &&
  19803. screenPositionPixels.x < viewportWidth &&
  19804. screenPositionPixels.y > 0 &&
  19805. screenPositionPixels.y < viewportHeight ) ) {
  19806. // save current RGB to temp texture
  19807. _gl.activeTexture( _gl.TEXTURE1 );
  19808. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  19809. _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
  19810. // render pink quad
  19811. _gl.uniform1i( uniforms.renderType, 0 );
  19812. _gl.uniform2f( uniforms.scale, scale.x, scale.y );
  19813. _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
  19814. _gl.disable( _gl.BLEND );
  19815. _gl.enable( _gl.DEPTH_TEST );
  19816. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  19817. // copy result to occlusionMap
  19818. _gl.activeTexture( _gl.TEXTURE0 );
  19819. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
  19820. _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
  19821. // restore graphics
  19822. _gl.uniform1i( uniforms.renderType, 1 );
  19823. _gl.disable( _gl.DEPTH_TEST );
  19824. _gl.activeTexture( _gl.TEXTURE1 );
  19825. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  19826. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  19827. // update object positions
  19828. flare.positionScreen.copy( screenPosition )
  19829. if ( flare.customUpdateCallback ) {
  19830. flare.customUpdateCallback( flare );
  19831. } else {
  19832. flare.updateLensFlares();
  19833. }
  19834. // render flares
  19835. _gl.uniform1i( uniforms.renderType, 2 );
  19836. _gl.enable( _gl.BLEND );
  19837. for ( j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
  19838. sprite = flare.lensFlares[ j ];
  19839. if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
  19840. screenPosition.x = sprite.x;
  19841. screenPosition.y = sprite.y;
  19842. screenPosition.z = sprite.z;
  19843. size = sprite.size * sprite.scale / viewportHeight;
  19844. scale.x = size * invAspect;
  19845. scale.y = size;
  19846. _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
  19847. _gl.uniform2f( uniforms.scale, scale.x, scale.y );
  19848. _gl.uniform1f( uniforms.rotation, sprite.rotation );
  19849. _gl.uniform1f( uniforms.opacity, sprite.opacity );
  19850. _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
  19851. _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
  19852. _renderer.setTexture( sprite.texture, 1 );
  19853. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  19854. }
  19855. }
  19856. }
  19857. }
  19858. // restore gl
  19859. _gl.enable( _gl.CULL_FACE );
  19860. _gl.enable( _gl.DEPTH_TEST );
  19861. _gl.depthMask( true );
  19862. };
  19863. function createProgram ( shader ) {
  19864. var program = _gl.createProgram();
  19865. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  19866. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  19867. _gl.shaderSource( fragmentShader, shader.fragmentShader );
  19868. _gl.shaderSource( vertexShader, shader.vertexShader );
  19869. _gl.compileShader( fragmentShader );
  19870. _gl.compileShader( vertexShader );
  19871. _gl.attachShader( program, fragmentShader );
  19872. _gl.attachShader( program, vertexShader );
  19873. _gl.linkProgram( program );
  19874. return program;
  19875. };
  19876. };/**
  19877. * @author alteredq / http://alteredqualia.com/
  19878. */
  19879. THREE.ShadowMapPlugin = function ( ) {
  19880. var _gl,
  19881. _renderer,
  19882. _depthMaterial, _depthMaterialMorph, _depthMaterialSkin,
  19883. _frustum = new THREE.Frustum(),
  19884. _projScreenMatrix = new THREE.Matrix4(),
  19885. _min = new THREE.Vector3(),
  19886. _max = new THREE.Vector3();
  19887. this.init = function ( renderer ) {
  19888. _gl = renderer.context;
  19889. _renderer = renderer;
  19890. var depthShader = THREE.ShaderLib[ "depthRGBA" ];
  19891. var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
  19892. _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
  19893. _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
  19894. _depthMaterialSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, skinning: true } );
  19895. _depthMaterial._shadowPass = true;
  19896. _depthMaterialMorph._shadowPass = true;
  19897. _depthMaterialSkin._shadowPass = true;
  19898. };
  19899. this.render = function ( scene, camera ) {
  19900. if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
  19901. this.update( scene, camera );
  19902. };
  19903. this.update = function ( scene, camera ) {
  19904. var i, il, j, jl, n,
  19905. shadowMap, shadowMatrix, shadowCamera,
  19906. program, buffer, material,
  19907. webglObject, object, light,
  19908. renderList,
  19909. lights = [],
  19910. k = 0,
  19911. fog = null;
  19912. // set GL state for depth map
  19913. _gl.clearColor( 1, 1, 1, 1 );
  19914. _gl.disable( _gl.BLEND );
  19915. _gl.enable( _gl.CULL_FACE );
  19916. if ( _renderer.shadowMapCullFrontFaces ) {
  19917. _gl.cullFace( _gl.FRONT );
  19918. } else {
  19919. _gl.cullFace( _gl.BACK );
  19920. }
  19921. _renderer.setDepthTest( true );
  19922. // preprocess lights
  19923. // - skip lights that are not casting shadows
  19924. // - create virtual lights for cascaded shadow maps
  19925. for ( i = 0, il = scene.__lights.length; i < il; i ++ ) {
  19926. light = scene.__lights[ i ];
  19927. if ( ! light.castShadow ) continue;
  19928. if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {
  19929. for ( n = 0; n < light.shadowCascadeCount; n ++ ) {
  19930. var virtualLight;
  19931. if ( ! light.shadowCascadeArray[ n ] ) {
  19932. virtualLight = createVirtualLight( light, n );
  19933. virtualLight.originalCamera = camera;
  19934. var gyro = new THREE.Gyroscope();
  19935. gyro.position = light.shadowCascadeOffset;
  19936. gyro.add( virtualLight );
  19937. gyro.add( virtualLight.target );
  19938. camera.add( gyro );
  19939. light.shadowCascadeArray[ n ] = virtualLight;
  19940. console.log( "Created virtualLight", virtualLight );
  19941. } else {
  19942. virtualLight = light.shadowCascadeArray[ n ];
  19943. }
  19944. updateVirtualLight( light, n );
  19945. lights[ k ] = virtualLight;
  19946. k ++;
  19947. }
  19948. } else {
  19949. lights[ k ] = light;
  19950. k ++;
  19951. }
  19952. }
  19953. // render depth map
  19954. for ( i = 0, il = lights.length; i < il; i ++ ) {
  19955. light = lights[ i ];
  19956. if ( ! light.shadowMap ) {
  19957. var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
  19958. light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
  19959. light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
  19960. light.shadowMatrix = new THREE.Matrix4();
  19961. }
  19962. if ( ! light.shadowCamera ) {
  19963. if ( light instanceof THREE.SpotLight ) {
  19964. light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
  19965. } else if ( light instanceof THREE.DirectionalLight ) {
  19966. light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
  19967. } else {
  19968. console.error( "Unsupported light type for shadow" );
  19969. continue;
  19970. }
  19971. scene.add( light.shadowCamera );
  19972. if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
  19973. }
  19974. if ( light.shadowCameraVisible && ! light.cameraHelper ) {
  19975. light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
  19976. light.shadowCamera.add( light.cameraHelper );
  19977. }
  19978. if ( light.isVirtual && virtualLight.originalCamera == camera ) {
  19979. updateShadowCamera( camera, light );
  19980. }
  19981. shadowMap = light.shadowMap;
  19982. shadowMatrix = light.shadowMatrix;
  19983. shadowCamera = light.shadowCamera;
  19984. shadowCamera.position.copy( light.matrixWorld.getPosition() );
  19985. shadowCamera.lookAt( light.target.matrixWorld.getPosition() );
  19986. shadowCamera.updateMatrixWorld();
  19987. shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
  19988. if ( light.cameraHelper ) light.cameraHelper.lines.visible = light.shadowCameraVisible;
  19989. if ( light.shadowCameraVisible ) light.cameraHelper.update();
  19990. // compute shadow matrix
  19991. shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
  19992. 0.0, 0.5, 0.0, 0.5,
  19993. 0.0, 0.0, 0.5, 0.5,
  19994. 0.0, 0.0, 0.0, 1.0 );
  19995. shadowMatrix.multiplySelf( shadowCamera.projectionMatrix );
  19996. shadowMatrix.multiplySelf( shadowCamera.matrixWorldInverse );
  19997. // update camera matrices and frustum
  19998. if ( ! shadowCamera._viewMatrixArray ) shadowCamera._viewMatrixArray = new Float32Array( 16 );
  19999. if ( ! shadowCamera._projectionMatrixArray ) shadowCamera._projectionMatrixArray = new Float32Array( 16 );
  20000. shadowCamera.matrixWorldInverse.flattenToArray( shadowCamera._viewMatrixArray );
  20001. shadowCamera.projectionMatrix.flattenToArray( shadowCamera._projectionMatrixArray );
  20002. _projScreenMatrix.multiply( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
  20003. _frustum.setFromMatrix( _projScreenMatrix );
  20004. // render shadow map
  20005. _renderer.setRenderTarget( shadowMap );
  20006. _renderer.clear();
  20007. // set object matrices & frustum culling
  20008. renderList = scene.__webglObjects;
  20009. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20010. webglObject = renderList[ j ];
  20011. object = webglObject.object;
  20012. webglObject.render = false;
  20013. if ( object.visible && object.castShadow ) {
  20014. if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
  20015. object._modelViewMatrix.multiply( shadowCamera.matrixWorldInverse, object.matrixWorld );
  20016. webglObject.render = true;
  20017. }
  20018. }
  20019. }
  20020. // render regular objects
  20021. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20022. webglObject = renderList[ j ];
  20023. if ( webglObject.render ) {
  20024. object = webglObject.object;
  20025. buffer = webglObject.buffer;
  20026. // culling is overriden globally for all objects
  20027. // while rendering depth map
  20028. //_renderer.setObjectFaces( object );
  20029. if ( object.customDepthMaterial ) {
  20030. material = object.customDepthMaterial;
  20031. } else if ( object.geometry.morphTargets.length ) {
  20032. material = _depthMaterialMorph;
  20033. } else if ( object instanceof THREE.SkinnedMesh ) {
  20034. material = _depthMaterialSkin;
  20035. } else {
  20036. material = _depthMaterial;
  20037. }
  20038. if ( buffer instanceof THREE.BufferGeometry ) {
  20039. _renderer.renderBufferDirect( shadowCamera, scene.__lights, fog, material, buffer, object );
  20040. } else {
  20041. _renderer.renderBuffer( shadowCamera, scene.__lights, fog, material, buffer, object );
  20042. }
  20043. }
  20044. }
  20045. // set matrices and render immediate objects
  20046. renderList = scene.__webglObjectsImmediate;
  20047. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20048. webglObject = renderList[ j ];
  20049. object = webglObject.object;
  20050. if ( object.visible && object.castShadow ) {
  20051. object._modelViewMatrix.multiply( shadowCamera.matrixWorldInverse, object.matrixWorld );
  20052. _renderer.renderImmediateObject( shadowCamera, scene.__lights, fog, _depthMaterial, object );
  20053. }
  20054. }
  20055. }
  20056. // restore GL state
  20057. var clearColor = _renderer.getClearColor(),
  20058. clearAlpha = _renderer.getClearAlpha();
  20059. _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
  20060. _gl.enable( _gl.BLEND );
  20061. if ( _renderer.shadowMapCullFrontFaces ) {
  20062. _gl.cullFace( _gl.BACK );
  20063. }
  20064. };
  20065. function createVirtualLight( light, cascade ) {
  20066. var virtualLight = new THREE.DirectionalLight();
  20067. virtualLight.isVirtual = true;
  20068. virtualLight.onlyShadow = true;
  20069. virtualLight.castShadow = true;
  20070. virtualLight.shadowCameraNear = light.shadowCameraNear;
  20071. virtualLight.shadowCameraFar = light.shadowCameraFar;
  20072. virtualLight.shadowCameraLeft = light.shadowCameraLeft;
  20073. virtualLight.shadowCameraRight = light.shadowCameraRight;
  20074. virtualLight.shadowCameraBottom = light.shadowCameraBottom;
  20075. virtualLight.shadowCameraTop = light.shadowCameraTop;
  20076. virtualLight.shadowCameraVisible = light.shadowCameraVisible;
  20077. virtualLight.shadowDarkness = light.shadowDarkness;
  20078. virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
  20079. virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
  20080. virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];
  20081. virtualLight.pointsWorld = [];
  20082. virtualLight.pointsFrustum = [];
  20083. var pointsWorld = virtualLight.pointsWorld,
  20084. pointsFrustum = virtualLight.pointsFrustum;
  20085. for ( var i = 0; i < 8; i ++ ) {
  20086. pointsWorld[ i ] = new THREE.Vector3();
  20087. pointsFrustum[ i ] = new THREE.Vector3();
  20088. }
  20089. var nearZ = light.shadowCascadeNearZ[ cascade ];
  20090. var farZ = light.shadowCascadeFarZ[ cascade ];
  20091. pointsFrustum[ 0 ].set( -1, -1, nearZ );
  20092. pointsFrustum[ 1 ].set( 1, -1, nearZ );
  20093. pointsFrustum[ 2 ].set( -1, 1, nearZ );
  20094. pointsFrustum[ 3 ].set( 1, 1, nearZ );
  20095. pointsFrustum[ 4 ].set( -1, -1, farZ );
  20096. pointsFrustum[ 5 ].set( 1, -1, farZ );
  20097. pointsFrustum[ 6 ].set( -1, 1, farZ );
  20098. pointsFrustum[ 7 ].set( 1, 1, farZ );
  20099. return virtualLight;
  20100. }
  20101. // Synchronize virtual light with the original light
  20102. function updateVirtualLight( light, cascade ) {
  20103. var virtualLight = light.shadowCascadeArray[ cascade ];
  20104. virtualLight.position.copy( light.position );
  20105. virtualLight.target.position.copy( light.target.position );
  20106. virtualLight.lookAt( virtualLight.target );
  20107. virtualLight.shadowCameraVisible = light.shadowCameraVisible;
  20108. virtualLight.shadowDarkness = light.shadowDarkness;
  20109. virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
  20110. var nearZ = light.shadowCascadeNearZ[ cascade ];
  20111. var farZ = light.shadowCascadeFarZ[ cascade ];
  20112. var pointsFrustum = virtualLight.pointsFrustum;
  20113. pointsFrustum[ 0 ].z = nearZ;
  20114. pointsFrustum[ 1 ].z = nearZ;
  20115. pointsFrustum[ 2 ].z = nearZ;
  20116. pointsFrustum[ 3 ].z = nearZ;
  20117. pointsFrustum[ 4 ].z = farZ;
  20118. pointsFrustum[ 5 ].z = farZ;
  20119. pointsFrustum[ 6 ].z = farZ;
  20120. pointsFrustum[ 7 ].z = farZ;
  20121. }
  20122. // Fit shadow camera's ortho frustum to camera frustum
  20123. function updateShadowCamera( camera, light ) {
  20124. var shadowCamera = light.shadowCamera,
  20125. pointsFrustum = light.pointsFrustum,
  20126. pointsWorld = light.pointsWorld;
  20127. _min.set( Infinity, Infinity, Infinity );
  20128. _max.set( -Infinity, -Infinity, -Infinity );
  20129. for ( var i = 0; i < 8; i ++ ) {
  20130. var p = pointsWorld[ i ];
  20131. p.copy( pointsFrustum[ i ] );
  20132. THREE.ShadowMapPlugin.__projector.unprojectVector( p, camera );
  20133. shadowCamera.matrixWorldInverse.multiplyVector3( p );
  20134. if ( p.x < _min.x ) _min.x = p.x;
  20135. if ( p.x > _max.x ) _max.x = p.x;
  20136. if ( p.y < _min.y ) _min.y = p.y;
  20137. if ( p.y > _max.y ) _max.y = p.y;
  20138. if ( p.z < _min.z ) _min.z = p.z;
  20139. if ( p.z > _max.z ) _max.z = p.z;
  20140. }
  20141. shadowCamera.left = _min.x;
  20142. shadowCamera.right = _max.x;
  20143. shadowCamera.top = _max.y;
  20144. shadowCamera.bottom = _min.y;
  20145. // can't really fit near/far
  20146. //shadowCamera.near = _min.z;
  20147. //shadowCamera.far = _max.z;
  20148. shadowCamera.updateProjectionMatrix();
  20149. }
  20150. };
  20151. THREE.ShadowMapPlugin.__projector = new THREE.Projector();
  20152. /**
  20153. * @author mikael emtinger / http://gomo.se/
  20154. * @author alteredq / http://alteredqualia.com/
  20155. */
  20156. THREE.SpritePlugin = function ( ) {
  20157. var _gl, _renderer, _sprite = {};
  20158. this.init = function ( renderer ) {
  20159. _gl = renderer.context;
  20160. _renderer = renderer;
  20161. _sprite.vertices = new Float32Array( 8 + 8 );
  20162. _sprite.faces = new Uint16Array( 6 );
  20163. var i = 0;
  20164. _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = -1; // vertex 0
  20165. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // uv 0
  20166. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = -1; // vertex 1
  20167. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; // uv 1
  20168. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // vertex 2
  20169. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // uv 2
  20170. _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1; // vertex 3
  20171. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 1; // uv 3
  20172. i = 0;
  20173. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2;
  20174. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3;
  20175. _sprite.vertexBuffer = _gl.createBuffer();
  20176. _sprite.elementBuffer = _gl.createBuffer();
  20177. _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  20178. _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW );
  20179. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  20180. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW );
  20181. _sprite.program = createProgram( THREE.ShaderSprite[ "sprite" ] );
  20182. _sprite.attributes = {};
  20183. _sprite.uniforms = {};
  20184. _sprite.attributes.position = _gl.getAttribLocation ( _sprite.program, "position" );
  20185. _sprite.attributes.uv = _gl.getAttribLocation ( _sprite.program, "uv" );
  20186. _sprite.uniforms.uvOffset = _gl.getUniformLocation( _sprite.program, "uvOffset" );
  20187. _sprite.uniforms.uvScale = _gl.getUniformLocation( _sprite.program, "uvScale" );
  20188. _sprite.uniforms.rotation = _gl.getUniformLocation( _sprite.program, "rotation" );
  20189. _sprite.uniforms.scale = _gl.getUniformLocation( _sprite.program, "scale" );
  20190. _sprite.uniforms.alignment = _gl.getUniformLocation( _sprite.program, "alignment" );
  20191. _sprite.uniforms.color = _gl.getUniformLocation( _sprite.program, "color" );
  20192. _sprite.uniforms.map = _gl.getUniformLocation( _sprite.program, "map" );
  20193. _sprite.uniforms.opacity = _gl.getUniformLocation( _sprite.program, "opacity" );
  20194. _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" );
  20195. _sprite.uniforms.affectedByDistance = _gl.getUniformLocation( _sprite.program, "affectedByDistance" );
  20196. _sprite.uniforms.screenPosition = _gl.getUniformLocation( _sprite.program, "screenPosition" );
  20197. _sprite.uniforms.modelViewMatrix = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" );
  20198. _sprite.uniforms.projectionMatrix = _gl.getUniformLocation( _sprite.program, "projectionMatrix" );
  20199. _sprite.attributesEnabled = false;
  20200. };
  20201. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  20202. var sprites = scene.__webglSprites,
  20203. nSprites = sprites.length;
  20204. if ( ! nSprites ) return;
  20205. var attributes = _sprite.attributes,
  20206. uniforms = _sprite.uniforms;
  20207. var invAspect = viewportHeight / viewportWidth;
  20208. var halfViewportWidth = viewportWidth * 0.5,
  20209. halfViewportHeight = viewportHeight * 0.5;
  20210. var mergeWith3D = true;
  20211. // setup gl
  20212. _gl.useProgram( _sprite.program );
  20213. if ( ! _sprite.attributesEnabled ) {
  20214. _gl.enableVertexAttribArray( attributes.position );
  20215. _gl.enableVertexAttribArray( attributes.uv );
  20216. _sprite.attributesEnabled = true;
  20217. }
  20218. _gl.disable( _gl.CULL_FACE );
  20219. _gl.enable( _gl.BLEND );
  20220. _gl.depthMask( true );
  20221. _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  20222. _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
  20223. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
  20224. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  20225. _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera._projectionMatrixArray );
  20226. _gl.activeTexture( _gl.TEXTURE0 );
  20227. _gl.uniform1i( uniforms.map, 0 );
  20228. // update positions and sort
  20229. var i, sprite, screenPosition, size, scale = [];
  20230. for( i = 0; i < nSprites; i ++ ) {
  20231. sprite = sprites[ i ];
  20232. if ( ! sprite.visible || sprite.opacity === 0 ) continue;
  20233. if( ! sprite.useScreenCoordinates ) {
  20234. sprite._modelViewMatrix.multiply( camera.matrixWorldInverse, sprite.matrixWorld );
  20235. sprite.z = - sprite._modelViewMatrix.elements[14];
  20236. } else {
  20237. sprite.z = - sprite.position.z;
  20238. }
  20239. }
  20240. sprites.sort( painterSort );
  20241. // render all sprites
  20242. for( i = 0; i < nSprites; i ++ ) {
  20243. sprite = sprites[ i ];
  20244. if ( ! sprite.visible || sprite.opacity === 0 ) continue;
  20245. if ( sprite.map && sprite.map.image && sprite.map.image.width ) {
  20246. if ( sprite.useScreenCoordinates ) {
  20247. _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
  20248. _gl.uniform3f( uniforms.screenPosition, ( sprite.position.x - halfViewportWidth ) / halfViewportWidth,
  20249. ( halfViewportHeight - sprite.position.y ) / halfViewportHeight,
  20250. Math.max( 0, Math.min( 1, sprite.position.z ) ) );
  20251. } else {
  20252. _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
  20253. _gl.uniform1i( uniforms.affectedByDistance, sprite.affectedByDistance ? 1 : 0 );
  20254. _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
  20255. }
  20256. size = sprite.map.image.width / ( sprite.scaleByViewport ? viewportHeight : 1 );
  20257. scale[ 0 ] = size * invAspect * sprite.scale.x;
  20258. scale[ 1 ] = size * sprite.scale.y;
  20259. _gl.uniform2f( uniforms.uvScale, sprite.uvScale.x, sprite.uvScale.y );
  20260. _gl.uniform2f( uniforms.uvOffset, sprite.uvOffset.x, sprite.uvOffset.y );
  20261. _gl.uniform2f( uniforms.alignment, sprite.alignment.x, sprite.alignment.y );
  20262. _gl.uniform1f( uniforms.opacity, sprite.opacity );
  20263. _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
  20264. _gl.uniform1f( uniforms.rotation, sprite.rotation );
  20265. _gl.uniform2fv( uniforms.scale, scale );
  20266. if ( sprite.mergeWith3D && !mergeWith3D ) {
  20267. _gl.enable( _gl.DEPTH_TEST );
  20268. mergeWith3D = true;
  20269. } else if ( ! sprite.mergeWith3D && mergeWith3D ) {
  20270. _gl.disable( _gl.DEPTH_TEST );
  20271. mergeWith3D = false;
  20272. }
  20273. _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
  20274. _renderer.setTexture( sprite.map, 0 );
  20275. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  20276. }
  20277. }
  20278. // restore gl
  20279. _gl.enable( _gl.CULL_FACE );
  20280. _gl.enable( _gl.DEPTH_TEST );
  20281. _gl.depthMask( true );
  20282. };
  20283. function createProgram ( shader ) {
  20284. var program = _gl.createProgram();
  20285. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  20286. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  20287. _gl.shaderSource( fragmentShader, shader.fragmentShader );
  20288. _gl.shaderSource( vertexShader, shader.vertexShader );
  20289. _gl.compileShader( fragmentShader );
  20290. _gl.compileShader( vertexShader );
  20291. _gl.attachShader( program, fragmentShader );
  20292. _gl.attachShader( program, vertexShader );
  20293. _gl.linkProgram( program );
  20294. return program;
  20295. };
  20296. function painterSort ( a, b ) {
  20297. return b.z - a.z;
  20298. };
  20299. };/**
  20300. * @author alteredq / http://alteredqualia.com/
  20301. */
  20302. THREE.DepthPassPlugin = function ( ) {
  20303. this.enabled = false;
  20304. this.renderTarget = null;
  20305. var _gl,
  20306. _renderer,
  20307. _depthMaterial, _depthMaterialMorph,
  20308. _frustum = new THREE.Frustum(),
  20309. _projScreenMatrix = new THREE.Matrix4();
  20310. this.init = function ( renderer ) {
  20311. _gl = renderer.context;
  20312. _renderer = renderer;
  20313. var depthShader = THREE.ShaderLib[ "depthRGBA" ];
  20314. var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
  20315. _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
  20316. _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
  20317. _depthMaterial._shadowPass = true;
  20318. _depthMaterialMorph._shadowPass = true;
  20319. };
  20320. this.render = function ( scene, camera ) {
  20321. if ( ! this.enabled ) return;
  20322. this.update( scene, camera );
  20323. };
  20324. this.update = function ( scene, camera ) {
  20325. var i, il, j, jl, n,
  20326. program, buffer, material,
  20327. webglObject, object, light,
  20328. renderList,
  20329. fog = null;
  20330. // set GL state for depth map
  20331. _gl.clearColor( 1, 1, 1, 1 );
  20332. _gl.disable( _gl.BLEND );
  20333. _renderer.setDepthTest( true );
  20334. // update scene
  20335. if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
  20336. // update camera matrices and frustum
  20337. if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
  20338. if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
  20339. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  20340. camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
  20341. camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
  20342. _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
  20343. _frustum.setFromMatrix( _projScreenMatrix );
  20344. // render depth map
  20345. _renderer.setRenderTarget( this.renderTarget );
  20346. _renderer.clear();
  20347. // set object matrices & frustum culling
  20348. renderList = scene.__webglObjects;
  20349. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20350. webglObject = renderList[ j ];
  20351. object = webglObject.object;
  20352. webglObject.render = false;
  20353. if ( object.visible ) {
  20354. if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
  20355. //object.matrixWorld.flattenToArray( object._objectMatrixArray );
  20356. object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld);
  20357. webglObject.render = true;
  20358. }
  20359. }
  20360. }
  20361. // render regular objects
  20362. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20363. webglObject = renderList[ j ];
  20364. if ( webglObject.render ) {
  20365. object = webglObject.object;
  20366. buffer = webglObject.buffer;
  20367. _renderer.setObjectFaces( object );
  20368. if ( object.customDepthMaterial ) {
  20369. material = object.customDepthMaterial;
  20370. } else if ( object.geometry.morphTargets.length ) {
  20371. material = _depthMaterialMorph;
  20372. } else {
  20373. material = _depthMaterial;
  20374. }
  20375. if ( buffer instanceof THREE.BufferGeometry ) {
  20376. _renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object );
  20377. } else {
  20378. _renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object );
  20379. }
  20380. }
  20381. }
  20382. // set matrices and render immediate objects
  20383. renderList = scene.__webglObjectsImmediate;
  20384. for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
  20385. webglObject = renderList[ j ];
  20386. object = webglObject.object;
  20387. if ( object.visible && object.castShadow ) {
  20388. /*
  20389. if ( object.matrixAutoUpdate ) {
  20390. object.matrixWorld.flattenToArray( object._objectMatrixArray );
  20391. }
  20392. */
  20393. object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld);
  20394. _renderer.renderImmediateObject( camera, scene.__lights, fog, _depthMaterial, object );
  20395. }
  20396. }
  20397. // restore GL state
  20398. var clearColor = _renderer.getClearColor(),
  20399. clearAlpha = _renderer.getClearAlpha();
  20400. _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
  20401. _gl.enable( _gl.BLEND );
  20402. };
  20403. };
  20404. /**
  20405. * @author mikael emtinger / http://gomo.se/
  20406. *
  20407. */
  20408. THREE.ShaderFlares = {
  20409. 'lensFlareVertexTexture': {
  20410. vertexShader: [
  20411. "uniform vec3 screenPosition;",
  20412. "uniform vec2 scale;",
  20413. "uniform float rotation;",
  20414. "uniform int renderType;",
  20415. "uniform sampler2D occlusionMap;",
  20416. "attribute vec2 position;",
  20417. "attribute vec2 uv;",
  20418. "varying vec2 vUV;",
  20419. "varying float vVisibility;",
  20420. "void main() {",
  20421. "vUV = uv;",
  20422. "vec2 pos = position;",
  20423. "if( renderType == 2 ) {",
  20424. "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +",
  20425. "texture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +",
  20426. "texture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +",
  20427. "texture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +",
  20428. "texture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +",
  20429. "texture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +",
  20430. "texture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +",
  20431. "texture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +",
  20432. "texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
  20433. "vVisibility = ( visibility.r / 9.0 ) *",
  20434. "( 1.0 - visibility.g / 9.0 ) *",
  20435. "( visibility.b / 9.0 ) *",
  20436. "( 1.0 - visibility.a / 9.0 );",
  20437. "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
  20438. "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
  20439. "}",
  20440. "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
  20441. "}"
  20442. ].join( "\n" ),
  20443. fragmentShader: [
  20444. "precision mediump float;",
  20445. "uniform sampler2D map;",
  20446. "uniform float opacity;",
  20447. "uniform int renderType;",
  20448. "uniform vec3 color;",
  20449. "varying vec2 vUV;",
  20450. "varying float vVisibility;",
  20451. "void main() {",
  20452. // pink square
  20453. "if( renderType == 0 ) {",
  20454. "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );",
  20455. // restore
  20456. "} else if( renderType == 1 ) {",
  20457. "gl_FragColor = texture2D( map, vUV );",
  20458. // flare
  20459. "} else {",
  20460. "vec4 texture = texture2D( map, vUV );",
  20461. "texture.a *= opacity * vVisibility;",
  20462. "gl_FragColor = texture;",
  20463. "gl_FragColor.rgb *= color;",
  20464. "}",
  20465. "}"
  20466. ].join( "\n" )
  20467. },
  20468. 'lensFlare': {
  20469. vertexShader: [
  20470. "uniform vec3 screenPosition;",
  20471. "uniform vec2 scale;",
  20472. "uniform float rotation;",
  20473. "uniform int renderType;",
  20474. "attribute vec2 position;",
  20475. "attribute vec2 uv;",
  20476. "varying vec2 vUV;",
  20477. "void main() {",
  20478. "vUV = uv;",
  20479. "vec2 pos = position;",
  20480. "if( renderType == 2 ) {",
  20481. "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
  20482. "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
  20483. "}",
  20484. "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
  20485. "}"
  20486. ].join( "\n" ),
  20487. fragmentShader: [
  20488. "precision mediump float;",
  20489. "uniform sampler2D map;",
  20490. "uniform sampler2D occlusionMap;",
  20491. "uniform float opacity;",
  20492. "uniform int renderType;",
  20493. "uniform vec3 color;",
  20494. "varying vec2 vUV;",
  20495. "void main() {",
  20496. // pink square
  20497. "if( renderType == 0 ) {",
  20498. "gl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );",
  20499. // restore
  20500. "} else if( renderType == 1 ) {",
  20501. "gl_FragColor = texture2D( map, vUV );",
  20502. // flare
  20503. "} else {",
  20504. "float visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +",
  20505. "texture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +",
  20506. "texture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +",
  20507. "texture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;",
  20508. "visibility = ( 1.0 - visibility / 4.0 );",
  20509. "vec4 texture = texture2D( map, vUV );",
  20510. "texture.a *= opacity * visibility;",
  20511. "gl_FragColor = texture;",
  20512. "gl_FragColor.rgb *= color;",
  20513. "}",
  20514. "}"
  20515. ].join( "\n" )
  20516. }
  20517. };
  20518. /**
  20519. * @author mikael emtinger / http://gomo.se/
  20520. *
  20521. */
  20522. THREE.ShaderSprite = {
  20523. 'sprite': {
  20524. vertexShader: [
  20525. "uniform int useScreenCoordinates;",
  20526. "uniform int affectedByDistance;",
  20527. "uniform vec3 screenPosition;",
  20528. "uniform mat4 modelViewMatrix;",
  20529. "uniform mat4 projectionMatrix;",
  20530. "uniform float rotation;",
  20531. "uniform vec2 scale;",
  20532. "uniform vec2 alignment;",
  20533. "uniform vec2 uvOffset;",
  20534. "uniform vec2 uvScale;",
  20535. "attribute vec2 position;",
  20536. "attribute vec2 uv;",
  20537. "varying vec2 vUV;",
  20538. "void main() {",
  20539. "vUV = uvOffset + uv * uvScale;",
  20540. "vec2 alignedPosition = position + alignment;",
  20541. "vec2 rotatedPosition;",
  20542. "rotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;",
  20543. "rotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;",
  20544. "vec4 finalPosition;",
  20545. "if( useScreenCoordinates != 0 ) {",
  20546. "finalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );",
  20547. "} else {",
  20548. "finalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );",
  20549. "finalPosition.xy += rotatedPosition * ( affectedByDistance == 1 ? 1.0 : finalPosition.z );",
  20550. "}",
  20551. "gl_Position = finalPosition;",
  20552. "}"
  20553. ].join( "\n" ),
  20554. fragmentShader: [
  20555. "precision mediump float;",
  20556. "uniform vec3 color;",
  20557. "uniform sampler2D map;",
  20558. "uniform float opacity;",
  20559. "varying vec2 vUV;",
  20560. "void main() {",
  20561. "vec4 texture = texture2D( map, vUV );",
  20562. "gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );",
  20563. "}"
  20564. ].join( "\n" )
  20565. }
  20566. };