threejs.js 260 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. function rebuildAllMaterials( obj )
  15. {
  16. if( obj === undefined )
  17. {
  18. for(var i in this.state.scenes)
  19. {
  20. rebuildAllMaterials.call( this, this.state.scenes[i].threeScene );
  21. }
  22. } else {
  23. if(obj && obj.material)
  24. {
  25. obj.material.needsUpdate = true;
  26. }
  27. if(obj && obj.children)
  28. {
  29. for(var i in obj.children)
  30. rebuildAllMaterials.call( this, obj.children[i] );
  31. }
  32. }
  33. }
  34. function matCpy( mat )
  35. {
  36. var ret = [];
  37. for ( var i =0; i < mat.length; i++ )
  38. ret.push( mat[i] );
  39. // I don't think there is any reason we need to copy the return array
  40. return ret;
  41. // return ret.slice(0);
  42. }
  43. define( [ "module",
  44. "vwf/model",
  45. "vwf/utility",
  46. "vwf/utility/color",
  47. "jquery"
  48. ],
  49. function( module, model, utility, Color, $ ) {
  50. var self;
  51. var checkLights = true;
  52. var sceneCreated = false;
  53. return model.load( module, {
  54. // == Module Definition ====================================================================
  55. // -- initialize ---------------------------------------------------------------------------
  56. initialize: function() {
  57. self = this;
  58. checkCompatibility.call(this);
  59. this.state.scenes = {}; // id => { glgeDocument: new GLGE.Document(), glgeRenderer: new GLGE.Renderer(), glgeScene: new GLGE.Scene() }
  60. this.state.nodes = {}; // id => { name: string, glgeObject: GLGE.Object, GLGE.Collada, GLGE.Light, or other...? }
  61. this.state.prototypes = {};
  62. this.state.kernel = this.kernel.kernel.kernel;
  63. this.state.lights = {};
  64. this.state.setMeshPropertyRecursively = function( threeObject, propertyName, value ) {
  65. if ( !threeObject ) {
  66. return;
  67. }
  68. threeObject[ propertyName ] = value;
  69. var meshes = findAllMeshes( threeObject );
  70. for ( var i = 0; i < meshes.length; i++ ) {
  71. meshes[ i ][ propertyName ] = value;
  72. }
  73. }
  74. this.state.setGeometryPropertyRecursively = function( threeObject, propertyName, value ) {
  75. if ( !threeObject ) {
  76. return;
  77. }
  78. threeObject[ propertyName ] = value;
  79. var geoList = findAllGeometries( threeObject );
  80. for ( var i = 0; i < geoList.length; i++ ) {
  81. geoList[ i ][ propertyName ] = value;
  82. }
  83. }
  84. // turns on logger debugger console messages
  85. this.debug = {
  86. "creation": false,
  87. "initializing": false,
  88. "parenting": false,
  89. "deleting": false,
  90. "properties": false,
  91. "setting": false,
  92. "getting": false,
  93. "prototypes": false
  94. };
  95. },
  96. // == Model API ============================================================================
  97. // -- creatingNode ------------------------------------------------------------------------
  98. creatingNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  99. childSource, childType, childIndex, childName, callback ) {
  100. self = this;
  101. // If the parent nodeID is 0, this node is attached directly to the root and is therefore either
  102. // the scene or a prototype. In either of those cases, save the uri of the new node
  103. var childURI = ( nodeID === 0 ? childIndex : undefined );
  104. var appID = this.kernel.application();
  105. if ( this.debug.creation ) {
  106. this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
  107. }
  108. // If the node being created is a prototype, construct it and add it to the array of prototypes,
  109. // and then return
  110. var prototypeID = utility.ifPrototypeGetId( appID, this.state.prototypes, nodeID, childID );
  111. if ( prototypeID !== undefined ) {
  112. if ( this.debug.prototypes ) {
  113. this.logger.infox( "prototype: ", prototypeID );
  114. }
  115. this.state.prototypes[ prototypeID ] = {
  116. parentID: nodeID,
  117. ID: childID,
  118. extendsID: childExtendsID,
  119. implementsID: childImplementsIDs,
  120. source: childSource,
  121. type: childType,
  122. uri: childURI,
  123. name: childName,
  124. };
  125. return;
  126. }
  127. var node = undefined;
  128. var parentNode;
  129. var threeChild;
  130. var threeParent;
  131. var waiting = false;
  132. if ( nodeID )
  133. {
  134. parentNode = this.state.nodes[ nodeID ];
  135. // If parent is not a node, see if it is a scene
  136. if ( !parentNode )
  137. parentNode = this.state.scenes[ nodeID ];
  138. if ( parentNode )
  139. {
  140. threeParent = parentNode.threeObject ? parentNode.threeObject : parentNode.threeScene;
  141. if ( threeParent && childName )
  142. {
  143. threeChild = FindChildByName.call( this,threeParent,childName,childExtendsID,false );
  144. }
  145. }
  146. }
  147. var kernel = this.kernel.kernel.kernel;
  148. var protos = getPrototypes.call( this, kernel, childExtendsID );
  149. if ( isSceneDefinition.call(this, protos) && childID == this.kernel.application() )
  150. {
  151. var sceneNode = CreateThreeJSSceneNode( nodeID, childID, childExtendsID );
  152. this.state.scenes[ childID ] = sceneNode;
  153. this.state.cameraInUse = sceneNode.camera.defaultCamera;
  154. sceneCreated = true;
  155. if ( childImplementsIDs && childImplementsIDs.length > 0 ) {
  156. for ( var i = 0; i < childImplementsIDs.length; i++ ) {
  157. switch ( childImplementsIDs[ i ] ) {
  158. case "http://vwf.example.com/threejs/fogExp2.vwf":
  159. sceneNode.threeScene.fog = new THREE.FogExp2( 0x000000 );
  160. break;
  161. case "http://vwf.example.com/threejs/fog.vwf":
  162. sceneNode.threeScene.fog = new THREE.Fog( 0x000000 );
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. if ( protos && isCameraDefinition.call( this, protos ) ) {
  169. var sceneID = this.kernel.application();
  170. var camName = this.kernel.name( childID );
  171. var sceneNode = this.state.scenes[ sceneID ];
  172. node = this.state.nodes[ childID ] = {
  173. name: childName,
  174. threeObject: threeChild,
  175. ID: childID,
  176. parentID: nodeID,
  177. sceneID: this.kernel.application(),
  178. threeScene: sceneNode ? sceneNode.threeScene : undefined,
  179. type: childExtendsID,
  180. sourceType: childType,
  181. prototypes: protos
  182. };
  183. // if there was not a preexisting object, then you have to make a new camera
  184. if ( node.threeObject === undefined ) {
  185. if ( nodeID === sceneID && childName === "camera" ) {
  186. node.threeObject = sceneNode.camera.defaultCamera;
  187. if ( sceneNode.camera.ID !== undefined ) {
  188. sceneNode.camera.ID = childID;
  189. }
  190. } else {
  191. createCamera.call( this, nodeID, childID, childName );
  192. }
  193. }
  194. } else if(protos && isLightDefinition.call( this, protos )) {
  195. node = this.state.nodes[ childID ] = this.state.lights[ childID ] = {
  196. name: childName,
  197. threeObject: threeChild,
  198. ID: childID,
  199. parentID: nodeID,
  200. type: childExtendsID,
  201. sourceType: childType,
  202. };
  203. if ( !node.threeObject ) {
  204. createLight.call( this, nodeID, childID, childExtendsID, childName );
  205. } else {
  206. if ( !( node.threeObject instanceof THREE.Light ) ) {
  207. if ( node.threeObject.children ) {
  208. var child = undefined;
  209. var light = undefined;
  210. for ( var j = 0; light === undefined &&
  211. j < node.threeObject.children.length; j++ ) {
  212. child = node.threeObject.children[ j ];
  213. switch ( childExtendsID ) {
  214. case "http://vwf.example.com/directionallight.vwf":
  215. if ( child instanceof THREE.DirectionalLight ) {
  216. light = child;
  217. }
  218. break;
  219. case "http://vwf.example.com/spotlight.vwf":
  220. if ( child instanceof THREE.SpotLight ) {
  221. light = child;
  222. }
  223. break;
  224. case "http://vwf.example.com/hemispherelight.vwf":
  225. if ( child instanceof THREE.HemisphereLight ) {
  226. light = child;
  227. }
  228. break;
  229. case "http://vwf.example.com/pointlight.vwf":
  230. default:
  231. if ( child instanceof THREE.PointLight ) {
  232. light = child;
  233. }
  234. break;
  235. }
  236. }
  237. if ( light !== undefined ) {
  238. node.threeObject = light;
  239. }
  240. }
  241. }
  242. }
  243. } else if ( protos && isMaterialDefinition.call( this, protos ) ) {
  244. var mat;
  245. var matDef = undefined;
  246. if ( parentNode && parentNode.threeObject ) {
  247. mat = GetMaterial( parentNode.threeObject, childName );
  248. }
  249. node = this.state.nodes[childID] = {
  250. name: childName,
  251. threeObject: mat,
  252. ID: childID,
  253. parentID: nodeID,
  254. type: childExtendsID,
  255. sourceType: childType
  256. };
  257. if ( childType !== undefined ) {
  258. if ( childType !== "material/definition" ) {
  259. // define childType to be one of the material types
  260. // then the uniform properties and be set in the
  261. // uniforms component as a child of this component
  262. matDef = { "type": childType };
  263. }
  264. } else if ( !node.threeObject ) {
  265. matDef = { "type": "MeshPhongMaterial" };
  266. }
  267. if ( matDef !== undefined ) {
  268. node.threeObject = createMaterial( matDef );
  269. if ( node.threeObject ) {
  270. if ( parentNode && parentNode.threeObject ) {
  271. SetMaterial( parentNode.threeObject, node.threeObject, childName );
  272. } else {
  273. console.info( "unable to find: " + nodeID );
  274. }
  275. }
  276. }
  277. } else if ( protos && isShaderMaterialDefinition.call( this, protos ) ) {
  278. node = this.state.nodes[ childID ] = {
  279. name: childName,
  280. //threeObject: GetMaterial( parentNode.threeObject, childName ),
  281. threeObject: undefined,
  282. ID: childID,
  283. parentID: nodeID,
  284. type: childExtendsID,
  285. sourceType: childType
  286. };
  287. if ( childType !== undefined ) {
  288. if ( childType !== "shader/definition" ) {
  289. // define childType to be one of the preexisting shaderTypes
  290. // then the uniform properties and be set in the
  291. // uniforms component as a child of this component
  292. node.threeObject = createMaterial( { "type": 'ShaderMaterial', "shaderType": childType } );
  293. node.shaderType = childType;
  294. }
  295. } else {
  296. node.threeObject = new THREE.ShaderMaterial();
  297. }
  298. if ( node.threeObject ) {
  299. if ( parentNode && parentNode.threeObject ) {
  300. SetMaterial( parentNode.threeObject, node.threeObject, childName );
  301. }
  302. }
  303. } else if ( protos && isShaderUniformsDefinition.call( this, protos ) ) {
  304. var mat = this.state.nodes[ nodeID ];
  305. node = this.state.nodes[ childID ] = {
  306. name: childName,
  307. threeObject: undefined,
  308. ID: childID,
  309. parentID: nodeID,
  310. type: childExtendsID,
  311. sourceType: childType,
  312. isUniformObject: true
  313. };
  314. if ( mat ) {
  315. node.threeObject = mat.threeObject.uniforms;
  316. }
  317. } else if ( protos && isTextureDefinition.call( this, protos ) ) {
  318. var mat = this.state.nodes[ nodeID ];
  319. node = this.state.nodes[ childID ] = {
  320. name: childName,
  321. threeObject: undefined,
  322. ID: childID,
  323. parentID: nodeID,
  324. type: childExtendsID,
  325. sourceType: childType,
  326. isUniformObject: true
  327. };
  328. if ( mat ) {
  329. node.threeObject = mat.threeObject.map;
  330. }
  331. } else if ( protos && isParticleDefinition.call( this, protos ) ) {
  332. node = this.state.nodes[childID] = {
  333. name: childName,
  334. threeObject: threeChild,
  335. ID: childID,
  336. parentID: nodeID,
  337. type: childExtendsID,
  338. sourceType: childType,
  339. };
  340. if(!node.threeObject)
  341. {
  342. CreateParticleSystem.call(this,nodeID,childID,childName);
  343. }
  344. } else if ( protos && isNodeDefinition.call( this, protos ) && childName !== undefined ) {
  345. var sceneNode = this.state.scenes[ this.kernel.application() ];
  346. if ( supportedFileType( childType ) ) {
  347. // Most often this callback is used to suspend the queue until the load is complete
  348. callback( false );
  349. node = this.state.nodes[ childID ] = {
  350. name: childName,
  351. threeObject: threeChild,
  352. source: utility.resolveURI( childSource, this.kernel.uri( childID, true ) ),
  353. ID: childID,
  354. parentID: nodeID,
  355. sourceType: childType,
  356. type: childExtendsID,
  357. // Hang on to the callback and call it again in assetLoaded with ready=true
  358. loadingCallback: callback,
  359. sceneID: this.kernel.application()
  360. };
  361. loadAsset.call( this, parentNode, node, childType, notifyDriverOfPrototypeAndBehaviorProps );
  362. }
  363. else if ( childType == "mesh/definition" ) {
  364. //callback( false );
  365. node = this.state.nodes[ childID ] = {
  366. name: childName,
  367. source: utility.resolveURI( childSource, this.kernel.uri( childID, true ) ),
  368. ID: childID,
  369. parentID: nodeID,
  370. sourceType: childType,
  371. type: childExtendsID,
  372. sceneID: this.kernel.application(),
  373. prototypes: protos,
  374. };
  375. node.threeObject = new THREE.Object3D();
  376. node.threeObject.name = childName;
  377. if ( threeParent !== undefined ) {
  378. threeParent.add( node.threeObject );
  379. }
  380. } else {
  381. node = this.state.nodes[childID] = {
  382. name: childName,
  383. threeObject: threeChild,
  384. source: utility.resolveURI( childSource, this.kernel.uri( childID, true ) ),
  385. ID: childID,
  386. parentID: nodeID,
  387. sourceType: childType,
  388. type: childExtendsID,
  389. //no load callback, maybe don't need this?
  390. //loadingCallback: callback,
  391. sceneID: this.kernel.application(),
  392. prototypes: protos,
  393. };
  394. if( !node.threeObject )
  395. node.threeObject = findThreeObjectInParent.call(this,childName,nodeID);
  396. //The parent three object did not have any childrent with the name matching the nodeID, so make a new group
  397. if( !node.threeObject ) {
  398. // doesn't this object need to be added to the parent node
  399. node.threeObject = new THREE.Object3D();
  400. node.threeObject.name = childName;
  401. if ( threeParent !== undefined ) {
  402. threeParent.add( node.threeObject );
  403. }
  404. }
  405. }
  406. if ( node && node.threeObject )
  407. {
  408. if ( !node.threeObject.vwfID )
  409. node.threeObject.vwfID = childID;
  410. if ( !node.threeObject.name )
  411. node.threeObject.name = childName;
  412. }
  413. }
  414. updateStoredTransform( node );
  415. // If we do not have a load a model for this node, then we are almost done, so we can update all
  416. // the driver properties w/ the stop-gap function below.
  417. // Else, it will be called at the end of the assetLoaded callback
  418. if ( ! supportedFileType( childType ) ) {
  419. notifyDriverOfPrototypeAndBehaviorProps();
  420. }
  421. // Since prototypes are created before the object, it does not get "setProperty" updates for
  422. // its prototype (and behavior) properties. Therefore, we cycle through those properties to
  423. // notify the drivers of the property values so they can react accordingly
  424. // TODO: Have the kernel send the "setProperty" updates itself so the driver need not
  425. // NOTE: Identical code exists in GLGE driver, so if an change is necessary, it should be made
  426. // there, too
  427. function notifyDriverOfPrototypeAndBehaviorProps() {
  428. var ptPropValue;
  429. var protos = getPrototypes.call( this, kernel, childExtendsID );
  430. protos.forEach( function( prototypeID ) {
  431. for ( var propertyName in kernel.getProperties( prototypeID ) ) {
  432. ptPropValue = kernel.getProperty( childExtendsID, propertyName );
  433. if ( ptPropValue !== undefined && ptPropValue !== null && childID !== undefined && childID !== null) {
  434. self.settingProperty( childID, propertyName, ptPropValue );
  435. }
  436. }
  437. } );
  438. childImplementsIDs.forEach( function( behaviorID ) {
  439. for ( var propertyName in kernel.getProperties( behaviorID ) ) {
  440. ptPropValue = kernel.getProperty( behaviorID, propertyName );
  441. if ( ptPropValue !== undefined && ptPropValue !== null && childID !== undefined && childID !== null) {
  442. self.settingProperty( childID, propertyName, ptPropValue );
  443. }
  444. }
  445. } );
  446. };
  447. },
  448. initializingNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  449. childSource, childType, childIndex, childName ) {
  450. var myNode = this.state.nodes[childID];
  451. if ( this.debug.initializing ) {
  452. this.logger.infox( "initializingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
  453. }
  454. if ( myNode && !( myNode.threeObject instanceof THREE.Material ) ) {
  455. generateNodeMaterial.call( this, childID, myNode );//Potential node, need to do node things!
  456. }
  457. },
  458. // -- deletingNode -------------------------------------------------------------------------
  459. deletingNode: function( nodeID ) {
  460. if ( this.debug.deleting ) {
  461. this.logger.infox( "deletingNode", nodeID );
  462. }
  463. if(nodeID)
  464. {
  465. var childNode = this.state.nodes[nodeID];
  466. if(childNode)
  467. {
  468. var threeObject = childNode.threeObject;
  469. if(threeObject && threeObject.parent)
  470. {
  471. threeObject.parent.remove(threeObject);
  472. }
  473. delete this.state.nodes[childNode];
  474. }
  475. }
  476. },
  477. // -- addingChild ------------------------------------------------------------------------
  478. addingChild: function( nodeID, childID, childName ) {
  479. var threeObjParent = getThreeObject.call( this, nodeID );
  480. var threeObjChild = getThreeObject.call( this, childID );
  481. if ( threeObjParent && threeObjChild ) {
  482. if ( threeObjParent instanceof THREE.Object3D ) {
  483. if ( !( threeObjChild instanceof THREE.Material ) ) {
  484. var childParent = threeObjChild.parent;
  485. if ( childParent !== threeObjParent ) {
  486. // what does vwf do here? add only if parent is currently undefined
  487. if ( childParent ) {
  488. childParent.remove( threeObjChild )
  489. }
  490. threeObjParent.add( threeObjChild );
  491. }
  492. } else {
  493. // TODO
  494. // this is adding of a material
  495. }
  496. }
  497. }
  498. },
  499. // -- movingChild ------------------------------------------------------------------------
  500. movingChild: function( nodeID, childID, childName ) {
  501. var threeObjParent = getThreeObject.call( this, nodeID );
  502. var threeObjChild = getThreeObject.call( this, childID );
  503. if ( threeObjParent && threeObjChild && ( threeObjParent instanceof THREE.Object3D ) ){
  504. var childParent = threeObjChild.parent;
  505. // do we only move if there is currently a parent
  506. if ( childParent && ( childParent !== threeObjParent ) ) {
  507. childParent.remove( threeObjChild );
  508. threeObjParent.add( threeObjChild );
  509. }
  510. }
  511. },
  512. // -- removingChild ------------------------------------------------------------------------
  513. removingChild: function( nodeID, childID, childName ) {
  514. var threeObjParent = getThreeObject.call( this, nodeID );
  515. var threeObjChild = getThreeObject.call( this, childID );
  516. if ( threeObjParent && threeObjChild && ( threeObjParent instanceof THREE.Object3D ) ){
  517. var childParent = threeObjChild.parent;
  518. if ( childParent === threeObjParent ) {
  519. childParent.remove( threeObjChild )
  520. }
  521. }
  522. },
  523. // -- creatingProperty ---------------------------------------------------------------------
  524. creatingProperty: function( nodeID, propertyName, propertyValue ) {
  525. if ( this.debug.properties ) {
  526. this.logger.infox( "C === creatingProperty ", nodeID, propertyName, propertyValue );
  527. }
  528. return this.initializingProperty( nodeID, propertyName, propertyValue );
  529. },
  530. // -- initializingProperty -----------------------------------------------------------------
  531. initializingProperty: function( nodeID, propertyName, propertyValue ) {
  532. var value = undefined;
  533. if ( this.debug.properties ) {
  534. this.logger.infox( " I === initializingProperty ", nodeID, propertyName, propertyValue );
  535. }
  536. if ( propertyValue !== undefined ) {
  537. var node = this.state.nodes[ nodeID ];
  538. if ( node === undefined ) node = this.state.scenes[ nodeID ];
  539. if ( node !== undefined ) {
  540. var objectType, objectDef;
  541. switch ( propertyName ) {
  542. case "meshDefinition":
  543. createMesh.call( this, node, propertyValue, true );
  544. value = propertyValue;
  545. break;
  546. case "shaderDefinition":
  547. objectType = propertyValue.type || propertyValue.shaderType || propertyValue;
  548. objectDef = { "type": 'ShaderMaterial', "shaderType": objectType };
  549. if ( propertyValue instanceof Object ) {
  550. for ( var prop in propertyValue ) {
  551. switch ( prop ) {
  552. case "type":
  553. case "shaderType":
  554. break;
  555. default:
  556. objectDef[ prop ] = propertyValue[ prop ];
  557. break;
  558. }
  559. }
  560. }
  561. node.threeObject = createMaterial( objectDef );
  562. value = propertyValue;
  563. if ( node.threeObject ) {
  564. var parentNode = this.state.nodes[ node.parentID ];
  565. if ( parentNode && parentNode.threeObject ) {
  566. SetMaterial( parentNode.threeObject, node.threeObject, node.name );
  567. }
  568. }
  569. break;
  570. case "materialDefinition":
  571. objectType = propertyValue.type || propertyValue;
  572. objectDef = { "type": objectType };
  573. if ( propertyValue instanceof Object ) {
  574. for ( var prop in propertyValue ) {
  575. switch ( prop ) {
  576. case "type":
  577. break;
  578. case "color":
  579. case "specular":
  580. case "emissive":
  581. objectDef[ prop ] = new THREE.Color( propertyValue[ prop ] );
  582. break;
  583. case "shininess":
  584. case "bumpScale":
  585. case "reflectivity":
  586. case "wireframeLinewidth":
  587. case "refractionRatio":
  588. case "opacity":
  589. case "linewidth":
  590. case "scale":
  591. case "dashSize":
  592. case "gapSize":
  593. case "overdraw":
  594. case "alphaTest":
  595. case "polygonOffsetFactor":
  596. case "polygonOffsetUnits":
  597. case "size":
  598. objectDef[ prop ] = parseFloat( propertyValue[ prop ] );
  599. break;
  600. case "map":
  601. case "specularMap":
  602. case "normalMap":
  603. case "alphaMap":
  604. case "bumpMap":
  605. case "lightMap":
  606. objectDef[ prop ] = loadTexture( undefined, propertyValue[ prop ] );
  607. break;
  608. case "envMap":
  609. objectDef[ prop ] = THREE.ImageUtils.loadTextureCube( propertyValue[ prop ] );
  610. break;
  611. case "normalScale":
  612. case "uvOffset":
  613. case "uvScale":
  614. objectDef[ prop ] = new THREE.Vector2( propertyValue[ prop ][ 0 ], propertyValue[ prop ][ 1 ] );
  615. break;
  616. case "wrapRGB":
  617. objectDef[ prop ] = new THREE.Vector3( propertyValue[ prop ][ 0 ], propertyValue[ prop ][ 1 ], propertyValue[ prop ][ 2 ] );
  618. break;
  619. case "wrapAround":
  620. case "metal":
  621. case "fog":
  622. case "skinning":
  623. case "morphTargets":
  624. case "morphNormals":
  625. case "wireframe":
  626. case "depthTest":
  627. case "depthWrite":
  628. case "transparent":
  629. case "polygonOffset":
  630. case "visible":
  631. case "lights":
  632. objectDef[ prop ] = Boolean( propertyValue[ prop ] );
  633. break;
  634. case "vertexColors":
  635. switch ( propertyValue[ prop ] ) {
  636. case "true":
  637. objectDef[ prop ] = true;
  638. break;
  639. case "false":
  640. objectDef[ prop ] = false;
  641. break;
  642. case 1:
  643. case "1":
  644. case "face":
  645. objectDef[ prop ] = THREE.FaceColors;
  646. break;
  647. case 2:
  648. case "2":
  649. case "vertex":
  650. objectDef[ prop ] = THREE.VertexColors;
  651. break;
  652. case 0:
  653. case "0":
  654. case "no":
  655. default:
  656. objectDef[ prop ] = THREE.NoColors;
  657. break;
  658. }
  659. break;
  660. case "blendSrc":
  661. case "blendDst":
  662. switch ( propertyValue[ prop ] ) {
  663. case 200:
  664. case "200":
  665. case "zero":
  666. objectDef[ prop ] = THREE.ZeroFactor;
  667. break;
  668. case 201:
  669. case "201":
  670. case "one":
  671. objectDef[ prop ] = THREE.OneFactor;
  672. break;
  673. case 202:
  674. case "202":
  675. case "srcColor":
  676. objectDef[ prop ] = THREE.SrcColorFactor;
  677. break;
  678. case 203:
  679. case "203":
  680. case "oneMinusSrcColor":
  681. objectDef[ prop ] = THREE.OneMinusSrcColorFactor;
  682. break;
  683. case 204:
  684. case "204":
  685. case "srcAlpha":
  686. objectDef[ prop ] = THREE.SrcAlphaFactor;
  687. break;
  688. case 205:
  689. case "205":
  690. case "oneMinusSrcAlpha":
  691. objectDef[ prop ] = THREE.OneMinusSrcAlphaFactor;
  692. break;
  693. case 206:
  694. case "206":
  695. case "dstAlpha":
  696. objectDef[ prop ] = THREE.DstAlphaFactor;
  697. break;
  698. case 207:
  699. case "207":
  700. case "oneMinusDstAlpha":
  701. objectDef[ prop ] = THREE.OneMinusDstAlphaFactor;
  702. break;
  703. case 208:
  704. case "208":
  705. case "dstColor":
  706. objectDef[ prop ] = THREE.DstColorFactor;
  707. break;
  708. case 209:
  709. case "209":
  710. case "oneMinusDstColor":
  711. objectDef[ prop ] = THREE.OneMinusDstColorFactor;
  712. break;
  713. case 210:
  714. case "210":
  715. case "srcAlphaSaturate":
  716. objectDef[ prop ] = THREE.SrcAlphaSaturateFactor;
  717. break;
  718. }
  719. break;
  720. case "blendEquation":
  721. switch ( propertyValue[ prop ] ) {
  722. case 100:
  723. case "100":
  724. case "add":
  725. objectDef[ prop ] = THREE.AddEquation;
  726. break;
  727. case 101:
  728. case "101":
  729. case "sub":
  730. case "subtract":
  731. objectDef[ prop ] = THREE.SubtractEquation;
  732. break;
  733. case 102:
  734. case "102":
  735. case "revSub":
  736. case "revSubtract":
  737. objectDef[ prop ] = THREE.ReverseSubtractEquation;
  738. break;
  739. case 103:
  740. case "103":
  741. case "min":
  742. objectDef[ prop ] = THREE.MinEquation;
  743. break;
  744. case 104:
  745. case "104":
  746. case "max":
  747. objectDef[ prop ] = THREE.MaxEquation;
  748. break;
  749. }
  750. break;
  751. case "combine":
  752. switch ( propertyValue[ prop ] ) {
  753. case 1:
  754. case "1":
  755. case "mix":
  756. objectDef[ prop ] = THREE.MixOperation;
  757. break;
  758. case 2:
  759. case "2":
  760. case "add":
  761. objectDef[ prop ] = THREE.AddOperation;
  762. break;
  763. case 0:
  764. case "0":
  765. case "mult":
  766. case "multiply":
  767. default:
  768. objectDef[ prop ] = THREE.MultiplyOperation;
  769. break;
  770. }
  771. break;
  772. case "shading":
  773. switch ( propertyValue[ prop ] ) {
  774. case 1:
  775. case "1":
  776. case "flat":
  777. objectDef[ prop ] = THREE.FlatShading;
  778. break;
  779. case 2:
  780. case "2":
  781. case "smooth":
  782. objectDef[ prop ] = THREE.SmoothShading;
  783. break;
  784. case 0:
  785. case "0":
  786. case "no":
  787. default:
  788. objectDef[ prop ] = THREE.NoShading;
  789. break;
  790. }
  791. break;
  792. case "blending":
  793. switch ( propertyValue[ prop ] ) {
  794. case 1:
  795. case "1":
  796. case "normal":
  797. objectDef[ prop ] = THREE.NormalBlending;
  798. break;
  799. case 2:
  800. case "2":
  801. case "add":
  802. case "additive":
  803. objectDef[ prop ] = THREE.AdditiveBlending;
  804. break;
  805. case 3:
  806. case "3":
  807. case "sub":
  808. case "subtractive":
  809. objectDef[ prop ] = THREE.SubtractiveBlending;
  810. break;
  811. case 4:
  812. case "4":
  813. case "mult":
  814. case "multiply":
  815. objectDef[ prop ] = THREE.MultiplyBlending;
  816. break;
  817. case 5:
  818. case "5":
  819. case "custom":
  820. objectDef[ prop ] = THREE.CustomBlending;
  821. break;
  822. case 0:
  823. case "0":
  824. case "no":
  825. default:
  826. objectDef[ prop ] = THREE.NoBlending;
  827. break;
  828. }
  829. break;
  830. case "side":
  831. switch ( propertyValue[ prop ] ) {
  832. case 2:
  833. case "2":
  834. case "double":
  835. objectDef[ prop ] = THREE.DoubleSide;
  836. break;
  837. case 1:
  838. case "1":
  839. case "back":
  840. objectDef[ prop ] = THREE.BackSide;
  841. break;
  842. case 0:
  843. case "0":
  844. case "front":
  845. default:
  846. objectDef[ prop ] = THREE.FrontSide;
  847. break;
  848. }
  849. break;
  850. case "linecap":
  851. case "linejoin":
  852. default:
  853. objectDef[ prop ] = propertyValue[ prop ];
  854. break;
  855. }
  856. }
  857. }
  858. node.threeObject = createMaterial( objectDef );
  859. value = propertyValue;
  860. if ( node.threeObject ) {
  861. var parentNode = this.state.nodes[ node.parentID ];
  862. if ( parentNode && parentNode.threeObject ) {
  863. SetMaterial( parentNode.threeObject, node.threeObject, node.name );
  864. }
  865. }
  866. break;
  867. default:
  868. value = this.settingProperty( nodeID, propertyName, propertyValue );
  869. break;
  870. }
  871. }
  872. }
  873. return value;
  874. },
  875. // -- settingProperty ----------------------------------------------------------------------
  876. settingProperty: function( nodeID, propertyName, propertyValue ) {
  877. if ( this.debug.properties || this.debug.setting ) {
  878. this.logger.infox( " S === settingProperty ", nodeID, propertyName, propertyValue );
  879. }
  880. var node = this.state.nodes[ nodeID ]; // { name: childName, glgeObject: undefined }
  881. if( node === undefined ) node = this.state.scenes[ nodeID ]; // { name: childName, glgeObject: undefined }
  882. var value = undefined;
  883. //this driver has no representation of this node, so there is nothing to do.
  884. if(!node) return;
  885. var parentNode = this.state.nodes[ node.parentID ];
  886. if ( parentNode === undefined ) {
  887. parentNode = this.state.scenes[ node.parentID ];
  888. }
  889. var threeObject = node.threeObject;
  890. if ( !threeObject )
  891. threeObject = node.threeScene;
  892. //There is not three object for this node, so there is nothing this driver can do. return
  893. if(!threeObject) return value;
  894. if ( propertyValue !== undefined )
  895. {
  896. self = this;
  897. if ( threeObject instanceof THREE.Object3D )
  898. {
  899. // Function to make the object continuously look at a position or node
  900. // (for use when setting 'transform' or 'lookAt')
  901. // An almost identical function is copied in view/threejs.js, so if any modifications are made here, they
  902. // should be made there, also
  903. var lookAt = function( lookAtValue ) {
  904. // Function to make the object look at a particular position
  905. // (For use in the following conditional)
  906. var lookAtWorldPosition = function( targetWorldPos ) {
  907. // Get the eye position
  908. var eye = new THREE.Vector3();
  909. var worldTransform = getWorldTransform( node );
  910. eye.setFromMatrixPosition( worldTransform );
  911. var look = new THREE.Vector3();
  912. look.subVectors( targetWorldPos, eye );
  913. if ( look.length() > 0 ) {
  914. look.normalize();
  915. // Set the up vector to be z
  916. var roughlyUp = new THREE.Vector3();
  917. roughlyUp.set( 0, 0, 1 );
  918. var right = new THREE.Vector3();
  919. right.crossVectors( look, roughlyUp );
  920. if ( right.length() == 0 ) {
  921. look.x += 0.0001;
  922. right.crossVectors( look, roughlyUp );
  923. }
  924. right.normalize();
  925. var up = new THREE.Vector3();
  926. up.crossVectors( right, look );
  927. var worldTransformArray = worldTransform.elements;
  928. worldTransformArray[ 0 ] = right.x;
  929. worldTransformArray[ 1 ] = right.y;
  930. worldTransformArray[ 2 ] = right.z;
  931. worldTransformArray[ 4 ] = look.x;
  932. worldTransformArray[ 5 ] = look.y;
  933. worldTransformArray[ 6 ] = look.z;
  934. worldTransformArray[ 8 ] = up.x;
  935. worldTransformArray[ 9 ] = up.y;
  936. worldTransformArray[ 10 ] = up.z;
  937. setWorldTransform( node, worldTransform );
  938. }
  939. }
  940. // The position for the object to look at - to be set in the following conditional
  941. var targetWorldPos = new THREE.Vector3();
  942. //Threejs does not currently support auto tracking the lookat,
  943. //instead, we'll take the position of the node and look at that.
  944. if ( utility.isString( lookAtValue ) ) {
  945. // We use '' to denote that there is no object to look at.
  946. // Therefore, we only care if it is something other than that.
  947. if ( lookAtValue != '' ) {
  948. var lookatNode = self.state.nodes[ lookAtValue ];
  949. if ( lookatNode )
  950. {
  951. node.lookatval = lookAtValue;
  952. var targetWorldTransform = getWorldTransform( lookatNode );
  953. targetWorldPos.setFromMatrixPosition( targetWorldTransform );
  954. lookAtWorldPosition( targetWorldPos );
  955. } else {
  956. self.logger.errorx( "Lookat node does not exist: '" + lookAtValue + "'" );
  957. }
  958. }
  959. } else if ( lookAtValue instanceof Array ) {
  960. node.lookatval = lookAtValue;
  961. targetWorldPos.set( lookAtValue[0], lookAtValue[1], lookAtValue[2] );
  962. lookAtWorldPosition( targetWorldPos );
  963. } else if ( !lookAtValue ) {
  964. node.lookatval = null;
  965. } else {
  966. self.logger.errorx( "Invalid lookat property value: '" + lookAtValue + "'" );
  967. }
  968. return node.lookatval;
  969. }
  970. // Begin handling properties
  971. if ( propertyName == 'transform' && node.transform ) {
  972. //console.info( "setting transform of: " + nodeID + " to " + Array.prototype.slice.call( propertyValue ) );
  973. var transformMatrix = goog.vec.Mat4.createFromArray( propertyValue || [] );
  974. if( threeObject instanceof THREE.PointCloud )
  975. {
  976. threeObject.updateTransform(propertyValue);
  977. }
  978. // Store the value locally
  979. // It must be stored separately from the threeObject so the view can change the
  980. // threeObject's transform to get ahead of the model state without polluting it
  981. node.transform.elements = matCpy( transformMatrix );
  982. value = propertyValue;
  983. //because threejs does not do auto tracking of lookat, we must do it manually.
  984. //after updating the matrix for an ojbect, if it's looking at something, update to lookat from
  985. //the new position
  986. if ( node.lookatval ) {
  987. lookAt( node.lookatval );
  988. }
  989. setTransformsDirty( threeObject );
  990. }
  991. else if ( propertyName == 'lookAt' ) {
  992. value = lookAt( propertyValue );
  993. }
  994. else if ( propertyName == 'visible' )
  995. {
  996. value = Boolean( propertyValue );
  997. // this was the old style of recursively setting visible
  998. // self.state.setMeshPropertyRecursively( threeObject, "visible", value );
  999. SetVisible( threeObject, value );
  1000. // SetVisible will only set visible on the children
  1001. // that the driver has NOT binding to, bad/good, was the old way better?
  1002. }
  1003. else if ( propertyName == 'castShadows' )
  1004. {
  1005. value = Boolean( propertyValue );
  1006. // TODO: We should call setMeshPropertyRecursively here instead of repeating code
  1007. threeObject.castShadow = value;
  1008. var meshes = findAllMeshes.call( this, threeObject );
  1009. for(var i = 0, il = meshes.length; i < il; i++) {
  1010. meshes[i].castShadow = value;
  1011. }
  1012. }
  1013. else if ( propertyName == 'receiveShadows' )
  1014. {
  1015. value = Boolean( propertyValue );
  1016. // TODO: We should call setMeshPropertyRecursively here instead of repeating code
  1017. threeObject.receiveShadow = value;
  1018. var meshes = findAllMeshes.call( this, threeObject );
  1019. for(var i = 0, il = meshes.length; i < il; i++) {
  1020. meshes[i].receiveShadow = value;
  1021. }
  1022. }
  1023. //This can be a bit confusing, as the node has a material property, and a material child node.
  1024. //setting the property does this, but the code in the component is ambigious
  1025. else if ( propertyName == 'material' )
  1026. {
  1027. var material = GetMaterial(node.threeObject);
  1028. if(!material)
  1029. {
  1030. material = new THREE.MeshPhongMaterial();
  1031. SetMaterial(node.threeObject,material);
  1032. }
  1033. if(propertyValue == 'red')
  1034. material.color.setRGB(1,0,0);
  1035. if(propertyValue == 'green')
  1036. material.color.setRGB(0,1,0);
  1037. if(propertyValue == 'blue')
  1038. material.color.setRGB(0,0,1);
  1039. if(propertyValue == 'purple')
  1040. material.color.setRGB(1,0,1);
  1041. if(propertyValue == 'orange')
  1042. material.color.setRGB(1,.5,0);
  1043. if(propertyValue == 'yellow')
  1044. material.color.setRGB(1,1,0);
  1045. if(propertyValue == 'gray')
  1046. material.color.setRGB(.5,.5,.5);
  1047. if(propertyValue == 'white')
  1048. material.color.setRGB(1,1,1);
  1049. if(propertyValue == 'black')
  1050. material.color.setRGB(0,0,0);
  1051. material.ambient.setRGB( material.color.r,material.color.g,material.color.b);
  1052. value = propertyValue;
  1053. }
  1054. else if ( propertyName == "animationTimeUpdated" ) {
  1055. // Keyframe Animations
  1056. if ( node.threeObject.kfAnimations && node.threeObject.kfAnimations.length && propertyValue !== undefined ) {
  1057. for ( var i = 0; i < node.threeObject.kfAnimations.length; i++ ) {
  1058. node.threeObject.kfAnimations[i].stop()
  1059. node.threeObject.kfAnimations[i].play( false, 0 );
  1060. node.threeObject.kfAnimations[i].update( propertyValue );
  1061. }
  1062. }
  1063. // Both JSON and Collada models can be skinned mesh animations, but the Collada loader does not support bones
  1064. // therefore Collada models will fall in the Morph Target conditional if applicable.
  1065. // Skeletal Animations (takes precedence over Morph Target)
  1066. if ( node.threeObject.bones && node.threeObject.bones.length > 0 ) {
  1067. var animRate = this.state.kernel.getProperty( nodeID, "animationRate" ) || 1;
  1068. THREE.AnimationHandler.update(animRate);
  1069. }
  1070. // Morph Target Animations
  1071. else if ( node.threeObject.animatedMesh && node.threeObject.animatedMesh.length && propertyValue !== undefined ) {
  1072. var fps = this.state.kernel.getProperty( nodeID, "animationFPS" ) || 30;
  1073. for( var i = 0; i < node.threeObject.animatedMesh.length; i++ ) {
  1074. if ( node.threeObject.animatedMesh[i].morphTargetInfluences ) {
  1075. for( var j = 0; j < node.threeObject.animatedMesh[i].morphTargetInfluences.length; j++ ) {
  1076. node.threeObject.animatedMesh[i].morphTargetInfluences[j] = 0;
  1077. }
  1078. node.threeObject.animatedMesh[i].morphTargetInfluences[ Math.floor(propertyValue * fps) ] = 1;
  1079. }
  1080. }
  1081. }
  1082. // the transform is being stored locally which is probably the
  1083. // main source of the problem( animated transforms are incorrect while
  1084. // being animated ), I'm not sure why this has been done
  1085. //updateStoredTransform( node );
  1086. // calling updateStoredTransform here seemed to be
  1087. // too big of a performance hit, so setting a flag
  1088. // to be checked in the getter before getting the transform
  1089. // node.storedTransformDirty = true;
  1090. setTransformsDirty( node.threeObject );
  1091. }
  1092. else if ( propertyName == "animationDuration" ) {
  1093. if( node.threeObject.animatedMesh && node.threeObject.animatedMesh.length || node.threeObject.kfAnimations ) {
  1094. value = this.gettingProperty( nodeID, "animationDuration" );
  1095. }
  1096. }
  1097. else if ( propertyName == "animationFPS" ) {
  1098. if( node.threeObject.animatedMesh && node.threeObject.animatedMesh.length || node.threeObject.kfAnimations ) {
  1099. value = this.gettingProperty( nodeID, "animationFPS" );
  1100. }
  1101. }
  1102. }
  1103. if( threeObject instanceof THREE.PointCloud )
  1104. {
  1105. var ps = threeObject;
  1106. var particles = ps.geometry;
  1107. switch( propertyName ) {
  1108. case 'emitterSize':
  1109. case 'emitterType':
  1110. case 'gravity':
  1111. case 'gravityCenter':
  1112. case 'velocityMode':
  1113. case 'damping':
  1114. case 'maxRate':
  1115. ps[propertyName] = propertyValue;
  1116. if( ps.material == ps.shaderMaterial_analytic ) {
  1117. ps.rebuildParticles();
  1118. }
  1119. break;
  1120. case 'size':
  1121. ps[propertyName] = propertyValue;
  1122. for( var i = 0; i < ps.material.attributes.size.value.length; i++ ) {
  1123. ps.material.attributes.size.value[i] = propertyValue;
  1124. }
  1125. ps.material.attributes.size.needsUpdate = true;
  1126. break;
  1127. case 'particleCount':
  1128. ps.setParticleCount(propertyValue);
  1129. break;
  1130. case 'startSize':
  1131. ps[propertyName] = propertyValue;
  1132. ps.shaderMaterial_analytic.uniforms.startSize.value = propertyValue;
  1133. // ps.material.uniforms.startSize.value = propertyValue;
  1134. break;
  1135. case 'endSize':
  1136. ps[propertyName] = propertyValue;
  1137. ps.shaderMaterial_analytic.uniforms.endSize.value = propertyValue;
  1138. // ps.material.uniforms.endSize.value = propertyValue;
  1139. break;
  1140. case 'sizeRange':
  1141. ps[propertyName] = propertyValue;
  1142. ps.shaderMaterial_analytic.uniforms.sizeRange.value = propertyValue;
  1143. // ps.material.uniforms.sizeRange.value = propertyValue;
  1144. break;
  1145. case 'maxSpin':
  1146. ps[propertyName] = propertyValue;
  1147. ps.shaderMaterial_analytic.uniforms.maxSpin.value = propertyValue;
  1148. // ps.material.uniforms.maxSpin.value = propertyValue;
  1149. break;
  1150. case 'minSpin':
  1151. ps[propertyName] = propertyValue;
  1152. ps.shaderMaterial_analytic.uniforms.minSpin.value = propertyValue;
  1153. // ps.material.uniforms.minSpin.value = propertyValue;
  1154. break;
  1155. case 'textureTiles':
  1156. ps[propertyName] = propertyValue;
  1157. ps.shaderMaterial_analytic.uniforms.textureTiles.value = propertyValue;
  1158. // ps.material.uniforms.textureTiles.value = propertyValue;
  1159. break;
  1160. case 'maxOrientation':
  1161. ps[propertyName] = propertyValue;
  1162. ps.shaderMaterial_analytic.uniforms.maxOrientation.value = propertyValue;
  1163. // ps.material.uniforms.maxOrientation.value = propertyValue;
  1164. break;
  1165. case 'minOrientation':
  1166. ps[propertyName] = propertyValue;
  1167. ps.shaderMaterial_analytic.uniforms.minOrientation.value = propertyValue;
  1168. // ps.material.uniforms.minOrientation.value = propertyValue;
  1169. break;
  1170. case 'colorRange':
  1171. ps[propertyName] = propertyValue;
  1172. ps.shaderMaterial_analytic.uniforms.colorRange.value.x = propertyValue[0];
  1173. ps.shaderMaterial_analytic.uniforms.colorRange.value.y = propertyValue[1];
  1174. ps.shaderMaterial_analytic.uniforms.colorRange.value.z = propertyValue[2];
  1175. ps.shaderMaterial_analytic.uniforms.colorRange.value.w = propertyValue[3];
  1176. break;
  1177. case 'startColor':
  1178. ps[propertyName] = propertyValue;
  1179. ps.shaderMaterial_analytic.uniforms.startColor.value.x = propertyValue[0];
  1180. ps.shaderMaterial_analytic.uniforms.startColor.value.y = propertyValue[1];
  1181. ps.shaderMaterial_analytic.uniforms.startColor.value.z = propertyValue[2];
  1182. ps.shaderMaterial_analytic.uniforms.startColor.value.w = propertyValue[3];
  1183. break;
  1184. case 'endColor':
  1185. ps[propertyName] = propertyValue;
  1186. ps.shaderMaterial_analytic.uniforms.endColor.value.x = propertyValue[0];
  1187. ps.shaderMaterial_analytic.uniforms.endColor.value.y = propertyValue[1];
  1188. ps.shaderMaterial_analytic.uniforms.endColor.value.z = propertyValue[2];
  1189. ps.shaderMaterial_analytic.uniforms.endColor.value.w = propertyValue[3];
  1190. break;
  1191. case 'solver':
  1192. ps[propertyName] = propertyValue;
  1193. ps.setSolverType(propertyValue);
  1194. break;
  1195. case 'image':
  1196. ps[propertyName] = propertyValue;
  1197. ps.shaderMaterial_default.uniforms.texture.value = loadTexture( undefined, propertyValue );
  1198. ps.shaderMaterial_default.uniforms.useTexture.value = 1.0;
  1199. ps.shaderMaterial_analytic.uniforms.texture.value = loadTexture( undefined, propertyValue );
  1200. ps.shaderMaterial_analytic.uniforms.useTexture.value = 1.0;
  1201. break;
  1202. case 'additive':
  1203. ps[propertyName] = propertyValue;
  1204. if ( Boolean( propertyValue ) )
  1205. {
  1206. ps.shaderMaterial_default.blending = THREE.AdditiveBlending;
  1207. ps.shaderMaterial_default.transparent = true;
  1208. ps.shaderMaterial_analytic.blending = THREE.AdditiveBlending;
  1209. ps.shaderMaterial_analytic.transparent = true;
  1210. ps.shaderMaterial_interpolate.blending = THREE.AdditiveBlending;
  1211. ps.shaderMaterial_interpolate.transparent = true;
  1212. }
  1213. else
  1214. {
  1215. ps.shaderMaterial_default.blending = THREE.NormalBlending;
  1216. ps.shaderMaterial_default.transparent = true;
  1217. ps.shaderMaterial_analytic.blending = THREE.NormalBlending;
  1218. ps.shaderMaterial_analytic.transparent = true;
  1219. ps.shaderMaterial_interpolate.blending = THREE.NormalBlending;
  1220. ps.shaderMaterial_interpolate.transparent = true;
  1221. }
  1222. ps.shaderMaterial_default.needsUpdate = true;
  1223. ps.shaderMaterial_analytic.needsUpdate = true;
  1224. ps.shaderMaterial_interpolate.needsUpdate = true;
  1225. break;
  1226. case 'depthTest':
  1227. ps[propertyName] = propertyValue;
  1228. ps.shaderMaterial_default.depthTest = propertyValue;
  1229. ps.shaderMaterial_analytic.depthTest = propertyValue;
  1230. ps.shaderMaterial_interpolate.depthTest = propertyValue;
  1231. break;
  1232. case 'depthWrite':
  1233. ps[propertyName] = propertyValue;
  1234. ps.shaderMaterial_default.depthWrite = propertyValue;
  1235. ps.shaderMaterial_analytic.depthWrite = propertyValue;
  1236. ps.shaderMaterial_interpolate.depthWrite = propertyValue;
  1237. break;
  1238. case 'minAcceleration':
  1239. case 'maxAcceleration':
  1240. ps[propertyName] = propertyValue;
  1241. if(!ps.minAcceleration) ps.minAcceleration = [0,0,0];
  1242. if(!ps.maxAcceleration) ps.maxAcceleration = [0,0,0];
  1243. for(var i = 0; i < particles.vertices.length; i++)
  1244. {
  1245. particles.vertices[i].acceleration.x = ps.minAcceleration[0] + (ps.maxAcceleration[0] - ps.minAcceleration[0]) * Math.random();
  1246. particles.vertices[i].acceleration.y = ps.minAcceleration[1] + (ps.maxAcceleration[1] - ps.minAcceleration[1]) * Math.random();
  1247. particles.vertices[i].acceleration.z = ps.minAcceleration[2] + (ps.maxAcceleration[2] - ps.minAcceleration[2]) * Math.random();
  1248. }
  1249. if( ps.material == ps.shaderMaterial_analytic ) {
  1250. ps.rebuildParticles();
  1251. }
  1252. break;
  1253. case 'minVelocity':
  1254. case 'maxVelocity':
  1255. ps[propertyName] = propertyValue;
  1256. if(!ps.minVelocity) ps.minVelocity = [0,0,0];
  1257. if(!ps.maxVelocity) ps.maxVelocity = [0,0,0];
  1258. for(var i = 0; i < particles.vertices.length; i++)
  1259. {
  1260. particles.vertices[i].velocity.x = ps.minVelocity[0] + (ps.maxVelocity[0] - ps.minVelocity[0]) * Math.random();
  1261. particles.vertices[i].velocity.y = ps.minVelocity[1] + (ps.maxVelocity[1] - ps.minVelocity[1]) * Math.random();
  1262. particles.vertices[i].velocity.z = ps.minVelocity[2] + (ps.maxVelocity[2] - ps.minVelocity[2]) * Math.random();
  1263. }
  1264. if( ps.material == ps.shaderMaterial_analytic ) {
  1265. ps.rebuildParticles();
  1266. }
  1267. break;
  1268. case 'minLifeTime':
  1269. case 'maxLifeTime':
  1270. ps[propertyName] = propertyValue;
  1271. if(ps.minLifeTime === undefined) ps.minLifeTime = 0;
  1272. if(ps.maxLifeTime === undefined) ps.maxLifeTime = 1;
  1273. for(var i = 0; i < particles.vertices.length; i++)
  1274. {
  1275. particles.vertices[i].lifespan = ps.minLifeTime + (ps.maxLifeTime - ps.minLifeTime) * Math.random();
  1276. }
  1277. break;
  1278. }
  1279. }
  1280. if(threeObject instanceof THREE.Camera)
  1281. {
  1282. if(propertyName == "fovy")
  1283. {
  1284. if(propertyValue)
  1285. {
  1286. value = parseFloat(propertyValue);
  1287. threeObject.fov = value;
  1288. threeObject.updateProjectionMatrix();
  1289. }
  1290. }
  1291. if(propertyName == "near")
  1292. {
  1293. if(propertyValue)
  1294. {
  1295. value = parseFloat(propertyValue);
  1296. threeObject.near = value;
  1297. threeObject.updateProjectionMatrix();
  1298. }
  1299. }
  1300. if(propertyName == "aspect")
  1301. {
  1302. if(propertyValue)
  1303. {
  1304. value = parseFloat(propertyValue);
  1305. threeObject.aspect = value;
  1306. threeObject.updateProjectionMatrix();
  1307. }
  1308. }
  1309. if(propertyName == "far")
  1310. {
  1311. if(propertyValue)
  1312. {
  1313. value = parseFloat(propertyValue);
  1314. threeObject.far = value;
  1315. threeObject.updateProjectionMatrix();
  1316. }
  1317. }
  1318. if(propertyName == "cameraType")
  1319. {
  1320. if(propertyValue == 'perspective')
  1321. {
  1322. value = propertyValue;
  1323. var parent = threeObject.parent;
  1324. if(parent && threeObject && !(threeObject instanceof THREE.PerspectiveCamera))
  1325. {
  1326. var sceneNode = this.state.scenes[ this.kernel.application() ];
  1327. parent.remove(threeObject);
  1328. var cam = new THREE.PerspectiveCamera(35,$(document).width()/$(document).height() ,.01,10000);
  1329. cam.far = threeObject.far;
  1330. cam.near = threeObject.near;
  1331. cam.matrix.elements = matCpy(threeObject.matrix.elements);
  1332. cam.matrixAutoUpdate = false;
  1333. if ( threeObject.fov )
  1334. cam.fov = threeObject.fov;
  1335. if ( threeObject.aspect )
  1336. cam.aspect = threeObject.aspect;
  1337. // If the camera we are replacing, is the active camera,
  1338. // set the active camera
  1339. if ( this.state.cameraInUse == threeObject )
  1340. this.state.cameraInUse = cam;
  1341. threeObject.updateProjectionMatrix();
  1342. node.threeObject = cam;
  1343. parent.add(node.threeObject);
  1344. }
  1345. }
  1346. if(propertyValue == 'orthographic')
  1347. {
  1348. value = propertyValue;
  1349. var parent = threeObject.parent;
  1350. if(parent && threeObject && !(threeObject instanceof THREE.OrthographicCamera))
  1351. {
  1352. var sceneNode = this.state.scenes[ this.kernel.application() ];
  1353. parent.remove(threeObject);
  1354. var offset = threeObject.far * Math.cos(threeObject.fov/2 * 0.0174532925);
  1355. offset = offset/2;
  1356. var aspect = threeObject.aspect;
  1357. var cam = new THREE.OrthographicCamera(-offset,offset,offset/aspect,-offset/aspect,threeObject.near,threeObject.far);
  1358. cam.far = threeObject.far;
  1359. cam.near = threeObject.near;
  1360. cam.matrix = threeObject.matrix;
  1361. cam.matrixAutoUpdate = false;
  1362. if ( threeObject.fov )
  1363. cam.fov = threeObject.fov;
  1364. if ( threeObject.aspect )
  1365. cam.aspect = threeObject.aspect;
  1366. // If the camera we are replacing, is the active camera,
  1367. // set the active camera
  1368. if ( this.state.cameraInUse == threeObject )
  1369. this.state.cameraInUse = cam;
  1370. node.threeObject = cam;
  1371. parent.add(node.threeObject);
  1372. }
  1373. }
  1374. }
  1375. }
  1376. if ( threeObject instanceof THREE.Material ) {
  1377. value = setMaterialProperty( threeObject, propertyName, propertyValue );
  1378. if ( value !== undefined ) {
  1379. if ( this.state.nodes[ node.parentID ] && this.state.nodes[ node.parentID ].threeObject ) {
  1380. var obj3 = this.state.nodes[ node.parentID ].threeObject;
  1381. this.state.setGeometryPropertyRecursively( obj3, "uvsNeedUpdate", true );
  1382. }
  1383. }
  1384. }
  1385. if ( threeObject instanceof THREE.Texture ) {
  1386. value = setTextureProperty( threeObject, propertyName, propertyValue );
  1387. if ( value !== undefined ) {
  1388. if ( this.state.nodes[ node.parentID ] && this.state.nodes[ node.parentID ].threeObject ) {
  1389. var obj3 = this.state.nodes[ node.parentID ].threeObject;
  1390. this.state.setGeometryPropertyRecursively( obj3, "uvsNeedUpdate", true );
  1391. }
  1392. }
  1393. }
  1394. if ( threeObject instanceof THREE.ShaderMaterial ) {
  1395. if ( utility.validObject( propertyValue ) ) {
  1396. if ( propertyName === "uniforms" ) {
  1397. value = propertyValue;
  1398. threeObject.uniforms = value;
  1399. }
  1400. if ( propertyName === "vertexShader" ) {
  1401. value = propertyValue;
  1402. threeObject.vertexShader = value;
  1403. }
  1404. if ( propertyName === "fragmentShader" ) {
  1405. value = propertyValue;
  1406. threeObject.fragmentShader = value;
  1407. }
  1408. if ( propertyName === "updateFunction" ) {
  1409. value = propertyValue;
  1410. threeObject.updateFunction = value;
  1411. threeObject.update = function() {
  1412. eval( this.updateFunction );
  1413. }
  1414. }
  1415. }
  1416. }
  1417. if ( node.isUniformObject ) {
  1418. value = setUniformProperty( threeObject, propertyName, propertyValue.type, propertyValue.pValue );
  1419. }
  1420. if( threeObject instanceof THREE.Scene )
  1421. {
  1422. if(propertyName == 'activeCamera')
  1423. {
  1424. if ( this.state.nodes[ propertyValue ] !== undefined ) {
  1425. // Update the model's activeCamera
  1426. this.state.scenes[ this.kernel.application() ].camera.ID = propertyValue;
  1427. value = propertyValue;
  1428. }
  1429. }
  1430. if( propertyName == 'ambientColor' )
  1431. {
  1432. var lightsFound = 0;
  1433. var vwfColor = new utility.color( propertyValue );
  1434. if ( vwfColor ) {
  1435. for( var i = 0; i < threeObject.children.length; i++ )
  1436. {
  1437. if( threeObject.children[i] instanceof THREE.AmbientLight )
  1438. {
  1439. threeObject.children[i].color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1440. lightsFound++;
  1441. }
  1442. }
  1443. if ( lightsFound == 0 ) {
  1444. node.ambientlight = new THREE.AmbientLight( '#000000' );
  1445. node.ambientlight.color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1446. node.threeScene.add( node.ambientlight );
  1447. this.state.lights[ node.nodeID ] = node.ambientlight;
  1448. }
  1449. value = vwfColor.toString();
  1450. }
  1451. }
  1452. // backgroundColor, enableShadows, shadowMapCullFace and shadowMapType are dependent
  1453. // on the renderer object, but if they are set in a prototype,
  1454. // the renderer is not available yet, so store them until it is ready.
  1455. if ( propertyName == 'backgroundColor' )
  1456. {
  1457. if ( node && node.renderer ) {
  1458. var vwfColor = new utility.color( propertyValue );
  1459. if ( vwfColor ) {
  1460. node.renderer.setClearColor( vwfColor.getHex(), vwfColor.alpha() );
  1461. value = vwfColor.toString();
  1462. }
  1463. }
  1464. else if(node) {
  1465. node.rendererProperties["backgroundColor"] = propertyValue;
  1466. }
  1467. }
  1468. if(propertyName == 'enableShadows')
  1469. {
  1470. if ( node && node.renderer ) {
  1471. value = Boolean( propertyValue );
  1472. node.renderer.shadowMapEnabled = value;
  1473. }
  1474. else if(node) {
  1475. node.rendererProperties["enableShadows"] = propertyValue;
  1476. }
  1477. // Need to reset the viewport or you just get a blank screen
  1478. this.state.kernel.dispatchEvent( nodeID, "resetViewport" );
  1479. }
  1480. if ( propertyName == 'shadowMapCullFace') {
  1481. var shadowMapCullFace;
  1482. switch(propertyValue) {
  1483. case "none":
  1484. shadowMapCullFace = 0;
  1485. value = propertyValue;
  1486. break;
  1487. case "back":
  1488. shadowMapCullFace = 1;
  1489. value = propertyValue;
  1490. break;
  1491. case "front":
  1492. shadowMapCullFace = 2;
  1493. value = propertyValue;
  1494. break;
  1495. case "both":
  1496. shadowMapCullFace = 3;
  1497. value = propertyValue;
  1498. break;
  1499. }
  1500. if ( node && node.renderer ) {
  1501. node.renderer.shadowMapCullFace = shadowMapCullFace;
  1502. }
  1503. else if ( node ) {
  1504. node.rendererProperties["shadowMapCullFace"] = shadowMapCullFace;
  1505. }
  1506. }
  1507. if ( propertyName == 'shadowMapType') {
  1508. var shadowMapType;
  1509. switch(propertyValue) {
  1510. case "basic":
  1511. shadowMapType = 0;
  1512. value = propertyValue;
  1513. break;
  1514. case "PCF":
  1515. shadowMapType = 1;
  1516. value = propertyValue;
  1517. break;
  1518. case "PCFSoft":
  1519. shadowMapType = 2;
  1520. value = propertyValue;
  1521. break;
  1522. }
  1523. if ( node && node.renderer ) {
  1524. node.renderer.shadowMapType = shadowMapType;
  1525. }
  1526. else if ( node ) {
  1527. node.rendererProperties["shadowMapType"] = shadowMapType;
  1528. }
  1529. }
  1530. if ( propertyName === 'fogexp_color' ) {
  1531. if ( threeObject.fog && threeObject.fog instanceof THREE.FogExp2 ) {
  1532. var vwfColor = new utility.color( propertyValue );
  1533. if ( vwfColor ) {
  1534. threeObject.fog.color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1535. }
  1536. }
  1537. }
  1538. if ( propertyName === 'fogexp_density' ) {
  1539. if ( threeObject.fog && threeObject.fog instanceof THREE.FogExp2 ) {
  1540. threeObject.fog.density = parseFloat( propertyValue );
  1541. }
  1542. }
  1543. if ( propertyName === 'fog_color' ) {
  1544. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  1545. var vwfColor = new utility.color( propertyValue );
  1546. if ( vwfColor ) {
  1547. threeObject.fog.color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1548. }
  1549. }
  1550. }
  1551. if ( propertyName === 'fog_near' ) {
  1552. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  1553. threeObject.fog.fog_near = parseFloat( propertyValue );
  1554. }
  1555. }
  1556. if ( propertyName === 'fog_far' ) {
  1557. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  1558. threeObject.fog.fog_far = parseFloat( propertyValue );
  1559. }
  1560. }
  1561. }
  1562. if(threeObject instanceof THREE.PointLight || threeObject instanceof THREE.DirectionalLight
  1563. || threeObject instanceof THREE.SpotLight || threeObject instanceof THREE.HemisphereLight )
  1564. {
  1565. if(propertyName == 'lightType')
  1566. {
  1567. var newlight;
  1568. var parent = threeObject.parent;
  1569. var currProps = {
  1570. "name": threeObject.name,
  1571. "distance": threeObject.distance,
  1572. "color": threeObject.color,
  1573. "groundColor": threeObject.groundColor,
  1574. "intensity": threeObject.intensity,
  1575. "castShadow": threeObject.castShadow,
  1576. "shadowCameraLeft": threeObject.shadowCameraLeft,
  1577. "shadowCameraRight": threeObject.shadowCameraRight,
  1578. "shadowCameraTop": threeObject.shadowCameraTop,
  1579. "shadowCameraBottom": threeObject.shadowCameraBottom,
  1580. "shadowCameraNear": threeObject.shadowCameraNear,
  1581. "shadowCameraFar": threeObject.shadowCameraFar,
  1582. "shadowDarkness": threeObject.shadowDarkness,
  1583. "shadowMapHeight": threeObject.shadowMapHeight,
  1584. "shadowMapWidth": threeObject.shadowMapWidth,
  1585. "shadowBias": threeObject.shadowBias,
  1586. "target": threeObject.target,
  1587. "position": threeObject.position,
  1588. "clone": function( newObj ) {
  1589. newObj.name = this.name;
  1590. newObj.distance = this.distance;
  1591. //console.info( "light.clone.color = " + JSON.stringify( this.color ) )
  1592. newObj.color.setRGB( this.color.r, this.color.g, this.color.b );
  1593. if (this.groundColor !== undefined) {
  1594. newObj.groundColor = new THREE.Color().setRGB( this.groundColor.r, this.groundColor.g, this.groundColor.b );
  1595. }
  1596. newObj.intensity = this.intensity;
  1597. newObj.castShadow = this.castShadow;
  1598. newObj.shadowCameraLeft = this.shadowCameraLeft;
  1599. newObj.shadowCameraRight = this.shadowCameraRight;
  1600. newObj.shadowCameraTop = this.shadowCameraTop;
  1601. newObj.shadowCameraBottom = this.shadowCameraBottom;
  1602. newObj.shadowCameraNear = this.shadowCameraNear;
  1603. newObj.shadowCameraFar = this.shadowCameraFar;
  1604. newObj.shadowDarkness = this.shadowDarkness;
  1605. newObj.shadowMapHeight = this.shadowMapHeight;
  1606. newObj.shadowMapWidth = this.shadowMapWidth;
  1607. newObj.shadowBias = this.shadowBias;
  1608. if ( this.target ) {
  1609. newObj.target = this.target;
  1610. }
  1611. newObj.position.set( this.position.x, this.position.y, this.position.z );
  1612. }
  1613. };
  1614. if(propertyValue == 'point' && !(threeObject instanceof THREE.PointLight))
  1615. {
  1616. newlight = new THREE.PointLight('FFFFFF',1,0);
  1617. currProps.clone( newlight );
  1618. //newlight.matrixAutoUpdate = false;
  1619. parent.remove( node.threeObject );
  1620. parent.add( newlight );
  1621. node.threeObject = newlight;
  1622. rebuildAllMaterials.call(this);
  1623. }
  1624. if(propertyValue == 'directional' && !(threeObject instanceof THREE.DirectionalLight))
  1625. {
  1626. newlight = new THREE.DirectionalLight( 'FFFFFF' );
  1627. currProps.clone( newlight );
  1628. //newlight.matrixAutoUpdate = false;
  1629. parent.remove( node.threeObject );
  1630. parent.add( newlight );
  1631. node.threeObject = newlight;
  1632. rebuildAllMaterials.call(this);
  1633. }
  1634. if(propertyValue == 'spot' && !(threeObject instanceof THREE.SpotLight))
  1635. {
  1636. newlight = new THREE.SpotLight('FFFFFF',1,0);
  1637. currProps.clone( newlight );
  1638. //newlight.matrixAutoUpdate = false;
  1639. parent.remove( node.threeObject );
  1640. parent.add( newlight );
  1641. node.threeObject = newlight;
  1642. rebuildAllMaterials.call(this);
  1643. }
  1644. if(propertyValue == 'hemisphere' && !(threeObject instanceof THREE.HemisphereLight))
  1645. {
  1646. newlight = new THREE.HemisphereLight('FFFFFF','FFFFFF',1);
  1647. currProps.clone( newlight );
  1648. //newlight.matrixAutoUpdate = false;
  1649. parent.remove( node.threeObject );
  1650. parent.add( newlight );
  1651. node.threeObject = newlight;
  1652. rebuildAllMaterials.call(this);
  1653. }
  1654. if ( propertyValue == 'point' || propertyValue == 'directional' || propertyValue == 'spot' || propertyValue == 'hemisphere' ) {
  1655. value = propertyValue;
  1656. }
  1657. }
  1658. //if(propertyName == 'diffuse')
  1659. //{
  1660. // threeObject.color.setRGB(propertyValue[0]/255,propertyValue[1]/255,propertyValue[2]/255);
  1661. //}
  1662. else if ( propertyName == 'enable' ) {
  1663. if ( parentNode !== undefined ) {
  1664. var threeParent = ( parentNode.threeObject !== undefined ) ? parentNode.threeObject : parentNode.threeScene;
  1665. if ( threeParent !== undefined ) {
  1666. if ( Boolean( propertyValue ) ) {
  1667. if ( threeObject.parent === undefined ) {
  1668. threeParent.add( threeObject );
  1669. }
  1670. } else {
  1671. if ( threeObject.parent !== undefined ) {
  1672. threeParent.remove( threeObject );
  1673. }
  1674. }
  1675. }
  1676. }
  1677. } else if ( propertyName == 'position' ) {
  1678. if ( threeObject.position !== null && propertyValue.length ) {
  1679. threeObject.position.set( propertyValue[0], propertyValue[1], propertyValue[2] );
  1680. }
  1681. }
  1682. else if ( propertyName == 'distance' ) {
  1683. value = Number( propertyValue );
  1684. threeObject.distance = value;
  1685. }
  1686. else if ( propertyName == 'color' ) {
  1687. var vwfColor = new utility.color( propertyValue );
  1688. if ( vwfColor ) {
  1689. threeObject.color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1690. }
  1691. value = vwfColor.toString();
  1692. }
  1693. else if ( propertyName == 'groundColor' ) {
  1694. var vwfColor = new utility.color( propertyValue );
  1695. if ( vwfColor ) {
  1696. threeObject.groundColor = new THREE.Color().setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  1697. }
  1698. value = vwfColor.toString();
  1699. }
  1700. else if ( propertyName == 'intensity' ) {
  1701. value = parseFloat( propertyValue );
  1702. threeObject.intensity = value;
  1703. }
  1704. else if ( propertyName == 'castShadows' ) {
  1705. value = Boolean( propertyValue );
  1706. threeObject.castShadow = value;
  1707. }
  1708. else if ( propertyName == 'shadowCameraBottom' ) {
  1709. value = Number( propertyValue );
  1710. threeObject.shadowCameraBottom = value;
  1711. }
  1712. else if ( propertyName == 'shadowCameraLeft' ) {
  1713. value = Number( propertyValue );
  1714. threeObject.shadowCameraLeft = value;
  1715. }
  1716. else if ( propertyName == 'shadowCameraRight' ) {
  1717. value = Number( propertyValue );
  1718. threeObject.shadowCameraRight = value;
  1719. }
  1720. else if ( propertyName == 'shadowCameraTop' ) {
  1721. value = Number( propertyValue );
  1722. threeObject.shadowCameraTop = value;
  1723. }
  1724. else if ( propertyName == 'shadowCameraNear' ) {
  1725. value = Number( propertyValue );
  1726. threeObject.shadowCameraNear = value;
  1727. }
  1728. else if ( propertyName == 'shadowCameraFar' ) {
  1729. value = Number( propertyValue );
  1730. threeObject.shadowCameraFar = value;
  1731. }
  1732. else if ( propertyName == 'shadowDarkness' ) {
  1733. value = Number( propertyValue );
  1734. threeObject.shadowDarkness = value;
  1735. }
  1736. else if ( propertyName == 'shadowMapHeight' ) {
  1737. value = Number ( propertyValue );
  1738. threeObject.shadowMapHeight = value;
  1739. if(threeObject.shadowMapSize) {
  1740. threeObject.shadowMapSize.y = value;
  1741. }
  1742. if(threeObject.shadowMap) {
  1743. threeObject.shadowMap.height = value;
  1744. }
  1745. }
  1746. else if ( propertyName == 'shadowMapWidth' ) {
  1747. value = Number ( propertyValue );
  1748. threeObject.shadowMapWidth = value;
  1749. if(threeObject.shadowMapSize) {
  1750. threeObject.shadowMapSize.x = value;
  1751. }
  1752. if(threeObject.shadowMap) {
  1753. threeObject.shadowMap.width = value;
  1754. }
  1755. }
  1756. else if ( propertyName == 'shadowBias' ) {
  1757. value = Number ( propertyValue );
  1758. threeObject.shadowBias = value;
  1759. }
  1760. else if ( propertyName == "target" ) {
  1761. if ( propertyValue instanceof Array ) {
  1762. value = propertyValue;
  1763. if ( threeObject.target ) {
  1764. threeObject.target.position.set( value[ 0 ], value[ 1 ], value[ 2 ] );
  1765. }
  1766. } else if ( this.state.nodes[ propertyValue ] ) {
  1767. value = propertyValue;
  1768. threeObject.target = this.state.nodes[ value ].threeObject;
  1769. } else {
  1770. this.logger.warnx( "settingProperty", "Invalid target: " + propertyValue );
  1771. }
  1772. }
  1773. }
  1774. }
  1775. return value;
  1776. },
  1777. // -- gettingProperty ----------------------------------------------------------------------
  1778. gettingProperty: function( nodeID, propertyName ) {
  1779. if ( this.debug.properties || this.debug.getting ) {
  1780. this.logger.infox( " G === gettingProperty ", nodeID, propertyName );
  1781. }
  1782. var node = this.state.nodes[ nodeID ]; // { name: childName, glgeObject: undefined }
  1783. if(!node) node = this.state.scenes[ nodeID ]; // { name: childName, glgeObject: undefined }
  1784. var value = undefined;
  1785. //this driver has no representation of this node, so there is nothing to do.
  1786. if(!node) return;
  1787. var threeObject = node.threeObject;
  1788. if( !threeObject )
  1789. threeObject = node.threeScene;
  1790. //There is not three object for this node, so there is nothing this driver can do. return
  1791. if(!threeObject) return value;
  1792. if(threeObject instanceof THREE.Object3D)
  1793. {
  1794. if(propertyName == 'transform' && node.transform)
  1795. {
  1796. if ( node.storedTransformDirty ) {
  1797. updateStoredTransform( node );
  1798. }
  1799. value = matCpy( node.transform.elements );
  1800. return value;
  1801. }
  1802. if(propertyName =='lookAt')
  1803. {
  1804. value = node.lookatval;
  1805. return value;
  1806. }
  1807. if(propertyName == "boundingbox")
  1808. {
  1809. value = getBoundingBox.call( this, threeObject );
  1810. return value;
  1811. }
  1812. if ( propertyName == "centerOffset" )
  1813. {
  1814. value = getCenterOffset.call( this, threeObject );
  1815. return value;
  1816. }
  1817. if(propertyName == "meshData")
  1818. {
  1819. value = [];
  1820. var scale = this.gettingProperty( nodeID, "scale", [] );
  1821. scale = [1,1,1];
  1822. var meshList = findAllMeshes.call( this, threeObject );
  1823. for ( var i = 0; i < meshList.length; i++ ) {
  1824. value.push( { "vertices": getMeshVertices.call( this, meshList[i],threeObject ),
  1825. "vertexIndices": getMeshVertexIndices.call( this, meshList[i] ),
  1826. "scale": scale
  1827. } );
  1828. }
  1829. return value;
  1830. }
  1831. if(propertyName == "animationDuration") {
  1832. var animationDuration = 0;
  1833. if(node.threeObject.animations) {
  1834. for(var i=0, il = node.threeObject.animations.length; i < il; i++) {
  1835. if(node.threeObject.animations[i].length > animationDuration) {
  1836. animationDuration = node.threeObject.animations[i].length;
  1837. }
  1838. }
  1839. value = animationDuration;
  1840. }
  1841. else if ( node.threeObject.animatedMesh && node.threeObject.animatedMesh.length ) {
  1842. var fps = this.state.kernel.getProperty( nodeID, "animationFPS") || 30;
  1843. for(var i=0, il = node.threeObject.animatedMesh.length; i < il; i++) {
  1844. if (node.threeObject.animatedMesh[i].bones) {
  1845. // Skeletal animations take precedence over Morph Targets
  1846. animationDuration = node.threeObject.animatedMesh[i].bones.length;
  1847. }
  1848. else if( node.threeObject.animatedMesh[i].morphTargetInfluences.length > animationDuration ) {
  1849. animationDuration = node.threeObject.animatedMesh[i].morphTargetInfluences.length;
  1850. }
  1851. }
  1852. value = animationDuration / fps;
  1853. }
  1854. return value;
  1855. }
  1856. if(propertyName == "animationFPS") {
  1857. if(node.threeObject.animations) {
  1858. var animationDuration = 0;
  1859. var animationFrameCount = 0;
  1860. for(var i=0, il = node.threeObject.animations.length; i < il; i++) {
  1861. for(var i=0, il = node.threeObject.animations.length; i < il; i++) {
  1862. if(node.threeObject.animations[i].length > animationDuration) {
  1863. animationDuration = node.threeObject.animations[i].length;
  1864. }
  1865. if(node.threeObject.animations[i].hierarchy[0].keys.length > animationFrameCount) {
  1866. animationFrameCount = node.threeObject.animations[i].hierarchy[0].keys.length;
  1867. }
  1868. }
  1869. }
  1870. value = Math.floor(animationFrameCount / animationDuration);
  1871. }
  1872. return value;
  1873. }
  1874. if( propertyName == "visible" ) {
  1875. value = node.threeObject.visible;
  1876. return value;
  1877. }
  1878. if ( propertyName == "castShadows" ) {
  1879. value = node.threeObject.castShadow;
  1880. return value;
  1881. }
  1882. if ( propertyName == "receiveShadows" ) {
  1883. value = node.threeObject.receiveShadow;
  1884. return value;
  1885. }
  1886. }
  1887. if(threeObject instanceof THREE.Material)
  1888. {
  1889. if(propertyName == "texture")
  1890. {
  1891. if( threeObject.map && threeObject.map.image )
  1892. return threeObject.map.image.src;
  1893. }
  1894. if(propertyName == "color") {
  1895. var vwfColor = new utility.color( [ threeObject.color.r*255, threeObject.color.g*255, threeObject.color.b*255 ] );
  1896. value = vwfColor.toString();
  1897. return value;
  1898. }
  1899. if ( propertyName == "specColor" ) {
  1900. if ( threeObject.specular !== undefined ) {
  1901. var vwfColor = new utility.color( [ threeObject.specular.r*255, threeObject.specular.g*255, threeObject.specular.b*255 ] );
  1902. value = vwfColor.toString();
  1903. return value;
  1904. }
  1905. }
  1906. if ( propertyName == "reflect" ) {
  1907. value = threeObject.reflectivity;
  1908. return value;
  1909. }
  1910. if ( propertyName == "shininess" ) {
  1911. value = threeObject.shininess;
  1912. return value;
  1913. }
  1914. if ( propertyName == "emit" ) {
  1915. if ( threeObject.emissive ) {
  1916. var vwfColor = new utility.color( [ threeObject.emissive.r*255, threeObject.emissive.g*255, threeObject.emissive.b*255 ] );
  1917. value = vwfColor.toString();
  1918. return value;
  1919. }
  1920. }
  1921. if ( propertyName == "ambient" ) {
  1922. if ( threeObject.ambient ) {
  1923. var vwfColor = new utility.color( [ threeObject.ambient.r*255, threeObject.ambient.g*255, threeObject.ambient.b*255 ] );
  1924. value = vwfColor.toString();
  1925. return value;
  1926. }
  1927. }
  1928. if ( ( propertyName == "bumpScale" ) && ( threeObject.bumpMap ) ) {
  1929. value = threeObject.bumpScale;
  1930. return value;
  1931. }
  1932. if ( propertyName == "alphaTest" ) {
  1933. value = threeObject.alphaTest;
  1934. return value;
  1935. }
  1936. if ( propertyName == "transparent" ) {
  1937. value = threeObject.transparent;
  1938. return value;
  1939. }
  1940. if ( propertyName == "opacity" ) {
  1941. value = threeObject.opacity;
  1942. return value;
  1943. }
  1944. if ( propertyName === "side" ) {
  1945. switch ( threeObject.side ) {
  1946. case THREE.DoubleSide:
  1947. value = "double";
  1948. break;
  1949. case THREE.FrontSide:
  1950. value = "front";
  1951. break;
  1952. case THREE.BackSide:
  1953. value = "back";
  1954. break;
  1955. }
  1956. }
  1957. }
  1958. if ( threeObject instanceof THREE.ShaderMaterial ) {
  1959. if ( propertyName === "uniforms" ) {
  1960. value = {};
  1961. for ( var uni in threeObject.uniforms ) {
  1962. if ( threeObject.uniforms[ uni ].type === 't' ) {
  1963. if ( threeObject.uniforms[ uni ].value ) {
  1964. value[ uni ] = { "type": 't', "value": threeObject.uniforms[ uni ].value.sourceFile };
  1965. } else {
  1966. value[ uni ] = threeObject.uniforms[ uni ];
  1967. }
  1968. } else {
  1969. value[ uni ] = threeObject.uniforms[ uni ];
  1970. }
  1971. }
  1972. return value;
  1973. }
  1974. if ( propertyName === "vertexShader" ) {
  1975. value = threeObject.vertexShader;
  1976. return value;
  1977. }
  1978. if ( propertyName === "fragmentShader" ) {
  1979. value = threeObject.fragmentShader;
  1980. return value;
  1981. }
  1982. if ( propertyName === "updateFunction" ) {
  1983. value = threeObject.updateFunction;
  1984. return value;
  1985. }
  1986. }
  1987. if ( node.isUniformObject ) {
  1988. value = {};
  1989. for ( var prop in threeObject ) {
  1990. if ( ! utility.isFunction( threeObject[ prop ] ) ) {
  1991. if ( threeObject[ prop ].type !== 't' ) {
  1992. value[ prop ] = {
  1993. "type": threeObject[ prop ].type,
  1994. "pValue": threeObject[ prop ].value
  1995. };
  1996. } else {
  1997. value[ prop ] = {
  1998. "type": threeObject[ prop ].type,
  1999. "pValue": threeObject[ prop ].src
  2000. };
  2001. }
  2002. }
  2003. }
  2004. return value;
  2005. }
  2006. if ( threeObject instanceof THREE.Texture ) {
  2007. value = undefined;
  2008. switch ( propertyName ) {
  2009. case "url":
  2010. if( threeObject.image ) {
  2011. value = threeObject.image.src;
  2012. } else {
  2013. value = "";
  2014. }
  2015. break;
  2016. case "wrapT":
  2017. switch ( threeObject.wrapT ) {
  2018. case THREE.ClampToEdgeWrapping:
  2019. value = "clamp";
  2020. break;
  2021. case THREE.RepeatWrapping:
  2022. value = "repeat";
  2023. break;
  2024. case THREE.MirroredRepeatWrapping:
  2025. value = "mirror";
  2026. break;
  2027. }
  2028. break;
  2029. case "wrapS":
  2030. switch ( threeObject.wrapS ) {
  2031. case THREE.ClampToEdgeWrapping:
  2032. value = "clamp";
  2033. break;
  2034. case THREE.RepeatWrapping:
  2035. value = "repeat";
  2036. break;
  2037. case THREE.MirroredRepeatWrapping:
  2038. value = "mirror";
  2039. break;
  2040. }
  2041. break;
  2042. case "repeat":
  2043. if ( threeObject.repeat ) {
  2044. value = [ threeObject.repeat.x, threeObject.repeat.y ]
  2045. }
  2046. break;
  2047. case "offset":
  2048. if ( threeObject.offset ) {
  2049. value = [ threeObject.repeat.x, threeObject.offset.y ]
  2050. }
  2051. break;
  2052. case "magFilter":
  2053. switch ( threeObject.magFilter ) {
  2054. case THREE.NearestFilter:
  2055. value = "nearest";
  2056. break;
  2057. case THREE.NearestMipMapNearestFilter:
  2058. value = "nearestNearest";
  2059. break;
  2060. case THREE.NearestMipMapLinearFilter:
  2061. value = "nearestLinear";
  2062. break;
  2063. case THREE.LinearFilter:
  2064. value = "linear";
  2065. break;
  2066. case THREE.LinearMipMapNearestFilter:
  2067. value = "linearNearest";
  2068. break;
  2069. case THREE.LinearMipMapLinearFilter:
  2070. value = "linearLinear";
  2071. break;
  2072. }
  2073. break;
  2074. case "minFilter":
  2075. switch ( threeObject.minFilter ) {
  2076. case THREE.NearestFilter:
  2077. value = "nearest";
  2078. break;
  2079. case THREE.NearestMipMapNearestFilter:
  2080. value = "nearestNearest";
  2081. break;
  2082. case THREE.NearestMipMapLinearFilter:
  2083. value = "nearestLinear";
  2084. break;
  2085. case THREE.LinearFilter:
  2086. value = "linear";
  2087. break;
  2088. case THREE.LinearMipMapNearestFilter:
  2089. value = "linearNearest";
  2090. break;
  2091. case THREE.LinearMipMapLinearFilter:
  2092. value = "linearLinear";
  2093. break;
  2094. }
  2095. break;
  2096. case "anisotropy":
  2097. value = threeObject.anisotropy;
  2098. break;
  2099. }
  2100. if ( value !== undefined ) {
  2101. return value;
  2102. }
  2103. }
  2104. if( threeObject instanceof THREE.Camera ) {
  2105. switch ( propertyName ) {
  2106. case "fovy":
  2107. value = threeObject.fovy;
  2108. break;
  2109. case "near":
  2110. value = threeObject.near;
  2111. break;
  2112. case "aspect":
  2113. value = threeObject.aspect;
  2114. break;
  2115. case "far":
  2116. value = threeObject.far;
  2117. break;
  2118. case "cameraType":
  2119. if ( threeObject instanceof THREE.OrthographicCamera ) {
  2120. value = 'orthographic';
  2121. } else {
  2122. value = 'perspective';
  2123. }
  2124. break;
  2125. }
  2126. }
  2127. if( threeObject instanceof THREE.Scene ) {
  2128. var found = false;
  2129. var vwfColor, color;
  2130. switch ( propertyName ) {
  2131. case "ambientColor":
  2132. for( var i = 0; i < threeObject.children.length && !found; i++ ) {
  2133. if( threeObject.children[i] instanceof THREE.AmbientLight ) {
  2134. color = threeObject.children[i].color;
  2135. vwfColor = new utility.color( [ color.r*255, color.g*255, color.b*255 ] );
  2136. value = vwfColor.toString();
  2137. found = true;
  2138. }
  2139. }
  2140. break;
  2141. case "backgroundColor":
  2142. if ( node.renderer ) {
  2143. color = node.renderer.getClearColor();
  2144. var alpha = node.renderer.getClearAlpha();
  2145. if ( alpha !== undefined && alpha != 1 ){
  2146. vwfColor = new utility.color( [ color.r*255, color.g*255, color.b*255, alpha ] );
  2147. } else {
  2148. vwfColor = new utility.color( [ color.r*255, color.g*255, color.b*255 ] );
  2149. }
  2150. value = vwfColor.toString();
  2151. }
  2152. break;
  2153. case 'enableShadows':
  2154. if ( node.renderer ) {
  2155. value = node.renderer.shadowMapEnabled;
  2156. }
  2157. break;
  2158. case "activeCamera":
  2159. value = node.camera.ID;
  2160. break;
  2161. case "shadowMapCullFace":
  2162. if ( node.renderer ) {
  2163. value = node.renderer.shadowMapCullFace;
  2164. }
  2165. break;
  2166. case "shadowMapType":
  2167. if ( node.renderer ) {
  2168. value = node.renderer.shadowMapType;
  2169. }
  2170. break;
  2171. case "fogexp_color":
  2172. if ( threeObject.fog && threeObject.fog instanceof THREE.FogExp2 ) {
  2173. color = threeObject.fog.color;
  2174. vwfColor = new utility.color( [ color.r*255, color.g*255, color.b*255 ] );
  2175. value = vwfColor.toString();
  2176. }
  2177. break;
  2178. case "fogexp_density":
  2179. if ( threeObject.fog && threeObject.fog instanceof THREE.FogExp2 ) {
  2180. value = threeObject.fog.density;
  2181. }
  2182. break;
  2183. case "fog_color":
  2184. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  2185. color = threeObject.fog.color;
  2186. vwfColor = new utility.color( [ color.r*255, color.g*255, color.b*255 ] );
  2187. value = vwfColor.toString();
  2188. }
  2189. break;
  2190. case "fog_near":
  2191. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  2192. value = threeObject.fog.near;
  2193. }
  2194. break;
  2195. case "fog_far":
  2196. if ( threeObject.fog && threeObject.fog instanceof THREE.Fog ) {
  2197. value = threeObject.fog.far;
  2198. }
  2199. break;
  2200. }
  2201. }
  2202. if( threeObject instanceof THREE.Light ) {
  2203. switch ( propertyName ) {
  2204. case "lightType":
  2205. if ( threeObject instanceof THREE.DirectionalLight ){
  2206. value = 'directional';
  2207. } else if ( threeObject instanceof THREE.SpotLight ) {
  2208. value = 'spot';
  2209. } else if ( threeObject instanceof THREE.HemisphereLight ) {
  2210. value = 'hemisphere';
  2211. } else {
  2212. value = 'point';
  2213. }
  2214. break;
  2215. case "enable":
  2216. value = ( threeObject.parent !== undefined );
  2217. break;
  2218. case "position":
  2219. if ( threeObject.position !== null ) {
  2220. value = [ threeObject.position.x, threeObject.position.y, threeObject.position.z ];
  2221. }
  2222. break;
  2223. case "distance":
  2224. value = threeObject.distance;
  2225. break;
  2226. case "color":
  2227. var clr = new utility.color( [ threeObject.color.r * 255, threeObject.color.g * 255,
  2228. threeObject.color.b * 255 ] )
  2229. value = clr.toString();
  2230. break;
  2231. case "groundColor":
  2232. var clr = new utility.color( [ threeObject.groundColor.r * 255, threeObject.groundColor.g * 255,
  2233. threeObject.groundColor.b * 255 ] )
  2234. value = clr.toString();
  2235. break;
  2236. case "intensity":
  2237. value = threeObject.intensity;
  2238. break;
  2239. case "castShadows":
  2240. value = threeObject.castShadow;
  2241. break;
  2242. case "shadowCameraBottom":
  2243. value = threeObject.shadowCameraBottom;
  2244. break;
  2245. case "shadowCameraLeft":
  2246. value = threeObject.shadowCameraLeft;
  2247. break;
  2248. case "shadowCameraRight":
  2249. value = threeObject.shadowCameraRight;
  2250. break;
  2251. case "shadowCameraTop":
  2252. value = threeObject.shadowCameraTop;
  2253. break;
  2254. case "shadowCameraNear":
  2255. value = threeObject.shadowCameraNear;
  2256. break;
  2257. case "shadowCameraFar":
  2258. value = threeObject.shadowCameraFar;
  2259. break;
  2260. case "shadowDarkness":
  2261. value = threeObject.shadowDarkness;
  2262. break;
  2263. case "shadowMapHeight":
  2264. value = threeObject.shadowMapHeight;
  2265. break;
  2266. case "shadowMapWidth":
  2267. value = threeObject.shadowMapWidth;
  2268. break;
  2269. case "shadowBias":
  2270. value = threeObject.shadowBias;
  2271. break;
  2272. case "target":
  2273. // TODO: Return target node information if target is a node.
  2274. // The threeObjects of some nodes do not have a vwfID. This
  2275. // will incorrectly return a position in those cases. This
  2276. // needs to be fixed.
  2277. if ( threeObject.target !== undefined ) {
  2278. if ( threeObject.target.vwfID !== undefined ) {
  2279. value = threeObject.target.vwfID;
  2280. } else {
  2281. var targetPos = [ threeObject.target.position.x,
  2282. threeObject.target.position.y,
  2283. threeObject.target.position.z ];
  2284. value = targetPos;
  2285. }
  2286. }
  2287. break;
  2288. }
  2289. }
  2290. return value;
  2291. },
  2292. // TODO: deletingMethod
  2293. // -- callingMethod --------------------------------------------------------------------------
  2294. callingMethod: function( nodeID, methodName, parameters /* [, parameter1, parameter2, ... ] */ ) { // TODO: parameters
  2295. if ( methodName === "raycast" ) {
  2296. var origin, direction, near, far, recursive, objectIDs;
  2297. if ( parameters ) {
  2298. if ( parameters[0] instanceof THREE.Vector3 ) {
  2299. origin = parameters[0];
  2300. } else if ( parameters[0] instanceof Array && parameters[0].length === 3 ) {
  2301. var x, y, z;
  2302. x = isNaN( parameters[0][0] ) ? 0 : parameters[0][0];
  2303. y = isNaN( parameters[0][1] ) ? 0 : parameters[0][1];
  2304. z = isNaN( parameters[0][2] ) ? 0 : parameters[0][2];
  2305. origin = new THREE.Vector3( x, y, z );
  2306. } else {
  2307. origin = new THREE.Vector3();
  2308. }
  2309. if ( parameters[1] instanceof THREE.Vector3 ) {
  2310. direction = parameters[1];
  2311. } else if ( parameters[1] instanceof Array && parameters[1].length === 3 ) {
  2312. var x, y, z;
  2313. x = isNaN( parameters[1][0] ) ? 0 : parameters[1][0];
  2314. y = isNaN( parameters[1][1] ) ? 0 : parameters[1][1];
  2315. z = isNaN( parameters[1][2] ) ? 0 : parameters[1][2];
  2316. direction = new THREE.Vector3( x, y, z );
  2317. } else {
  2318. direction = new THREE.Vector3();
  2319. }
  2320. near = isNaN( parameters[2] ) ? 0 : parameters[2];
  2321. far = isNaN( parameters[3] ) ? Infinity : parameters[3];
  2322. recursive = typeof parameters[4] === "boolean" ? parameters[4] : false;
  2323. if ( parameters[5] instanceof Array ) {
  2324. objectIDs = parameters[5];
  2325. } else if ( utility.isString( parameters[5] ) ) {
  2326. objectIDs = new Array();
  2327. objectIDs.push( parameters[5] );
  2328. } else {
  2329. objectIDs = null;
  2330. }
  2331. } else {
  2332. origin = new THREE.Vector3();
  2333. direction = new THREE.Vector3();
  2334. near = 0;
  2335. far = Infinity;
  2336. recursive = false;
  2337. objectIDs = null;
  2338. }
  2339. var objects = new Array();
  2340. if ( objectIDs !== null ) {
  2341. for ( var i = 0; i < objectIDs.length; i++ ) {
  2342. var object = this.state.nodes[ objectIDs[i] ];
  2343. if ( object !== undefined && object.threeObject !== undefined ) {
  2344. objects.push( object.threeObject );
  2345. }
  2346. }
  2347. } else {
  2348. for ( nodeID in this.state.nodes ) {
  2349. var object = this.state.nodes[ nodeID ];
  2350. if ( object.threeObject !== undefined ) {
  2351. objects.push( object.threeObject );
  2352. }
  2353. }
  2354. }
  2355. var raycaster = new THREE.Raycaster( origin, direction, near, far );
  2356. var intersects = raycaster.intersectObjects( objects, recursive );
  2357. return intersects;
  2358. }
  2359. return undefined;
  2360. },
  2361. // TODO: creatingEvent, deltetingEvent, firingEvent
  2362. // -- executing ------------------------------------------------------------------------------
  2363. executing: function( nodeID, scriptText, scriptType ) {
  2364. return undefined;
  2365. },
  2366. // == ticking =============================================================================
  2367. ticking: function( vwfTime ) {
  2368. if ( checkLights && this.state.appInitialized && sceneCreated ) {
  2369. var lightsInScene = sceneLights.call( this );
  2370. createDefaultLighting.call( this, lightsInScene );
  2371. checkLights = false;
  2372. }
  2373. }
  2374. } );
  2375. // == PRIVATE ========================================================================================
  2376. function checkCompatibility() {
  2377. this.compatibilityStatus = { compatible:true, errors:{} }
  2378. var contextNames = ["webgl","experimental-webgl","moz-webgl","webkit-3d"];
  2379. for(var i = 0; i < contextNames.length; i++){
  2380. try{
  2381. var canvas = document.createElement('canvas');
  2382. var gl = canvas.getContext(contextNames[i]);
  2383. if(gl){
  2384. return true;
  2385. }
  2386. }
  2387. catch(e){}
  2388. }
  2389. this.compatibilityStatus.compatible = false;
  2390. this.compatibilityStatus.errors["WGL"] = "This browser is not compatible. The vwf/view/threejs driver requires WebGL.";
  2391. return false;
  2392. }
  2393. function getPrototypes( kernel, extendsID ) {
  2394. var prototypes = [];
  2395. var id = extendsID;
  2396. while ( id !== undefined ) {
  2397. prototypes.push( id );
  2398. id = kernel.prototype( id );
  2399. }
  2400. return prototypes;
  2401. }
  2402. function getThreeScene( id ) {
  2403. if ( id === undefined ) {
  2404. id = this.kernel.application();
  2405. }
  2406. if ( this.state.scenes[ id ] ) {
  2407. return this.state.scenes[ id ].threeScene;
  2408. }
  2409. return undefined;
  2410. }
  2411. function isSceneDefinition( prototypes ) {
  2412. var foundScene = false;
  2413. if ( prototypes ) {
  2414. for ( var i = 0; i < prototypes.length && !foundScene; i++ ) {
  2415. foundScene = ( prototypes[i] == "http://vwf.example.com/navscene.vwf" || prototypes[i] == "http://vwf.example.com/scene.vwf" );
  2416. }
  2417. }
  2418. return foundScene;
  2419. }
  2420. function isMaterialDefinition( prototypes ) {
  2421. var foundMaterial = false;
  2422. if ( prototypes ) {
  2423. for ( var i = 0; i < prototypes.length && !foundMaterial; i++ ) {
  2424. foundMaterial = ( prototypes[i] == "http://vwf.example.com/material.vwf" );
  2425. }
  2426. }
  2427. return foundMaterial;
  2428. }
  2429. function isShaderMaterialDefinition( prototypes ) {
  2430. var foundMaterial = false;
  2431. if ( prototypes ) {
  2432. for ( var i = 0; i < prototypes.length && !foundMaterial; i++ ) {
  2433. foundMaterial = ( prototypes[i] == "http://vwf.example.com/shaderMaterial.vwf" );
  2434. }
  2435. }
  2436. return foundMaterial;
  2437. }
  2438. function isShaderUniformsDefinition( prototypes ) {
  2439. var found = false;
  2440. if ( prototypes ) {
  2441. for ( var i = 0; i < prototypes.length && !found; i++ ) {
  2442. found = ( prototypes[i] == "http://vwf.example.com/threejs/uniforms.vwf" );
  2443. }
  2444. }
  2445. return found;
  2446. }
  2447. function isTextureDefinition( prototypes ) {
  2448. var found = false;
  2449. if ( prototypes ) {
  2450. for ( var i = 0; i < prototypes.length && !found; i++ ) {
  2451. found = ( prototypes[i] == "http://vwf.example.com/texture.vwf" );
  2452. }
  2453. }
  2454. return found;
  2455. }
  2456. function isCameraDefinition( prototypes ) {
  2457. var foundCamera = false;
  2458. if ( prototypes ) {
  2459. for ( var i = 0; i < prototypes.length && !foundCamera; i++ ) {
  2460. foundCamera = ( prototypes[i] == "http://vwf.example.com/camera.vwf" );
  2461. }
  2462. }
  2463. return foundCamera;
  2464. }
  2465. function isParticleDefinition( prototypes ) {
  2466. var foundSystem = false;
  2467. if ( prototypes ) {
  2468. for ( var i = 0; i < prototypes.length && !foundSystem; i++ ) {
  2469. foundSystem = ( prototypes[i] == "http://vwf.example.com/particlesystem.vwf" );
  2470. }
  2471. }
  2472. return foundSystem;
  2473. }
  2474. function isNodeDefinition( prototypes ) {
  2475. var foundNode = false;
  2476. if ( prototypes ) {
  2477. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2478. foundNode = ( prototypes[i] == "http://vwf.example.com/node3.vwf" );
  2479. }
  2480. }
  2481. return foundNode;
  2482. }
  2483. function isStarFieldDefinition( prototypes ) {
  2484. var foundNode = false;
  2485. if ( prototypes ) {
  2486. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2487. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/starfield.vwf" );
  2488. }
  2489. }
  2490. return foundNode;
  2491. }
  2492. function isCubeDefinition( prototypes ) {
  2493. var foundNode = false;
  2494. if ( prototypes ) {
  2495. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2496. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/cube.vwf" );
  2497. }
  2498. }
  2499. return foundNode;
  2500. }
  2501. function isCircleDefinition( prototypes ) {
  2502. var foundNode = false;
  2503. if ( prototypes ) {
  2504. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2505. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/circle.vwf" );
  2506. }
  2507. }
  2508. return foundNode;
  2509. }
  2510. function isPlaneDefinition( prototypes ) {
  2511. var foundNode = false;
  2512. if ( prototypes ) {
  2513. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2514. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/plane.vwf" );
  2515. }
  2516. }
  2517. return foundNode;
  2518. }
  2519. function isSphereDefinition( prototypes ) {
  2520. var foundNode = false;
  2521. if ( prototypes ) {
  2522. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2523. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/sphere.vwf" );
  2524. }
  2525. }
  2526. return foundNode;
  2527. }
  2528. function isCylinderDefinition( prototypes ) {
  2529. var foundNode = false;
  2530. if ( prototypes ) {
  2531. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2532. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/cylinder.vwf" );
  2533. }
  2534. }
  2535. return foundNode;
  2536. }
  2537. function isTextDefinition( prototypes ) {
  2538. var foundNode = false;
  2539. if ( prototypes ) {
  2540. for ( var i = 0; i < prototypes.length && !foundNode; i++ ) {
  2541. foundNode = ( prototypes[i] == "http://vwf.example.com/threejs/text.vwf" );
  2542. }
  2543. }
  2544. return foundNode;
  2545. }
  2546. function supportedFileType( type ) {
  2547. return ( type == "model/vnd.collada+xml" ||
  2548. type == "model/vnd.osgjs+json+compressed" ||
  2549. type == "model/x-threejs-morphanim+json" ||
  2550. type == "model/vnd.gltf+json" ||
  2551. type == "model/x-threejs-skinned+json" );
  2552. }
  2553. function CreateThreeJSSceneNode( parentID, thisID, extendsID )
  2554. {
  2555. var node = {};
  2556. node.name = "scene";
  2557. node.camera = {
  2558. "ID": undefined,
  2559. "defaultCamera": CreateThreeCamera()
  2560. };
  2561. node.ID = thisID;
  2562. node.parentID = parentID;
  2563. node.type = extendsID;
  2564. node.viewInited = false;
  2565. node.modelInited = false;
  2566. node.threeScene = new THREE.Scene();
  2567. node.threeScene.name = "scene";
  2568. node.pendingLoads = 0;
  2569. node.srcAssetObjects = [];
  2570. node.rendererProperties = {};
  2571. return node;
  2572. }
  2573. function nameTest( obj, name ) {
  2574. if ( obj.name == "" ) {
  2575. return ( obj.parent.name+"Child" == name );
  2576. } else {
  2577. return ( obj.name == name || obj.id == name || obj.vwfID == name );
  2578. }
  2579. }
  2580. // Changing this function significantly from the GLGE code
  2581. // Will search hierarchy down until encountering a matching child
  2582. // Will look into nodes that don't match.... this might not be desirable
  2583. function FindChildByName( obj, childName, childType, recursive ) {
  2584. var child = undefined;
  2585. if ( recursive ) {
  2586. // TODO: If the obj itself has the child name, the object will be returned by this function
  2587. // I don't think this this desirable.
  2588. if( nameTest.call( this, obj, childName ) ) {
  2589. child = obj;
  2590. } else if ( obj.children && obj.children.length > 0) {
  2591. for( var i = 0; i < obj.children.length && child === undefined; i++ ) {
  2592. child = FindChildByName( obj.children[i], childName, childType, true );
  2593. }
  2594. }
  2595. } else {
  2596. if ( obj.children ) {
  2597. for( var i = 0; i < obj.children.length && child === undefined; i++ ) {
  2598. if ( nameTest.call( this, obj.children[i], childName ) ) {
  2599. child = obj.children[i];
  2600. }
  2601. }
  2602. }
  2603. }
  2604. return child;
  2605. }
  2606. function findObject( objName, type ) {
  2607. //there is no global registry of threejs objects. return undefined;
  2608. return undefined;
  2609. }
  2610. function CreateThreeCamera()
  2611. {
  2612. var cam = new THREE.PerspectiveCamera( 35, $(document).width()/$(document).height() , 0.01, 10000 );
  2613. cam.matrixAutoUpdate = false;
  2614. cam.up = new THREE.Vector3( 0, 0, 1 );
  2615. cam.matrix.elements = [ 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 ];
  2616. cam.updateMatrixWorld( true );
  2617. return cam;
  2618. }
  2619. function createAmbientLight( threeScene, clr ){
  2620. var ambient = new THREE.AmbientLight();
  2621. if ( clr !== undefined && clr instanceof Array ) {
  2622. ambient.color.r = clr[0];
  2623. ambient.color.g = clr[1];
  2624. ambient.color.b = clr[2];
  2625. } else {
  2626. ambient.color.r = 0.5;
  2627. ambient.color.g = 0.5;
  2628. ambient.color.b = 0.5;
  2629. }
  2630. threeScene.add( ambient );
  2631. }
  2632. function createCamera( nodeID, childID, childName ) {
  2633. var sceneNode = this.state.scenes[ nodeID ];
  2634. var parent = sceneNode ? sceneNode : this.state.nodes[ nodeID ];
  2635. if ( !sceneNode ) sceneNode = this.state.scenes[ parent.sceneID ];
  2636. if ( sceneNode && parent ) {
  2637. var child = this.state.nodes[ childID ];
  2638. if ( child ) {
  2639. var cam = CreateThreeCamera.call( this );;
  2640. var threeParent = parent.threeObject;
  2641. if( !threeParent ) threeParent = parent.threeScene;
  2642. if ( threeParent && threeParent.add ) {
  2643. threeParent.add( cam );
  2644. }
  2645. child.name = childName;
  2646. child.threeObject = cam;
  2647. child.uid = child.threeObject.uid;
  2648. cam.name = childName;
  2649. }
  2650. }
  2651. }
  2652. function getThreeObject( ID ) {
  2653. var threeObject = undefined;
  2654. var node = this.state.nodes[ ID ]; // { name: childName, glgeObject: undefined }
  2655. if( node === undefined ) node = this.state.scenes[ ID ]; // { name: childName, glgeObject: undefined }
  2656. if( node ) {
  2657. threeObject = node.threeObject;
  2658. if( !threeObject )
  2659. threeObject = node.threeScene;
  2660. }
  2661. return threeObject;
  2662. }
  2663. function findAllGeometries( threeObject, list ) {
  2664. if( threeObject === undefined ) return;
  2665. if( list === undefined ) list = [];
  2666. if( threeObject instanceof THREE.Geometry )
  2667. list.push( threeObject );
  2668. if( threeObject.children ) {
  2669. for( var i = 0; i < threeObject.children.length; i++ ) {
  2670. findAllGeometries( threeObject.children[i], list );
  2671. }
  2672. }
  2673. return list;
  2674. }
  2675. function findAllMeshes(threeObject,list)
  2676. {
  2677. if(!threeObject) return;
  2678. if(!list) list = [];
  2679. if(threeObject instanceof THREE.Mesh)
  2680. list.push(threeObject);
  2681. if(threeObject.children)
  2682. {
  2683. for(var i = 0; i < threeObject.children.length; i++)
  2684. {
  2685. findAllMeshes(threeObject.children[i],list);
  2686. }
  2687. }
  2688. return list;
  2689. }
  2690. function createLightContainer() {
  2691. return {
  2692. "ambientLights": [],
  2693. "directionalLights": [],
  2694. "spotLights": [],
  2695. "pointLights": []
  2696. };
  2697. }
  2698. function findAllLights( threeObject, lights ) {
  2699. if( !threeObject )
  2700. return;
  2701. if ( threeObject instanceof THREE.DirectionalLight )
  2702. lights.directionalLights.push( threeObject );
  2703. else if ( threeObject instanceof THREE.SpotLight )
  2704. lights.spotLights.push( threeObject );
  2705. else if ( threeObject instanceof THREE.PointLight )
  2706. lights.pointLights.push( threeObject );
  2707. else if ( threeObject instanceof THREE.AmbientLight )
  2708. lights.ambientLights.push( threeObject );
  2709. if( threeObject.children ) {
  2710. for ( var i = 0; i < threeObject.children.length; i++) {
  2711. findAllLights( threeObject.children[ i ], lights );
  2712. }
  2713. }
  2714. return lights;
  2715. }
  2716. function getMeshVertexIndices(mesh)
  2717. {
  2718. var ret = [];
  2719. for(var i = 0; i < mesh.geometry.faces.length; i++)
  2720. {
  2721. var face = mesh.geometry.faces[i];
  2722. ret.push([face.a,face.b,face.c]);
  2723. }
  2724. return ret;
  2725. }
  2726. //Get all mesh verts. Transform via matrix stack up to threeObject. Thus, get all sub mesh verts relative to this object's transform
  2727. function getMeshVertices(mesh,threeObject )
  2728. {
  2729. var matrix = new THREE.Matrix4();
  2730. matrix.copy(mesh.matrix);
  2731. var parent = mesh.parent;
  2732. while(parent && parent != threeObject)
  2733. {
  2734. var mat = new THREE.Matrix4();
  2735. mat.copy(parent.matrix);
  2736. matrix = matrix.multiplyMatrices(mat,matrix);
  2737. parent = parent.parent;
  2738. }
  2739. var mat = new THREE.Matrix4();
  2740. mat.copy(threeObject.matrix);
  2741. matrix = matrix.multiplyMatrices(mat,matrix);
  2742. var ret = [];
  2743. for(var i = 0; i < mesh.geometry.vertices.length; i++)
  2744. {
  2745. var vert = new THREE.Vector3();
  2746. vert.copy(mesh.geometry.vertices[i]);
  2747. vert.applyMatrix4( matrix );
  2748. ret.push([vert.x,-vert.y,vert.z]);
  2749. }
  2750. return ret;
  2751. }
  2752. function GetAllMaterials( threeObject ) {
  2753. var result = [];
  2754. var resultUUID = [];
  2755. if ( !threeObject ) {
  2756. return result;
  2757. }
  2758. if ( threeObject && threeObject.material ) {
  2759. if ( ( threeObject.material instanceof THREE.Material ) && ( resultUUID.indexOf( threeObject.material.uuid ) < 0 ) ) {
  2760. result.push( threeObject.material );
  2761. resultUUID.push( threeObject.material.uuid );
  2762. }
  2763. else if ( threeObject.material instanceof THREE.MeshFaceMaterial ) {
  2764. if ( threeObject.material.materials ) {
  2765. for ( var index = 0; index < threeObject.material.materials.length; index++ ) {
  2766. if ( ( threeObject.material.materials[ index ] instanceof THREE.Material ) && ( resultUUID.indexOf( threeObject.material.materials[ index ].uuid ) < 0 ) ) {
  2767. result.push( threeObject.material.materials[ index ] );
  2768. resultUUID.push( threeObject.material.materials[ index ].uuid );
  2769. }
  2770. }
  2771. }
  2772. }
  2773. }
  2774. if ( threeObject && threeObject.children ) {
  2775. for ( var index = 0; index < threeObject.children.length; index++ ) {
  2776. var childrenMaterials = GetAllMaterials( threeObject.children[ index ] );
  2777. for ( var subindex = 0; subindex < childrenMaterials.length; subindex++ ) {
  2778. if ( resultUUID.indexOf( childrenMaterials[ subindex ].uuid ) < 0 ) {
  2779. result.push( childrenMaterials[ subindex ] );
  2780. resultUUID.push( childrenMaterials[ subindex ].uuid );
  2781. }
  2782. }
  2783. }
  2784. }
  2785. return result;
  2786. }
  2787. //do a depth first search of the children, return the first material
  2788. function GetMaterial(threeObject, optionalName)
  2789. {
  2790. //something must be pretty seriously wrong if no threeobject
  2791. if(!threeObject)
  2792. {
  2793. return null;
  2794. }
  2795. var allMaterialChildren = GetAllMaterials( threeObject );
  2796. if ( optionalName ) {
  2797. var regExResult = optionalName.match(/^material_\d+_/);
  2798. if ( regExResult ) {
  2799. var updatedName = optionalName.slice( regExResult[ 0 ].length );
  2800. var firstMatch = undefined;
  2801. var nameIndex = parseInt( optionalName.slice( 9, regExResult[ 0 ].length - 1 ) );
  2802. var foundIndex = 0;
  2803. for ( var index = 0; index < allMaterialChildren.length; index++ ) {
  2804. if ( allMaterialChildren[ index ].name == updatedName ) {
  2805. if ( ! firstMatch ) {
  2806. firstMatch = allMaterialChildren[ index ];
  2807. }
  2808. foundIndex++;
  2809. if ( foundIndex == nameIndex ) {
  2810. return allMaterialChildren[ index ];
  2811. }
  2812. }
  2813. }
  2814. if ( firstMatch ) {
  2815. return firstMatch;
  2816. }
  2817. }
  2818. for ( var index = 0; index < allMaterialChildren.length; index++ ) {
  2819. if ( allMaterialChildren[ index ].name == optionalName ) {
  2820. return allMaterialChildren[ index ];
  2821. }
  2822. }
  2823. }
  2824. if ( allMaterialChildren.length > 0 ) {
  2825. return allMaterialChildren[ 0 ];
  2826. }
  2827. return null;
  2828. }
  2829. function GetAllLeafMeshes(threeObject,list)
  2830. {
  2831. if(threeObject instanceof THREE.Mesh)
  2832. {
  2833. list.push(threeObject);
  2834. }
  2835. if(threeObject.children)
  2836. {
  2837. for(var i=0; i < threeObject.children.length; i++)
  2838. {
  2839. GetAllLeafMeshes(threeObject.children[i],list);
  2840. }
  2841. }
  2842. }
  2843. function fixMissingUVs(mesh)
  2844. {
  2845. if ( mesh.geometry instanceof THREE.BufferGeometry ) {
  2846. return;
  2847. }
  2848. var geometry = mesh.geometry;
  2849. if ( !geometry.faceVertexUvs[ 0 ] ) {
  2850. geometry.faceVertexUvs[ 0 ] = [];
  2851. }
  2852. if ( geometry.faceVertexUvs[ 0 ].length === 0 ) {
  2853. for ( var i = 0; i < geometry.faces.length; i++ ) {
  2854. var face = geometry.faces[ i ];
  2855. if ( face instanceof THREE.Face4 ) {
  2856. geometry.faceVertexUvs[0].push( [ new THREE.Vector2( 0, 1 ),
  2857. new THREE.Vector2( 0, 1 ),
  2858. new THREE.Vector2( 0, 1 ),
  2859. new THREE.Vector2( 0, 1 )
  2860. ] );
  2861. } else if ( face instanceof THREE.Face3 ) {
  2862. geometry.faceVertexUvs[0].push( [ new THREE.Vector2( 0, 1 ),
  2863. new THREE.Vector2( 0, 1 ),
  2864. new THREE.Vector2( 0, 1 )
  2865. ] );
  2866. }
  2867. }
  2868. }
  2869. geometry.computeCentroids && geometry.computeCentroids();
  2870. geometry.computeFaceNormals && geometry.computeFaceNormals();
  2871. geometry.computeVertexNormals && geometry.computeVertexNormals();
  2872. geometry.uvsNeedUpdate = true;
  2873. }
  2874. //set the material on all the sub meshes of an object.
  2875. //This could cause some strangeness in cases where an asset has multiple sub materials
  2876. //best to only specify the material sub-node where an asset is a mesh leaf
  2877. function SetMaterial( threeObject, material, materialname )
  2878. {
  2879. //something must be pretty seriously wrong if no threeobject
  2880. if(!threeObject)
  2881. return null;
  2882. var meshes =[];
  2883. GetAllLeafMeshes(threeObject,meshes);
  2884. //apply to all sub meshes
  2885. if(!materialname || materialname == 'material')
  2886. {
  2887. for(var i=0; i < meshes.length; i++)
  2888. {
  2889. meshes[i].material = material;
  2890. meshes[i].needsUpdate = true;
  2891. }
  2892. }else
  2893. {
  2894. var index = parseInt(materialname.substr(8));
  2895. if(meshes[index])
  2896. {
  2897. meshes[index].material = material;
  2898. meshes[index].needsUpdate = true;
  2899. window._dMesh =meshes[index];
  2900. }
  2901. }
  2902. }
  2903. function createShader( shaderDef ) {
  2904. var shaderMaterial = undefined;
  2905. if ( shaderDef && shaderDef.shaderType ) {
  2906. if ( THREE.ShaderLib[ shaderDef.shaderType ] !== undefined ) {
  2907. var shader = THREE.ShaderLib[ shaderDef.shaderType ];
  2908. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  2909. var mergedShader = {
  2910. fragmentShader: shader.fragmentShader,
  2911. vertexShader: shader.vertexShader,
  2912. uniforms: uniforms
  2913. };
  2914. for ( var prop in shaderDef ) {
  2915. switch ( prop ) {
  2916. case "shaderType":
  2917. break;
  2918. case "uniforms":
  2919. for ( var uProp in shaderDef.uniforms ) {
  2920. var uniProp = shaderDef.uniforms[ uProp ];
  2921. setUniformProperty( mergedShader.uniforms, uProp, uniProp.type, uniProp.pValue );
  2922. }
  2923. break;
  2924. default:
  2925. mergedShader[ prop ] = shaderDef[ prop ];
  2926. break;
  2927. }
  2928. }
  2929. shaderMaterial = new THREE.ShaderMaterial( mergedShader );
  2930. } else {
  2931. shaderMaterial = new THREE.ShaderMaterial( shaderDef );
  2932. }
  2933. }
  2934. return shaderMaterial;
  2935. }
  2936. function createGeometry( node, meshDef, doubleSided ) {
  2937. var geo = undefined;
  2938. var i, face, sides;
  2939. if ( ( node && isCubeDefinition.call( this, node.prototypes ) ) || meshDef.type === "box" ) {
  2940. sides = meshDef.sides || { px: true, nx: true, py: true, ny: true, pz: true, nz: true };
  2941. geo = new THREE.BoxGeometry( meshDef.width || 10, meshDef.height || 10, meshDef.depth || 10,
  2942. meshDef.segmentsWidth || 1, meshDef.segmentsHeight || 1, meshDef.segmentsDepth || 1 );
  2943. } else if ( ( node && isPlaneDefinition.call( this, node.prototypes ) ) || meshDef.type === "plane" ) {
  2944. geo = new THREE.PlaneGeometry( meshDef.width || 1, meshDef.height || 1,
  2945. meshDef.segmentsWidth || 1, meshDef.segmentsHeight || 1 );
  2946. } else if ( ( node && isCircleDefinition.call( this, node.prototypes ) ) || meshDef.type === "circle" ) {
  2947. geo = new THREE.CircleGeometry( meshDef.radius || 10,
  2948. meshDef.segments || 8, meshDef.thetaStart || 0,
  2949. meshDef.thetaLength || Math.PI * 2 );
  2950. } else if ( ( node && isSphereDefinition.call( this, node.prototypes ) ) || meshDef.type === "sphere" ) {
  2951. geo = new THREE.SphereGeometry( meshDef.radius || 10, meshDef.segmentsWidth || 8,
  2952. meshDef.segmentsHeight || 6, meshDef.phiStart || 0,
  2953. meshDef.phiLength || Math.PI * 2, meshDef.thetaStart || 0,
  2954. meshDef.thetaLength || Math.PI );
  2955. } else if ( ( node && isCylinderDefinition.call( this, node.prototypes ) ) || meshDef.type === "cylinder" ) {
  2956. geo = new THREE.CylinderGeometry( meshDef.radiusTop || 10, meshDef.radiusBottom || 10,
  2957. meshDef.height || 10, meshDef.segmentsRadius || 8,
  2958. meshDef.segmentsHeight || 1, meshDef.openEnded );
  2959. } else if ( ( node && isTextDefinition.call( this, node.prototypes ) ) || meshDef.type === "text" ) {
  2960. if ( meshDef.text != "" ) {
  2961. var parms = meshDef.parameters || {};
  2962. geo = new THREE.TextGeometry( meshDef.text, { "size": parms.size || 100,
  2963. "curveSegments": parms.curveSegments || 4, "font": parms.font || "helvetiker",
  2964. "weight": parms.weight || "normal", "style": parms.style || "normal",
  2965. "amount": parms.amount || 50, "height": parms.height || 50,
  2966. "bevelThickness": parms.bevelThickness || 10, "bevelSize": parms.bevelSize || 8,
  2967. "bevelEnabled": Boolean( parms.bevelEnabled ),
  2968. } );
  2969. // geo = new THREE.TextGeometry( meshDef.text, {
  2970. // size: 80,
  2971. // height: 20,
  2972. // curveSegments: 2,
  2973. // font: "helvetiker"
  2974. // } );
  2975. }
  2976. } else {
  2977. geo = new THREE.Geometry();
  2978. for ( i = 0; geo.vertices && meshDef.positions && ((i*3) < meshDef.positions.length); i++ ) {
  2979. //console.info( " adding vertices: [" + (meshDef.positions[i*3]) + ", " + (meshDef.positions[i*3+1]) + ", "+ (meshDef.positions[i*3+2]) + " ]" )
  2980. geo.vertices.push( new THREE.Vector3( meshDef.positions[i*3], meshDef.positions[i*3+1],meshDef.positions[i*3+2] ) );
  2981. }
  2982. for ( i = 0; geo.faces && meshDef.faces && ( (i*3) < meshDef.faces.length ); i++ ) {
  2983. //console.info( " adding face: [" + (meshDef.faces[i*3]) + ", " + (meshDef.faces[i*3+1]) + ", "+ (meshDef.faces[i*3+2]) + " ]" );
  2984. face = new THREE.Face3( meshDef.faces[i*3], meshDef.faces[i*3+1],meshDef.faces[i*3+2] );
  2985. geo.faces.push( face );
  2986. if ( doubleSided ) {
  2987. //console.info( " adding face: [" + (meshDef.faces[i*3+2]) + ", " + (meshDef.faces[i*3+1]) + ", "+ (meshDef.faces[i*3]) + " ]" );
  2988. face = new THREE.Face3( meshDef.faces[i*3+2], meshDef.faces[i*3+1],meshDef.faces[i*3] );
  2989. geo.faces.push( face );
  2990. }
  2991. }
  2992. // TODO: needed doubleSided support for normals
  2993. for ( i = 0 ; geo.faces && meshDef.normals && i < geo.faces.length; i++ ) {
  2994. face = geo.faces[ i ];
  2995. //console.info( " adding face normal: [" + (meshDef.normals[i*3]) + ", " + (meshDef.normals[i*3+1]) + ", "+ (meshDef.normals[i*3+2]) + " ]" );
  2996. face.vertexNormals.push( new THREE.Vector3( meshDef.normals[i*3], meshDef.normals[i*3+1],meshDef.normals[i*3+2] ) );
  2997. }
  2998. for ( i = 0; geo.faceVertexUvs && meshDef.uv1 && i < meshDef.uv1.length; i++ ) {
  2999. //console.info( " adding face vertex uv: [" + (meshDef.uv1[i*2]) + ", " + (meshDef.uv1[i*2+1]) + " ]" );
  3000. geo.faceVertexUvs.push( new THREE.Vector2( meshDef.uv1[i*2], meshDef.uv1[i*2+1] ) );
  3001. }
  3002. }
  3003. return geo;
  3004. }
  3005. function createMesh( node, meshDef, doubleSided ) {
  3006. if ( node.threeObject && node.threeObject instanceof THREE.Object3D ) {
  3007. var vwfColor, colorValue = 0xFFFFFF;
  3008. if ( meshDef.color !== undefined ) {
  3009. vwfColor = new utility.color( meshDef.color );
  3010. if ( vwfColor ) {
  3011. colorValue = vwfColor._decimal;
  3012. }
  3013. }
  3014. var mat = new THREE.MeshLambertMaterial( { "color": colorValue, "ambient": colorValue, side: THREE.DoubleSide } );
  3015. var geo = createGeometry( node, meshDef, doubleSided );
  3016. if ( meshDef.children ) {
  3017. var childGeo = undefined;
  3018. var matrix = new THREE.Matrix4();
  3019. var trans = [];
  3020. for ( var child in meshDef.children ) {
  3021. childGeo = createGeometry( undefined, meshDef.children[ child ], doubleSided );
  3022. if ( childGeo ) {
  3023. trans[ 0 ] = meshDef.children[ child ].properties.translation[ 0 ] || 0;
  3024. trans[ 1 ] = meshDef.children[ child ].properties.translation[ 1 ] || 0;
  3025. trans[ 2 ] = meshDef.children[ child ].properties.translation[ 2 ] || 0;
  3026. geo.merge( childGeo, matrix.makeTranslation( trans[ 0 ], trans[ 1 ], trans[ 2 ] ) );
  3027. }
  3028. }
  3029. geo.computeBoundingBoxSphere && geo.computeBoundingBoxSphere();
  3030. }
  3031. if ( geo !== undefined ) {
  3032. //geo.computeTangents && geo.computeTangents();
  3033. var mesh = new THREE.Mesh( geo, mat );
  3034. // The child mesh is created after the properties have been initialized, so copy
  3035. // the values of cast and receive shadow so they match
  3036. mesh.castShadow = node.threeObject.castShadow;
  3037. mesh.receiveShadow = node.threeObject.receiveShadow;
  3038. node.threeObject.add( mesh );
  3039. node.threeObject.vwfID = node.ID;
  3040. node.threeObject.name = node.name;
  3041. mesh.vwfID = node.ID;
  3042. mesh.name = node.name;
  3043. //geo.computeCentroids();
  3044. geo.computeFaceNormals && geo.computeFaceNormals();
  3045. }
  3046. }
  3047. }
  3048. //walk the graph of an object, and set all materials to new material clones
  3049. function cloneMaterials( nodein ) {
  3050. //sort the materials in the model, and when cloneing, make the new model share the same material setup as the old.
  3051. var materialMap = {};
  3052. walkGraph( nodein, function( node ) {
  3053. if(node.material) {
  3054. if ( node.material instanceof THREE.Material ) {
  3055. if(!materialMap[node.material.uuid]) {
  3056. materialMap[node.material.uuid] = [];
  3057. }
  3058. materialMap[node.material.uuid].push( [ node, -1 ] );
  3059. }
  3060. else if ( node.material instanceof THREE.MeshFaceMaterial ) {
  3061. if ( node.material.materials ) {
  3062. for ( var index = 0; index < node.material.materials.length; index++ ) {
  3063. if ( node.material.materials[ index ] instanceof THREE.Material ) {
  3064. if(!materialMap[node.material.materials[ index ].uuid]) {
  3065. materialMap[node.material.materials[ index ].uuid] = [];
  3066. }
  3067. materialMap[node.material.materials[ index ].uuid].push( [ node, index ] );
  3068. }
  3069. }
  3070. }
  3071. }
  3072. }
  3073. });
  3074. for(var i in materialMap)
  3075. {
  3076. var newmat;
  3077. if ( materialMap[ i ][ 0 ][ 1 ] < 0 ) {
  3078. newmat = materialMap[ i ][ 0 ][ 0 ].material.clone( );
  3079. }
  3080. else {
  3081. newmat = materialMap[ i ][ 0 ][ 0 ].material.materials[ materialMap[ i ][ 0 ][ 1 ] ].clone( );
  3082. }
  3083. for ( var j =0; j < materialMap[i].length; j++ ) {
  3084. if ( materialMap[ i ][ j ][ 1 ] < 0 ) {
  3085. materialMap[ i ][ j ][ 0 ].material = newmat;
  3086. }
  3087. else {
  3088. materialMap[ i ][ j ][ 0 ].material.materials[ materialMap[ i ][ j ][ 1 ] ] = newmat;
  3089. }
  3090. }
  3091. }
  3092. }
  3093. function loadAsset( parentNode, node, childType, propertyNotifyCallback ) {
  3094. var nodeCopy = node;
  3095. var nodeID = node.ID;
  3096. var childName = node.name;
  3097. var threeModel = this;
  3098. var sceneNode = this.state.scenes[ this.kernel.application() ];
  3099. var parentObject3 = parentNode.threeObject ? parentNode.threeObject : parentNode.threeScene;
  3100. //console.info( "---- loadAsset( "+parentNode.name+", "+node.name+", "+childType+" )" );
  3101. node.assetLoaded = function( geometry , materials) {
  3102. //console.info( "++++ assetLoaded( "+parentNode.name+", "+node.name+", "+childType+" )" );
  3103. sceneNode.pendingLoads--;
  3104. var removed = false;
  3105. // THREE JSON model
  3106. if ( childType == "model/x-threejs-morphanim+json" || childType == "model/x-threejs-skinned+json" ) {
  3107. for ( var i = 0; i < materials.length; i++ ) {
  3108. var m = materials[ i ];
  3109. // Do we have Morph Target animations?
  3110. if ( geometry.morphTargets.length > 0 ) {
  3111. m.morphTargets = true;
  3112. }
  3113. // Do we have skeletal animations?
  3114. if ( geometry.animation ) {
  3115. m.skinning = true;
  3116. }
  3117. }
  3118. var meshMaterial;
  3119. if ( materials.length > 1 ) {
  3120. // THREE.MeshFaceMaterial for meshes that have multiple materials
  3121. meshMaterial = new THREE.MeshFaceMaterial( materials );
  3122. } else {
  3123. // This mesh has only one material
  3124. meshMaterial = materials[ 0 ];
  3125. }
  3126. if ( childType == "model/x-threejs-morphanim+json" ) {
  3127. var asset = new THREE.MorphAnimMesh( geometry, meshMaterial );
  3128. } else { // childType == "model/x-threejs-skinned+json"
  3129. // THREE.AnimationHandler had a couple of methods
  3130. // depricated, check THREE.UCSCharacter
  3131. // THREE.AnimationHandler.add( geometry.animation );
  3132. var asset = new THREE.SkinnedMesh( geometry, meshMaterial );
  3133. var skinnedAnimation = new THREE.Animation( asset, geometry.animation );
  3134. skinnedAnimation.play();
  3135. }
  3136. asset.updateMatrix();
  3137. } else { // Collada model
  3138. var asset = geometry;
  3139. }
  3140. var keyframeAnimations, animatedMesh;
  3141. if ( asset.animations && asset.animations.length > 0 ) {
  3142. keyframeAnimations = asset.animations;
  3143. }
  3144. if ( asset.scene ) {
  3145. asset = asset.scene;
  3146. }
  3147. var meshes = [];
  3148. GetAllLeafMeshes( asset, meshes );
  3149. for ( var i = 0; i < meshes.length; i++ ) {
  3150. if ( meshes[ i ].material.map != null ) {
  3151. fixMissingUVs( meshes[ i ] );
  3152. }
  3153. }
  3154. asset.updateMatrixWorld();
  3155. asset.matrix = new THREE.Matrix4();
  3156. asset.matrixAutoUpdate = false;
  3157. // Don't make a copy of the three object if there are keyframe or skeletal animations associated with it
  3158. // until we figure out a way to copy them successfully.
  3159. if ( keyframeAnimations || skinnedAnimation ) {
  3160. nodeCopy.threeObject = asset;
  3161. }
  3162. else {
  3163. nodeCopy.threeObject = asset.clone();
  3164. }
  3165. //make sure that the new object has a unique material
  3166. cloneMaterials( nodeCopy.threeObject );
  3167. //find and bind the animations
  3168. //NOTE: this would probably be better handled by walking and finding the animations and skins only on the
  3169. //property setter when needed.
  3170. animatedMesh = [];
  3171. walkGraph(nodeCopy.threeObject,function( node ){
  3172. if( node instanceof THREE.SkinnedMesh || node instanceof THREE.MorphAnimMesh ) {
  3173. animatedMesh.push( node );
  3174. }
  3175. });
  3176. nodeCopy.threeObject.animatedMesh = animatedMesh;
  3177. nodeCopy.threeObject.updateMatrixWorld();
  3178. removeAmbientLights.call( this, nodeCopy.threeObject );
  3179. parentObject3.add( nodeCopy.threeObject );
  3180. nodeCopy.threeObject.name = childName;
  3181. nodeCopy.threeObject.vwfID = nodeID;
  3182. nodeCopy.threeObject.matrixAutoUpdate = false;
  3183. if( keyframeAnimations ) {
  3184. //var animHandler = THREE.AnimationHandler;
  3185. nodeCopy.threeObject.kfAnimations = [];
  3186. nodeCopy.threeObject.animations = keyframeAnimations;
  3187. // Initialize the key frame animations
  3188. for ( var i = 0; i < keyframeAnimations.length; i++ ) {
  3189. var animation = keyframeAnimations[ i ];
  3190. if ( !animation.node ) {
  3191. continue;
  3192. }
  3193. // Save references to the animations on the node that is animated, so that it can play separately
  3194. if( animation.node.animations == undefined ) {
  3195. animation.node.animations = [];
  3196. }
  3197. if( animation.node.kfAnimations == undefined ) {
  3198. animation.node.kfAnimations = [];
  3199. }
  3200. animation.node.animations.push( animation );
  3201. // add has been depricated
  3202. //animHandler.add( animation );
  3203. //var kfAnimation = new THREE.KeyFrameAnimation( animation.node, animation.name );
  3204. var kfAnimation = new THREE.KeyFrameAnimation( animation );
  3205. kfAnimation.timeScale = 1;
  3206. nodeCopy.threeObject.kfAnimations.push( kfAnimation );
  3207. animation.node.kfAnimations.push( kfAnimation );
  3208. for ( var h = 0; h < kfAnimation.hierarchy.length; h++ ) {
  3209. var keys = kfAnimation.data.hierarchy[ h ].keys;
  3210. var sids = kfAnimation.data.hierarchy[ h ].sids;
  3211. var obj = kfAnimation.hierarchy[ h ];
  3212. if ( keys.length && sids ) {
  3213. for(var s = 0; s < sids.length; s++) {
  3214. var sid = sids[s];
  3215. var next = kfAnimation.getNextKeyWith(sid, h, 0);
  3216. if(next) next.apply(sid);
  3217. }
  3218. obj.matrixAutoUpdate = false;
  3219. kfAnimation.data.hierarchy[h].node.updateMatrix();
  3220. obj.matrixWorldNeedsUpdate = true;
  3221. }
  3222. }
  3223. kfAnimation.play(false, 0);
  3224. }
  3225. }
  3226. if(animatedMesh) {
  3227. nodeCopy.threeObject.animatedMesh = animatedMesh;
  3228. }
  3229. // remember that this was a loaded collada file
  3230. nodeCopy.threeObject.loadedColladaNode = true;
  3231. for ( var j = 0; j < sceneNode.srcAssetObjects.length; j++ ) {
  3232. if ( sceneNode.srcAssetObjects[j] == nodeCopy ){
  3233. sceneNode.srcAssetObjects.splice( j, 1 );
  3234. removed = true;
  3235. }
  3236. }
  3237. updateStoredTransform( node );
  3238. // Since prototypes are created before the object, it does not get "setProperty" updates for
  3239. // its prototype (and behavior) properties. Therefore, we cycle through those properties to
  3240. // notify the drivers of the property values so they can react accordingly
  3241. // TODO: Have the kernel send the "setProperty" updates itself so the driver need not
  3242. propertyNotifyCallback();
  3243. // let vwf know the asset is loaded
  3244. if ( nodeCopy.loadingCallback ) {
  3245. //console.info( "========= LOADED ========== "+node.name+" ========= LOADED ==========" );
  3246. nodeCopy.loadingCallback( true );
  3247. }
  3248. //get the entry from the asset registry
  3249. reg = threeModel.assetRegistry[nodeCopy.source];
  3250. // If there are animations, set loaded to false and don't store the asset
  3251. // in the registry, since the animations don't work with the copy process
  3252. if(keyframeAnimations) {
  3253. reg.pending = false;
  3254. reg.loaded = false;
  3255. }
  3256. else {
  3257. //it's not pending, and it is loaded
  3258. reg.pending = false;
  3259. reg.loaded = true;
  3260. //store this asset in the registry
  3261. reg.node = asset;
  3262. }
  3263. //if any callbacks were waiting on the asset, call those callbacks
  3264. for( var i = 0; i < reg.callbacks.length; i++ ) {
  3265. reg.callbacks[i]( asset );
  3266. }
  3267. //nothing should be waiting on callbacks now.
  3268. reg.callbacks = [];
  3269. }
  3270. node.name = childName;
  3271. //create an asset registry if one does not exist for this driver
  3272. if( !this.assetRegistry ) {
  3273. this.assetRegistry = {};
  3274. }
  3275. // if there is no entry in the registry, create one
  3276. if( !this.assetRegistry[node.source] ) {
  3277. //it's new, so not waiting, and not loaded
  3278. this.assetRegistry[node.source] = {};
  3279. this.assetRegistry[node.source].loaded = false;
  3280. this.assetRegistry[node.source].pending = false;
  3281. this.assetRegistry[node.source].callbacks = [];
  3282. }
  3283. //grab the registry entry for this asset
  3284. var reg = this.assetRegistry[node.source];
  3285. //if the asset entry is not loaded and not pending, you'll have to actually go download and parse it
  3286. if( reg.loaded == false && reg.pending == false ) {
  3287. //thus, it becomes pending
  3288. reg.pending = true;
  3289. sceneNode.srcAssetObjects.push( node.threeObject );
  3290. //node.threeObject.vwfID = nodeID;
  3291. sceneNode.pendingLoads++;
  3292. switch ( childType ) {
  3293. case "model/vnd.collada+xml":
  3294. node.parse = true;
  3295. node.loader = new THREE.ColladaLoader();
  3296. node.loader.options.convertUpAxis = true;
  3297. node.loader.options.upAxis = "Z";
  3298. node.loader.load(node.source,node.assetLoaded.bind( this ));
  3299. break;
  3300. case "model/vnd.osgjs+json+compressed":
  3301. node.loader = new UTF8JsonLoader( node,node.assetLoaded.bind( this ) );
  3302. break;
  3303. case "model/x-threejs-morphanim+json":
  3304. case "model/x-threejs-skinned+json":
  3305. node.loader = new THREE.JSONLoader()
  3306. node.loader.load( node.source, node.assetLoaded.bind( this ) );
  3307. break;
  3308. case "model/vnd.gltf+json":
  3309. //create a queue to hold requests to the loader, since the loader cannot be re-entered for parallel loads
  3310. if ( !THREE.glTFLoader.queue )
  3311. {
  3312. //task is an object that holds the info about what to load
  3313. //nextTask is supplied by async to trigger the next in the queue
  3314. THREE.glTFLoader.queue = new async.queue( function( task, nextTask ) {
  3315. var node = task.node;
  3316. var cb = task.cb;
  3317. //call the actual load function
  3318. //signature of callback dictated by loader
  3319. node.loader.load( node.source, function( geometry , materials ) {
  3320. //ok, this model loaded, we can start the next load
  3321. nextTask();
  3322. //do whatever it was (asset loaded) that this load was going to do when complete
  3323. cb( geometry , materials );
  3324. } );
  3325. }, 1 );
  3326. }
  3327. node.loader = new THREE.glTFLoader();
  3328. node.loader.useBufferGeometry = true;
  3329. //we need to queue up our entry to this module, since it cannot handle re-entry. This means that while it
  3330. //is an async function, it cannot be entered again before it completes
  3331. THREE.glTFLoader.queue.push( {
  3332. node: node,
  3333. cb: node.assetLoaded.bind( this )
  3334. } );
  3335. break;
  3336. default:
  3337. self.logger.warnx( "Unable to import " + node.source + ". Unsupported file type: " + childType );
  3338. break;
  3339. }
  3340. }
  3341. //if the asset registry entry is not pending and it is loaded, then just grab a copy,
  3342. //no download or parse necessary
  3343. else if( reg.loaded == true && reg.pending == false ) {
  3344. var asset = (reg.node.clone());
  3345. // make sure the materails are unique
  3346. cloneMaterials( asset );
  3347. var n = asset;
  3348. var skins = [];
  3349. walkGraph( n, function( node ) {
  3350. if( node instanceof THREE.SkinnedMesh || node instanceof THREE.MorphAnimMesh ) {
  3351. skins.push( node );
  3352. }
  3353. });
  3354. n.animatedMesh = skins;
  3355. nodeCopy.threeObject = asset;
  3356. nodeCopy.threeObject.matrix = new THREE.Matrix4();
  3357. nodeCopy.threeObject.matrixAutoUpdate = false;
  3358. parentObject3.add( nodeCopy.threeObject );
  3359. nodeCopy.threeObject.name = childName;
  3360. nodeCopy.threeObject.vwfID = nodeID;
  3361. nodeCopy.threeObject.matrixAutoUpdate = false;
  3362. nodeCopy.threeObject.updateMatrixWorld( true );
  3363. propertyNotifyCallback();
  3364. window.setTimeout( function() {
  3365. nodeCopy.loadingCallback( true );
  3366. }, 10);
  3367. }
  3368. //if it's pending but not done, register a callback so that when it is done, it can be attached.
  3369. else if( reg.loaded == false && reg.pending == true ) {
  3370. sceneNode.srcAssetObjects.push( node.threeObject );
  3371. //so, not necessary to do all the other VWF node goo stuff, as that will be handled by the node that requested
  3372. //the asset in teh first place
  3373. reg.callbacks.push( function( node ) {
  3374. //just clone the node and attach it.
  3375. //this should not clone the geometry, so much lower memory.
  3376. //seems to take near nothing to duplicated animated avatar
  3377. var n = node.clone();
  3378. cloneMaterials( n );
  3379. var skins = [];
  3380. walkGraph( n, function( node ) {
  3381. if( node instanceof THREE.SkinnedMesh || node instanceof THREE.MorphAnimMesh ) {
  3382. skins.push( node );
  3383. }
  3384. });
  3385. n.animatedMesh = skins;
  3386. nodeCopy.threeObject = n;
  3387. nodeCopy.threeObject.matrix = new THREE.Matrix4();
  3388. nodeCopy.threeObject.matrixAutoUpdate = false;
  3389. removeAmbientLights.call(this, nodeCopy.threeObject);
  3390. parentObject3.add( nodeCopy.threeObject );
  3391. nodeCopy.threeObject.name = childName;
  3392. nodeCopy.threeObject.vwfID = nodeID;
  3393. nodeCopy.threeObject.matrixAutoUpdate = false;
  3394. nodeCopy.threeObject.updateMatrixWorld( true );
  3395. propertyNotifyCallback();
  3396. nodeCopy.loadingCallback( true );
  3397. });
  3398. }
  3399. }
  3400. //walk the scenegraph from the given root, calling the given function on each node
  3401. function walkGraph( root, func ) {
  3402. if( root ) {
  3403. func( root );
  3404. }
  3405. for( var i =0; i < root.children.length; i++ ) {
  3406. walkGraph( root.children[i], func );
  3407. }
  3408. }
  3409. // Strips the imported scene's ambient lights
  3410. function removeAmbientLights( threeObject ) {
  3411. for( var i = threeObject.children.length -1; i >= 0; i-- )
  3412. {
  3413. if( threeObject.children[i] instanceof THREE.AmbientLight )
  3414. {
  3415. threeObject.remove( threeObject.children[i] );
  3416. }
  3417. }
  3418. }
  3419. function getObjectID( objectToLookFor, bubbleUp, debug ) {
  3420. var objectIDFound = -1;
  3421. while (objectIDFound == -1 && objectToLookFor) {
  3422. if ( debug ) {
  3423. this.logger.info("====>>> vwf.model-glge.mousePick: searching for: " + path(objectToLookFor) );
  3424. }
  3425. $.each( this.state.nodes, function (nodeID, node) {
  3426. if ( node.threeObject == objectToLookFor && !node.glgeMaterial ) {
  3427. if ( debug ) { this.logger.info("pick object name: " + name(objectToLookFor) + " with id = " + nodeID ); }
  3428. objectIDFound = nodeID;
  3429. }
  3430. });
  3431. if ( bubbleUp ) {
  3432. objectToLookFor = objectToLookFor.parent;
  3433. } else {
  3434. objectToLookFor = undefined;
  3435. }
  3436. }
  3437. if (objectIDFound != -1)
  3438. return objectIDFound;
  3439. return undefined;
  3440. }
  3441. function isLightDefinition( prototypes ) {
  3442. var foundLight = false;
  3443. if ( prototypes ) {
  3444. for ( var i = 0; i < prototypes.length && !foundLight; i++ ) {
  3445. foundLight = ( prototypes[i] == "http://vwf.example.com/light.vwf" );
  3446. }
  3447. }
  3448. return foundLight;
  3449. }
  3450. function createLight( nodeID, childID, type, childName ) {
  3451. var child = this.state.nodes[childID];
  3452. if ( child ) {
  3453. switch( type ) {
  3454. case "http://vwf.example.com/directionallight.vwf":
  3455. child.threeObject = new THREE.DirectionalLight( 'FFFFFF' );
  3456. break;
  3457. case "http://vwf.example.com/spotlight.vwf":
  3458. child.threeObject = new THREE.SpotLight( 'FFFFFF' );
  3459. break;
  3460. case "http://vwf.example.com/hemispherelight.vwf":
  3461. child.threeObject = new THREE.HemisphereLight('FFFFFF','FFFFFF',1);
  3462. break;
  3463. case "http://vwf.example.com/pointlight.vwf":
  3464. default:
  3465. child.threeObject = new THREE.PointLight( 'FFFFFF', 1, 1000 );
  3466. break;
  3467. }
  3468. child.threeObject.name = childName;
  3469. child.name = childName;
  3470. addThreeChild.call( this, nodeID, childID );
  3471. }
  3472. }
  3473. function vwfColor( color ) {
  3474. var vwfColor = {};
  3475. vwfColor['r'] = color['r']*255;
  3476. vwfColor['g'] = color['g']*255;
  3477. vwfColor['b'] = color['b']*255;
  3478. if ( color['a'] !== undefined && color['a'] != 1 ) {
  3479. vwfColor['a'] = color['a'];
  3480. vwfColor = new utility.color( "rgba("+vwfColor['r']+","+vwfColor['g']+","+vwfColor['b']+","+vwfColor['a']+")" );
  3481. } else {
  3482. vwfColor = new utility.color( "rgb("+vwfColor['r']+","+vwfColor['g']+","+vwfColor['b']+")" );
  3483. }
  3484. return vwfColor;
  3485. }
  3486. function CreateParticleSystem(nodeID, childID, childName )
  3487. {
  3488. var child = this.state.nodes[childID];
  3489. if ( child )
  3490. {
  3491. // create the particle variables
  3492. var particles = new THREE.Geometry();
  3493. //default material expects all computation done cpu side, just renders
  3494. // note that since the color, size, spin and orientation are just linear
  3495. // interpolations, they can be done in the shader
  3496. var vertShader_default =
  3497. "attribute float size; \n"+
  3498. "attribute vec4 vertexColor;\n"+
  3499. "varying vec4 vColor;\n"+
  3500. "attribute vec4 random;\n"+
  3501. "varying vec4 vRandom;\n"+
  3502. "uniform float sizeRange;\n"+
  3503. "uniform vec4 colorRange;\n"+
  3504. "void main() {\n"+
  3505. " vColor = vertexColor + (random -0.5) * colorRange;\n"+
  3506. " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n"+
  3507. " float psize = size + (random.y -0.5) * sizeRange;\n"+
  3508. " gl_PointSize = psize * ( 1000.0/ length( mvPosition.xyz ) );\n"+
  3509. " gl_Position = projectionMatrix * mvPosition;\n"+
  3510. " vRandom = random;"+
  3511. "} \n";
  3512. var fragShader_default =
  3513. "uniform float useTexture;\n"+
  3514. "uniform sampler2D texture;\n"+
  3515. "varying vec4 vColor;\n"+
  3516. "varying vec4 vRandom;\n"+
  3517. "uniform float time;\n"+
  3518. "uniform float maxSpin;\n"+
  3519. "uniform float minSpin;\n"+
  3520. "uniform float maxOrientation;\n"+
  3521. "uniform float minOrientation;\n"+
  3522. "uniform float textureTiles;\n"+
  3523. "void main() {\n"+
  3524. " vec2 coord = vec2(0.0,0.0);"+
  3525. " vec2 orig_coord = vec2(gl_PointCoord.s,1.0-gl_PointCoord.t);"+
  3526. " float spin = mix(maxSpin,minSpin,vRandom.x);"+
  3527. " float orientation = mix(maxOrientation,minOrientation,vRandom.y);"+
  3528. " coord.s = (orig_coord.s-.5)*cos(time*spin+orientation)-(orig_coord.t-.5)*sin(time*spin+orientation);"+
  3529. " coord.t = (orig_coord.t-.5)*cos(time*spin+orientation)+(orig_coord.s-.5)*sin(time*spin+orientation);"+
  3530. " coord = coord + vec2(.5,.5);\n"+
  3531. " coord = coord/textureTiles;\n"+
  3532. " coord.x = clamp(coord.x,0.0,1.0/textureTiles);\n"+
  3533. " coord.y = clamp(coord.y,0.0,1.0/textureTiles);\n"+
  3534. " coord += vec2(floor(vRandom.x*textureTiles)/textureTiles,floor(vRandom.y*textureTiles)/textureTiles);\n"+
  3535. " vec4 outColor = (vColor * texture2D( texture, coord )) *useTexture + vColor * (1.0-useTexture);\n"+
  3536. " gl_FragColor = outColor;\n"+
  3537. "}\n";
  3538. //the default shader - the one used by the analytic solver, just has some simple stuff
  3539. //note that this could be changed to do just life and lifespan, and calculate the
  3540. //size and color from to uniforms. Im not going to bother
  3541. var attributes_default = {
  3542. size: { type: 'f', value: [] },
  3543. vertexColor: { type: 'v4', value: [] },
  3544. random: { type: 'v4', value: [] },
  3545. };
  3546. var uniforms_default = {
  3547. amplitude: { type: "f", value: 1.0 },
  3548. texture: { type: "t", value: new THREE.Texture( new Image() ) },
  3549. useTexture: { type: "f", value: 0.0 },
  3550. maxSpin: { type: "f", value: 0.0 },
  3551. minSpin: { type: "f", value: 0.0 },
  3552. maxOrientation: { type: "f", value: 0.0 },
  3553. minOrientation: { type: "f", value: 0.0 },
  3554. time: { type: "f", value: 0.0 },
  3555. fractime: { type: "f", value: 0.0 },
  3556. sizeRange: { type: "f", value: 0.0 },
  3557. textureTiles: { type: "f", value: 1.0 },
  3558. colorRange: { type: 'v4', value: new THREE.Vector4(0,0,0,0) },
  3559. startColor:{type: "v4", value:new THREE.Vector4()},
  3560. endColor:{type: "v4", value:new THREE.Vector4()},
  3561. startSize:{type:"f", value:1},
  3562. endSize:{type:"f", value:1},
  3563. };
  3564. uniforms_default.texture.value.wrapS = uniforms_default.texture.value.wrapT = THREE.RepeatWrapping;
  3565. var shaderMaterial_default = new THREE.ShaderMaterial( {
  3566. uniforms: uniforms_default,
  3567. attributes: attributes_default,
  3568. vertexShader: vertShader_default,
  3569. fragmentShader: fragShader_default
  3570. });
  3571. //the interpolate shader blends from one simulation step to the next on the shader
  3572. //this allows for a complex sim to run at a low framerate, but still have smooth motion
  3573. //this is very efficient, as it only requires sending data up to the gpu on each sim tick
  3574. //reuse the frag shader from the normal material
  3575. var vertShader_interpolate =
  3576. "attribute float age; \n"+
  3577. "attribute float lifespan; \n"+
  3578. "attribute vec3 previousPosition;\n"+
  3579. "varying vec4 vColor;\n"+
  3580. "attribute vec4 random;\n"+
  3581. "varying vec4 vRandom;\n"+
  3582. "uniform float sizeRange;\n"+
  3583. "uniform vec4 colorRange;\n"+
  3584. "uniform float fractime;\n"+
  3585. "uniform float startSize;\n"+
  3586. "uniform float endSize;\n"+
  3587. "uniform vec4 startColor;\n"+
  3588. "uniform vec4 endColor;\n"+
  3589. "void main() {\n"+
  3590. " vColor = mix(startColor,endColor,(age+fractime*3.33)/lifespan) + (random -0.5) * colorRange;\n"+
  3591. " vec4 mvPosition = modelViewMatrix * vec4(mix(previousPosition,position,fractime), 1.0 );\n"+
  3592. " float psize = mix(startSize,endSize,(age+fractime*3.33)/lifespan) + (random.y -0.5) * sizeRange;\n"+
  3593. " gl_PointSize = psize * ( 1000.0/ length( mvPosition.xyz ) );\n"+
  3594. " gl_Position = projectionMatrix * mvPosition;\n"+
  3595. " vRandom = random;"+
  3596. "} \n";
  3597. //the interpolation does need to remember the previous position
  3598. var attributes_interpolate = {
  3599. random: attributes_default.random,
  3600. previousPosition: { type: 'v3', value: [] },
  3601. age: { type: 'f', value: [] },
  3602. lifespan: { type: 'f', value: [] }
  3603. };
  3604. var shaderMaterial_interpolate = new THREE.ShaderMaterial( {
  3605. uniforms: uniforms_default,
  3606. attributes: attributes_interpolate,
  3607. vertexShader: vertShader_interpolate,
  3608. fragmentShader: fragShader_default
  3609. });
  3610. //analytic shader does entire simulation on GPU
  3611. //it cannot account for drag, gravity. nor can it generate new randomness. Each particle has it's randomness assigned and it
  3612. //just repeats the same motion over and over. Also, the other solvers can hold a particle until
  3613. //it can be reused based on the emitRate. This cannot, as the entire life of the particle must be
  3614. //computed from an equation given just time t. It does offset them in time to avoid all the particles
  3615. //being generated at once. Also, it does not account for emitter motion.
  3616. //upside : very very efficient. No CPU intervention required
  3617. var vertShader_analytic =
  3618. "attribute float size; \n"+
  3619. "attribute vec4 vertexColor;\n"+
  3620. "attribute vec3 acceleration;\n"+
  3621. "attribute vec3 velocity;\n"+
  3622. "attribute float lifespan;\n"+
  3623. "attribute vec4 random;\n"+
  3624. "uniform float time;\n"+
  3625. "uniform float startSize;\n"+
  3626. "uniform float endSize;\n"+
  3627. "uniform vec4 startColor;\n"+
  3628. "uniform vec4 endColor;\n"+
  3629. "varying vec4 vColor;\n"+
  3630. "varying vec4 vRandom;\n"+
  3631. "uniform float sizeRange;\n"+
  3632. "uniform vec4 colorRange;\n"+
  3633. "void main() {\n"+
  3634. //randomly offset in time
  3635. " float lifetime = mod( random.x * lifespan + time, lifespan );"+
  3636. //solve for position
  3637. " vec3 pos2 = position.xyz + velocity*lifetime + (acceleration*lifetime*lifetime)/2.0;"+ // ;
  3638. " vec4 mvPosition = modelViewMatrix * vec4( pos2.xyz, 1.0 );\n"+
  3639. //find random size based on randomness, start and end size, and size range
  3640. " float psize = mix(startSize,endSize,lifetime/lifespan) + (random.y -0.5) * sizeRange;\n"+
  3641. " gl_PointSize = psize * ( 1000.0/ length( mvPosition.xyz ) );\n"+
  3642. " gl_Position = projectionMatrix * mvPosition;\n"+
  3643. " vec4 nR = (random -0.5);\n"+
  3644. //find random color based on start and endcolor, time and colorRange
  3645. " vColor = mix(startColor,endColor,lifetime/lifespan) + nR * colorRange;\n"+
  3646. " vRandom = random;"+
  3647. "} \n";
  3648. var fragShader_analytic =
  3649. "uniform float useTexture;\n"+
  3650. "uniform sampler2D texture;\n"+
  3651. "uniform float time;\n"+
  3652. "uniform float maxSpin;\n"+
  3653. "uniform float minSpin;\n"+
  3654. "varying vec4 vColor;\n"+
  3655. "varying vec4 vRandom;\n"+
  3656. "uniform float maxOrientation;\n"+
  3657. "uniform float minOrientation;\n"+
  3658. "uniform float textureTiles;\n"+
  3659. "void main() {\n"+
  3660. //bit of drama for dividing into 4 or 9 'virtual' textures
  3661. //nice to be able to have different images on particles
  3662. " vec2 coord = vec2(0.0,0.0);"+
  3663. " vec2 orig_coord = vec2(gl_PointCoord.s,1.0-gl_PointCoord.t);"+
  3664. " float spin = mix(maxSpin,minSpin,vRandom.x);"+
  3665. " float orientation = mix(maxOrientation,minOrientation,vRandom.y);"+
  3666. " coord.s = (orig_coord.s-.5)*cos(time*spin+orientation)-(orig_coord.t-.5)*sin(time*spin+orientation);"+
  3667. " coord.t = (orig_coord.t-.5)*cos(time*spin+orientation)+(orig_coord.s-.5)*sin(time*spin+orientation);"+
  3668. " coord = coord + vec2(.5,.5);\n"+
  3669. " coord = coord/textureTiles;\n"+
  3670. " coord.x = clamp(coord.x,0.0,1.0/textureTiles);\n"+
  3671. " coord.y = clamp(coord.y,0.0,1.0/textureTiles);\n"+
  3672. " coord += vec2(floor(vRandom.x*textureTiles)/textureTiles,floor(vRandom.y*textureTiles)/textureTiles);\n"+
  3673. //get the color from the texture and blend with the vertexColor.
  3674. " vec4 outColor = (vColor * texture2D( texture, coord )) *useTexture + vColor * (1.0-useTexture);\n"+
  3675. " gl_FragColor = outColor;\n"+
  3676. "}\n";
  3677. var attributes_analytic = {
  3678. acceleration: { type: 'v3', value: [] },
  3679. velocity: { type: 'v3', value: [] },
  3680. lifespan: attributes_interpolate.lifespan,
  3681. random: attributes_default.random,
  3682. vertexColor : attributes_default.vertexColor,
  3683. size: attributes_default.size
  3684. };
  3685. var shaderMaterial_analytic = new THREE.ShaderMaterial( {
  3686. uniforms: uniforms_default,
  3687. attributes: attributes_analytic,
  3688. vertexShader: vertShader_analytic,
  3689. fragmentShader: fragShader_analytic
  3690. });
  3691. // create the particle system
  3692. var particleSystem = new THREE.PointCloud( particles, shaderMaterial_default );
  3693. //keep track of the shaders
  3694. particleSystem.shaderMaterial_analytic = shaderMaterial_analytic;
  3695. particleSystem.shaderMaterial_default = shaderMaterial_default;
  3696. particleSystem.shaderMaterial_interpolate = shaderMaterial_interpolate;
  3697. //setup all the default values
  3698. particleSystem.minVelocity = [0,0,0];
  3699. particleSystem.maxVelocity = [0,0,0];
  3700. particleSystem.maxAcceleration = [0,0,0];
  3701. particleSystem.minAcceleration = [0,0,0];
  3702. particleSystem.minLifeTime = 0;
  3703. particleSystem.maxLifeTime = 1;
  3704. particleSystem.emitterType = 'point';
  3705. particleSystem.emitterSize = [0,0,0];
  3706. particleSystem.startColor = [1,1,1,1];
  3707. particleSystem.endColor = [0,0,0,0];
  3708. particleSystem.regenParticles = [];
  3709. particleSystem.maxRate = 1000;
  3710. particleSystem.particleCount = 1000;
  3711. particleSystem.damping = 0;
  3712. particleSystem.startSize = 3;
  3713. particleSystem.endSize = 3;
  3714. particleSystem.gravity = 0;
  3715. particleSystem.gravityCenter = [0,0,0];
  3716. particleSystem.velocityMode = 'cartesian';
  3717. particleSystem.temp = new THREE.Vector3();
  3718. //create a new particle. create and store all the values for vertex attributes in each shader
  3719. particleSystem.createParticle = function(i)
  3720. {
  3721. var particle = new THREE.Vector3(0,0,0);
  3722. this.geometry.vertices.push(particle);
  3723. particle.i = i;
  3724. //the world space position
  3725. particle.world = new THREE.Vector3();
  3726. //the previous !tick! (not frame) position
  3727. particle.prevworld = new THREE.Vector3();
  3728. this.shaderMaterial_interpolate.attributes.previousPosition.value.push(particle.prevworld);
  3729. //the color
  3730. var color = new THREE.Vector4(1,1,1,1);
  3731. this.shaderMaterial_default.attributes.vertexColor.value.push(color);
  3732. //age
  3733. this.shaderMaterial_interpolate.attributes.age.value.push(1);
  3734. particle.color = color;
  3735. //the sise
  3736. this.shaderMaterial_default.attributes.size.value.push(1);
  3737. var self = this;
  3738. //set the size - stored per vertex
  3739. particle.setSize = function(s)
  3740. {
  3741. self.material.attributes.size.value[this.i] = s;
  3742. }
  3743. //set the age - stored per vertex
  3744. particle.setAge = function(a)
  3745. {
  3746. this.age = a;
  3747. self.shaderMaterial_interpolate.attributes.age.value[this.i] = this.age;
  3748. }
  3749. //the lifespan - stored per vertex
  3750. particle.setLifespan = function(a)
  3751. {
  3752. this.lifespan = a;
  3753. self.shaderMaterial_interpolate.attributes.lifespan.value[this.i] = this.a;
  3754. }
  3755. //This looks like it could be computed from the start and end plus random on the shader
  3756. //doing this saves computetime on the shader at expense of gpu mem
  3757. shaderMaterial_analytic.attributes.acceleration.value.push(new THREE.Vector3());
  3758. shaderMaterial_analytic.attributes.velocity.value.push(new THREE.Vector3());
  3759. shaderMaterial_analytic.attributes.lifespan.value.push(1);
  3760. shaderMaterial_analytic.attributes.random.value.push(new THREE.Vector4(Math.random(),Math.random(),Math.random(),Math.random()));
  3761. return particle;
  3762. }
  3763. //Generate a new point in space based on the emitter type and size
  3764. particleSystem.generatePoint = function()
  3765. {
  3766. //generate from a point
  3767. //TODO: specify point?
  3768. if(this.emitterType.toLowerCase() == 'point')
  3769. {
  3770. return new THREE.Vector3(0,0,0);
  3771. }
  3772. //Generate in a box
  3773. //assumes centered at 0,0,0
  3774. if(this.emitterType.toLowerCase() == 'box')
  3775. {
  3776. var x = this.emitterSize[0] * Math.random() - this.emitterSize[0]/2;
  3777. var y = this.emitterSize[1] * Math.random() - this.emitterSize[1]/2;
  3778. var z = this.emitterSize[2] * Math.random() - this.emitterSize[2]/2;
  3779. return new THREE.Vector3(x,y,z);
  3780. }
  3781. //Generate in a sphere
  3782. //assumes centered at 0,0,0
  3783. if(this.emitterType.toLowerCase() == 'sphere')
  3784. {
  3785. var u2 = Math.random();
  3786. u2 = Math.pow(u2,1/3);
  3787. var o = this.emitterSize[0] * Math.random() * Math.PI*2;
  3788. var u = this.emitterSize[1] * Math.random() * 2 - 1;
  3789. var r = this.emitterSize[2] * u2;
  3790. var x = Math.cos(o)*Math.sqrt(1-(u*u));
  3791. var y = Math.sin(o)*Math.sqrt(1-(u*u));
  3792. var z = u;
  3793. return new THREE.Vector3(x,y,z).setLength(r);
  3794. }
  3795. }
  3796. //setup the particles with new values
  3797. particleSystem.rebuildParticles = function()
  3798. {
  3799. for(var i = 0; i < this.geometry.vertices.length; i++)
  3800. {
  3801. this.setupParticle(this.geometry.vertices[i],this.matrix);
  3802. }
  3803. }
  3804. //set the particles initial values. Used when creating and resuing particles
  3805. particleSystem.setupParticle = function(particle,mat,inv)
  3806. {
  3807. particle.x = 0;
  3808. particle.y = 0;
  3809. particle.z = 0;
  3810. //generate a point in objects space, the move to world space
  3811. particle.world = this.generatePoint().applyMatrix4( mat );
  3812. //back up initial (needed by the analyticShader)
  3813. particle.initialx = particle.world.x;
  3814. particle.initialy = particle.world.y;
  3815. particle.initialz = particle.world.z;
  3816. //start at initial pos
  3817. particle.x = particle.initialx;
  3818. particle.y = particle.initialy;
  3819. particle.z = particle.initialz;
  3820. //start stoped, age 0
  3821. particle.age = 0;
  3822. particle.velocity = new THREE.Vector3(0,0,0);
  3823. particle.acceleration = new THREE.Vector3( 0,0,0);
  3824. particle.lifespan = 1;
  3825. //Generate the initial velocity
  3826. //In this mode, you specify a min and max x,y,z
  3827. if(this.velocityMode == 'cartesian')
  3828. {
  3829. particle.velocity.x = this.minVelocity[0] + (this.maxVelocity[0] - this.minVelocity[0]) * Math.random();
  3830. particle.velocity.y = this.minVelocity[1] + (this.maxVelocity[1] - this.minVelocity[1]) * Math.random();
  3831. particle.velocity.z = this.minVelocity[2] + (this.maxVelocity[2] - this.minVelocity[2]) * Math.random();
  3832. }
  3833. //In this mode, you give a pitch and yaw from 0,1, and a min and max length.
  3834. //This is easier to emit into a circle, or a cone section
  3835. if(this.velocityMode == 'spherical')
  3836. {
  3837. //random sphercial points concentrate at poles
  3838. /* var r = this.minVelocity[2] + (this.maxVelocity[2] - this.minVelocity[2]) * Math.random();
  3839. var t = this.minVelocity[1] + (this.maxVelocity[1] - this.minVelocity[1]) * Math.random() * Math.PI*2;
  3840. var w = this.minVelocity[0] + (this.maxVelocity[0] - this.minVelocity[0]) * Math.random() * Math.PI - Math.PI/2;
  3841. particle.velocity.x = r * Math.sin(t)*Math.cos(w);
  3842. particle.velocity.y = r * Math.sin(t)*Math.sin(w);
  3843. particle.velocity.z = r * Math.cos(t); */
  3844. //better distribution
  3845. var o = this.minVelocity[0] + (this.maxVelocity[0] - this.minVelocity[0]) * Math.random() * Math.PI*2;
  3846. var u = this.minVelocity[1] + (this.maxVelocity[1] - this.minVelocity[1]) * Math.random() * 2 - 1;
  3847. var u2 = Math.random();
  3848. u2 = Math.pow(u2,1/3);
  3849. var r = this.minVelocity[2] + (this.maxVelocity[2] - this.minVelocity[2]) * u2;
  3850. particle.velocity.x = Math.cos(o)*Math.sqrt(1-(u*u));
  3851. particle.velocity.y = Math.sin(o)*Math.sqrt(1-(u*u));
  3852. particle.velocity.z = u;
  3853. particle.velocity.setLength(r);
  3854. }
  3855. //The velocity should be in world space, but is generated in local space for
  3856. //ease of use
  3857. mat = mat.clone();
  3858. mat.elements[12] = 0;
  3859. mat.elements[13] = 0;
  3860. mat.elements[14] = 0;
  3861. particle.velocity.applyMatrix4( mat );
  3862. //accelerations are always world space, just min and max on each axis
  3863. particle.acceleration.x = this.minAcceleration[0] + (this.maxAcceleration[0] - this.minAcceleration[0]) * Math.random();
  3864. particle.acceleration.y = this.minAcceleration[1] + (this.maxAcceleration[1] - this.minAcceleration[1]) * Math.random();
  3865. particle.acceleration.z = this.minAcceleration[2] + (this.maxAcceleration[2] - this.minAcceleration[2]) * Math.random();
  3866. particle.setLifespan(this.minLifeTime + (this.maxLifeTime - this.minLifeTime) * Math.random());
  3867. //color is start color
  3868. particle.color.x = this.startColor[0];
  3869. particle.color.y = this.startColor[1];
  3870. particle.color.z = this.startColor[2];
  3871. particle.color.w = this.startColor[3];
  3872. //save the values into the attributes
  3873. shaderMaterial_analytic.attributes.acceleration.value[particle.i] = (particle.acceleration);
  3874. shaderMaterial_analytic.attributes.velocity.value[particle.i] = (particle.velocity);
  3875. shaderMaterial_analytic.attributes.lifespan.value[particle.i] = (particle.lifespan);
  3876. shaderMaterial_analytic.attributes.acceleration.needsUpdate = true;
  3877. shaderMaterial_analytic.attributes.velocity.needsUpdate = true;
  3878. shaderMaterial_analytic.attributes.lifespan.needsUpdate = true;
  3879. this.geometry.verticesNeedUpdate = true;
  3880. //randomly move the particle up to one step in time
  3881. particle.prevworld.x = particle.x;
  3882. particle.prevworld.y = particle.y;
  3883. particle.prevworld.z = particle.z;
  3884. }
  3885. //when updating in AnalyticShader mode, is very simple, just inform the shader of new time.
  3886. particleSystem.updateAnalyticShader = function(time)
  3887. {
  3888. particleSystem.material.uniforms.time.value += time/1000;
  3889. }
  3890. //In Analytic mode, run the equation for the position
  3891. particleSystem.updateAnalytic =function(time)
  3892. {
  3893. particleSystem.material.uniforms.time.value += time/3333.0;
  3894. var time_in_ticks = time/33.333;
  3895. var inv = this.matrix.clone();
  3896. inv = inv.getInverse(inv);
  3897. var particles = this.geometry;
  3898. //update each particle
  3899. var pCount = this.geometry.vertices.length;
  3900. while(pCount--)
  3901. {
  3902. var particle =particles.vertices[pCount];
  3903. this.updateParticleAnalytic(particle,this.matrix,inv,time_in_ticks);
  3904. }
  3905. //examples developed with faster tick - maxrate *33 is scale to make work
  3906. //with new timing
  3907. //Reuse up to maxRate particles, sliced for delta_time
  3908. //Once a particle reaches it's end of life, its available to be regenerated.
  3909. //We hold extras in limbo with alpha 0 until they can be regenerated
  3910. //Note the maxRate never creates or destroys particles, just manages when they will restart
  3911. //after dying
  3912. var len = Math.min(this.regenParticles.length,this.maxRate*15*time_in_ticks);
  3913. for(var i =0; i < len; i++)
  3914. {
  3915. //setup with new random values, and move randomly forward in time one step
  3916. var particle = this.regenParticles.shift();
  3917. this.setupParticle(particle,this.matrix,inv);
  3918. this.updateParticleAnalytic(particle,this.matrix,inv,Math.random()*3.33);
  3919. particle.waitForRegen = false;
  3920. }
  3921. //only these things change, other properties are in the shader as they are linear WRT time
  3922. this.geometry.verticesNeedUpdate = true;
  3923. this.geometry.colorsNeedUpdate = true;
  3924. this.material.attributes.vertexColor.needsUpdate = true;
  3925. this.material.attributes.size.needsUpdate = true;
  3926. }
  3927. particleSystem.counter = 0;
  3928. particleSystem.testtime = 0;
  3929. particleSystem.totaltime = 0;
  3930. //timesliced Euler integrator
  3931. //todo: switch to RK4
  3932. //This can do more complex sim, maybe even a cloth sim or such. It ticks 10 times a second, and blends tick with previous via a shader
  3933. particleSystem.updateEuler = function(time)
  3934. {
  3935. particleSystem.material.uniforms.time.value += time/3333.0;
  3936. var time_in_ticks = time/100.0;
  3937. if(this.lastTime === undefined) this.lastTime = 0;
  3938. this.lastTime += time_in_ticks;//ticks - Math.floor(ticks);
  3939. var inv = this.matrix.clone();
  3940. inv = inv.getInverse(inv);
  3941. var particles = this.geometry;
  3942. //timesliced tick give up after 5 steps - just cant go fast enough
  3943. if(Math.floor(this.lastTime) > 5)
  3944. this.lastTime = 1;
  3945. for(var i=0; i < Math.floor(this.lastTime) ; i++)
  3946. {
  3947. this.lastTime--;
  3948. var pCount = this.geometry.vertices.length;
  3949. while(pCount--)
  3950. {
  3951. var particle =particles.vertices[pCount];
  3952. this.updateParticleEuler(particle,this.matrix,inv,3.333);
  3953. }
  3954. //examples developed with faster tick - maxrate *33 is scale to make work
  3955. //with new timing
  3956. //Reuse up to maxRate particles, sliced for delta_time
  3957. //Once a particle reaches it's end of life, its available to be regenerated.
  3958. //We hold extras in limbo with alpha 0 until they can be regenerated
  3959. //Note the maxRate never creates or destroys particles, just manages when they will restart
  3960. //after dying
  3961. var len = Math.min(this.regenParticles.length,this.maxRate*333);
  3962. for(var i =0; i < len; i++)
  3963. {
  3964. particle.waitForRegen = false;
  3965. var particle = this.regenParticles.shift();
  3966. this.setupParticle(particle,this.matrix,inv);
  3967. this.updateParticleEuler(particle,this.matrix,inv,Math.random()*3.33);
  3968. this.material.attributes.lifespan.needsUpdate = true;
  3969. }
  3970. //only need to send up the age, position, and previous position. other props handled in the shader
  3971. this.geometry.verticesNeedUpdate = true;
  3972. this.material.attributes.previousPosition.needsUpdate = true;
  3973. this.material.attributes.age.needsUpdate = true;
  3974. }
  3975. //even if this is not a sim tick, we need to send the fractional time up to the shader for the interpolation
  3976. this.material.uniforms.fractime.value = this.lastTime;
  3977. }
  3978. //Update a particle from the Analytic solver
  3979. particleSystem.updateParticleAnalytic = function(particle,mat,inv,delta_time)
  3980. {
  3981. particle.age += delta_time;
  3982. //Make the particle dead. Hide it until it can be reused
  3983. if(particle.age >= particle.lifespan && !particle.waitForRegen)
  3984. {
  3985. this.regenParticles.push(particle);
  3986. particle.waitForRegen = true;
  3987. particle.x = 0;
  3988. particle.y = 0;
  3989. particle.z = 0;
  3990. particle.color.w = 0.0;
  3991. }else
  3992. {
  3993. //Run the formula to get position.
  3994. var percent = particle.age/particle.lifespan;
  3995. particle.world.x = particle.initialx + (particle.velocity.x * particle.age) + 0.5*(particle.acceleration.x * particle.age * particle.age)
  3996. particle.world.y = particle.initialy + (particle.velocity.y * particle.age) + 0.5*(particle.acceleration.y * particle.age * particle.age)
  3997. particle.world.z = particle.initialz + (particle.velocity.z * particle.age) + 0.5*(particle.acceleration.z * particle.age * particle.age)
  3998. this.temp.x = particle.world.x;
  3999. this.temp.y = particle.world.y;
  4000. this.temp.z = particle.world.z;
  4001. //need to specify in object space, event though comptued in local
  4002. this.temp.applyMatrix4( inv );
  4003. particle.x = this.temp.x;
  4004. particle.y = this.temp.y;
  4005. particle.z = this.temp.z;
  4006. //Should probably move this to the shader. Linear with time, no point in doing on CPU
  4007. particle.color.x = this.startColor[0] + (this.endColor[0] - this.startColor[0]) * percent;
  4008. particle.color.y = this.startColor[1] + (this.endColor[1] - this.startColor[1]) * percent;
  4009. particle.color.z = this.startColor[2] + (this.endColor[2] - this.startColor[2]) * percent;
  4010. particle.color.w = this.startColor[3] + (this.endColor[3] - this.startColor[3]) * percent;
  4011. particle.setSize(this.startSize + (this.endSize - this.startSize) * percent);
  4012. }
  4013. }
  4014. //updtae a partilce with the Euler solver
  4015. particleSystem.updateParticleEuler = function(particle,mat,inv,step_dist)
  4016. {
  4017. particle.prevage = particle.age;
  4018. particle.age += step_dist;
  4019. particle.setAge(particle.age + step_dist);
  4020. //If the particle is dead ,hide it unitl it can be reused
  4021. if(particle.age >= particle.lifespan && !particle.waitForRegen)
  4022. {
  4023. this.regenParticles.push(particle);
  4024. particle.waitForRegen = true;
  4025. particle.x = 0;
  4026. particle.y = 0;
  4027. particle.z = 0;
  4028. particle.world.x = 0;
  4029. particle.world.y = 0;
  4030. particle.world.z = 0;
  4031. particle.prevworld.x = 0;
  4032. particle.prevworld.y = 0;
  4033. particle.prevworld.z = 0;
  4034. particle.color.w = 1.0;
  4035. particle.size = 100;
  4036. }else
  4037. {
  4038. // and the position
  4039. particle.prevworld.x = particle.world.x;
  4040. particle.prevworld.y = particle.world.y;
  4041. particle.prevworld.z = particle.world.z;
  4042. //find direction to center for gravity
  4043. var gravityAccel = new THREE.Vector3(particle.world.x,particle.world.y,particle.world.z);
  4044. gravityAccel.x -= this.gravityCenter[0];
  4045. gravityAccel.y -= this.gravityCenter[1];
  4046. gravityAccel.z -= this.gravityCenter[2];
  4047. var len = gravityAccel.length()+.1;
  4048. gravityAccel.normalize();
  4049. gravityAccel.multiplyScalar(-Math.min(1/(len*len),100));
  4050. gravityAccel.multiplyScalar(this.gravity);
  4051. //update position
  4052. particle.world.x += particle.velocity.x * step_dist + (particle.acceleration.x + gravityAccel.x)* step_dist * step_dist;
  4053. particle.world.y += particle.velocity.y * step_dist + (particle.acceleration.y + gravityAccel.y )* step_dist * step_dist;;
  4054. particle.world.z += particle.velocity.z * step_dist + (particle.acceleration.z + gravityAccel.z )* step_dist * step_dist;;
  4055. //update velocity
  4056. particle.velocity.x += (particle.acceleration.x + gravityAccel.x) * step_dist * step_dist;
  4057. particle.velocity.y += (particle.acceleration.y + gravityAccel.y) * step_dist * step_dist;
  4058. particle.velocity.z += (particle.acceleration.z + gravityAccel.z) * step_dist * step_dist
  4059. var damping = 1-(this.damping * step_dist);
  4060. //drag
  4061. particle.velocity.x *= damping;
  4062. particle.velocity.y *= damping;
  4063. particle.velocity.z *= damping;
  4064. //move from world to local space
  4065. this.temp.x = particle.world.x ;
  4066. this.temp.y = particle.world.y ;
  4067. this.temp.z = particle.world.z;
  4068. this.temp.applyMatrix4( inv );
  4069. particle.x = this.temp.x;
  4070. particle.y = this.temp.y;
  4071. particle.z = this.temp.z;
  4072. //careful to have prev and current pos in same space!!!!
  4073. particle.prevworld.applyMatrix4( inv );
  4074. }
  4075. }
  4076. //Change the solver type for the system
  4077. particleSystem.setSolverType =function(type)
  4078. {
  4079. this.solver = type;
  4080. if(type == 'Euler')
  4081. {
  4082. particleSystem.update = particleSystem.updateEuler;
  4083. particleSystem.material = particleSystem.shaderMaterial_interpolate;
  4084. particleSystem.rebuildParticles();
  4085. }
  4086. if(type == 'Analytic')
  4087. {
  4088. particleSystem.update = particleSystem.updateAnalytic;
  4089. particleSystem.material = particleSystem.shaderMaterial_default;
  4090. particleSystem.rebuildParticles();
  4091. }
  4092. if(type == 'AnalyticShader')
  4093. {
  4094. particleSystem.update = particleSystem.updateAnalyticShader ;
  4095. particleSystem.material = particleSystem.shaderMaterial_analytic;
  4096. particleSystem.rebuildParticles();
  4097. }
  4098. }
  4099. //If you move a system, all the particles need to be recomputed to look like they stick in world space
  4100. //not that we pointedly dont do this for the AnalyticShader. We could, but that solver is ment to be very high performance, do we dont
  4101. particleSystem.updateTransform = function(newtransform)
  4102. {
  4103. //Get he current transform, and invert new one
  4104. var inv = new THREE.Matrix4();
  4105. var newt = new THREE.Matrix4();
  4106. inv.elements = matCpy(newtransform);
  4107. newt = newt.copy(this.matrix);
  4108. inv = inv.getInverse(inv);
  4109. //don't adjust for the high performance shader
  4110. if(particleSystem.solver == 'AnalyticShader')
  4111. {
  4112. return;
  4113. }
  4114. //Move all particles out of old space to world, then back into new space.
  4115. //this will make it seem like they stay at the correct position in the world, though
  4116. //acutally they change position
  4117. //note that it would actually be more efficient to leave the matrix as identity, and change the position of the
  4118. //emitters for this...... Could probably handle it in the model setter actually... would be much more efficient, but linking
  4119. //a system to a moving object would break.
  4120. for(var i =0; i < this.geometry.vertices.length; i++)
  4121. {
  4122. this.geometry.vertices[ i ].applyMatrix4( inv );
  4123. this.shaderMaterial_interpolate.attributes.previousPosition.value[ i ].applyMatrix4( inv );
  4124. this.geometry.vertices[ i ].applyMatrix4( newt );
  4125. this.shaderMaterial_interpolate.attributes.previousPosition.value[ i ].applyMatrix4( newt );
  4126. }
  4127. this.geometry.verticesNeedUpdate = true;
  4128. this.shaderMaterial_interpolate.attributes.previousPosition.needsUpdate = true;
  4129. }
  4130. //Change the system count. Note that this must be set before the first frame renders, cant be changed at runtime.
  4131. particleSystem.setParticleCount = function(newcount)
  4132. {
  4133. var inv = this.matrix.clone();
  4134. inv = inv.getInverse(inv);
  4135. var particles = this.geometry;
  4136. while(this.geometry.vertices.length > newcount)
  4137. {
  4138. this.geometry.vertices.pop();
  4139. }
  4140. while(this.geometry.vertices.length < newcount)
  4141. {
  4142. var particle = particleSystem.createParticle(this.geometry.vertices.length);
  4143. particleSystem.setupParticle(particle,particleSystem.matrix,inv);
  4144. particle.age = Infinity;
  4145. this.regenParticles.push(particle);
  4146. particle.waitForRegen = true;
  4147. }
  4148. this.geometry.verticesNeedUpdate = true;
  4149. this.geometry.colorsNeedUpdate = true;
  4150. this.shaderMaterial_default.attributes.vertexColor.needsUpdate = true;
  4151. this.particleCount = newcount;
  4152. }
  4153. //Setup some defaults
  4154. particleSystem.setParticleCount(1000);
  4155. particleSystem.setSolverType('AnalyticShader');
  4156. particleSystem.update(1);
  4157. child.threeObject = particleSystem;
  4158. child.threeObject.name = childName;
  4159. child.name = childName;
  4160. addThreeChild.call( this, nodeID, childID );
  4161. }
  4162. }
  4163. function addThreeChild( parentID, childID ) {
  4164. var threeParent;
  4165. var parent = this.state.nodes[ parentID ];
  4166. if ( !parent && this.state.scenes[ parentID ] ) {
  4167. parent = this.state.scenes[ parentID ];
  4168. threeParent = parent.threeScene;
  4169. } else {
  4170. threeParent = parent.threeObject;
  4171. }
  4172. if ( threeParent && this.state.nodes[ childID ]) {
  4173. var child = this.state.nodes[ childID ];
  4174. if ( child.threeObject ) {
  4175. threeParent.add( child.threeObject );
  4176. }
  4177. }
  4178. }
  4179. //search the threeObject of the parent sim node for the threeChild with the name of the sim child node
  4180. function findThreeObjectInParent(childID,parentID)
  4181. {
  4182. var parentThreeObject;
  4183. if(this.state.nodes[parentID])
  4184. parentThreeObject = this.state.nodes[parentID].threeObject;
  4185. if(!parentThreeObject && this.state.scenes[parentID])
  4186. parentThreeObject = this.state.scenes[parentID].threeScene;
  4187. //If there is no parent object render node, then there does not need to be a child node
  4188. if(!parentThreeObject) return null;
  4189. var threeChild = findChildThreeObject(parentThreeObject,childID);
  4190. return threeChild;
  4191. }
  4192. function findChildThreeObject(threeParent,childID)
  4193. {
  4194. var ret = null;
  4195. if(threeParent.name == childID)
  4196. ret = threeParent;
  4197. else if(threeParent.children)
  4198. {
  4199. for(var i = 0; i< threeParent.children.length; i++)
  4200. var child = findChildThreeObject(threeParent.children[i],childID);
  4201. if(child)
  4202. ret = child;
  4203. }
  4204. return ret;
  4205. }
  4206. function sceneLights() {
  4207. var scene = getThreeScene.call( this );
  4208. var lightList = createLightContainer.call( this );
  4209. if ( scene ) {
  4210. lightList = findAllLights( scene, lightList );
  4211. }
  4212. return lightList;
  4213. }
  4214. function createDefaultLighting( lights ) {
  4215. var sceneID = this.kernel.application();
  4216. var ambientCount = lights.ambientLights.length;
  4217. var lightCount = lights.spotLights.length + lights.directionalLights.length + lights.pointLights.length;
  4218. var scene = getThreeScene.call( this );
  4219. if ( lightCount == 0 ) {
  4220. var light1 = new THREE.DirectionalLight( '808080', 2 );
  4221. var light2 = new THREE.DirectionalLight( '808080', 2 );
  4222. light1.distance = light2.distance = 2000;
  4223. scene.add( light1 );
  4224. scene.add( light2 );
  4225. light1.position.set( 0.7, -0.7, 0.3 );
  4226. light2.position.set( -0.7, 0.7, 0.3 );
  4227. }
  4228. if ( ambientCount == 0 ) {
  4229. createAmbientLight.call( this, scene, [ 0.20, 0.20, 0.20 ] );
  4230. }
  4231. }
  4232. function findVwfChildren( threeObj, children ) {
  4233. if ( threeObj !== undefined ) {
  4234. if ( threeObj.vwfID !== undefined ) {
  4235. children.push( threeObj.vwfID );
  4236. }
  4237. if ( threeObj && threeObj.children ) {
  4238. for ( var i = 0; i < threeObj.children.length; i++ ) {
  4239. findVwfChildren( threeObj.children[ i ], children );
  4240. }
  4241. }
  4242. }
  4243. }
  4244. function SetVisible( node, state ) {
  4245. if ( node ) {
  4246. node.visible = state;
  4247. }
  4248. if ( node && node.children ) {
  4249. for( var i = 0; i < node.children.length; i++ ) {
  4250. var child = node.children[i];
  4251. if( !child.vwfID ) {
  4252. SetVisible( child, state );
  4253. }
  4254. }
  4255. }
  4256. }
  4257. function setTransformsDirty( threeObject ) {
  4258. var vwfChildren = [];
  4259. var childNode;
  4260. findVwfChildren( threeObject, vwfChildren );
  4261. for ( var i = 0; i < vwfChildren.length; i++ ) {
  4262. childNode = self.state.nodes[ vwfChildren[ i ] ];
  4263. if ( childNode && childNode.transform !== undefined ) {
  4264. childNode.storedTransformDirty = true;
  4265. }
  4266. }
  4267. }
  4268. function getWorldTransform( node ) {
  4269. var parent = self.state.nodes[ node.parentID ];
  4270. if ( parent === undefined ) {
  4271. parent = self.state.scenes[ node.parentID ];
  4272. }
  4273. if ( parent ) {
  4274. var worldTransform = new THREE.Matrix4();
  4275. if ( node.transform === undefined ) {
  4276. node.transform = new THREE.Matrix4();
  4277. }
  4278. return worldTransform.multiplyMatrices( getWorldTransform( parent ), node.transform );
  4279. } else {
  4280. return node.transform || new THREE.Matrix4();
  4281. }
  4282. }
  4283. function setWorldTransform( node, worldTransform ) {
  4284. if ( node.parent ) {
  4285. var parentInverse = goog.vec.Mat4.create();
  4286. if ( goog.vec.Mat4.invert( getWorldTransform( node.parent ), parentInverse ) ) {
  4287. node.transform = goog.vec.Mat4.multMat( parentInverse, worldTransform,
  4288. goog.vec.Mat4.create() );
  4289. } else {
  4290. self.logger.errorx( "Parent world transform is not invertible - did not set world transform " +
  4291. "on node '" + node.id + "'" );
  4292. }
  4293. } else {
  4294. node.transform = worldTransform;
  4295. }
  4296. }
  4297. function updateStoredTransform( node ) {
  4298. if ( node && node.threeObject && ( node.threeObject instanceof THREE.Object3D ) ) {
  4299. // Add a local model-side transform that can stay pure even if the view changes the
  4300. // transform on the threeObject - this already happened in creatingNode for those nodes that
  4301. // didn't need to load a model
  4302. node.transform = new THREE.Matrix4();
  4303. node.transform.elements = matCpy( node.threeObject.matrix.elements );
  4304. // If this threeObject is a camera, it has a 90-degree rotation on it to account for the
  4305. // different coordinate systems of VWF and three.js. We need to undo that rotation before
  4306. // setting the VWF property.
  4307. if ( node.threeObject instanceof THREE.Camera ) {
  4308. var transformArray = node.transform.elements;
  4309. // Get column y and z out of the matrix
  4310. var columny = goog.vec.Vec4.create();
  4311. goog.vec.Mat4.getColumn( transformArray, 1, columny );
  4312. var columnz = goog.vec.Vec4.create();
  4313. goog.vec.Mat4.getColumn( transformArray, 2, columnz );
  4314. // Swap the two columns, negating columny
  4315. goog.vec.Mat4.setColumn( transformArray, 1, goog.vec.Vec4.negate( columnz, columnz ) );
  4316. goog.vec.Mat4.setColumn( transformArray, 2, columny );
  4317. }
  4318. node.storedTransformDirty = false;
  4319. }
  4320. }
  4321. // -- getBoundingBox ------------------------------------------------------------------------------
  4322. function getBoundingBox( object3 ) {
  4323. var bBox = {
  4324. min: { x: Number.MAX_VALUE, y: Number.MAX_VALUE, z: Number.MAX_VALUE },
  4325. max: { x: -Number.MAX_VALUE, y: -Number.MAX_VALUE, z: -Number.MAX_VALUE }
  4326. };
  4327. if (object3 instanceof THREE.Object3D)
  4328. {
  4329. object3.traverse (function (mesh)
  4330. {
  4331. if (mesh instanceof THREE.Mesh)
  4332. {
  4333. mesh.geometry.computeBoundingBox ();
  4334. var meshBoundingBox = mesh.geometry.boundingBox;
  4335. // compute overall bbox
  4336. bBox.min.x = Math.min (bBox.min.x, meshBoundingBox.min.x);
  4337. bBox.min.y = Math.min (bBox.min.y, meshBoundingBox.min.y);
  4338. bBox.min.z = Math.min (bBox.min.z, meshBoundingBox.min.z);
  4339. bBox.max.x = Math.max (bBox.max.x, meshBoundingBox.max.x);
  4340. bBox.max.y = Math.max (bBox.max.y, meshBoundingBox.max.y);
  4341. bBox.max.z = Math.max (bBox.max.z, meshBoundingBox.max.z);
  4342. }
  4343. });
  4344. }
  4345. else if ( object3 && object3.geometry && object3.geometry.computeBoundingBox ) {
  4346. object3.geometry.computeBoundingBox();
  4347. var bx = object3.geometry.boundingBox;
  4348. bBox = {
  4349. min: { x: bx.min.x, y: bx.min.y, z: bx.min.z },
  4350. max: { x: bx.max.x, y: bx.max.y, z: bx.max.z }
  4351. };
  4352. }
  4353. return bBox;
  4354. }
  4355. function getCenterOffset( object3 ) {
  4356. var offset = [ 0, 0, 0 ];
  4357. if ( object3 ) {
  4358. var bBox = getBoundingBox.call( this, object3 );
  4359. offset[0] = ( bBox.max.x + bBox.min.x ) * 0.50;
  4360. offset[1] = ( bBox.max.y + bBox.min.y ) * 0.50;
  4361. offset[2] = ( bBox.max.z + bBox.min.z ) * 0.50;
  4362. }
  4363. return offset;
  4364. }
  4365. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  4366. //UTF8 loader
  4367. function DecodeARRAY_BUFFER(str,range,inmin,stride,bits)
  4368. {
  4369. str = blobarray[str];
  4370. var attribs_out = [];//new Float32Array(str.length);
  4371. //min = min + 0.0;
  4372. var prev = [0,0,0];
  4373. var divisor = Math.pow(2,bits);
  4374. for (var i = 5; i < str.length-5; i+=stride) {
  4375. for(var j = 0; j< stride; j++)
  4376. {
  4377. var code = str.charCodeAt(i+j);
  4378. var dezigzag = (Number(code) >> 1) ^ (-(Number(code) & 1));
  4379. prev[j] += dezigzag;
  4380. var prev_attrib = ((prev[j]/divisor)*(range)) + Number(inmin) ;//(code >> 1) ^ (-(code & 1));
  4381. attribs_out.push(prev_attrib);
  4382. }
  4383. }
  4384. return attribs_out;
  4385. }
  4386. var debugarraytype = "";
  4387. function DecodeELEMENT_ARRAY_BUFFER(str,range)
  4388. {
  4389. str = blobarray[str];
  4390. var attribs_out = [];//new Uint16Array(str.length);
  4391. var prev = 0;
  4392. for (var i = 5; i < str.length-5; i++) {
  4393. var code = str.charCodeAt(i);
  4394. var dezigzag = (code >> 1) ^ (-(code & 1));;
  4395. prev += dezigzag;
  4396. // alert("char code " +code + " dezigzag " + dezigzag + " new value " + prev);
  4397. attribs_out.push(prev);
  4398. }
  4399. return attribs_out;
  4400. }
  4401. function DecodeArray(array,key)
  4402. {
  4403. var type = array.type;
  4404. var array2 =[];
  4405. var itemsize = array.itemSize;
  4406. if(type == "ELEMENT_ARRAY_BUFFER")
  4407. array2 = DecodeELEMENT_ARRAY_BUFFER(array.elements.values,array.elements.range);
  4408. if(type == "ARRAY_BUFFER")
  4409. array2 = DecodeARRAY_BUFFER(array.elements.values,array.elements.range,array.elements.min,itemsize,array.elements.bits);
  4410. return array2;
  4411. }
  4412. function UTF8JsonLoader(node,callback)
  4413. {
  4414. this.url = node.source;
  4415. this.callback = callback;
  4416. this.children=[];
  4417. this.jsonLoaded = function(e)
  4418. {
  4419. var test = 1+1;
  4420. var jsonData = JSON.parse(decompress(e));
  4421. var texture_load_callback = function(texturename)
  4422. {
  4423. var src = "";
  4424. if(this.url.toLowerCase().indexOf('3dr_federation') != -1)
  4425. src = this.url.substr(0,this.url.indexOf("Model/")) + "textures/NoRedirect/" + encodeURIComponent(texturename) +"?ID=00-00-00";
  4426. else
  4427. src = this.url.substr(0,this.url.indexOf("Model/")) + "textures/" + encodeURIComponent(texturename) +"?ID=00-00-00";
  4428. console.log(src);
  4429. src = src.replace("AnonymousUser:@","");
  4430. var tex = loadTexture( undefined, src );
  4431. return tex;
  4432. }
  4433. this.scene = ParseSceneGraph(jsonData,texture_load_callback.bind(this));
  4434. if(this.callback)
  4435. this.callback(this);
  4436. }.bind(this);
  4437. this.error = function(e)
  4438. {
  4439. alert(e.responseText);
  4440. }.bind(this);
  4441. $.ajax({
  4442. url: this.url,
  4443. data: {},
  4444. success: this.jsonLoaded,
  4445. error: this.error,
  4446. dataType:'text'
  4447. });
  4448. ;
  4449. }
  4450. function BuildUTF8JsonNode(node,callback)
  4451. {
  4452. return new UTF8JsonLoader(node,callback);
  4453. }
  4454. function toColor(arr)
  4455. {
  4456. var color = new THREE.Color();
  4457. color.setRGB(arr[0],arr[1],arr[2],arr[3]);
  4458. return color;
  4459. }
  4460. function ApplyMaterial(newnode,newmaterial)
  4461. {
  4462. if(newnode instanceof THREE.Mesh)
  4463. newnode.material = newmaterial;
  4464. else if( newnode.children)
  4465. {
  4466. for(var i =0; i < newnode.children.length;i++)
  4467. ApplyMaterial(newnode.children[0],newmaterial);
  4468. }
  4469. }
  4470. function isIdentityMatrix( elements ) {
  4471. if ( ( elements.length == 16 ) || ( elements.length == 9 ) ) {
  4472. var modNumber = Math.sqrt( elements.length ) + 1;
  4473. for ( var index = 0; index < elements.length; index++ ) {
  4474. if ( ( index % modNumber ) == 0 ) {
  4475. if ( elements[ index ] != 1 ) {
  4476. return false;
  4477. }
  4478. }
  4479. else {
  4480. if ( elements[ index ] != 0 ) {
  4481. return false;
  4482. }
  4483. }
  4484. }
  4485. return true;
  4486. }
  4487. return false;
  4488. }
  4489. function ParseSceneGraph(node, texture_load_callback) {
  4490. var newnode;
  4491. //its geometry
  4492. if (node.primitives) {
  4493. //newnode = new THREE.Object3D();
  4494. var geo = new THREE.Geometry();
  4495. var mesh = newnode = new THREE.Mesh(geo);
  4496. mesh.geometry.normals = [];
  4497. mesh.geometry.UVS = [];
  4498. //vertex data
  4499. if (node.attributes) {
  4500. $.each(node.attributes, function(key, element) {
  4501. debugarraytype = key;
  4502. var attributeArray = node.attributes[key];
  4503. node.attributes[key] = DecodeArray(attributeArray,key);
  4504. if(key == "Vertex")
  4505. {
  4506. for(var i = 0; i < node.attributes[key].length-2; i+= 3)
  4507. {
  4508. var vert = new THREE.Vector3( node.attributes[ key ][ i ],
  4509. node.attributes[ key ][ i + 1 ],
  4510. node.attributes[ key ][ i + 2 ] );
  4511. mesh.geometry.vertices.push(vert);
  4512. }
  4513. }
  4514. if(key == "Normal")
  4515. {
  4516. for(var i = 0; i < node.attributes[key].length-2; i+= 3)
  4517. {
  4518. var norm = new THREE.Vector3( node.attributes[ key ][ i ],
  4519. node.attributes[ key ][ i + 1 ],
  4520. node.attributes[ key ][ i + 2 ] );
  4521. mesh.geometry.normals.push(norm);
  4522. }
  4523. }
  4524. if(key == "TexCoord0")
  4525. {
  4526. for(var i = 0; i < node.attributes[key].length-1; i+= 2)
  4527. {
  4528. var uv = new THREE.Vector2( node.attributes[ key ][ i ],
  4529. node.attributes[ key ][ i + 1 ] );
  4530. mesh.geometry.UVS.push(uv);
  4531. }
  4532. }
  4533. if(key == "VertexColor")
  4534. {
  4535. for(var i = 0; i < node.attributes[key].length-3; i+= 4)
  4536. {
  4537. var vert = new THREE.Vector3( node.attributes[ key ][ i ],
  4538. node.attributes[ key ][ i + 1 ],
  4539. node.attributes[ key ][ i + 2 ] );
  4540. mesh.geometry.colors.push(vert);
  4541. }
  4542. }
  4543. });
  4544. }
  4545. var i;
  4546. for (i in node.primitives) {
  4547. if (node.primitives[i].indices) {
  4548. var array = node.primitives[i].indices;
  4549. array = DecodeArray(array);
  4550. for(var j = 0; j < array.length-2; j+= 3)
  4551. {
  4552. var face = new THREE.Face3(array[j],array[j+1],array[j+2],new THREE.Vector3(0,1,0),new THREE.Color('#000000'),0);
  4553. face.vertexNormals.push(mesh.geometry.normals[face.a]);
  4554. face.vertexNormals.push(mesh.geometry.normals[face.b]);
  4555. face.vertexNormals.push(mesh.geometry.normals[face.c]);
  4556. mesh.geometry.faces.push(face);
  4557. mesh.geometry.faceVertexUvs[0].push([mesh.geometry.UVS[face.a],mesh.geometry.UVS[face.b],mesh.geometry.UVS[face.c]]);
  4558. }
  4559. } else {
  4560. mode = gl[mode];
  4561. var first = node.primitives[i].first;
  4562. var count = node.primitives[i].count;
  4563. if (count > 65535)
  4564. count = 32740;
  4565. //node.primitives[i] = new osg.DrawArrays(mode, first, count);
  4566. }
  4567. }
  4568. mesh.geometry.verticesNeedUpdate = true;
  4569. mesh.geometry.facesNeedUpdate = true;
  4570. }
  4571. var newmaterial = null;
  4572. if (node.stateset) {
  4573. newmaterial = new THREE.MeshPhongMaterial();
  4574. if (node.stateset.textures) {
  4575. var textures = node.stateset.textures;
  4576. for ( var t = 0, tl = textures.length; t < tl; t++) {
  4577. if (textures[t] === undefined) {
  4578. continue;
  4579. }
  4580. if (!textures[t].file) {
  4581. if (console !== undefined) {
  4582. console.log("no 'file' field for texture "
  4583. + textures[t]);
  4584. }
  4585. }
  4586. var tex;
  4587. if ( texture_load_callback ) {
  4588. tex = texture_load_callback( textures[t].file );
  4589. } else {
  4590. tex = loadTexture( newmaterial, textures[t].file );
  4591. }
  4592. if (tex) {
  4593. tex.wrapS = THREE.RepeatWrapping;
  4594. tex.wrapT = THREE.RepeatWrapping;
  4595. newmaterial.map = tex;
  4596. newmaterial.needsUpdate = true;
  4597. }
  4598. }
  4599. }
  4600. if (node.stateset.material) {
  4601. newmaterial.ambient = (toColor(node.stateset.material.ambient));
  4602. newmaterial.color = (toColor(node.stateset.material.diffuse));
  4603. newmaterial.shininess = (node.stateset.material.shininess);
  4604. newmaterial.specular = (toColor(node.stateset.material.specular));
  4605. newmaterial.needsUpdate = true;
  4606. }
  4607. }
  4608. if (node.matrix) {
  4609. if(newnode == null)
  4610. newnode = new THREE.Object3D();
  4611. var matrix = [];
  4612. for(var i =0; i < node.matrix.length; i++)
  4613. matrix.push(node.matrix[i]);
  4614. var glmat = new THREE.Matrix4();
  4615. glmat.elements = matrix;
  4616. var flipmat = new THREE.Matrix4(1, 0,0,0,
  4617. 0, 0,1,0,
  4618. 0,-1,0,0,
  4619. 0, 0,0,1);
  4620. glmat = glmat.multiplyMatrices(flipmat,glmat);
  4621. //glmat = glmat.transpose();
  4622. newnode.matrix.copy(glmat)
  4623. newnode.matrixAutoUpdate = false;
  4624. }
  4625. if (node.children) {
  4626. if(newnode == null)
  4627. newnode = new THREE.Object3D();
  4628. for ( var child = 0; child < node.children.length; child++) {
  4629. var childnode = ParseSceneGraph(node.children[child],texture_load_callback);
  4630. if(childnode)
  4631. newnode.add(childnode);
  4632. }
  4633. }
  4634. if(newnode && newmaterial)
  4635. ApplyMaterial(newnode,newmaterial);
  4636. if(node.name && newnode)
  4637. newnode.name = node.name;
  4638. if(newnode && newnode.children && newnode.children.length == 1 && isIdentityMatrix(newnode.matrix.elements))
  4639. return newnode.children[0];
  4640. return newnode;
  4641. }
  4642. var blobsfound = 0;
  4643. var blobarray = [];
  4644. function DecompressStrings(data, replace, find)
  4645. {
  4646. var reg = new RegExp(find,'g');
  4647. return data.replace(reg, replace);
  4648. }
  4649. function decompressJsonStrings(data)
  4650. {
  4651. data = DecompressStrings(data,"\"min\":","min:");
  4652. data = DecompressStrings(data,"\"max\":","max:");
  4653. data = DecompressStrings(data,"\"stateset\":","ss:");
  4654. data = DecompressStrings(data,"\"LINE_LOOP\"","\"LL\"");
  4655. data = DecompressStrings(data,"\"LINEAR\"","\"L\"");
  4656. data = DecompressStrings(data,"\"LINEAR_MIPMAP_LINEAR\"","\"LML\"");
  4657. data = DecompressStrings(data,"\"LINEAR_MIPMAP_NEAREST\"","\"LMN\"");
  4658. data = DecompressStrings(data,"\"NEAREST\"","\"NE\"");
  4659. data = DecompressStrings(data,"\"NEAREST_MIPMAP_LINEAR\"","\"NML\"");
  4660. data = DecompressStrings(data,"\"NEAREST_MIPMAP_NEAREST\"","\"NMN\"");
  4661. data = DecompressStrings(data,"\"mag_filter\":","maf:");
  4662. data = DecompressStrings(data,"\"min_filter\":","mif:");
  4663. data = DecompressStrings(data,"\"file\":","f:");
  4664. data = DecompressStrings(data,"\"name\":","n:");
  4665. data = DecompressStrings(data,"\"ambient\":","a:");
  4666. data = DecompressStrings(data,"\"diffuse\":","d:");
  4667. data = DecompressStrings(data,"\"specular\":","s:");
  4668. data = DecompressStrings(data,"\"emission\":","e:");
  4669. data = DecompressStrings(data,"\"shininess\":","sh:");
  4670. data = DecompressStrings(data,"\"textures\":","t:");
  4671. data = DecompressStrings(data,"\"material\":","m:");
  4672. data = DecompressStrings(data,"\"POINTS\"","\"P\"");
  4673. data = DecompressStrings(data,"\"LINES\"","\"LI\"");
  4674. data = DecompressStrings(data,"\"LINE_STRIP\"","\"LS\"");
  4675. data = DecompressStrings(data,"\"TRIANGLES\"","\"T\"");
  4676. data = DecompressStrings(data,"\"TRIANGLE_FAN\"","\"TF\"");
  4677. data = DecompressStrings(data,"\"TRIANGLE_STRIP\"","\"TS\"");
  4678. data = DecompressStrings(data,"\"first\":","fi:");
  4679. data = DecompressStrings(data,"\"count\":","co:");
  4680. data = DecompressStrings(data,"\"mode\":","mo:");
  4681. data = DecompressStrings(data,"\"undefined\":","u:");
  4682. data = DecompressStrings(data,"\"children\":","c:");
  4683. data = DecompressStrings(data,"\"range\":","r:");
  4684. data = DecompressStrings(data,"\"bits\":","b:");
  4685. data = DecompressStrings(data,"\"values\":","v:");
  4686. data = DecompressStrings(data,"\"elements\":","el:");
  4687. data = DecompressStrings(data,"\"itemSize\":","iS:");
  4688. data = DecompressStrings(data,"\"type\":","ty:");
  4689. data = DecompressStrings(data,"\"ARRAY_BUFFER\"","\"AB\"");
  4690. data = DecompressStrings(data,"\"ELEMENT_ARRAY_BUFFER\"","\"EAB\"");
  4691. data = DecompressStrings(data,"\"indices\":","i:");
  4692. data = DecompressStrings(data,"\"Vertex\":","V:");
  4693. data = DecompressStrings(data,"\"Normal\":","N:");
  4694. data = DecompressStrings(data,"\"TexCoord0\":","T0:");
  4695. data = DecompressStrings(data,"\"TexCoord1\":","T1:");
  4696. data = DecompressStrings(data,"\"TexCoord2\":","T2:");
  4697. data = DecompressStrings(data,"\"TexCoord3\":","T3:");
  4698. data = DecompressStrings(data,"\"TexCoord4\":","T4:");
  4699. data = DecompressStrings(data,"\"attributes\":","A:");
  4700. data = DecompressStrings(data,"\"primitives\":","p:");
  4701. data = DecompressStrings(data,"\"projection\":","pr:");
  4702. data = DecompressStrings(data,"\"matrix\":","M:");
  4703. return data;
  4704. }
  4705. function isUUIDinArray( value, arrayToCheck ) {
  4706. for ( var index = 0; index < arrayToCheck.length; index++ ) {
  4707. if ( value.uuid == arrayToCheck[ index ].uuid ) {
  4708. return true;
  4709. }
  4710. }
  4711. return false;
  4712. }
  4713. function threeMaterialsFromIDs( nodeIDs ) {
  4714. var result = [];
  4715. for ( var index = 0; index < nodeIDs.length; index++ ) {
  4716. var node = this.state.nodes[ nodeIDs[ index ] ];
  4717. if ( node && ( node.threeObject instanceof THREE.Material ) ) {
  4718. result.push( node.threeObject );
  4719. }
  4720. }
  4721. return result;
  4722. }
  4723. function createInheritedMaterial( parentID, threeObject, name ) {
  4724. var nodeName = "material";
  4725. if ( name ) {
  4726. nodeName = name;
  4727. }
  4728. else if ( threeObject.name.length > 0 ) {
  4729. nodeName = threeObject.name;
  4730. }
  4731. var newNode = {
  4732. "id": nodeName,
  4733. "uri": nodeName,
  4734. "extends": "http://vwf.example.com/material.vwf",
  4735. "properties": {
  4736. "private": null,
  4737. },
  4738. "methods": {
  4739. },
  4740. "scripts": []
  4741. };
  4742. vwf.createChild( parentID, nodeName, newNode);
  4743. }
  4744. function generateNodeMaterial( nodeID, node ) {
  4745. if ( false ) {
  4746. if ( node.threeObject instanceof THREE.Object3D ) {
  4747. var representedMaterialsVWF = vwf.find( nodeID, "./element(*,'http://vwf.example.com/material.vwf')" );
  4748. var representedMaterialsThreeJS = threeMaterialsFromIDs.call( this, representedMaterialsVWF );
  4749. var allChildrenMaterials = GetAllMaterials( node.threeObject );
  4750. var nameTallys = {};
  4751. for ( var index = 0; index < allChildrenMaterials.length; index ++ ) {
  4752. if ( nameTallys[ allChildrenMaterials[ index ].name ] ) {
  4753. nameTallys[ allChildrenMaterials[ index ].name ] = nameTallys[ allChildrenMaterials[ index ].name ] + 1;
  4754. }
  4755. else {
  4756. nameTallys[ allChildrenMaterials[ index ].name ] = 1;
  4757. }
  4758. if ( ! isUUIDinArray( allChildrenMaterials[ index ], representedMaterialsThreeJS ) ) {
  4759. var newName = "material_" + nameTallys[ allChildrenMaterials[ index ].name ] + "_" + allChildrenMaterials[ index ].name;
  4760. createInheritedMaterial.call( this, nodeID, allChildrenMaterials[ index ], newName );
  4761. }
  4762. }
  4763. }
  4764. }
  4765. }
  4766. function setUniformProperty( obj, prop, type, value ) {
  4767. //console.info( "setUniformProperty( obj, "+prop+", "+type+", "+value+" )" );
  4768. switch ( type ) {
  4769. case 'i':
  4770. obj[ prop ].value = Number( value );
  4771. break
  4772. case 'f':
  4773. obj[ prop ].value = parseFloat( value );
  4774. break;
  4775. case 'c':
  4776. obj[ prop ].value = new THREE.Color( value );
  4777. break;
  4778. case 'v2':
  4779. obj[ prop ].value = new THREE.Vector2( value[0], value[1] );
  4780. break;
  4781. case 'v3':
  4782. obj[ prop ].value = new THREE.Vector3( value[0], value[1], value[2] );
  4783. break;
  4784. case 'v4':
  4785. obj[ prop ].value = new THREE.Vector4( value[0], value[1], value[2], value[3] );
  4786. break;
  4787. case 't':
  4788. obj[ prop ].src = value;
  4789. obj[ prop ].value = loadTexture( undefined, value );
  4790. break;
  4791. }
  4792. }
  4793. function decompress(dataencoded)
  4794. {
  4795. blobsfound = 0;
  4796. blobarray = [];
  4797. var regex = new RegExp('\u7FFF\u7FFE\u7FFF\u7FFE\u7FFF[\\S\\s]*?\u7FFE\u7FFF\u7FFE\u7FFF\u7FFE','igm');
  4798. blobarray = dataencoded.match(regex);
  4799. var data = dataencoded.replace(regex,function(match) { return "\""+(blobsfound++)+"\"";});
  4800. data = decompressJsonStrings(data);
  4801. return data;
  4802. }
  4803. function loadTexture( mat, def ) {
  4804. var txt = undefined;
  4805. var url = undefined;
  4806. var mapping = undefined;
  4807. var onLoad = function( texture ) {
  4808. if ( mat ) {
  4809. mat.map = texture;
  4810. mat.needsUpdate = true;
  4811. }
  4812. };
  4813. function onError() {
  4814. self.logger.warnx( )
  4815. }
  4816. //console.log( [ "loadTexture: ", JSON.stringify( def ) ] );
  4817. if ( utility.isString( def ) ) {
  4818. url = def;
  4819. } else {
  4820. url = def.url;
  4821. mapping = def.mapping;
  4822. }
  4823. if ( mat === undefined ) {
  4824. if ( mapping === undefined ) {
  4825. txt = THREE.ImageUtils.loadTexture( url );
  4826. } else {
  4827. txt = THREE.ImageUtils.loadTexture( url, mapping );
  4828. }
  4829. } else {
  4830. txt = THREE.ImageUtils.loadTexture( url, mapping, onLoad, onError );
  4831. }
  4832. return txt;
  4833. }
  4834. function createMaterial( matDef ) {
  4835. var mat, text;
  4836. //console.log( [ "createMaterial: ", JSON.stringify( matDef ) ] );
  4837. if ( matDef.texture !== undefined ) {
  4838. text = loadTexture( undefined, matDef.texture );
  4839. if ( !utility.isString( matDef.texture ) ) {
  4840. for ( var prop in matDef.texture ) {
  4841. if ( prop !== 'url' && prop !== 'mapping' ) {
  4842. setTextureProperty( text, prop, matDef.texture[ prop ] );
  4843. }
  4844. }
  4845. }
  4846. }
  4847. if ( matDef.type !== undefined ) {
  4848. var matParameters = {};
  4849. for ( var prop in matDef ) {
  4850. switch ( prop ) {
  4851. case "type":
  4852. case "texture":
  4853. break;
  4854. default:
  4855. matParameters[ prop ] = matDef[ prop ];
  4856. break;
  4857. }
  4858. }
  4859. if ( text ) {
  4860. matParameters.map = text;
  4861. }
  4862. switch ( matDef.type ) {
  4863. case "MeshBasicMaterial":
  4864. mat = new THREE.MeshBasicMaterial( matParameters );
  4865. break;
  4866. case "MeshLambertMaterial":
  4867. mat = new THREE.MeshLambertMaterial( matParameters );
  4868. break;
  4869. case "MeshPhongMaterial":
  4870. mat = new THREE.MeshPhongMaterial( matParameters );
  4871. break;
  4872. case "MeshNormalMaterial":
  4873. mat = new THREE.MeshNormalMaterial( matParameters );
  4874. break;
  4875. case "MeshDepthMaterial":
  4876. mat = new THREE.MeshDepthMaterial( matParameters );
  4877. break;
  4878. case "ShaderMaterial":
  4879. mat = createShader( matParameters );
  4880. break;
  4881. case "SpriteMaterial":
  4882. mat = new THREE.SpriteMaterial( matParameters );
  4883. break;
  4884. case "LineBasicMaterial":
  4885. mat = new THREE.LineBasicMaterial( matParameters );
  4886. break;
  4887. case "LineDashedMaterial":
  4888. mat = new THREE.LineDashedMaterial( matParameters );
  4889. break;
  4890. case "MeshFaceMaterial":
  4891. mat = new THREE.MeshFaceMaterial( matParameters );
  4892. break;
  4893. case "PointCloudMaterial":
  4894. mat = new THREE.PointCloudMaterial( matParameters );
  4895. break;
  4896. case "RawShaderMaterial":
  4897. mat = new THREE.RawShaderMaterial( matParameters );
  4898. break;
  4899. }
  4900. //if ( mat ) {
  4901. // console.info( "Material created: " + matDef.type );
  4902. //}
  4903. } else {
  4904. mat = new THREE.MeshBasicMaterial( matDef );
  4905. }
  4906. return mat;
  4907. }
  4908. function setMaterialProperty( material, propertyName, propertyValue ) {
  4909. var value = propertyValue;
  4910. if ( material === undefined ) {
  4911. return undefined;
  4912. }
  4913. //console.log( [ "setMaterialProperty: ", propertyName, propertyValue ] );
  4914. switch ( propertyName ) {
  4915. case "texture":
  4916. if ( propertyValue !== "" && utility.validObject( propertyValue ) ) {
  4917. loadTexture( material, propertyValue );
  4918. } else {
  4919. material.map = null;
  4920. material.needsUpdate;
  4921. }
  4922. break;
  4923. case "color":
  4924. case "diffuse":
  4925. var vwfColor = new utility.color( propertyValue );
  4926. if ( vwfColor ) {
  4927. material.color.setRGB( vwfColor.red()/255, vwfColor.green()/255, vwfColor.blue()/255 );
  4928. }
  4929. if ( material.ambient !== undefined ) {
  4930. material.ambient.setRGB( material.color.r, material.color.g, material.color.b );
  4931. }
  4932. value = vwfColor.toString();
  4933. break;
  4934. case "specColor":
  4935. var vwfColor = new utility.color( propertyValue );
  4936. if ( vwfColor ) {
  4937. material.specular.setRGB( vwfColor.red() / 255, vwfColor.green() / 255, vwfColor.blue() / 255 );
  4938. value = vwfColor.toString();
  4939. }
  4940. break;
  4941. case "reflect":
  4942. value = Number( propertyValue );
  4943. material.reflectivity = value;
  4944. break;
  4945. case "shininess":
  4946. value = Number( propertyValue );
  4947. material.shininess = value;
  4948. break;
  4949. case "bumpScale":
  4950. value = Number( propertyValue );
  4951. material.bumpScale = value;
  4952. break;
  4953. case "alphaTest":
  4954. value = Number( propertyValue );
  4955. material.alphaTest = value;
  4956. break;
  4957. case "ambient":
  4958. var vwfColor = new utility.color( propertyValue );
  4959. if ( vwfColor ) {
  4960. material.ambient.setRGB( vwfColor.red( ) / 255, vwfColor.green( ) / 255, vwfColor.blue( ) / 255 );
  4961. value = vwfColor.toString();
  4962. }
  4963. break;
  4964. case "emit":
  4965. var vwfColor = new utility.color( propertyValue );
  4966. if ( vwfColor ) {
  4967. material.emissive.setRGB( vwfColor.red( ) / 255, vwfColor.green( ) / 255, vwfColor.blue( ) / 255 );
  4968. value = vwfColor.toString();
  4969. }
  4970. break;
  4971. case "transparent":
  4972. value = Boolean( propertyValue );
  4973. material.transparent = value;
  4974. break;
  4975. case "opacity":
  4976. value = Number( propertyValue );
  4977. material.opacity = value;
  4978. break;
  4979. case "side":
  4980. switch ( propertyValue ) {
  4981. case 2:
  4982. case "2":
  4983. case "double":
  4984. material.side = THREE.DoubleSide;
  4985. break;
  4986. case 0:
  4987. case "0":
  4988. case "front":
  4989. material.side = THREE.FrontSide;
  4990. break;
  4991. case 1:
  4992. case "1":
  4993. case "back":
  4994. material.side = THREE.BackSide;
  4995. break;
  4996. default:
  4997. value = undefined;
  4998. break;
  4999. }
  5000. break;
  5001. default:
  5002. value = undefined;
  5003. break;
  5004. }
  5005. if ( value !== undefined ) {
  5006. material.needsUpdate = true;
  5007. }
  5008. return value;
  5009. }
  5010. function setTextureProperty( texture, propertyName, propertyValue ) {
  5011. var value = propertyValue;
  5012. if ( texture === undefined ) {
  5013. return undefined;
  5014. }
  5015. //console.log( [ "setTextureProperty: ", propertyName, propertyValue ] );
  5016. switch ( propertyName ) {
  5017. case "wrapT":
  5018. switch ( propertyValue ) {
  5019. case 1001:
  5020. case "1001":
  5021. case "clamp":
  5022. texture.wrapT = THREE.ClampToEdgeWrapping;
  5023. break;
  5024. case 1000:
  5025. case "1000":
  5026. case "repeat":
  5027. texture.wrapT = THREE.RepeatWrapping;
  5028. break;
  5029. case 1002:
  5030. case "1002":
  5031. case "mirror":
  5032. texture.wrapT = THREE.MirroredRepeatWrapping;
  5033. break;
  5034. default:
  5035. value = undefined;
  5036. break;
  5037. }
  5038. break;
  5039. case "wrapS":
  5040. switch ( propertyValue ) {
  5041. case 1001:
  5042. case "1001":
  5043. case "clamp":
  5044. texture.wrapS = THREE.ClampToEdgeWrapping;
  5045. break;
  5046. case 1000:
  5047. case "1000":
  5048. case "repeat":
  5049. texture.wrapS = THREE.RepeatWrapping;
  5050. break;
  5051. case 1002:
  5052. case "1002":
  5053. case "mirror":
  5054. texture.wrapS = THREE.MirroredRepeatWrapping;
  5055. break;
  5056. default:
  5057. value = undefined;
  5058. break;
  5059. }
  5060. break;
  5061. case "repeat":
  5062. if ( propertyValue instanceof Array && propertyValue.length > 1 ) {
  5063. texture.repeat = new THREE.Vector2( propertyValue[0], propertyValue[1] );
  5064. } else {
  5065. value = undefined;
  5066. }
  5067. break;
  5068. case "offset":
  5069. if ( propertyValue instanceof Array && propertyValue.length > 1 ) {
  5070. texture.offset = new THREE.Vector2( propertyValue[0], propertyValue[1] );
  5071. } else {
  5072. value = undefined;
  5073. }
  5074. break
  5075. case "magFilter":
  5076. switch ( propertyValue ) {
  5077. case 1003:
  5078. case "1003":
  5079. case "nearest":
  5080. texture.magFilter = THREE.NearestFilter;
  5081. break;
  5082. case 1004:
  5083. case "1004":
  5084. case "nearestNearest":
  5085. texture.magFilter = THREE.NearestMipMapNearestFilter;
  5086. break;
  5087. case 1005:
  5088. case "1005":
  5089. case "nearestLinear":
  5090. texture.magFilter = THREE.NearestMipMapLinearFilter;
  5091. break;
  5092. case 1006:
  5093. case "1006":
  5094. case "linear":
  5095. texture.magFilter = THREE.LinearFilter;
  5096. break;
  5097. case 1007:
  5098. case "1007":
  5099. case "linearNearest":
  5100. texture.magFilter = THREE.LinearMipMapNearestFilter;
  5101. break;
  5102. case 1008:
  5103. case "1008":
  5104. case "linearLinear":
  5105. texture.magFilter = THREE.LinearMipMapLinearFilter;
  5106. break;
  5107. default:
  5108. value = undefined;
  5109. break;
  5110. }
  5111. break;
  5112. case "minFilter":
  5113. switch ( propertyValue ) {
  5114. case 1003:
  5115. case "1003":
  5116. case "nearest":
  5117. texture.minFilter = THREE.NearestFilter;
  5118. break;
  5119. case 1004:
  5120. case "1004":
  5121. case "nearestNearest":
  5122. texture.minFilter = THREE.NearestMipMapNearestFilter;
  5123. break;
  5124. case 1005:
  5125. case "1005":
  5126. case "nearestLinear":
  5127. texture.minFilter = THREE.NearestMipMapLinearFilter;
  5128. break;
  5129. case 1006:
  5130. case "1006":
  5131. case "linear":
  5132. texture.minFilter = THREE.LinearFilter;
  5133. break;
  5134. case 1007:
  5135. case "1007":
  5136. case "linearNearest":
  5137. texture.minFilter = THREE.LinearMipMapNearestFilter;
  5138. break;
  5139. case 1008:
  5140. case "1008":
  5141. case "linearLinear":
  5142. texture.minFilter = THREE.LinearMipMapLinearFilter;
  5143. break;
  5144. default:
  5145. value = undefined;
  5146. break;
  5147. }
  5148. break;
  5149. case "anisotropy":
  5150. texture.anisotropy = parseFloat( prop );
  5151. break;
  5152. default:
  5153. value = undefined;
  5154. break;
  5155. }
  5156. if ( value !== undefined ) {
  5157. texture.needsUpdate = true;
  5158. }
  5159. return value;
  5160. }
  5161. });