| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117 |
- // Filename: nodePath.cxx
- // Created by: drose (25Feb02)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
- //
- // All use of this software is subject to the terms of the Panda 3d
- // Software license. You should have received a copy of this license
- // along with this source code; you will also find a current copy of
- // the license at http://etc.cmu.edu/panda3d/docs/license/ .
- //
- // To contact the maintainers of this program write to
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "nodePath.h"
- #include "nodePathCollection.h"
- #include "findApproxPath.h"
- #include "findApproxLevelEntry.h"
- #include "config_pgraph.h"
- #include "colorAttrib.h"
- #include "colorScaleAttrib.h"
- #include "cullBinAttrib.h"
- #include "textureAttrib.h"
- #include "texMatrixAttrib.h"
- #include "texGenAttrib.h"
- #include "materialAttrib.h"
- #include "lightAttrib.h"
- #include "clipPlaneAttrib.h"
- #include "polylightEffect.h"
- #include "fogAttrib.h"
- #include "renderModeAttrib.h"
- #include "cullFaceAttrib.h"
- #include "alphaTestAttrib.h"
- #include "depthTestAttrib.h"
- #include "depthWriteAttrib.h"
- #include "shaderAttrib.h"
- #include "billboardEffect.h"
- #include "compassEffect.h"
- #include "showBoundsEffect.h"
- #include "transparencyAttrib.h"
- #include "antialiasAttrib.h"
- #include "texProjectorEffect.h"
- #include "texturePool.h"
- #include "planeNode.h"
- #include "lensNode.h"
- #include "materialPool.h"
- #include "look_at.h"
- #include "plist.h"
- #include "boundingSphere.h"
- #include "geomNode.h"
- #include "sceneGraphAnalyzer.h"
- #include "sceneGraphReducer.h"
- #include "textureCollection.h"
- #include "textureStageCollection.h"
- #include "globPattern.h"
- #include "shader.h"
- #include "shaderInput.h"
- #include "config_gobj.h"
- #include "bamFile.h"
- #include "preparedGraphicsObjects.h"
- #include "dcast.h"
- // stack seems to overflow on Intel C++ at 7000. If we need more than
- // 7000, need to increase stack size.
- int NodePath::_max_search_depth = 7000;
- TypeHandle NodePath::_type_handle;
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_num_nodes
- // Access: Published
- // Description: Returns the number of nodes in the path.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- get_num_nodes() const {
- if (is_empty()) {
- return 0;
- }
- return _head->get_length();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_node
- // Access: Published
- // Description: Returns the nth node of the path, where 0 is the
- // referenced (bottom) node and get_num_nodes() - 1 is
- // the top node. This requires iterating through the
- // path.
- //
- // Also see node(), which is a convenience function to
- // return the same thing as get_node(0) (since the
- // bottom node is the most important node in the
- // NodePath, and is the one most frequently referenced).
- ////////////////////////////////////////////////////////////////////
- PandaNode *NodePath::
- get_node(int index) const {
- nassertr(index >= 0 && index < get_num_nodes(), NULL);
- NodePathComponent *comp = _head;
- while (index > 0) {
- // If this assertion fails, the index was out of range; the
- // component's length must have been invalid.
- nassertr(comp != (NodePathComponent *)NULL, NULL);
- comp = comp->get_next();
- index--;
- }
- // If this assertion fails, the index was out of range; the
- // component's length must have been invalid.
- nassertr(comp != (NodePathComponent *)NULL, NULL);
- return comp->get_node();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_top
- // Access: Published
- // Description: Returns a singleton NodePath that represents the top
- // of the path, or empty NodePath if this path is empty.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_top() const {
- if (is_empty()) {
- return *this;
- }
- NodePathComponent *comp = _head;
- while (!comp->is_top_node()) {
- comp = comp->get_next();
- nassertr(comp != (NodePathComponent *)NULL, NULL);
- }
- NodePath top;
- top._head = comp;
- return top;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_children
- // Access: Published
- // Description: Returns the set of all child nodes of the referenced
- // node.
- ////////////////////////////////////////////////////////////////////
- NodePathCollection NodePath::
- get_children() const {
- NodePathCollection result;
- nassertr_always(!is_empty(), result);
- PandaNode *bottom_node = node();
- PandaNode::Children cr = bottom_node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- NodePath child;
- child._head = PandaNode::get_component(_head, cr.get_child(i));
- result.add_path(child);
- }
- return result;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_stashed_children
- // Access: Published
- // Description: Returns the set of all child nodes of the referenced
- // node that have been stashed. These children are not
- // normally visible on the node, and do not appear in
- // the list returned by get_children().
- ////////////////////////////////////////////////////////////////////
- NodePathCollection NodePath::
- get_stashed_children() const {
- NodePathCollection result;
- nassertr_always(!is_empty(), result);
- PandaNode *bottom_node = node();
- int num_stashed = bottom_node->get_num_stashed();
- for (int i = 0; i < num_stashed; i++) {
- NodePath stashed;
- stashed._head = PandaNode::get_component(_head, bottom_node->get_stashed(i));
- result.add_path(stashed);
- }
- return result;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_sort
- // Access: Published
- // Description: Returns the sort value of the referenced node within
- // its parent; that is, the sort number passed on the
- // last reparenting operation for this node. This will
- // control the position of the node within its parent's
- // list of children.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- get_sort() const {
- if (!has_parent()) {
- return 0;
- }
- PandaNode *parent = _head->get_next()->get_node();
- PandaNode *child = node();
- nassertr(parent != (PandaNode *)NULL && child != (PandaNode *)NULL, 0);
- int child_index = parent->find_child(child);
- if (child_index != -1) {
- return parent->get_child_sort(child_index);
- }
- child_index = parent->find_stashed(child);
- if (child_index != -1) {
- return parent->get_stashed_sort(child_index);
- }
- nassertr(false, 0);
- return 0;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find
- // Access: Published
- // Description: Searches for a node below the referenced node that
- // matches the indicated string. Returns the shortest
- // match found, if any, or an empty NodePath if no match
- // can be found.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- find(const string &path) const {
- nassertr_always(!is_empty(), fail());
- NodePathCollection col;
- find_matches(col, path, 1);
- if (col.is_empty()) {
- return NodePath::not_found();
- }
- return col.get_path(0);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_path_to
- // Access: Published
- // Description: Searches for the indicated node below this node and
- // returns the shortest NodePath that connects them.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- find_path_to(PandaNode *node) const {
- nassertr_always(!is_empty(), fail());
- nassertr(node != (PandaNode *)NULL, fail());
- NodePathCollection col;
- FindApproxPath approx_path;
- approx_path.add_match_many(0);
- approx_path.add_match_pointer(node, 0);
- find_matches(col, approx_path, 1);
- if (col.is_empty()) {
- return NodePath::not_found();
- }
- return col.get_path(0);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_matches
- // Access: Published
- // Description: Returns the complete set of all NodePaths that begin
- // with this NodePath and can be extended by
- // path. The shortest paths will be listed
- // first.
- ////////////////////////////////////////////////////////////////////
- NodePathCollection NodePath::
- find_all_matches(const string &path) const {
- NodePathCollection col;
- nassertr_always(!is_empty(), col);
- nassertr(verify_complete(), col);
- find_matches(col, path, -1);
- return col;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_paths_to
- // Access: Published
- // Description: Returns the set of all NodePaths that extend from
- // this NodePath down to the indicated node. The
- // shortest paths will be listed first.
- ////////////////////////////////////////////////////////////////////
- NodePathCollection NodePath::
- find_all_paths_to(PandaNode *node) const {
- NodePathCollection col;
- nassertr_always(!is_empty(), col);
- nassertr(verify_complete(), col);
- nassertr(node != (PandaNode *)NULL, col);
- FindApproxPath approx_path;
- approx_path.add_match_many(0);
- approx_path.add_match_pointer(node, 0);
- find_matches(col, approx_path, -1);
- return col;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::reparent_to
- // Access: Published
- // Description: Removes the referenced node of the NodePath from its
- // current parent and attaches it to the referenced node
- // of the indicated NodePath.
- //
- // If the destination NodePath is empty, this is the
- // same thing as detach_node().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- reparent_to(const NodePath &other, int sort) {
- nassertv(verify_complete());
- nassertv(other.verify_complete());
- nassertv_always(!is_empty());
- nassertv(other._error_type == ET_ok);
- // Reparenting implicitly resents the delta vector.
- node()->reset_prev_transform();
- bool reparented = PandaNode::reparent(other._head, _head, sort, false);
- nassertv(reparented);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::wrt_reparent_to
- // Access: Published
- // Description: This functions identically to reparent_to(), except
- // the transform on this node is also adjusted so that
- // the node remains in the same place in world
- // coordinates, even if it is reparented into a
- // different coordinate system.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- wrt_reparent_to(const NodePath &other, int sort) {
- nassertv(verify_complete());
- nassertv(other.verify_complete());
- nassertv_always(!is_empty());
- nassertv(other._error_type == ET_ok);
- if (get_transform() == get_prev_transform()) {
- set_transform(get_transform(other));
- node()->reset_prev_transform();
- } else {
- set_transform(get_transform(other));
- set_prev_transform(get_prev_transform(other));
- }
- reparent_to(other, sort);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::instance_to
- // Access: Published
- // Description: Adds the referenced node of the NodePath as a child
- // of the referenced node of the indicated other
- // NodePath. Any other parent-child relations of the
- // node are unchanged; in particular, the node is not
- // removed from its existing parent, if any.
- //
- // If the node already had an existing parent, this
- // method will create a new instance of the node within
- // the scene graph.
- //
- // This does not change the NodePath itself, but does
- // return a new NodePath that reflects the new instance
- // node.
- //
- // If the destination NodePath is empty, this creates a
- // new instance which is not yet parented to any node.
- // A new instance of this sort cannot easily be
- // differentiated from other similar instances, but it
- // is nevertheless a different instance and it will
- // return a different get_id() value.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- instance_to(const NodePath &other, int sort) const {
- nassertr(verify_complete(), NodePath::fail());
- nassertr(other.verify_complete(), NodePath::fail());
- nassertr_always(!is_empty(), NodePath::fail());
- nassertr(other._error_type == ET_ok, NodePath::fail());
- NodePath new_instance;
- // First, we'll attach to NULL, to guarantee we get a brand new
- // instance.
- new_instance._head = PandaNode::attach(NULL, node(), sort);
- // Now, we'll reparent the new instance to the target node.
- bool reparented = PandaNode::reparent(other._head, new_instance._head,
- sort, false);
- nassertr(reparented, new_instance);
- // instance_to() doesn't reset the velocity delta, unlike most of
- // the other reparenting operations. The reasoning is that
- // instance_to() is not necessarily a reparenting operation, since
- // it doesn't change the original instance.
- return new_instance;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::instance_under_node
- // Access: Published
- // Description: Behaves like instance_to(), but implicitly creates a
- // new node to instance the geometry under, and returns a
- // NodePath to that new node. This allows the
- // programmer to set a unique state and/or transform on
- // this instance.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- instance_under_node(const NodePath &other, const string &name, int sort) const {
- NodePath new_node = other.attach_new_node(name, sort);
- NodePath instance = instance_to(new_node);
- if (instance.is_empty()) {
- new_node.remove_node();
- return instance;
- }
- return new_node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::copy_to
- // Access: Published
- // Description: Functions like instance_to(), except a deep
- // copy is made of the referenced node and all of its
- // descendents, which is then parented to the indicated
- // node. A NodePath to the newly created copy is
- // returned.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- copy_to(const NodePath &other, int sort) const {
- nassertr(verify_complete(), fail());
- nassertr(other.verify_complete(), fail());
- nassertr_always(!is_empty(), fail());
- nassertr(other._error_type == ET_ok, fail());
- PandaNode *source_node = node();
- PT(PandaNode) copy_node = source_node->copy_subgraph();
- nassertr(copy_node != (PandaNode *)NULL, fail());
- copy_node->reset_prev_transform();
- return other.attach_new_node(copy_node, sort);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::attach_new_node
- // Access: Published
- // Description: Attaches a new node, with or without existing
- // parents, to the scene graph below the referenced node
- // of this NodePath. This is the preferred way to add
- // nodes to the graph.
- //
- // If the node was already a child of the parent, this
- // returns a NodePath to the existing child.
- //
- // This does *not* automatically extend the current
- // NodePath to reflect the attachment; however, a
- // NodePath that does reflect this extension is
- // returned.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- attach_new_node(PandaNode *node, int sort) const {
- nassertr(verify_complete(), NodePath::fail());
- nassertr(_error_type == ET_ok, NodePath::fail());
- nassertr(node != (PandaNode *)NULL, NodePath::fail());
- NodePath new_path(*this);
- new_path._head = PandaNode::attach(_head, node, sort);
- return new_path;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::remove_node
- // Access: Published
- // Description: Disconnects the referenced node from the scene graph.
- // This will also delete the node if there are no other
- // pointers to it.
- //
- // Normally, this should be called only when you are
- // really done with the node. If you want to remove a
- // node from the scene graph but keep it around for
- // later, you should probably use detach_node() instead.
- //
- // In practice, the only difference between
- // remove_node() and detach_node() is that remove_node()
- // also resets the NodePath to empty, which will cause
- // the node to be deleted immediately if there are no
- // other references. On the other hand, detach_node()
- // leaves the NodePath referencing the node, which will
- // keep at least one reference to the node for as long
- // as the NodePath exists.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- remove_node() {
- nassertv(_error_type != ET_not_found);
- // If we have no parents, remove_node() is just a do-nothing
- // operation; if we have no nodes, maybe we were already removed.
- // In either case, quietly do nothing except to ensure the
- // NodePath is clear.
- if (!is_empty() && !is_singleton()) {
- node()->reset_prev_transform();
- PandaNode::detach(_head);
- }
- if (is_empty() || _head->has_key()) {
- // Preserve the key we had on the node before we removed it.
- int key = get_key();
- (*this) = NodePath::removed();
- _backup_key = key;
- } else {
- // We didn't have a key; just clear the NodePath.
- (*this) = NodePath::removed();
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::detach_node
- // Access: Published
- // Description: Disconnects the referenced node from its parent, but
- // does not immediately delete it. The NodePath retains
- // a pointer to the node, and becomes a singleton
- // NodePath.
- //
- // This should be called to detach a node from the scene
- // graph, with the option of reattaching it later to the
- // same parent or to a different parent.
- //
- // In practice, the only difference between
- // remove_node() and detach_node() is that remove_node()
- // also resets the NodePath to empty, which will cause
- // the node to be deleted immediately if there are no
- // other references. On the other hand, detach_node()
- // leaves the NodePath referencing the node, which will
- // keep at least one reference to the node for as long
- // as the NodePath exists.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- detach_node() {
- nassertv(_error_type != ET_not_found);
- if (!is_empty() && !is_singleton()) {
- node()->reset_prev_transform();
- PandaNode::detach(_head);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::output
- // Access: Published
- // Description: Writes a sensible description of the NodePath to the
- // indicated output stream.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- output(ostream &out) const {
- switch (_error_type) {
- case ET_not_found:
- out << "**not found**";
- return;
- case ET_removed:
- out << "**removed**";
- return;
- case ET_fail:
- out << "**error**";
- return;
- default:
- break;
- }
- if (_head == (NodePathComponent *)NULL) {
- out << "(empty)";
- } else {
- _head->output(out);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_state
- // Access: Published
- // Description: Returns the state changes that must be made to
- // transition to the render state of this node from the
- // render state of the other node.
- ////////////////////////////////////////////////////////////////////
- CPT(RenderState) NodePath::
- get_state(const NodePath &other) const {
- nassertr(_error_type == ET_ok && other._error_type == ET_ok, RenderState::make_empty());
- if (other.is_empty()) {
- return get_net_state();
- }
- if (is_empty()) {
- return other.get_net_state()->invert_compose(RenderState::make_empty());
- }
-
- nassertr(verify_complete(), RenderState::make_empty());
- nassertr(other.verify_complete(), RenderState::make_empty());
- int a_count, b_count;
- if (find_common_ancestor(*this, other, a_count, b_count) == (NodePathComponent *)NULL) {
- if (allow_unrelated_wrt) {
- pgraph_cat.debug()
- << *this << " is not related to " << other << "\n";
- } else {
- pgraph_cat.error()
- << *this << " is not related to " << other << "\n";
- nassertr(false, RenderState::make_empty());
- }
- }
- CPT(RenderState) a_state = r_get_partial_state(_head, a_count);
- CPT(RenderState) b_state = r_get_partial_state(other._head, b_count);
- return b_state->invert_compose(a_state);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_state
- // Access: Published
- // Description: Sets the state object on this node, relative to
- // the other node. This computes a new state object
- // that will have the indicated value when seen from the
- // other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_state(const NodePath &other, const RenderState *state) {
- nassertv(_error_type == ET_ok && other._error_type == ET_ok);
- nassertv_always(!is_empty());
- // First, we perform a wrt to the parent, to get the conversion.
- CPT(RenderState) rel_state;
- if (has_parent()) {
- rel_state = other.get_state(get_parent());
- } else {
- rel_state = other.get_state(NodePath());
- }
- CPT(RenderState) new_state = rel_state->compose(state);
- set_state(new_state);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_transform
- // Access: Published
- // Description: Returns the relative transform to this node from the
- // other node; i.e. the transformation of this node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- get_transform(const NodePath &other) const {
- nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
- if (other.is_empty()) {
- return get_net_transform();
- }
- if (is_empty()) {
- return other.get_net_transform()->invert_compose(TransformState::make_identity());
- }
-
- nassertr(verify_complete(), TransformState::make_identity());
- nassertr(other.verify_complete(), TransformState::make_identity());
- int a_count, b_count;
- if (find_common_ancestor(*this, other, a_count, b_count) == (NodePathComponent *)NULL) {
- if (allow_unrelated_wrt) {
- if (pgraph_cat.is_debug()) {
- pgraph_cat.debug()
- << *this << " is not related to " << other << "\n";
- }
- } else {
- pgraph_cat.error()
- << *this << " is not related to " << other << "\n";
- nassertr(false, TransformState::make_identity());
- }
- }
- CPT(TransformState) a_transform, b_transform;
- a_transform = r_get_partial_transform(_head, a_count);
- if (a_transform != (TransformState *)NULL) {
- b_transform = r_get_partial_transform(other._head, b_count);
- }
- if (b_transform == (TransformState *)NULL) {
- // If either path involved a node with a net_transform
- // RenderEffect applied, we have to go all the way up to the root
- // to get the right answer.
- a_transform = r_get_net_transform(_head);
- b_transform = r_get_net_transform(other._head);
- }
- return b_transform->invert_compose(a_transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_transform
- // Access: Published
- // Description: Sets the transform object on this node, relative to
- // the other node. This computes a new transform object
- // that will have the indicated value when seen from the
- // other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_transform(const NodePath &other, const TransformState *transform) {
- nassertv(_error_type == ET_ok && other._error_type == ET_ok);
- nassertv_always(!is_empty());
- // First, we perform a wrt to the parent, to get the conversion.
- CPT(TransformState) rel_trans;
- if (has_parent()) {
- rel_trans = other.get_transform(get_parent());
- } else {
- rel_trans = other.get_transform(NodePath());
- }
- CPT(TransformState) new_trans = rel_trans->compose(transform);
- set_transform(new_trans);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_prev_transform
- // Access: Published
- // Description: Returns the relative "previous" transform to this
- // node from the other node; i.e. the position of this
- // node in the previous frame, as seen by the other node
- // in the previous frame.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- get_prev_transform(const NodePath &other) const {
- nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
- if (other.is_empty()) {
- return get_net_prev_transform();
- }
- if (is_empty()) {
- return other.get_net_prev_transform()->invert_compose(TransformState::make_identity());
- }
-
- nassertr(verify_complete(), TransformState::make_identity());
- nassertr(other.verify_complete(), TransformState::make_identity());
- int a_count, b_count;
- if (find_common_ancestor(*this, other, a_count, b_count) == (NodePathComponent *)NULL) {
- if (allow_unrelated_wrt) {
- pgraph_cat.debug()
- << *this << " is not related to " << other << "\n";
- } else {
- pgraph_cat.error()
- << *this << " is not related to " << other << "\n";
- nassertr(false, TransformState::make_identity());
- }
- }
- CPT(TransformState) a_prev_transform = r_get_partial_prev_transform(_head, a_count);
- CPT(TransformState) b_prev_transform = r_get_partial_prev_transform(other._head, b_count);
- return b_prev_transform->invert_compose(a_prev_transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_prev_transform
- // Access: Published
- // Description: Sets the "previous" transform object on this node,
- // relative to the other node. This computes a new
- // transform object that will have the indicated value
- // when seen from the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_prev_transform(const NodePath &other, const TransformState *transform) {
- nassertv(_error_type == ET_ok && other._error_type == ET_ok);
- nassertv_always(!is_empty());
- // First, we perform a wrt to the parent, to get the conversion.
- CPT(TransformState) rel_trans;
- if (has_parent()) {
- rel_trans = other.get_prev_transform(get_parent());
- } else {
- rel_trans = other.get_prev_transform(NodePath());
- }
- CPT(TransformState) new_trans = rel_trans->compose(transform);
- set_prev_transform(new_trans);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos
- // Access: Published
- // Description: Sets the translation component of the transform,
- // leaving rotation and scale untouched. This also
- // resets the node's "previous" position, so that the
- // collision system will see the node as having suddenly
- // appeared in the new position, without passing any
- // points in between.
- // See Also: NodePath::set_fluid_pos
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos(const LVecBase3f &pos) {
- nassertv_always(!is_empty());
- set_transform(get_transform()->set_pos(pos));
- node()->reset_prev_transform();
- }
- void NodePath::
- set_x(float x) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[0] = x;
- set_pos(pos);
- }
- void NodePath::
- set_y(float y) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[1] = y;
- set_pos(pos);
- }
- void NodePath::
- set_z(float z) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[2] = z;
- set_pos(pos);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_fluid_pos
- // Access: Published
- // Description: Sets the translation component, without changing the
- // "previous" position, so that the collision system
- // will see the node as moving fluidly from its previous
- // position to its new position.
- // See Also: NodePath::set_pos
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_fluid_pos(const LVecBase3f &pos) {
- nassertv_always(!is_empty());
- set_transform(get_transform()->set_pos(pos));
- }
- void NodePath::
- set_fluid_x(float x) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[0] = x;
- set_fluid_pos(pos);
- }
- void NodePath::
- set_fluid_y(float y) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[1] = y;
- set_fluid_pos(pos);
- }
- void NodePath::
- set_fluid_z(float z) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- pos[2] = z;
- set_fluid_pos(pos);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_pos
- // Access: Published
- // Description: Retrieves the translation component of the transform.
- ////////////////////////////////////////////////////////////////////
- LPoint3f NodePath::
- get_pos() const {
- nassertr_always(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
- return get_transform()->get_pos();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_pos_delta
- // Access: Published
- // Description: Returns the delta vector from this node's position in
- // the previous frame (according to
- // set_prev_transform(), typically set via the use of
- // set_fluid_pos()) and its position in the current
- // frame. This is the vector used to determine
- // collisions. Generally, if the node was last
- // repositioned via set_pos(), the delta will be zero;
- // if it was adjusted via set_fluid_pos(), the delta
- // will represent the change from the previous frame's
- // position.
- ////////////////////////////////////////////////////////////////////
- LVector3f NodePath::
- get_pos_delta() const {
- nassertr_always(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
- return get_transform()->get_pos() - get_prev_transform()->get_pos();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_hpr
- // Access: Published
- // Description: Sets the rotation component of the transform,
- // leaving translation and scale untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_hpr(const LVecBase3f &hpr) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- nassertv(transform->has_hpr());
- set_transform(transform->set_hpr(hpr));
- }
- void NodePath::
- set_h(float h) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- nassertv(transform->has_hpr());
- LVecBase3f hpr = transform->get_hpr();
- hpr[0] = h;
- set_transform(transform->set_hpr(hpr));
- }
- void NodePath::
- set_p(float p) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- nassertv(transform->has_hpr());
- LVecBase3f hpr = transform->get_hpr();
- hpr[1] = p;
- set_transform(transform->set_hpr(hpr));
- }
- void NodePath::
- set_r(float r) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- nassertv(transform->has_hpr());
- LVecBase3f hpr = transform->get_hpr();
- hpr[2] = r;
- set_transform(transform->set_hpr(hpr));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_hpr
- // Access: Published
- // Description: Retrieves the rotation component of the transform.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_hpr() const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform();
- nassertr(transform->has_hpr(), LVecBase3f(0.0f, 0.0f, 0.0f));
- return transform->get_hpr();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_quat
- // Access: Published
- // Description: Sets the rotation component of the transform,
- // leaving translation and scale untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_quat(const LQuaternionf &quat) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- set_transform(transform->set_quat(quat));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_quat
- // Access: Published
- // Description: Retrieves the rotation component of the transform.
- ////////////////////////////////////////////////////////////////////
- LQuaternionf NodePath::
- get_quat() const {
- nassertr_always(!is_empty(), LQuaternionf::ident_quat());
- CPT(TransformState) transform = get_transform();
- return transform->get_quat();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_scale
- // Access: Published
- // Description: Sets the scale component of the transform,
- // leaving translation and rotation untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_scale(const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- set_transform(transform->set_scale(scale));
- }
- void NodePath::
- set_sx(float sx) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f scale = transform->get_scale();
- scale[0] = sx;
- set_transform(transform->set_scale(scale));
- }
- void NodePath::
- set_sy(float sy) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f scale = transform->get_scale();
- scale[1] = sy;
- set_transform(transform->set_scale(scale));
- }
- void NodePath::
- set_sz(float sz) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f scale = transform->get_scale();
- scale[2] = sz;
- set_transform(transform->set_scale(scale));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_scale
- // Access: Published
- // Description: Retrieves the scale component of the transform.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_scale() const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform();
- return transform->get_scale();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shear
- // Access: Published
- // Description: Sets the shear component of the transform,
- // leaving translation and rotation untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shear(const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- set_transform(transform->set_shear(shear));
- }
- void NodePath::
- set_shxy(float shxy) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f shear = transform->get_shear();
- shear[0] = shxy;
- set_transform(transform->set_shear(shear));
- }
- void NodePath::
- set_shxz(float shxz) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f shear = transform->get_shear();
- shear[1] = shxz;
- set_transform(transform->set_shear(shear));
- }
- void NodePath::
- set_shyz(float shyz) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- LVecBase3f shear = transform->get_shear();
- shear[2] = shyz;
- set_transform(transform->set_shear(shear));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_shear
- // Access: Published
- // Description: Retrieves the shear component of the transform.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_shear() const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform();
- return transform->get_shear();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr
- // Access: Published
- // Description: Sets the translation and rotation component of the
- // transform, leaving scale untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr(const LVecBase3f &pos, const LVecBase3f &hpr) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- transform = TransformState::make_pos_hpr_scale_shear
- (pos, hpr, transform->get_scale(), transform->get_shear());
- set_transform(transform);
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat
- // Access: Published
- // Description: Sets the translation and rotation component of the
- // transform, leaving scale untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat(const LVecBase3f &pos, const LQuaternionf &quat) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- transform = TransformState::make_pos_quat_scale_shear
- (pos, quat, transform->get_scale(), transform->get_shear());
- set_transform(transform);
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_hpr_scale
- // Access: Published
- // Description: Sets the rotation and scale components of the
- // transform, leaving translation untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_hpr_scale(const LVecBase3f &hpr, const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- transform = TransformState::make_pos_hpr_scale_shear
- (transform->get_pos(), hpr, scale, transform->get_shear());
- set_transform(transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_quat_scale
- // Access: Published
- // Description: Sets the rotation and scale components of the
- // transform, leaving translation untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_quat_scale(const LQuaternionf &quat, const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform();
- transform = TransformState::make_pos_quat_scale_shear
- (transform->get_pos(), quat, scale, transform->get_shear());
- set_transform(transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr_scale
- // Access: Published
- // Description: Replaces the translation, rotation, and scale
- // components, implicitly setting shear to 0.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr_scale(const LVecBase3f &pos, const LVecBase3f &hpr,
- const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- set_transform(TransformState::make_pos_hpr_scale
- (pos, hpr, scale));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat_scale
- // Access: Published
- // Description: Replaces the translation, rotation, and scale
- // components, implicitly setting shear to 0.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat_scale(const LVecBase3f &pos, const LQuaternionf &quat,
- const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- set_transform(TransformState::make_pos_quat_scale
- (pos, quat, scale));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr_scale_shear
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, scale, and shear components.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr_scale_shear(const LVecBase3f &pos, const LVecBase3f &hpr,
- const LVecBase3f &scale, const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- set_transform(TransformState::make_pos_hpr_scale_shear
- (pos, hpr, scale, shear));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat_scale_shear
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, scale, and shear components.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat_scale_shear(const LVecBase3f &pos, const LQuaternionf &quat,
- const LVecBase3f &scale, const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- set_transform(TransformState::make_pos_quat_scale_shear
- (pos, quat, scale, shear));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_mat
- // Access: Published
- // Description: Directly sets an arbitrary 4x4 transform matrix.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_mat(const LMatrix4f &mat) {
- nassertv_always(!is_empty());
- set_transform(TransformState::make_mat(mat));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::look_at
- // Access: Published
- // Description: Sets the hpr on this NodePath so that it
- // rotates to face the indicated point in space.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- look_at(const LPoint3f &point, const LVector3f &up) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- LQuaternionf quat;
- ::look_at(quat, point - pos, up);
- set_quat(quat);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::heads_up
- // Access: Published
- // Description: Behaves like look_at(), but with a strong preference
- // to keeping the up vector oriented in the indicated
- // "up" direction.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- heads_up(const LPoint3f &point, const LVector3f &up) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos();
- LQuaternionf quat;
- ::heads_up(quat, point - pos, up);
- set_quat(quat);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos
- // Access: Published
- // Description: Sets the translation component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos(const NodePath &other, const LVecBase3f &pos) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_hpr = orig_transform->get_hpr();
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, rel_transform->set_pos(pos));
- set_pos_hpr_scale_shear(get_transform()->get_pos(), orig_hpr, orig_scale, orig_shear);
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_pos(pos));
- }
- node()->reset_prev_transform();
- }
- void NodePath::
- set_x(const NodePath &other, float x) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[0] = x;
- set_pos(other, pos);
- }
- void NodePath::
- set_y(const NodePath &other, float y) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[1] = y;
- set_pos(other, pos);
- }
- void NodePath::
- set_z(const NodePath &other, float z) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[2] = z;
- set_pos(other, pos);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_fluid_pos
- // Access: Published
- // Description: Sets the translation component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_fluid_pos(const NodePath &other, const LVecBase3f &pos) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_hpr = orig_transform->get_hpr();
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- // Use the relative set_transform() to compute the relative pos, and
- // then reset all of the other components back to the way they were.
- set_transform(other, rel_transform->set_pos(pos));
- set_transform(TransformState::make_pos_hpr_scale_shear
- (get_transform()->get_pos(), orig_hpr, orig_scale, orig_shear));
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_pos(pos));
- }
- }
- void NodePath::
- set_fluid_x(const NodePath &other, float x) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[0] = x;
- set_fluid_pos(other, pos);
- }
- void NodePath::
- set_fluid_y(const NodePath &other, float y) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[1] = y;
- set_fluid_pos(other, pos);
- }
- void NodePath::
- set_fluid_z(const NodePath &other, float z) {
- nassertv_always(!is_empty());
- LPoint3f pos = get_pos(other);
- pos[2] = z;
- set_fluid_pos(other, pos);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_pos
- // Access: Published
- // Description: Returns the relative position of the referenced node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- LPoint3f NodePath::
- get_pos(const NodePath &other) const {
- nassertr_always(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
- return get_transform(other)->get_pos();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_pos_delta
- // Access: Published
- // Description: Returns the delta vector from this node's position in
- // the previous frame (according to
- // set_prev_transform(), typically set via the use of
- // set_fluid_pos()) and its position in the current
- // frame, as seen in the indicated node's coordinate
- // space. This is the vector used to determine
- // collisions. Generally, if the node was last
- // repositioned via set_pos(), the delta will be zero;
- // if it was adjusted via set_fluid_pos(), the delta
- // will represent the change from the previous frame's
- // position.
- ////////////////////////////////////////////////////////////////////
- LVector3f NodePath::
- get_pos_delta(const NodePath &other) const {
- nassertr_always(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
- return get_transform(other)->get_pos() - get_prev_transform(other)->get_pos();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_hpr
- // Access: Published
- // Description: Sets the rotation component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_hpr(const NodePath &other, const LVecBase3f &hpr) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- nassertv(rel_transform->has_hpr());
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_pos = orig_transform->get_pos();
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, rel_transform->set_hpr(hpr));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_transform(TransformState::make_pos_hpr_scale_shear
- (orig_pos, new_transform->get_hpr(), orig_scale, orig_shear));
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_hpr(hpr));
- }
- }
- void NodePath::
- set_h(const NodePath &other, float h) {
- nassertv_always(!is_empty());
- LVecBase3f hpr = get_hpr(other);
- hpr[0] = h;
- set_hpr(other, hpr);
- }
- void NodePath::
- set_p(const NodePath &other, float p) {
- nassertv_always(!is_empty());
- LVecBase3f hpr = get_hpr(other);
- hpr[1] = p;
- set_hpr(other, hpr);
- }
- void NodePath::
- set_r(const NodePath &other, float r) {
- nassertv_always(!is_empty());
- LVecBase3f hpr = get_hpr(other);
- hpr[2] = r;
- set_hpr(other, hpr);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_hpr
- // Access: Published
- // Description: Returns the relative orientation of the bottom node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_hpr(const NodePath &other) const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform(other);
- nassertr(transform->has_hpr(), LVecBase3f(0.0f, 0.0f, 0.0f));
- return transform->get_hpr();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_quat
- // Access: Published
- // Description: Sets the rotation component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_quat(const NodePath &other, const LQuaternionf &quat) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_pos = orig_transform->get_pos();
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, rel_transform->set_quat(quat));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_transform(TransformState::make_pos_quat_scale_shear
- (orig_pos, new_transform->get_quat(), orig_scale, orig_shear));
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_quat(quat));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_quat
- // Access: Published
- // Description: Returns the relative orientation of the bottom node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- LQuaternionf NodePath::
- get_quat(const NodePath &other) const {
- nassertr_always(!is_empty(), LQuaternionf::ident_quat());
- CPT(TransformState) transform = get_transform(other);
- return transform->get_quat();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_scale
- // Access: Published
- // Description: Sets the scale component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_scale(const NodePath &other, const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_pos = orig_transform->get_pos();
- const LVecBase3f &orig_hpr = orig_transform->get_hpr();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, rel_transform->set_scale(scale));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_transform(TransformState::make_pos_hpr_scale_shear
- (orig_pos, orig_hpr, new_transform->get_scale(), orig_shear));
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_scale(scale));
- }
- }
- void NodePath::
- set_sx(const NodePath &other, float sx) {
- nassertv_always(!is_empty());
- LVecBase3f scale = get_scale(other);
- scale[0] = sx;
- set_scale(other, scale);
- }
- void NodePath::
- set_sy(const NodePath &other, float sy) {
- nassertv_always(!is_empty());
- LVecBase3f scale = get_scale(other);
- scale[1] = sy;
- set_scale(other, scale);
- }
- void NodePath::
- set_sz(const NodePath &other, float sz) {
- nassertv_always(!is_empty());
- LVecBase3f scale = get_scale(other);
- scale[2] = sz;
- set_scale(other, scale);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_scale
- // Access: Published
- // Description: Returns the relative scale of the bottom node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_scale(const NodePath &other) const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform(other);
- return transform->get_scale();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shear
- // Access: Published
- // Description: Sets the shear component of the transform,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shear(const NodePath &other, const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other three components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_pos = orig_transform->get_pos();
- const LVecBase3f &orig_hpr = orig_transform->get_hpr();
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- set_transform(other, rel_transform->set_shear(shear));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_transform(TransformState::make_pos_hpr_scale_shear
- (orig_pos, orig_hpr, orig_scale, new_transform->get_shear()));
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, rel_transform->set_shear(shear));
- }
- }
- void NodePath::
- set_shxy(const NodePath &other, float shxy) {
- nassertv_always(!is_empty());
- LVecBase3f shear = get_shear(other);
- shear[0] = shxy;
- set_shear(other, shear);
- }
- void NodePath::
- set_shxz(const NodePath &other, float shxz) {
- nassertv_always(!is_empty());
- LVecBase3f shear = get_shear(other);
- shear[1] = shxz;
- set_shear(other, shear);
- }
- void NodePath::
- set_shyz(const NodePath &other, float shyz) {
- nassertv_always(!is_empty());
- LVecBase3f shear = get_shear(other);
- shear[2] = shyz;
- set_shear(other, shear);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_shear
- // Access: Published
- // Description: Returns the relative shear of the bottom node
- // as seen from the other node.
- ////////////////////////////////////////////////////////////////////
- LVecBase3f NodePath::
- get_shear(const NodePath &other) const {
- nassertr_always(!is_empty(), LVecBase3f(0.0f, 0.0f, 0.0f));
- CPT(TransformState) transform = get_transform(other);
- return transform->get_shear();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr
- // Access: Published
- // Description: Sets the translation and rotation component of the
- // transform, relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr(const NodePath &other, const LVecBase3f &pos,
- const LVecBase3f &hpr) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other two components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, TransformState::make_pos_hpr_scale_shear
- (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_pos_hpr_scale_shear(new_transform->get_pos(), new_transform->get_hpr(),
- orig_scale, orig_shear);
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, TransformState::make_pos_hpr_scale_shear
- (pos, hpr, rel_transform->get_scale(), rel_transform->get_shear()));
- node()->reset_prev_transform();
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat
- // Access: Published
- // Description: Sets the translation and rotation component of the
- // transform, relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat(const NodePath &other, const LVecBase3f &pos,
- const LQuaternionf &quat) {
- nassertv_always(!is_empty());
- CPT(TransformState) rel_transform = get_transform(other);
-
- CPT(TransformState) orig_transform = get_transform();
- if (orig_transform->has_components()) {
- // If we had a componentwise transform before we started, we
- // should be careful to preserve the other two components. We
- // wouldn't need to do this, except for the possibility of
- // numerical error or decompose ambiguity.
- const LVecBase3f &orig_scale = orig_transform->get_scale();
- const LVecBase3f &orig_shear = orig_transform->get_shear();
- set_transform(other, TransformState::make_pos_quat_scale_shear
- (pos, quat, rel_transform->get_scale(), rel_transform->get_shear()));
- const TransformState *new_transform = get_transform();
- if (new_transform->has_components()) {
- set_pos_quat_scale_shear(new_transform->get_pos(), new_transform->get_quat(),
- orig_scale, orig_shear);
- }
- } else {
- // If we didn't have a componentwise transform already, never
- // mind.
- set_transform(other, TransformState::make_pos_quat_scale_shear
- (pos, quat, rel_transform->get_scale(), rel_transform->get_shear()));
- node()->reset_prev_transform();
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_hpr_scale
- // Access: Published
- // Description: Sets the rotation and scale components of the
- // transform, leaving translation untouched. This, or
- // set_pos_hpr_scale, is the preferred way to update a
- // transform when both hpr and scale are to be changed.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_hpr_scale(const NodePath &other, const LVecBase3f &hpr, const LVecBase3f &scale) {
- // We don't bother trying very hard to preserve pos across this
- // operation, unlike the work we do above to preserve hpr or scale,
- // since it generally doesn't matter that much if pos is off by a
- // few thousandths.
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform(other);
- transform = TransformState::make_pos_hpr_scale_shear
- (transform->get_pos(), hpr, scale, transform->get_shear());
- set_transform(other, transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_quat_scale
- // Access: Published
- // Description: Sets the rotation and scale components of the
- // transform, leaving translation untouched. This, or
- // set_pos_quat_scale, is the preferred way to update a
- // transform when both quat and scale are to be changed.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_quat_scale(const NodePath &other, const LQuaternionf &quat,
- const LVecBase3f &scale) {
- // We don't bother trying very hard to preserve pos across this
- // operation, unlike the work we do above to preserve quat or scale,
- // since it generally doesn't matter that much if pos is off by a
- // few thousandths.
- nassertv_always(!is_empty());
- CPT(TransformState) transform = get_transform(other);
- transform = TransformState::make_pos_quat_scale_shear
- (transform->get_pos(), quat, scale, transform->get_shear());
- set_transform(other, transform);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr_scale
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, and scale components, relative
- // to the other node, implicitly setting shear to 0.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr_scale(const NodePath &other,
- const LVecBase3f &pos, const LVecBase3f &hpr,
- const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- set_transform(other, TransformState::make_pos_hpr_scale
- (pos, hpr, scale));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat_scale
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, and scale components, relative
- // to the other node, implicitly setting shear to 0.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat_scale(const NodePath &other,
- const LVecBase3f &pos, const LQuaternionf &quat,
- const LVecBase3f &scale) {
- nassertv_always(!is_empty());
- set_transform(other, TransformState::make_pos_quat_scale
- (pos, quat, scale));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_hpr_scale_shear
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, scale, and shear components,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_hpr_scale_shear(const NodePath &other,
- const LVecBase3f &pos, const LVecBase3f &hpr,
- const LVecBase3f &scale, const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- set_transform(other, TransformState::make_pos_hpr_scale_shear
- (pos, hpr, scale, shear));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_pos_quat_scale_shear
- // Access: Published
- // Description: Completely replaces the transform with new
- // translation, rotation, scale, and shear components,
- // relative to the other node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_pos_quat_scale_shear(const NodePath &other,
- const LVecBase3f &pos, const LQuaternionf &quat,
- const LVecBase3f &scale, const LVecBase3f &shear) {
- nassertv_always(!is_empty());
- set_transform(other, TransformState::make_pos_quat_scale_shear
- (pos, quat, scale, shear));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_mat
- // Access: Published
- // Description: Returns the matrix that describes the coordinate
- // space of the bottom node, relative to the other
- // path's bottom node's coordinate space.
- ////////////////////////////////////////////////////////////////////
- LMatrix4f NodePath::
- get_mat(const NodePath &other) const {
- CPT(TransformState) transform = get_transform(other);
- // We can't safely return a reference to the matrix, because we
- // can't assume the transform won't go away when the function
- // returns. If the transform was partially modified by, say, a
- // CompassEffect, it won't be stored in the cache, and thus we might
- // have the only reference to it.
- return transform->get_mat();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_mat
- // Access: Published
- // Description: Converts the indicated matrix from the other's
- // coordinate space to the local coordinate space, and
- // applies it to the node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_mat(const NodePath &other, const LMatrix4f &mat) {
- nassertv_always(!is_empty());
- set_transform(other, TransformState::make_mat(mat));
- node()->reset_prev_transform();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_relative_point
- // Access: Published
- // Description: Given that the indicated point is in the coordinate
- // system of the other node, returns the same point in
- // this node's coordinate system.
- ////////////////////////////////////////////////////////////////////
- LPoint3f NodePath::
- get_relative_point(const NodePath &other, const LVecBase3f &point) const {
- CPT(TransformState) transform = other.get_transform(*this);
- LPoint3f rel_point = LPoint3f(point) * transform->get_mat();
- return rel_point;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_relative_vector
- // Access: Published
- // Description: Given that the indicated vector is in the coordinate
- // system of the other node, returns the same vector in
- // this node's coordinate system.
- ////////////////////////////////////////////////////////////////////
- LVector3f NodePath::
- get_relative_vector(const NodePath &other, const LVecBase3f &vec) const {
- CPT(TransformState) transform = other.get_transform(*this);
- LVector3f rel_vector = LVector3f(vec) * transform->get_mat();
- return rel_vector;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::look_at
- // Access: Published
- // Description: Sets the transform on this NodePath so that it
- // rotates to face the indicated point in space, which
- // is relative to the other NodePath.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- look_at(const NodePath &other, const LPoint3f &point, const LVector3f &up) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = other.get_transform(get_parent());
- LPoint3f rel_point = point * transform->get_mat();
- LPoint3f pos = get_pos();
- LQuaternionf quat;
- ::look_at(quat, rel_point - pos, up);
- set_quat(quat);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::heads_up
- // Access: Published
- // Description: Behaves like look_at(), but with a strong preference
- // to keeping the up vector oriented in the indicated
- // "up" direction.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- heads_up(const NodePath &other, const LPoint3f &point, const LVector3f &up) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = other.get_transform(get_parent());
- LPoint3f rel_point = point * transform->get_mat();
- LPoint3f pos = get_pos();
- LQuaternionf quat;
- ::heads_up(quat, rel_point - pos, up);
- set_quat(quat);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_color
- // Access: Published
- // Description: Applies a scene-graph color to the referenced node.
- // This color will apply to all geometry at this level
- // and below (that does not specify a new color or a
- // set_color_off()).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_color(float r, float g, float b, float a,
- int priority) {
- set_color(Colorf(r, g, b, a), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_color
- // Access: Published
- // Description: Applies a scene-graph color to the referenced node.
- // This color will apply to all geometry at this level
- // and below (that does not specify a new color or a
- // set_color_off()).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_color(const Colorf &color, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(ColorAttrib::make_flat(color), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_color_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using the geometry color. This is normally the
- // default, but it may be useful to use this to
- // contradict set_color() at a higher node level (or,
- // with a priority, to override a set_color() at a lower
- // level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_color_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(ColorAttrib::make_vertex(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_color
- // Access: Published
- // Description: Completely removes any color adjustment from the node.
- // This allows the natural color of the geometry, or
- // whatever color transitions might be otherwise
- // affecting the geometry, to show instead.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_color() {
- nassertv_always(!is_empty());
- node()->clear_attrib(ColorAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_color
- // Access: Published
- // Description: Returns true if a color has been applied to the given
- // node, false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_color() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(ColorAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_color
- // Access: Published
- // Description: Returns the color that has been assigned to the node,
- // or black if no color has been assigned.
- ////////////////////////////////////////////////////////////////////
- Colorf NodePath::
- get_color() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(ColorAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ColorAttrib *ca = DCAST(ColorAttrib, attrib);
- if (ca->get_color_type() == ColorAttrib::T_flat) {
- return ca->get_color();
- }
- }
- pgraph_cat.warning()
- << "get_color() called on " << *this << " which has no color set.\n";
- return Colorf(1.0f, 1.0f, 1.0f, 1.0f);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_color_scale
- // Access: Published
- // Description: Returns true if a color scale has been applied
- // to the referenced node, false otherwise. It is still
- // possible that color at this node might have been
- // scaled by an ancestor node.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_color_scale() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(ColorScaleAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_color_scale
- // Access: Published
- // Description: Completely removes any color scale from the
- // referenced node. This is preferable to simply
- // setting the color scale to identity, as it also
- // removes the overhead associated with having a color
- // scale at all.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_color_scale() {
- nassertv_always(!is_empty());
- node()->clear_attrib(ColorScaleAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_color_scale
- // Access: Published
- // Description: Sets the color scale component of the transform,
- // leaving translation and rotation untouched.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_color_scale(const LVecBase4f &scale, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ColorScaleAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ColorScaleAttrib::get_class_type()));
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- // Modify the existing ColorScaleAttrib to add the indicated
- // colorScale.
- node()->set_attrib(csa->set_scale(scale), priority);
- } else {
- // Create a new ColorScaleAttrib for this node.
- node()->set_attrib(ColorScaleAttrib::make(scale), priority);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_color_scale_off
- // Access: Published
- // Description: Disables any color scale attribute inherited from
- // above. This is not the same thing as
- // clear_color_scale(), which undoes any previous
- // set_color_scale() operation on this node; rather,
- // this actively disables any set_color_scale() that
- // might be inherited from a parent node. This also
- // disables set_alpha_scale() at the same time.
- //
- // It is legal to specify a new color scale on the same
- // node with a subsequent call to set_color_scale() or
- // set_alpha_scale(); this new scale will apply to lower
- // geometry.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_color_scale_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(ColorScaleAttrib::make_off(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_alpha_scale
- // Access: Published
- // Description: Sets the alpha scale component of the transform
- // without (much) affecting the color scale. Note that
- // any priority specified will also apply to the color
- // scale.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_alpha_scale(float scale, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ColorScaleAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ColorScaleAttrib::get_class_type()));
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- // Modify the existing ColorScaleAttrib to add the indicated
- // colorScale.
- const LVecBase4f &sc = csa->get_scale();
- node()->set_attrib(csa->set_scale(LVecBase4f(sc[0], sc[1], sc[2], scale)), priority);
- } else {
- // Create a new ColorScaleAttrib for this node.
- node()->set_attrib(ColorScaleAttrib::make(LVecBase4f(1.0f, 1.0f, 1.0f, scale)), priority);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_all_color_scale
- // Access: Published
- // Description: Scales all the color components of the object by the
- // same amount, darkening the object, without (much)
- // affecting alpha. Note that any priority specified
- // will also apply to the alpha scale.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_all_color_scale(float scale, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ColorScaleAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ColorScaleAttrib::get_class_type()));
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- // Modify the existing ColorScaleAttrib to add the indicated
- // colorScale.
- const LVecBase4f &sc = csa->get_scale();
- node()->set_attrib(csa->set_scale(LVecBase4f(scale, scale, scale, sc[3])), priority);
- } else {
- // Create a new ColorScaleAttrib for this node.
- node()->set_attrib(ColorScaleAttrib::make(LVecBase4f(scale, scale, scale, 1.0f)), priority);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_color_scale
- // Access: Published
- // Description: Returns the complete color scale vector that has been
- // applied to this node via a previous call to
- // set_color_scale() and/or set_alpha_scale(), or all
- // 1's (identity) if no scale has been applied to this
- // particular node.
- ////////////////////////////////////////////////////////////////////
- const LVecBase4f &NodePath::
- get_color_scale() const {
- static const LVecBase4f ident_scale(1.0f, 1.0f, 1.0f, 1.0f);
- nassertr_always(!is_empty(), ident_scale);
- const RenderAttrib *attrib =
- node()->get_attrib(ColorScaleAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- return csa->get_scale();
- }
- return ident_scale;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_light
- // Access: Published
- // Description: Adds the indicated Light or PolylightNode to the list
- // of lights that illuminate geometry at this node and
- // below. The light itself should be parented into the
- // scene graph elsewhere, to represent the light's
- // position in space; but until set_light() is called it
- // will illuminate no geometry.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_light(const NodePath &light, int priority) {
- nassertv_always(!is_empty());
- if (!light.is_empty()) {
- Light *light_obj = light.node()->as_light();
- if (light_obj != (Light *)NULL) {
- // It's an actual Light object.
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(LightAttrib::get_class_type()));
- const LightAttrib *la = DCAST(LightAttrib, attrib);
-
- // Modify the existing LightAttrib to add the indicated
- // light.
- node()->set_attrib(la->add_on_light(light), priority);
-
- } else {
- // Create a new LightAttrib for this node.
- CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
- node()->set_attrib(la->add_on_light(light), priority);
- }
- return;
- } else if (light.node()->is_of_type(PolylightNode::get_class_type())) {
- // It's a Polylight object.
- if (priority != 0) {
- // PolylightEffects can't have a priority, since they're just
- // an effect to be applied immediately.
- pgraph_cat.warning()
- << "Ignoring priority on set_light(" << light << ")\n";
- }
- const RenderEffect *effect =
- node()->get_effect(PolylightEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- const PolylightEffect *ple = DCAST(PolylightEffect, effect);
-
- // Modify the existing PolylightEffect to add the indicated
- // light.
- node()->set_effect(ple->add_light(light));
-
- } else {
- // Create a new PolylightEffect for this node.
- CPT(PolylightEffect) ple = DCAST(PolylightEffect, PolylightEffect::make());
- node()->set_effect(ple->add_light(light));
- }
- return;
- }
- }
- nassert_raise("Not a Light object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_light_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no lights at all. This is different
- // from not specifying a light; rather, this
- // specifically contradicts set_light() at a higher
- // node level (or, with a priority, overrides a
- // set_light() at a lower level).
- //
- // If no lights are in effect on a particular piece of
- // geometry, that geometry is rendered with lighting
- // disabled.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_light_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(LightAttrib::make_all_off(), priority);
- node()->clear_effect(PolylightEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_light_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // without using the indicated Light. This is different
- // from not specifying the Light; rather, this
- // specifically contradicts set_light() at a higher node
- // level (or, with a priority, overrides a set_light()
- // at a lower level).
- //
- // This interface does not support PolylightNodes, which
- // cannot be turned off at a lower level.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_light_off(const NodePath &light, int priority) {
- nassertv_always(!is_empty());
- if (!light.is_empty()) {
- Light *light_obj = light.node()->as_light();
- if (light_obj != (Light *)NULL) {
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(LightAttrib::get_class_type()));
- const LightAttrib *la = DCAST(LightAttrib, attrib);
-
- // Modify the existing LightAttrib to add the indicated light
- // to the "off" list. This also, incidentally, removes it from
- // the "on" list if it is there.
- node()->set_attrib(la->add_off_light(light), priority);
-
- } else {
- // Create a new LightAttrib for this node that turns off the
- // indicated light.
- CPT(LightAttrib) la = DCAST(LightAttrib, LightAttrib::make());
- node()->set_attrib(la->add_off_light(light), priority);
- }
- return;
- }
- }
- nassert_raise("Not a Light object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_light
- // Access: Published
- // Description: Completely removes any lighting operations that may
- // have been set via set_light() or set_light_off()
- // from this particular node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_light() {
- nassertv_always(!is_empty());
- node()->clear_attrib(LightAttrib::get_class_type());
- node()->clear_effect(PolylightEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_light
- // Access: Published
- // Description: Removes any reference to the indicated Light or
- // PolylightNode from the NodePath.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_light(const NodePath &light) {
- nassertv_always(!is_empty());
- if (!light.is_empty()) {
- Light *light_obj = light.node()->as_light();
- if (light_obj != (Light *)NULL) {
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
- la = DCAST(LightAttrib, la->remove_on_light(light));
- la = DCAST(LightAttrib, la->remove_off_light(light));
-
- if (la->is_identity()) {
- node()->clear_attrib(LightAttrib::get_class_type());
-
- } else {
- int priority = node()->get_state()->get_override(LightAttrib::get_class_type());
- node()->set_attrib(la, priority);
- }
- }
- return;
- } else if (light.node()->is_of_type(PolylightNode::get_class_type())) {
- const RenderEffect *effect =
- node()->get_effect(PolylightEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- CPT(PolylightEffect) ple = DCAST(PolylightEffect, effect);
- ple = DCAST(PolylightEffect, ple->remove_light(light));
- node()->set_effect(ple);
- }
- return;
- }
- }
- nassert_raise("Not a Light object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_light
- // Access: Published
- // Description: Returns true if the indicated Light or PolylightNode
- // has been specifically enabled on this particular
- // node. This means that someone called set_light() on
- // this node with the indicated light.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_light(const NodePath &light) const {
- nassertr_always(!is_empty(), false);
- if (!light.is_empty()) {
- Light *light_obj = light.node()->as_light();
- if (light_obj != (Light *)NULL) {
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const LightAttrib *la = DCAST(LightAttrib, attrib);
- return la->has_on_light(light);
- }
- return false;
- } else if (light.node()->is_of_type(PolylightNode::get_class_type())) {
- const RenderEffect *effect =
- node()->get_effect(PolylightEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- const PolylightEffect *ple = DCAST(PolylightEffect, effect);
- return ple->has_light(light);
- }
- return false;
- }
- }
- nassert_raise("Not a Light object.");
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_light_off
- // Access: Published
- // Description: Returns true if all Lights have been specifically
- // disabled on this particular node. This means that
- // someone called set_light_off() on this node with no
- // parameters.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_light_off() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const LightAttrib *la = DCAST(LightAttrib, attrib);
- return la->has_all_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_light_off
- // Access: Published
- // Description: Returns true if the indicated Light has been
- // specifically disabled on this particular node. This
- // means that someone called set_light_off() on this
- // node with the indicated light.
- //
- // This interface does not support PolylightNodes, which
- // cannot be turned off at a lower level.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_light_off(const NodePath &light) const {
- nassertr_always(!is_empty(), false);
- if (!light.is_empty()) {
- Light *light_obj = light.node()->as_light();
- if (light_obj != (Light *)NULL) {
- const RenderAttrib *attrib =
- node()->get_attrib(LightAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const LightAttrib *la = DCAST(LightAttrib, attrib);
- return la->has_off_light(light);
- }
- }
- }
- nassert_raise("Not a Light object.");
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_clip_plane
- // Access: Published
- // Description: Adds the indicated clipping plane to the list of
- // planes that apply to geometry at this node and below.
- // The clipping plane itself, a PlaneNode, should be
- // parented into the scene graph elsewhere, to represent
- // the plane's position in space; but until
- // set_clip_plane() is called it will clip no geometry.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_clip_plane(const NodePath &clip_plane, int priority) {
- nassertv_always(!is_empty());
- if (!clip_plane.is_empty() && clip_plane.node()->is_of_type(PlaneNode::get_class_type())) {
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ClipPlaneAttrib::get_class_type()));
- const ClipPlaneAttrib *la = DCAST(ClipPlaneAttrib, attrib);
-
- // Modify the existing ClipPlaneAttrib to add the indicated
- // clip_plane.
- node()->set_attrib(la->add_on_plane(clip_plane), priority);
-
- } else {
- // Create a new ClipPlaneAttrib for this node.
- CPT(ClipPlaneAttrib) la = DCAST(ClipPlaneAttrib, ClipPlaneAttrib::make());
- node()->set_attrib(la->add_on_plane(clip_plane), priority);
- }
- return;
- }
- nassert_raise("Not a PlaneNode object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_clip_plane_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no clip_planes at all. This is different
- // from not specifying a clip_plane; rather, this
- // specifically contradicts set_clip_plane() at a higher
- // node level (or, with a priority, overrides a
- // set_clip_plane() at a lower level).
- //
- // If no clip_planes are in effect on a particular piece
- // of geometry, that geometry is rendered without being
- // clipped (other than by the viewing frustum).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_clip_plane_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(ClipPlaneAttrib::make_all_off(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_clip_plane_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // without being clipped by the indicated PlaneNode.
- // This is different from not specifying the PlaneNode;
- // rather, this specifically contradicts
- // set_clip_plane() at a higher node level (or, with a
- // priority, overrides a set_clip_plane() at a lower
- // level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_clip_plane_off(const NodePath &clip_plane, int priority) {
- nassertv_always(!is_empty());
- if (!clip_plane.is_empty() && clip_plane.node()->is_of_type(PlaneNode::get_class_type())) {
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ClipPlaneAttrib::get_class_type()));
- const ClipPlaneAttrib *la = DCAST(ClipPlaneAttrib, attrib);
-
- // Modify the existing ClipPlaneAttrib to add the indicated clip_plane
- // to the "off" list. This also, incidentally, removes it from
- // the "on" list if it is there.
- node()->set_attrib(la->add_off_plane(clip_plane), priority);
-
- } else {
- // Create a new ClipPlaneAttrib for this node that turns off the
- // indicated clip_plane.
- CPT(ClipPlaneAttrib) la = DCAST(ClipPlaneAttrib, ClipPlaneAttrib::make());
- node()->set_attrib(la->add_off_plane(clip_plane), priority);
- }
- return;
- }
- nassert_raise("Not a PlaneNode object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_clip_plane
- // Access: Published
- // Description: Completely removes any clip planes that may have been
- // set via set_clip_plane() or set_clip_plane_off() from
- // this particular node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_clip_plane() {
- nassertv_always(!is_empty());
- node()->clear_attrib(ClipPlaneAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_clip_plane
- // Access: Published
- // Description: Removes any reference to the indicated clipping plane
- // from the NodePath.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_clip_plane(const NodePath &clip_plane) {
- nassertv_always(!is_empty());
- if (!clip_plane.is_empty() && clip_plane.node()->is_of_type(PlaneNode::get_class_type())) {
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- CPT(ClipPlaneAttrib) la = DCAST(ClipPlaneAttrib, attrib);
- la = DCAST(ClipPlaneAttrib, la->remove_on_plane(clip_plane));
- la = DCAST(ClipPlaneAttrib, la->remove_off_plane(clip_plane));
-
- if (la->is_identity()) {
- node()->clear_attrib(ClipPlaneAttrib::get_class_type());
-
- } else {
- int priority = node()->get_state()->get_override(ClipPlaneAttrib::get_class_type());
- node()->set_attrib(la, priority);
- }
- }
- return;
- }
- nassert_raise("Not a PlaneNode object.");
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_clip_plane
- // Access: Published
- // Description: Returns true if the indicated clipping plane has been
- // specifically applied to this particular node. This
- // means that someone called set_clip_plane() on this
- // node with the indicated clip_plane.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_clip_plane(const NodePath &clip_plane) const {
- nassertr_always(!is_empty(), false);
- if (!clip_plane.is_empty() && clip_plane.node()->is_of_type(PlaneNode::get_class_type())) {
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ClipPlaneAttrib *la = DCAST(ClipPlaneAttrib, attrib);
- return la->has_on_plane(clip_plane);
- }
- return false;
- }
- nassert_raise("Not a PlaneNode object.");
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_clip_plane_off
- // Access: Published
- // Description: Returns true if all clipping planes have been
- // specifically disabled on this particular node. This
- // means that someone called set_clip_plane_off() on
- // this node with no parameters.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_clip_plane_off() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ClipPlaneAttrib *la = DCAST(ClipPlaneAttrib, attrib);
- return la->has_all_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_clip_plane_off
- // Access: Published
- // Description: Returns true if the indicated clipping plane has been
- // specifically disabled on this particular node. This
- // means that someone called set_clip_plane_off() on
- // this node with the indicated clip_plane.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_clip_plane_off(const NodePath &clip_plane) const {
- nassertr_always(!is_empty(), false);
- if (!clip_plane.is_empty() && clip_plane.node()->is_of_type(PlaneNode::get_class_type())) {
- const RenderAttrib *attrib =
- node()->get_attrib(ClipPlaneAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ClipPlaneAttrib *la = DCAST(ClipPlaneAttrib, attrib);
- return la->has_off_plane(clip_plane);
- }
- }
- nassert_raise("Not a PlaneNode object.");
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_bin
- // Access: Published
- // Description: Assigns the geometry at this level and below to the
- // named rendering bin. It is the user's responsibility
- // to ensure that such a bin already exists, either via
- // the cull-bin Configrc variable, or by explicitly
- // creating a GeomBin of the appropriate type at
- // runtime.
- //
- // There are two default bins created when Panda is
- // started: "default" and "fixed". Normally, all
- // geometry is assigned to "default" unless specified
- // otherwise. This bin renders opaque geometry in
- // state-sorted order, followed by transparent geometry
- // sorted back-to-front. If any geometry is assigned to
- // "fixed", this will be rendered following all the
- // geometry in "default", in the order specified by
- // draw_order for each piece of geometry so assigned.
- //
- // The draw_order parameter is meaningful only for
- // GeomBinFixed type bins, e.g. "fixed". Other kinds of
- // bins ignore it.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_bin(const string &bin_name, int draw_order, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(CullBinAttrib::make(bin_name, draw_order), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_bin
- // Access: Published
- // Description: Completely removes any bin adjustment that may have
- // been set via set_bin() from this particular node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_bin() {
- nassertv_always(!is_empty());
- node()->clear_attrib(CullBinAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_bin
- // Access: Published
- // Description: Returns true if the node has been assigned to the a
- // particular rendering bin via set_bin(), false
- // otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_bin() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(CullBinAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_bin_name
- // Access: Published
- // Description: Returns the name of the bin that this particular node
- // was assigned to via set_bin(), or the empty string if
- // no bin was assigned. See set_bin() and has_bin().
- ////////////////////////////////////////////////////////////////////
- string NodePath::
- get_bin_name() const {
- nassertr_always(!is_empty(), string());
- const RenderAttrib *attrib =
- node()->get_attrib(CullBinAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const CullBinAttrib *ba = DCAST(CullBinAttrib, attrib);
- return ba->get_bin_name();
- }
- return string();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_bin_draw_order
- // Access: Published
- // Description: Returns the drawing order associated with the bin
- // that this particular node was assigned to via
- // set_bin(), or 0 if no bin was assigned. See
- // set_bin() and has_bin().
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- get_bin_draw_order() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(CullBinAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const CullBinAttrib *ba = DCAST(CullBinAttrib, attrib);
- return ba->get_draw_order();
- }
- return 0;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_texture
- // Access: Published
- // Description: Adds the indicated texture to the list of textures
- // that will be rendered on the default texture stage.
- //
- // This is the deprecated single-texture variant of this
- // method; it is now superceded by set_texture() that
- // accepts a stage and texture. However, this method
- // may be used in the presence of multitexture if you
- // just want to adjust the default stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture(Texture *tex, int priority) {
- nassertv_always(!is_empty());
- PT(TextureStage) stage = TextureStage::get_default();
- set_texture(stage, tex, priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_texture
- // Access: Published
- // Description: Adds the indicated texture to the list of textures
- // that will be rendered on the indicated multitexture
- // stage. If there are multiple texture stages
- // specified (possibly on multiple different nodes at
- // different levels), they will all be applied to
- // geometry together, according to the stage
- // specification set up in the TextureStage object.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture(TextureStage *stage, Texture *tex, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(TextureAttrib::get_class_type()));
- const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
- // Modify the existing TextureAttrib to add the indicated
- // texture.
- node()->set_attrib(tsa->add_on_stage(stage, tex), priority);
- } else {
- // Create a new TextureAttrib for this node.
- CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
- node()->set_attrib(tsa->add_on_stage(stage, tex), priority);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_texture_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no texture, on any stage. This is different
- // from not specifying a texture; rather, this
- // specifically contradicts set_texture() at a higher
- // node level (or, with a priority, overrides a
- // set_texture() at a lower level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(TextureAttrib::make_all_off(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_texture_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no texture, on the indicated stage. This is
- // different from not specifying a texture; rather, this
- // specifically contradicts set_texture() at a higher
- // node level (or, with a priority, overrides a
- // set_texture() at a lower level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture_off(TextureStage *stage, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(TextureAttrib::get_class_type()));
- const TextureAttrib *tsa = DCAST(TextureAttrib, attrib);
- // Modify the existing TextureAttrib to add the indicated texture
- // to the "off" list. This also, incidentally, removes it from
- // the "on" list if it is there.
- node()->set_attrib(tsa->add_off_stage(stage), priority);
- } else {
- // Create a new TextureAttrib for this node that turns off the
- // indicated stage.
- CPT(TextureAttrib) tsa = DCAST(TextureAttrib, TextureAttrib::make());
- node()->set_attrib(tsa->add_off_stage(stage), priority);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_texture
- // Access: Published
- // Description: Completely removes any texture adjustment that may
- // have been set via set_texture() or set_texture_off()
- // from this particular node. This allows whatever
- // textures might be otherwise affecting the geometry to
- // show instead.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_texture() {
- nassertv_always(!is_empty());
- node()->clear_attrib(TextureAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_texture
- // Access: Published
- // Description: Removes any reference to the indicated texture stage
- // from the NodePath.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_texture(TextureStage *stage) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- CPT(TextureAttrib) tsa = DCAST(TextureAttrib, attrib);
- tsa = DCAST(TextureAttrib, tsa->remove_on_stage(stage));
- tsa = DCAST(TextureAttrib, tsa->remove_off_stage(stage));
- if (tsa->is_identity()) {
- node()->clear_attrib(TextureAttrib::get_class_type());
- } else {
- int priority = node()->get_state()->get_override(TextureAttrib::get_class_type());
- node()->set_attrib(tsa, priority);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_texture
- // Access: Published
- // Description: Returns true if a texture has been applied to this
- // particular node via set_texture(), false otherwise.
- // This is not the same thing as asking whether the
- // geometry at this node will be rendered with
- // texturing, as there may be a texture in effect from a
- // higher or lower level.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_texture() const {
- return get_texture() != (Texture *)NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_texture
- // Access: Published
- // Description: Returns true if texturing has been specifically
- // enabled on this particular node for the indicated
- // stage. This means that someone called
- // set_texture() on this node with the indicated stage
- // name, or the stage_name is the default stage_name,
- // and someone called set_texture() on this node.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_texture(TextureStage *stage) const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->has_on_stage(stage);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_texture_off
- // Access: Published
- // Description: Returns true if texturing has been specifically
- // disabled on this particular node via
- // set_texture_off(), false otherwise. This is not the
- // same thing as asking whether the geometry at this
- // node will be rendered untextured, as there may be a
- // texture in effect from a higher or lower level.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_texture_off() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->has_all_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_texture_off
- // Access: Published
- // Description: Returns true if texturing has been specifically
- // disabled on this particular node for the indicated
- // stage. This means that someone called
- // set_texture_off() on this node with the indicated
- // stage name, or that someone called set_texture_off()
- // on this node to remove all stages.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_texture_off(TextureStage *stage) const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->has_off_stage(stage);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_texture
- // Access: Published
- // Description: Returns the base-level texture that has been set on
- // this particular node, or NULL if no texture has been
- // set. This is not necessarily the texture that will
- // be applied to the geometry at or below this level, as
- // another texture at a higher or lower level may
- // override.
- //
- // See also find_texture().
- ////////////////////////////////////////////////////////////////////
- Texture *NodePath::
- get_texture() const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->get_texture();
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_texture
- // Access: Published
- // Description: Returns the texture that has been set on the
- // indicated stage for this particular node, or NULL if
- // no texture has been set for this stage.
- ////////////////////////////////////////////////////////////////////
- Texture *NodePath::
- get_texture(TextureStage *stage) const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->get_on_texture(stage);
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader(Shader *sha, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(ShaderAttrib::get_class_type()));
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- node()->set_attrib(sa->set_shader(sha, priority));
- } else {
- // Create a new ShaderAttrib for this node.
- CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
- node()->set_attrib(sa->set_shader(sha, priority));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_off
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_off(int priority) {
- set_shader(NULL, priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_shader
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_shader() {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- node()->set_attrib(sa->clear_shader());
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_shader
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- const Shader *NodePath::
- get_shader() const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- return sa->get_shader();
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(const ShaderInput *inp) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- node()->set_attrib(sa->set_shader_input(inp));
- } else {
- // Create a new ShaderAttrib for this node.
- CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make());
- node()->set_attrib(sa->set_shader_input(inp));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- const ShaderInput *NodePath::
- get_shader_input(InternalName *id) const {
- nassertr_always(!is_empty(), NULL);
-
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- return sa->get_shader_input(id);
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_shader_input(InternalName *id) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(ShaderAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib);
- node()->set_attrib(sa->clear_shader_input(id));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(InternalName *id, Texture *tex, int priority) {
- set_shader_input(new ShaderInput(id,tex,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(InternalName *id, const NodePath &np, int priority) {
- set_shader_input(new ShaderInput(id,np,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(InternalName *id, const LVector4f &v, int priority) {
- set_shader_input(new ShaderInput(id,v,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(InternalName *id, double n1, double n2, double n3, double n4, int priority) {
- set_shader_input(new ShaderInput(id,LVector4f(n1,n2,n3,n4),priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(const string &id, Texture *tex, int priority) {
- set_shader_input(new ShaderInput(InternalName::make(id),tex,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(const string &id, const NodePath &np, int priority) {
- set_shader_input(new ShaderInput(InternalName::make(id),np,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(const string &id, const LVector4f &v, int priority) {
- set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_shader_input(const string &id, double n1, double n2, double n3, double n4, int priority) {
- set_shader_input(new ShaderInput(InternalName::make(id),LVector4f(n1,n2,n3,n4),priority));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- const ShaderInput *NodePath::
- get_shader_input(const string &id) const {
- return get_shader_input(InternalName::make(id));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_shader_input
- // Access: Published
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_shader_input(const string &id) {
- clear_shader_input(InternalName::make(id));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_tex_transform
- // Access: Published
- // Description: Sets the texture matrix on the current node to the
- // indicated transform for the given stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_tex_transform(TextureStage *stage, const TransformState *transform) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attrib);
- // Modify the existing TexMatrixAttrib to add the indicated
- // stage.
- node()->set_attrib(tma->add_stage(stage, transform));
- } else {
- // Create a new TexMatrixAttrib for this node.
- node()->set_attrib(TexMatrixAttrib::make(stage, transform));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_transform
- // Access: Published
- // Description: Removes all texture matrices from the current node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_transform() {
- nassertv_always(!is_empty());
- node()->clear_attrib(TexMatrixAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_transform
- // Access: Published
- // Description: Removes the texture matrix on the current node for
- // the given stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_transform(TextureStage *stage) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- CPT(TexMatrixAttrib) tma = DCAST(TexMatrixAttrib, attrib);
- tma = DCAST(TexMatrixAttrib, tma->remove_stage(stage));
- if (tma->is_empty()) {
- node()->clear_attrib(TexMatrixAttrib::get_class_type());
- } else {
- node()->set_attrib(tma);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_tex_transform
- // Access: Published
- // Description: Returns true if there is an explicit texture matrix
- // on the current node for the given stage.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_tex_transform(TextureStage *stage) const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attrib);
- return tma->has_stage(stage);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_transform
- // Access: Published
- // Description: Returns the texture matrix on the current node for the
- // given stage, or identity transform if there is no
- // explicit transform set for the given stage.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- get_tex_transform(TextureStage *stage) const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attrib);
- return tma->get_transform(stage);
- }
- return TransformState::make_identity();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_tex_transform
- // Access: Published
- // Description: Sets the texture matrix on the current node to the
- // indicated transform for the given stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_tex_transform(const NodePath &other, TextureStage *stage, const TransformState *transform) {
- nassertv(_error_type == ET_ok && other._error_type == ET_ok);
- nassertv_always(!is_empty());
- CPT(RenderState) state = get_state(other);
- const RenderAttrib *attrib =
- state->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attrib);
- // Modify the existing TexMatrixAttrib to add the indicated
- // stage.
- state = state->add_attrib(tma->add_stage(stage, transform));
- } else {
- // Create a new TexMatrixAttrib for this node.
- state = state->add_attrib(TexMatrixAttrib::make(stage, transform));
- }
- // Now compose that with our parent's state.
- CPT(RenderState) rel_state;
- if (has_parent()) {
- rel_state = other.get_state(get_parent());
- } else {
- rel_state = other.get_state(NodePath());
- }
- CPT(RenderState) new_state = rel_state->compose(state);
- // And apply only the TexMatrixAttrib to the current node, leaving
- // the others unchanged.
- node()->set_attrib(new_state->get_attrib(TexMatrixAttrib::get_class_type()));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_transform
- // Access: Published
- // Description: Returns the texture matrix on the current node for the
- // given stage, relative to the other node.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- get_tex_transform(const NodePath &other, TextureStage *stage) const {
- nassertr(_error_type == ET_ok && other._error_type == ET_ok, TransformState::make_identity());
- CPT(RenderState) state = get_state(other);
- const RenderAttrib *attrib =
- state->get_attrib(TexMatrixAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attrib);
- return tma->get_transform(stage);
- }
- return TransformState::make_identity();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_tex_gen
- // Access: Published
- // Description: Enables automatic texture coordinate generation for
- // the indicated texture stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- CPT(TexGenAttrib) tga;
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(TextureAttrib::get_class_type()));
- tga = DCAST(TexGenAttrib, attrib);
- } else {
- tga = DCAST(TexGenAttrib, TexGenAttrib::make());
- }
- node()->set_attrib(tga->add_stage(stage, mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_tex_gen
- // Access: Published
- // Description: Enables automatic texture coordinate generation for
- // the indicated texture stage. This version of this
- // method is useful when setting M_light_vector, which
- // requires the name of the texture coordinate set that
- // supplies the tangent and binormal, as well as the
- // specific light to generate coordinates for.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode,
- const string &source_name, const NodePath &light, int priority) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- CPT(TexGenAttrib) tga;
- if (attrib != (const RenderAttrib *)NULL) {
- priority = max(priority,
- node()->get_state()->get_override(TextureAttrib::get_class_type()));
- tga = DCAST(TexGenAttrib, attrib);
- } else {
- tga = DCAST(TexGenAttrib, TexGenAttrib::make());
- }
- node()->set_attrib(tga->add_stage(stage, mode, source_name, light), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_gen
- // Access: Published
- // Description: Removes the texture coordinate generation mode from
- // all texture stages on this node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_gen() {
- nassertv_always(!is_empty());
- node()->clear_attrib(TexGenAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_gen
- // Access: Published
- // Description: Disables automatic texture coordinate generation for
- // the indicated texture stage.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_gen(TextureStage *stage) {
- nassertv_always(!is_empty());
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- CPT(TexGenAttrib) tga = DCAST(TexGenAttrib, attrib);
- tga = DCAST(TexGenAttrib, tga->remove_stage(stage));
- if (tga->is_empty()) {
- node()->clear_attrib(TexGenAttrib::get_class_type());
- } else {
- node()->set_attrib(tga);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_tex_gen
- // Access: Published
- // Description: Returns true if there is a mode for automatic texture
- // coordinate generation on the current node for the
- // given stage.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_tex_gen(TextureStage *stage) const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexGenAttrib *tga = DCAST(TexGenAttrib, attrib);
- return tga->has_stage(stage);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_gen
- // Access: Published
- // Description: Returns the texture coordinate generation mode for
- // the given stage, or M_off if there is no explicit
- // mode set for the given stage.
- ////////////////////////////////////////////////////////////////////
- RenderAttrib::TexGenMode NodePath::
- get_tex_gen(TextureStage *stage) const {
- nassertr_always(!is_empty(), TexGenAttrib::M_off);
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexGenAttrib *tga = DCAST(TexGenAttrib, attrib);
- return tga->get_mode(stage);
- }
- return TexGenAttrib::M_off;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_gen_light
- // Access: Published
- // Description: Returns the particular Light set for the indicated
- // texgen mode's texture stage, or empty NodePath if no
- // light is set. This is only meaningful if the texgen
- // mode (returned by get_tex_gen()) is M_light_vector.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_tex_gen_light(TextureStage *stage) const {
- nassertr_always(!is_empty(), NodePath::fail());
- const RenderAttrib *attrib =
- node()->get_attrib(TexGenAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TexGenAttrib *tga = DCAST(TexGenAttrib, attrib);
- return tga->get_light(stage);
- }
- return NodePath();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_tex_projector
- // Access: Published
- // Description: Establishes a TexProjectorEffect on this node, which
- // can be used to establish projective texturing (but
- // see also the NodePath::project_texture() convenience
- // function), or it can be used to bind this node's
- // texture transform to particular node's position in
- // space, allowing a LerpInterval (for instance) to
- // adjust this node's texture coordinates.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_tex_projector(TextureStage *stage, const NodePath &from, const NodePath &to) {
- nassertv_always(!is_empty());
- const RenderEffect *effect =
- node()->get_effect(TexProjectorEffect::get_class_type());
- CPT(TexProjectorEffect) tpe;
- if (effect != (const RenderEffect *)NULL) {
- tpe = DCAST(TexProjectorEffect, effect);
- } else {
- tpe = DCAST(TexProjectorEffect, TexProjectorEffect::make());
- }
- node()->set_effect(tpe->add_stage(stage, from, to));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_projector
- // Access: Published
- // Description: Removes the TexProjectorEffect for the indicated
- // stage from this node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_projector(TextureStage *stage) {
- nassertv_always(!is_empty());
- const RenderEffect *effect =
- node()->get_effect(TexProjectorEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- CPT(TexProjectorEffect) tpe = DCAST(TexProjectorEffect, effect);
- tpe = DCAST(TexProjectorEffect, tpe->remove_stage(stage));
- if (tpe->is_empty()) {
- node()->clear_effect(TexProjectorEffect::get_class_type());
- } else {
- node()->set_effect(tpe);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_tex_projector
- // Access: Published
- // Description: Removes the TexProjectorEffect for all stages from
- // this node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_tex_projector() {
- nassertv_always(!is_empty());
- node()->clear_effect(TexProjectorEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_tex_projector
- // Access: Published
- // Description: Returns true if this node has a TexProjectorEffect
- // for the indicated stage, false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_tex_projector(TextureStage *stage) const {
- nassertr_always(!is_empty(), false);
- const RenderEffect *effect =
- node()->get_effect(TexProjectorEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- const TexProjectorEffect *tpe = DCAST(TexProjectorEffect, effect);
- return tpe->has_stage(stage);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_projector_from
- // Access: Published
- // Description: Returns the "from" node associated with the
- // TexProjectorEffect on the indicated stage. The
- // relative transform between the "from" and the "to"
- // nodes is automatically applied to the texture
- // transform each frame.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_tex_projector_from(TextureStage *stage) const {
- nassertr_always(!is_empty(), NodePath::fail());
- const RenderEffect *effect =
- node()->get_effect(TexProjectorEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- const TexProjectorEffect *tpe = DCAST(TexProjectorEffect, effect);
- return tpe->get_from(stage);
- }
- return NodePath::not_found();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_tex_projector_to
- // Access: Published
- // Description: Returns the "to" node associated with the
- // TexProjectorEffect on the indicated stage. The
- // relative transform between the "from" and the "to"
- // nodes is automatically applied to the texture
- // transform each frame.
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_tex_projector_to(TextureStage *stage) const {
- nassertr_always(!is_empty(), NodePath::fail());
- const RenderEffect *effect =
- node()->get_effect(TexProjectorEffect::get_class_type());
- if (effect != (const RenderEffect *)NULL) {
- const TexProjectorEffect *tpe = DCAST(TexProjectorEffect, effect);
- return tpe->get_to(stage);
- }
- return NodePath::not_found();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::project_texture
- // Access: Published
- // Description: A convenience function to enable projective texturing
- // at this node level and below, using the indicated
- // NodePath (which should contain a LensNode) as the
- // projector.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- project_texture(TextureStage *stage, Texture *tex, const NodePath &projector) {
- nassertv(!projector.is_empty() && projector.node()->is_of_type(LensNode::get_class_type()));
- set_texture(stage, tex);
- set_tex_gen(stage, TexGenAttrib::M_world_position);
- set_tex_projector(stage, NodePath(), projector);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_normal_map
- // Access: Published
- // Description: A convenience function to set up a normal map on this
- // geometry. This uses the single highest-priority
- // light on the object only. It also requires
- // multitexture, and consumes at least two texture
- // stages, in addition to what may already be in use.
- //
- // The normal_map parameter is the texture that contains
- // the normal map information (with a 3-d delta vector
- // encoded into the r,g,b of each texel). texcoord_name is
- // the name of the texture coordinate set that contains
- // the tangent and binormal we wish to use. If
- // preserve_color is true, then one additional texture
- // stage is consumed to blend in the geometry's original
- // vertex color.
- //
- // Only one normal map may be in effect through this
- // interface at any given time.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_normal_map(Texture *normal_map, const string &texcoord_name,
- bool preserve_color) {
- clear_normal_map();
- // First, we apply the normal map itself, to the bottom layer.
- PT(TextureStage) normal_map_ts = new TextureStage("__normal_map");
- normal_map_ts->set_texcoord_name(texcoord_name);
- normal_map_ts->set_sort(-20);
- normal_map_ts->set_mode(TextureStage::M_replace);
- set_texture(normal_map_ts, normal_map);
- // Then, we apply a normalization map, to normalize, per-pixel, the
- // vector to the light.
- PT(Texture) normalization_map = TexturePool::get_normalization_cube_map(32);
- PT(TextureStage) normalization_map_ts = new TextureStage("__normalization_map");
- normalization_map_ts->set_combine_rgb
- (TextureStage::CM_dot3_rgb,
- TextureStage::CS_texture, TextureStage::CO_src_color,
- TextureStage::CS_previous, TextureStage::CO_src_color);
- normalization_map_ts->set_texcoord_name("light_vector");
- normalization_map_ts->set_sort(-15);
- set_texture(normalization_map_ts, normalization_map);
- // Finally, we enable M_light_vector texture coordinate generation.
- set_tex_gen(normalization_map_ts, TexGenAttrib::M_light_vector,
- texcoord_name, NodePath());
- if (preserve_color) {
- // One more stage to get back the original color.
- PT(TextureStage) orig_color_ts = new TextureStage("__orig_color");
- orig_color_ts->set_combine_rgb
- (TextureStage::CM_modulate,
- TextureStage::CS_primary_color, TextureStage::CO_src_color,
- TextureStage::CS_previous, TextureStage::CO_src_color);
- set_texture(orig_color_ts, normal_map);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_normal_map
- // Access: Published
- // Description: Undoes the effect of a previous call to
- // set_normal_map().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_normal_map() {
- // Scan through the TextureStages, and if we find any whose name
- // matches one of the stages that would have been left by
- // set_normal_map(), remove it from the state.
- CPT(RenderAttrib) attrib =
- get_state()->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- for (int i = 0; i < ta->get_num_on_stages(); i++) {
- TextureStage *stage = ta->get_on_stage(i);
- if (stage->get_name() == "__normal_map") {
- clear_texture(stage);
- } else if (stage->get_name() == "__normalization_map") {
- clear_texture(stage);
- clear_tex_gen(stage);
- } else if (stage->get_name() == "__orig_color") {
- clear_texture(stage);
- }
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_texture
- // Access: Published
- // Description: Returns the first texture found applied to geometry
- // at this node or below that matches the indicated name
- // (which may contain wildcards). Returns the texture
- // if it is found, or NULL if it is not.
- ////////////////////////////////////////////////////////////////////
- Texture *NodePath::
- find_texture(const string &name) const {
- GlobPattern glob(name);
- return r_find_texture(node(), get_net_state(), glob);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_texture
- // Access: Published
- // Description: Returns the first texture found applied to geometry
- // at this node or below that is assigned to the
- // indicated texture stage. Returns the texture if it
- // is found, or NULL if it is not.
- ////////////////////////////////////////////////////////////////////
- Texture *NodePath::
- find_texture(TextureStage *stage) const {
- return r_find_texture(node(), stage);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_textures
- // Access: Published
- // Description: Returns a list of a textures applied to geometry at
- // this node and below.
- ////////////////////////////////////////////////////////////////////
- TextureCollection NodePath::
- find_all_textures() const {
- Textures textures;
- r_find_all_textures(node(), get_net_state(), textures);
- TextureCollection tc;
- Textures::iterator ti;
- for (ti = textures.begin(); ti != textures.end(); ++ti) {
- tc.add_texture(*ti);
- }
- return tc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_textures
- // Access: Published
- // Description: Returns a list of a textures applied to geometry at
- // this node and below that match the indicated name
- // (which may contain wildcard characters).
- ////////////////////////////////////////////////////////////////////
- TextureCollection NodePath::
- find_all_textures(const string &name) const {
- Textures textures;
- r_find_all_textures(node(), get_net_state(), textures);
- GlobPattern glob(name);
- TextureCollection tc;
- Textures::iterator ti;
- for (ti = textures.begin(); ti != textures.end(); ++ti) {
- Texture *texture = (*ti);
- if (glob.matches(texture->get_name())) {
- tc.add_texture(texture);
- }
- }
- return tc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_textures
- // Access: Published
- // Description: Returns a list of a textures on geometry at
- // this node and below that are assigned to the
- // indicated texture stage.
- ////////////////////////////////////////////////////////////////////
- TextureCollection NodePath::
- find_all_textures(TextureStage *stage) const {
- Textures textures;
- r_find_all_textures(node(), stage, textures);
- TextureCollection tc;
- Textures::iterator ti;
- for (ti = textures.begin(); ti != textures.end(); ++ti) {
- Texture *texture = (*ti);
- tc.add_texture(texture);
- }
- return tc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_texture_stage
- // Access: Published
- // Description: Returns the first TextureStage found applied to
- // geometry at this node or below that matches the
- // indicated name (which may contain wildcards).
- // Returns the TextureStage if it is found, or NULL if
- // it is not.
- ////////////////////////////////////////////////////////////////////
- TextureStage *NodePath::
- find_texture_stage(const string &name) const {
- GlobPattern glob(name);
- return r_find_texture_stage(node(), get_net_state(), glob);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_texture_stages
- // Access: Published
- // Description: Returns a list of a TextureStages applied to geometry
- // at this node and below.
- ////////////////////////////////////////////////////////////////////
- TextureStageCollection NodePath::
- find_all_texture_stages() const {
- TextureStages texture_stages;
- r_find_all_texture_stages(node(), get_net_state(), texture_stages);
- TextureStageCollection tc;
- TextureStages::iterator ti;
- for (ti = texture_stages.begin(); ti != texture_stages.end(); ++ti) {
- tc.add_texture_stage(*ti);
- }
- return tc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::unify_texture_stages
- // Access: Published
- // Description: Searches through all TextureStages at this node and
- // below. Any TextureStages that share the same name as
- // the indicated TextureStage object are replaced with
- // this object, thus ensuring that all geometry at this
- // node and below with a particular TextureStage name is
- // using the same TextureStage object.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- unify_texture_stages(TextureStage *stage) {
- r_unify_texture_stages(node(), stage);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_all_texture_stages
- // Access: Published
- // Description: Returns a list of a TextureStages applied to geometry
- // at this node and below that match the indicated name
- // (which may contain wildcard characters).
- ////////////////////////////////////////////////////////////////////
- TextureStageCollection NodePath::
- find_all_texture_stages(const string &name) const {
- TextureStages texture_stages;
- r_find_all_texture_stages(node(), get_net_state(), texture_stages);
- GlobPattern glob(name);
- TextureStageCollection tc;
- TextureStages::iterator ti;
- for (ti = texture_stages.begin(); ti != texture_stages.end(); ++ti) {
- TextureStage *texture_stage = (*ti);
- if (glob.matches(texture_stage->get_name())) {
- tc.add_texture_stage(texture_stage);
- }
- }
- return tc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_material
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using the indicated material.
- //
- // Previously, this operation made a copy of the
- // material structure, but nowadays it assigns the
- // pointer directly.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_material(Material *mat, int priority) {
- nassertv_always(!is_empty());
- nassertv(mat != NULL);
- node()->set_attrib(MaterialAttrib::make(mat), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_material_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no material. This is normally the default, but
- // it may be useful to use this to contradict
- // set_material() at a higher node level (or, with a
- // priority, to override a set_material() at a lower
- // level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_material_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(MaterialAttrib::make_off(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_material
- // Access: Published
- // Description: Completely removes any material adjustment that may
- // have been set via set_material() from this particular
- // node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_material() {
- nassertv_always(!is_empty());
- node()->clear_attrib(MaterialAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_material
- // Access: Published
- // Description: Returns true if a material has been applied to this
- // particular node via set_material(), false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_material() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(MaterialAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const MaterialAttrib *ma = DCAST(MaterialAttrib, attrib);
- return !ma->is_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_material
- // Access: Published
- // Description: Returns the material that has been set on this
- // particular node, or NULL if no material has been set.
- // This is not necessarily the material that will be
- // applied to the geometry at or below this level, as
- // another material at a higher or lower level may
- // override.
- //
- // This function returns a copy of the given material,
- // to allow changes, if desired. Once changes are made,
- // they should be reapplied via set_material().
- ////////////////////////////////////////////////////////////////////
- PT(Material) NodePath::
- get_material() const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(MaterialAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const MaterialAttrib *ma = DCAST(MaterialAttrib, attrib);
- return new Material(*ma->get_material());
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_fog
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using the indicated fog.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_fog(Fog *fog, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(FogAttrib::make(fog), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_fog_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no fog. This is normally the default, but
- // it may be useful to use this to contradict
- // set_fog() at a higher node level (or, with a
- // priority, to override a set_fog() at a lower
- // level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_fog_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(FogAttrib::make_off(), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_fog
- // Access: Published
- // Description: Completely removes any fog adjustment that may
- // have been set via set_fog() or set_fog_off()
- // from this particular node. This allows whatever
- // fogs might be otherwise affecting the geometry to
- // show instead.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_fog() {
- nassertv_always(!is_empty());
- node()->clear_attrib(FogAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_fog
- // Access: Published
- // Description: Returns true if a fog has been applied to this
- // particular node via set_fog(), false otherwise.
- // This is not the same thing as asking whether the
- // geometry at this node will be rendered with
- // fog, as there may be a fog in effect from a higher or
- // lower level.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_fog() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(FogAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const FogAttrib *fa = DCAST(FogAttrib, attrib);
- return !fa->is_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_fog_off
- // Access: Published
- // Description: Returns true if a fog has been specifically
- // disabled on this particular node via
- // set_fog_off(), false otherwise. This is not the
- // same thing as asking whether the geometry at this
- // node will be rendered unfogged, as there may be a
- // fog in effect from a higher or lower level.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_fog_off() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(FogAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const FogAttrib *fa = DCAST(FogAttrib, attrib);
- return fa->is_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_fog
- // Access: Published
- // Description: Returns the fog that has been set on this
- // particular node, or NULL if no fog has been set.
- // This is not necessarily the fog that will be
- // applied to the geometry at or below this level, as
- // another fog at a higher or lower level may
- // override.
- ////////////////////////////////////////////////////////////////////
- Fog *NodePath::
- get_fog() const {
- nassertr_always(!is_empty(), NULL);
- const RenderAttrib *attrib =
- node()->get_attrib(FogAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const FogAttrib *fa = DCAST(FogAttrib, attrib);
- return fa->get_fog();
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_render_mode_wireframe
- // Access: Published
- // Description: Sets up the geometry at this level and below (unless
- // overridden) to render in wireframe mode.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_render_mode_wireframe(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_wireframe), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_render_mode_filled
- // Access: Published
- // Description: Sets up the geometry at this level and below (unless
- // overridden) to render in filled (i.e. not wireframe)
- // mode.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_render_mode_filled(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_render_mode
- // Access: Published
- // Description: Sets up the geometry at this level and below (unless
- // overridden) to render in the specified mode and with
- // the indicated line and/or point thickness.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_render_mode(RenderModeAttrib::Mode mode, float thickness, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(RenderModeAttrib::make(mode, thickness), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_render_mode
- // Access: Published
- // Description: Completely removes any render mode adjustment that
- // may have been set on this node via
- // set_render_mode_wireframe() or
- // set_render_mode_filled().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_render_mode() {
- nassertv_always(!is_empty());
- node()->clear_attrib(RenderModeAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_render_mode
- // Access: Published
- // Description: Returns true if a render mode has been explicitly set
- // on this particular node via set_render_mode() (or
- // set_render_mode_wireframe() or
- // set_render_mode_filled()), false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_render_mode() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(RenderModeAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_render_mode
- // Access: Published
- // Description: Returns the render mode that has been specifically
- // set on this node via set_render_mode(), or
- // M_unchanged if nothing has been set.
- ////////////////////////////////////////////////////////////////////
- RenderModeAttrib::Mode NodePath::
- get_render_mode() const {
- nassertr_always(!is_empty(), RenderModeAttrib::M_unchanged);
- const RenderAttrib *attrib =
- node()->get_attrib(RenderModeAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const RenderModeAttrib *ta = DCAST(RenderModeAttrib, attrib);
- return ta->get_mode();
- }
- return RenderModeAttrib::M_unchanged;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_render_mode_thickness
- // Access: Published
- // Description: Returns the render mode thickness that has been
- // specifically set on this node via set_render_mode(),
- // or 0.0 if nothing has been set.
- ////////////////////////////////////////////////////////////////////
- float NodePath::
- get_render_mode_thickness() const {
- nassertr_always(!is_empty(), 0.0f);
- const RenderAttrib *attrib =
- node()->get_attrib(RenderModeAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const RenderModeAttrib *ta = DCAST(RenderModeAttrib, attrib);
- return ta->get_thickness();
- }
- return 0.0f;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_two_sided
- // Access: Published
- // Description: Specifically sets or disables two-sided rendering
- // mode on this particular node. If no other nodes
- // override, this will cause backfacing polygons to be
- // drawn (in two-sided mode, true) or culled (in
- // one-sided mode, false).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_two_sided(bool two_sided, int priority) {
- nassertv_always(!is_empty());
- CullFaceAttrib::Mode mode =
- two_sided ?
- CullFaceAttrib::M_cull_none :
- CullFaceAttrib::M_cull_clockwise;
- node()->set_attrib(CullFaceAttrib::make(mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_two_sided
- // Access: Published
- // Description: Completely removes any two-sided adjustment that
- // may have been set on this node via set_two_sided().
- // The geometry at this level and below will
- // subsequently be rendered either two-sided or
- // one-sided, according to whatever other nodes may have
- // had set_two_sided() on it, or according to the
- // initial state otherwise.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_two_sided() {
- nassertv_always(!is_empty());
- node()->clear_attrib(CullFaceAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_two_sided
- // Access: Published
- // Description: Returns true if a two-sided adjustment has been
- // explicitly set on this particular node via
- // set_two_sided(). If this returns true, then
- // get_two_sided() may be called to determine which has
- // been set.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_two_sided() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(CullFaceAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_two_sided
- // Access: Published
- // Description: Returns true if two-sided rendering has been
- // specifically set on this node via set_two_sided(), or
- // false if one-sided rendering has been specifically
- // set, or if nothing has been specifically set. See
- // also has_two_sided(). This does not necessarily
- // imply that the geometry will or will not be rendered
- // two-sided, as there may be other nodes that override.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- get_two_sided() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(CullFaceAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, attrib);
- return (cfa->get_actual_mode() == CullFaceAttrib::M_cull_none);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_depth_test
- // Access: Published
- // Description: Specifically sets or disables the testing of the
- // depth buffer on this particular node. This is
- // normally on in the 3-d scene graph and off in the 2-d
- // scene graph; it should be on for rendering most 3-d
- // objects properly.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_depth_test(bool depth_test, int priority) {
- nassertv_always(!is_empty());
- DepthTestAttrib::PandaCompareFunc mode =
- depth_test ?
- DepthTestAttrib::M_less :
- DepthTestAttrib::M_none;
- node()->set_attrib(DepthTestAttrib::make(mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_depth_test
- // Access: Published
- // Description: Completely removes any depth-test adjustment that
- // may have been set on this node via set_depth_test().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_depth_test() {
- nassertv_always(!is_empty());
- node()->clear_attrib(DepthTestAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_depth_test
- // Access: Published
- // Description: Returns true if a depth-test adjustment has been
- // explicitly set on this particular node via
- // set_depth_test(). If this returns true, then
- // get_depth_test() may be called to determine which has
- // been set.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_depth_test() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(DepthTestAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_depth_test
- // Access: Published
- // Description: Returns true if depth-test rendering has been
- // specifically set on this node via set_depth_test(), or
- // false if depth-test rendering has been specifically
- // disabled, or if nothing has been specifically set. See
- // also has_depth_test().
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- get_depth_test() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(DepthTestAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const DepthTestAttrib *dta = DCAST(DepthTestAttrib, attrib);
- return (dta->get_mode() != DepthTestAttrib::M_none);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_depth_write
- // Access: Published
- // Description: Specifically sets or disables the writing to the
- // depth buffer on this particular node. This is
- // normally on in the 3-d scene graph and off in the 2-d
- // scene graph; it should be on for rendering most 3-d
- // objects properly.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_depth_write(bool depth_write, int priority) {
- nassertv_always(!is_empty());
- DepthWriteAttrib::Mode mode =
- depth_write ?
- DepthWriteAttrib::M_on :
- DepthWriteAttrib::M_off;
- node()->set_attrib(DepthWriteAttrib::make(mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_depth_write
- // Access: Published
- // Description: Completely removes any depth-write adjustment that
- // may have been set on this node via set_depth_write().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_depth_write() {
- nassertv_always(!is_empty());
- node()->clear_attrib(DepthWriteAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_depth_write
- // Access: Published
- // Description: Returns true if a depth-write adjustment has been
- // explicitly set on this particular node via
- // set_depth_write(). If this returns true, then
- // get_depth_write() may be called to determine which has
- // been set.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_depth_write() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(DepthWriteAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_depth_write
- // Access: Published
- // Description: Returns true if depth-write rendering has been
- // specifically set on this node via set_depth_write(), or
- // false if depth-write rendering has been specifically
- // disabled, or if nothing has been specifically set. See
- // also has_depth_write().
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- get_depth_write() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(DepthWriteAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const DepthWriteAttrib *dta = DCAST(DepthWriteAttrib, attrib);
- return (dta->get_mode() != DepthWriteAttrib::M_off);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::do_billboard_axis
- // Access: Published
- // Description: Performs a billboard-type rotate to the indicated
- // camera node, one time only, and leaves the object
- // rotated. This is similar in principle to heads_up().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- do_billboard_axis(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = camera.get_transform(get_parent());
- const LMatrix4f &rel_mat = transform->get_mat();
- LVector3f up = LVector3f::up();
- LVector3f rel_pos = -rel_mat.get_row3(3);
- LQuaternionf quat;
- ::heads_up(quat, rel_pos, up);
- set_quat(quat);
- // Also slide the geometry towards the camera according to the
- // offset factor.
- if (offset != 0.0f) {
- LVector3f translate = rel_mat.get_row3(3);
- translate.normalize();
- translate *= offset;
- set_pos(translate);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::do_billboard_point_eye
- // Access: Published
- // Description: Performs a billboard-type rotate to the indicated
- // camera node, one time only, and leaves the object
- // rotated. This is similar in principle to look_at(),
- // although the point_eye billboard effect cannot be
- // achieved using the ordinary look_at() call.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- do_billboard_point_eye(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = camera.get_transform(get_parent());
- const LMatrix4f &rel_mat = transform->get_mat();
- LVector3f up = LVector3f::up() * rel_mat;
- LVector3f rel_pos = LVector3f::forward() * rel_mat;
- LQuaternionf quat;
- ::look_at(quat, rel_pos, up);
- set_quat(quat);
- // Also slide the geometry towards the camera according to the
- // offset factor.
- if (offset != 0.0f) {
- LVector3f translate = rel_mat.get_row3(3);
- translate.normalize();
- translate *= offset;
- set_pos(translate);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::do_billboard_point_world
- // Access: Published
- // Description: Performs a billboard-type rotate to the indicated
- // camera node, one time only, and leaves the object
- // rotated. This is similar in principle to look_at().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- do_billboard_point_world(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(TransformState) transform = camera.get_transform(get_parent());
- const LMatrix4f &rel_mat = transform->get_mat();
- LVector3f up = LVector3f::up();
- LVector3f rel_pos = -rel_mat.get_row3(3);
- LQuaternionf quat;
- ::look_at(quat, rel_pos, up);
- set_quat(quat);
- // Also slide the geometry towards the camera according to the
- // offset factor.
- if (offset != 0.0f) {
- LVector3f translate = rel_mat.get_row3(3);
- translate.normalize();
- translate *= offset;
- set_pos(translate);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_billboard_axis
- // Access: Published
- // Description: Puts a billboard transition on the node such that it
- // will rotate in two dimensions around the up axis,
- // towards a specified "camera" instead of to the
- // viewing camera.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_billboard_axis(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(RenderEffect) billboard = BillboardEffect::make
- (LVector3f::up(), false, true,
- offset, camera, LPoint3f(0.0f, 0.0f, 0.0f));
- node()->set_effect(billboard);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_billboard_point_eye
- // Access: Published
- // Description: Puts a billboard transition on the node such that it
- // will rotate in three dimensions about the origin,
- // keeping its up vector oriented to the top of the
- // camera, towards a specified "camera" instead of to
- // the viewing camera.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_billboard_point_eye(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(RenderEffect) billboard = BillboardEffect::make
- (LVector3f::up(), true, false,
- offset, camera, LPoint3f(0.0f, 0.0f, 0.0f));
- node()->set_effect(billboard);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_billboard_point_world
- // Access: Published
- // Description: Puts a billboard transition on the node such that it
- // will rotate in three dimensions about the origin,
- // keeping its up vector oriented to the sky, towards a
- // specified "camera" instead of to the viewing camera.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_billboard_point_world(const NodePath &camera, float offset) {
- nassertv_always(!is_empty());
- CPT(RenderEffect) billboard = BillboardEffect::make
- (LVector3f::up(), false, false,
- offset, camera, LPoint3f(0.0f, 0.0f, 0.0f));
- node()->set_effect(billboard);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_billboard
- // Access: Published
- // Description: Removes any billboard effect from the node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_billboard() {
- nassertv_always(!is_empty());
- node()->clear_effect(BillboardEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_billboard
- // Access: Published
- // Description: Returns true if there is any billboard effect on
- // the node.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_billboard() const {
- nassertr_always(!is_empty(), false);
- return node()->has_effect(BillboardEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_compass
- // Access: Published
- // Description: Puts a compass effect on the node, so that it will
- // retain a fixed rotation relative to the reference
- // node (or render if the reference node is empty)
- // regardless of the transforms above it.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_compass(const NodePath &reference) {
- nassertv_always(!is_empty());
- node()->set_effect(CompassEffect::make(reference));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_compass
- // Access: Published
- // Description: Removes any compass effect from the node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_compass() {
- nassertv_always(!is_empty());
- node()->clear_effect(CompassEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_compass
- // Access: Published
- // Description: Returns true if there is any compass effect on
- // the node.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_compass() const {
- nassertr_always(!is_empty(), false);
- return node()->has_effect(CompassEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_transparency
- // Access: Published
- // Description: Specifically sets or disables transparent rendering
- // mode on this particular node. If no other nodes
- // override, this will cause items with a non-1 value
- // for alpha color to be rendered partially transparent.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_transparency(TransparencyAttrib::Mode mode, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(TransparencyAttrib::make(mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_transparency
- // Access: Published
- // Description: Completely removes any transparency adjustment that
- // may have been set on this node via set_transparency().
- // The geometry at this level and below will
- // subsequently be rendered either transparent or not,
- // to whatever other nodes may have had
- // set_transparency() on them.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_transparency() {
- nassertv_always(!is_empty());
- node()->clear_attrib(TransparencyAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_transparency
- // Access: Published
- // Description: Returns true if a transparent-rendering adjustment
- // has been explicitly set on this particular node via
- // set_transparency(). If this returns true, then
- // get_transparency() may be called to determine whether
- // transparency has been explicitly enabled or
- // explicitly disabled for this node.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_transparency() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(TransparencyAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_transparency
- // Access: Published
- // Description: Returns the transparent rendering that has been
- // specifically set on this node via set_transparency(), or
- // M_none if nontransparent rendering has been specifically
- // set, or if nothing has been specifically set. See
- // also has_transparency(). This does not necessarily
- // imply that the geometry will or will not be rendered
- // transparent, as there may be other nodes that override.
- ////////////////////////////////////////////////////////////////////
- TransparencyAttrib::Mode NodePath::
- get_transparency() const {
- nassertr_always(!is_empty(), TransparencyAttrib::M_none);
- const RenderAttrib *attrib =
- node()->get_attrib(TransparencyAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TransparencyAttrib *ta = DCAST(TransparencyAttrib, attrib);
- return ta->get_mode();
- }
- return TransparencyAttrib::M_none;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_antialias
- // Access: Published
- // Description: Specifies the antialiasing type that should be
- // applied at this node and below. See AntialiasAttrib.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_antialias(unsigned short mode, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(AntialiasAttrib::make(mode), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_antialias
- // Access: Published
- // Description: Completely removes any antialias setting that
- // may have been set on this node via set_antialias().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_antialias() {
- nassertv_always(!is_empty());
- node()->clear_attrib(AntialiasAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_antialias
- // Access: Published
- // Description: Returns true if an antialias setting has been
- // explicitly mode on this particular node via
- // set_antialias(). If this returns true, then
- // get_antialias() may be called to determine what the
- // setting was.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_antialias() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(AntialiasAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_antialias
- // Access: Published
- // Description: Returns the antialias setting that has been
- // specifically set on this node via set_antialias(), or
- // M_none if no setting has been made.
- ////////////////////////////////////////////////////////////////////
- unsigned short NodePath::
- get_antialias() const {
- nassertr_always(!is_empty(), AntialiasAttrib::M_none);
- const RenderAttrib *attrib =
- node()->get_attrib(AntialiasAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const AntialiasAttrib *ta = DCAST(AntialiasAttrib, attrib);
- return ta->get_mode();
- }
- return AntialiasAttrib::M_none;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_hidden_ancestor
- // Access: Published
- // Description: Returns the NodePath at or above the referenced node
- // that is hidden to the indicated camera(s), or an
- // empty NodePath if no ancestor of the referenced node
- // is hidden (and the node should be visible).
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_hidden_ancestor(DrawMask camera_mask) const {
- NodePathComponent *comp;
- for (comp = _head;
- comp != (NodePathComponent *)NULL;
- comp = comp->get_next()) {
- PandaNode *node = comp->get_node();
- if ((node->get_draw_mask() & camera_mask).is_zero()) {
- NodePath result;
- result._head = comp;
- return result;
- }
- }
- return not_found();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::stash
- // Access: Published
- // Description: Removes the referenced node (and the entire subgraph
- // below this node) from the scene graph in any normal
- // sense. The node will no longer be visible and is not
- // tested for collisions; furthermore, no normal scene
- // graph traversal will visit the node. The node's
- // bounding volume no longer contributes to its parent's
- // bounding volume.
- //
- // A stashed node cannot be located by a normal find()
- // operation (although a special find string can still
- // retrieve it).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- stash(int sort) {
- nassertv_always(!is_singleton() && !is_empty());
- nassertv(verify_complete());
- bool reparented = PandaNode::reparent(_head->get_next(), _head, sort, true);
- nassertv(reparented);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::unstash
- // Access: Published
- // Description: Undoes the effect of a previous stash() on this
- // node: makes the referenced node (and the entire
- // subgraph below this node) once again part of the
- // scene graph.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- unstash(int sort) {
- nassertv_always(!is_singleton() && !is_empty());
- nassertv(verify_complete());
- bool reparented = PandaNode::reparent(_head->get_next(), _head, sort, false);
- nassertv(reparented);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::unstash_all
- // Access: Published
- // Description: Unstashes this node and all stashed child nodes.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- unstash_all() {
- NodePathCollection stashed_descendents = find_all_matches("**/@@*");
- stashed_descendents.unstash();
- unstash();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_stashed_ancestor
- // Access: Published
- // Description: Returns the NodePath at or above the referenced node
- // that is stashed, or an empty NodePath if no ancestor
- // of the referenced node is stashed (and the node should
- // be visible).
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- get_stashed_ancestor() const {
- NodePathComponent *comp = _head;
- if (comp != (NodePathComponent *)NULL) {
- NodePathComponent *next = comp->get_next();
- while (next != (NodePathComponent *)NULL) {
- PandaNode *node = comp->get_node();
- PandaNode *parent_node = next->get_node();
- if (parent_node->find_stashed(node) >= 0) {
- NodePath result;
- result._head = comp;
- return result;
- }
- comp = next;
- next = next->get_next();
- }
- }
- return not_found();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::verify_complete
- // Access: Published
- // Description: Returns true if all of the nodes described in the
- // NodePath are connected, or false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- verify_complete() const {
- if (is_empty()) {
- return true;
- }
- const NodePathComponent *comp = _head;
- nassertr(comp != (const NodePathComponent *)NULL, false);
- PandaNode *node = comp->get_node();
- nassertr(node != (const PandaNode *)NULL, false);
- int length = comp->get_length();
- comp = comp->get_next();
- length--;
- while (comp != (const NodePathComponent *)NULL) {
- PandaNode *next_node = comp->get_node();
- nassertr(next_node != (const PandaNode *)NULL, false);
- if (node->find_parent(next_node) < 0) {
- pgraph_cat.warning()
- << *this << " is incomplete; " << *node << " is not a child of "
- << *next_node << "\n";
- return false;
- }
- if (comp->get_length() != length) {
- pgraph_cat.warning()
- << *this << " is incomplete; length at " << *next_node
- << " indicates " << comp->get_length() << " while length at "
- << *node << " indicates " << length << "\n";
- return false;
- }
- node = next_node;
- comp = comp->get_next();
- length--;
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::prepare_scene
- // Access: Published
- // Description: Walks through the scene graph beginning at the bottom
- // node, and does whatever initialization is required to
- // render the scene properly with the indicated GSG. It
- // is not strictly necessary to call this, since the GSG
- // will initialize itself when the scene is rendered,
- // but this may take some of the overhead away from that
- // process.
- //
- // In particular, this will ensure that textures within
- // the scene are loaded in texture memory, and display
- // lists are built up from static geometry.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- prepare_scene(GraphicsStateGuardianBase *gsg) {
- nassertv_always(!is_empty());
- PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
- CPT(RenderState) net_state = get_net_state();
- r_prepare_scene(node(), net_state, prepared_objects);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::show_bounds
- // Access: Published
- // Description: Causes the bounding volume of the bottom node and all
- // of its descendants (that is, the bounding volume
- // associated with the the bottom arc) to be rendered,
- // if possible. The rendering method is less than
- // optimal; this is intended primarily for debugging.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- show_bounds() {
- nassertv_always(!is_empty());
- node()->set_effect(ShowBoundsEffect::make(false));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::show_tight_bounds
- // Access: Published
- // Description: Similar to show_bounds(), this draws a bounding box
- // representing the "tight" bounds of this node and all
- // of its descendants. The bounding box is recomputed
- // every frame by reexamining all of the vertices; this
- // is far from efficient, but this is intended for
- // debugging.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- show_tight_bounds() {
- nassertv_always(!is_empty());
- node()->set_effect(ShowBoundsEffect::make(true));
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::hide_bounds
- // Access: Published
- // Description: Stops the rendering of the bounding volume begun with
- // show_bounds().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- hide_bounds() {
- nassertv_always(!is_empty());
- node()->clear_effect(ShowBoundsEffect::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_bounds
- // Access: Published
- // Description: Returns a newly-allocated bounding volume containing
- // the bottom node and all of its descendants. This is
- // the bounding volume on the bottom arc, converted to
- // the local coordinate space of the node.
- ////////////////////////////////////////////////////////////////////
- PT(BoundingVolume) NodePath::
- get_bounds() const {
- nassertr_always(!is_empty(), new BoundingSphere);
- return node()->get_bound().make_copy();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::force_recompute_bounds
- // Access: Published
- // Description: Forces the recomputing of all the bounding volumes at
- // every node in the subgraph beginning at this node and
- // below.
- //
- // This should not normally need to be called, since the
- // bounding volumes are supposed to be recomputed
- // automatically when necessary. It may be useful when
- // debugging, to verify that the bounding volumes have
- // not become inadvertently stale; it may also be useful
- // to force animated characters to update their bounding
- // volumes (which does not presently happen
- // automatically).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- force_recompute_bounds() {
- nassertv_always(!is_empty());
- r_force_recompute_bounds(node());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::write_bounds
- // Access: Published
- // Description: Writes a description of the bounding volume
- // containing the bottom node and all of its descendants
- // to the indicated output stream.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- write_bounds(ostream &out) const {
- get_bounds()->write(out);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::calc_tight_bounds
- // Access: Published
- // Description: Calculates the minimum and maximum vertices of all
- // Geoms at this NodePath's bottom node and below. This
- // is a tight bounding box; it will generally be tighter
- // than the bounding volume returned by get_bounds()
- // (but it is more expensive to compute).
- //
- // The return value is true if any points are within the
- // bounding volume, or false if none are.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point) {
- min_point.set(0.0f, 0.0f, 0.0f);
- max_point.set(0.0f, 0.0f, 0.0f);
- nassertr_always(!is_empty(), false);
- bool found_any = false;
- node()->calc_tight_bounds(min_point, max_point, found_any,
- TransformState::make_identity());
- return found_any;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::analyze
- // Access: Published
- // Description: Analyzes the geometry below this node and reports the
- // number of vertices, triangles, etc. This is the same
- // information reported by the bam-info program.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- analyze() const {
- nassertv_always(!is_empty());
- SceneGraphAnalyzer sga;
- sga.add_node(node());
- sga.write(nout);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::flatten_light
- // Access: Published
- // Description: Lightly flattens out the hierarchy below this node by
- // applying transforms, colors, and texture matrices
- // from the arcs onto the vertices, but does not remove
- // any nodes.
- //
- // This can result in improved rendering performance
- // because there will be fewer transforms in the
- // resulting scene graph, but the number of nodes will
- // remain the same.
- //
- // Particularly, any NodePaths that reference nodes
- // within this hierarchy will not be damaged. However,
- // since this operation will remove transforms from the
- // scene graph, it may be dangerous to apply to arcs
- // where you expect to dynamically modify the transform,
- // or where you expect the geometry to remain in a
- // particular local coordinate system.
- //
- // The return value is always 0, since flatten_light
- // does not remove any arcs.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- flatten_light() {
- nassertr_always(!is_empty(), 0);
- SceneGraphReducer gr;
- gr.apply_attribs(node());
- return 0;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::flatten_medium
- // Access: Published
- // Description: A more thorough flattening than flatten_light(), this
- // first applies all the transforms, colors, and texture
- // matrices from the arcs onto the vertices, and then
- // removes unneeded grouping nodes--nodes that have
- // exactly one child, for instance, but have no special
- // properties in themselves.
- //
- // This results in improved perforamance over
- // flatten_light() because the number of nodes in the
- // scene graph is reduced.
- //
- // If max_children is specified, it represents the
- // maximum number of children a node is allowed to have
- // and still be flattened. Normally, this is 1; we
- // don't typically want to flatten a node that has
- // multiple children. However, sometimes this may be
- // desirable; set this parameter to control the limit.
- // If this is set to -1, there is no limit.
- //
- // The return value is the number of arcs removed.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- flatten_medium() {
- nassertr_always(!is_empty(), 0);
- SceneGraphReducer gr;
- gr.apply_attribs(node());
- int num_removed = gr.flatten(node(), 0);
- return num_removed;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::flatten_strong
- // Access: Published
- // Description: The strongest possible flattening. This first
- // applies all of the transforms to the vertices, as in
- // flatten_medium(), but then it will combine sibling
- // nodes together when possible, in addition to removing
- // unnecessary parent-child nodes. This can result in
- // substantially fewer nodes, but any nicely-grouped
- // hierachical bounding volumes may be lost.
- //
- // It is generally a good idea to apply this kind of
- // flattening only to nodes that will be culled largely
- // as a single unit, like a car. Applying this to an
- // entire scene may result in overall poorer performance
- // because of less-effective culling.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- flatten_strong() {
- nassertr_always(!is_empty(), 0);
- SceneGraphReducer gr;
- gr.apply_attribs(node());
- int num_removed = gr.flatten(node(), ~0);
- return num_removed;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_net_tag
- // Access: Published
- // Description: Returns the lowest ancestor of this node that
- // contains a tag definition with the indicated key, if
- // any, or an empty NodePath if no ancestor of this node
- // contains this tag definition. See set_tag().
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- find_net_tag(const string &key) const {
- if (is_empty()) {
- return NodePath::not_found();
- }
- if (has_tag(key)) {
- return *this;
- }
- return get_parent().find_net_tag(key);
- }
- #ifdef HAVE_PYTHON
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_net_python_tag
- // Access: Published
- // Description: Returns the lowest ancestor of this node that
- // contains a tag definition with the indicated key, if
- // any, or an empty NodePath if no ancestor of this node
- // contains this tag definition. See set_python_tag().
- ////////////////////////////////////////////////////////////////////
- NodePath NodePath::
- find_net_python_tag(const string &key) const {
- if (is_empty()) {
- return NodePath::not_found();
- }
- if (has_python_tag(key)) {
- return *this;
- }
- return get_parent().find_net_python_tag(key);
- }
- #endif // HAVE_PYTHON
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::write_bam_file
- // Access: Published
- // Description: Writes the contents of this node and below out to a
- // bam file with the indicated filename. This file may
- // then be read in again, as is, at some later point.
- // Returns true if successful, false on some kind of
- // error.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- write_bam_file(const string &filename) const {
- nassertr_always(!is_empty(), false);
- BamFile bam_file;
- bool okflag = false;
- if (bam_file.open_write(filename)) {
- if (bam_file.write_object(node())) {
- okflag = true;
- }
- bam_file.close();
- }
- return okflag;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_common_ancestor
- // Access: Private, Static
- // Description: Walks up from both NodePaths to find the first node
- // that both have in common, if any. Fills a_count and
- // b_count with the number of nodes below the common
- // node in each path.
- //
- // The return value is the NodePathComponent of the node
- // they have in common, or NULL if they have nothing in
- // common.
- ////////////////////////////////////////////////////////////////////
- NodePathComponent *NodePath::
- find_common_ancestor(const NodePath &a, const NodePath &b,
- int &a_count, int &b_count) {
- nassertr(!a.is_empty() && !b.is_empty(), NULL);
- NodePathComponent *ac = a._head;
- NodePathComponent *bc = b._head;
- a_count = 0;
- b_count = 0;
- // Shorten up the longer one until they are the same length.
- while (ac->get_length() > bc->get_length()) {
- nassertr(ac != (NodePathComponent *)NULL, NULL);
- ac = ac->get_next();
- a_count++;
- }
- while (bc->get_length() > ac->get_length()) {
- nassertr(bc != (NodePathComponent *)NULL, NULL);
- bc = bc->get_next();
- b_count++;
- }
- // Now shorten them both up until we reach the same component.
- while (ac != bc) {
- // These shouldn't go to NULL unless they both go there together.
- nassertr(ac != (NodePathComponent *)NULL, NULL);
- nassertr(bc != (NodePathComponent *)NULL, NULL);
- ac = ac->get_next();
- a_count++;
- bc = bc->get_next();
- b_count++;
- }
- return ac;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_net_state
- // Access: Private
- // Description: Recursively determines the net state changes to the
- // indicated component node from the root of the graph.
- ////////////////////////////////////////////////////////////////////
- CPT(RenderState) NodePath::
- r_get_net_state(NodePathComponent *comp) const {
- if (comp == (NodePathComponent *)NULL) {
- return RenderState::make_empty();
- } else {
- CPT(RenderState) state = comp->get_node()->get_state();
- return r_get_net_state(comp->get_next())->compose(state);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_partial_state
- // Access: Private
- // Description: Recursively determines the net state changes to the
- // indicated component node from the nth node above it.
- // If n exceeds the length of the path, this returns the
- // net transform from the root of the graph.
- ////////////////////////////////////////////////////////////////////
- CPT(RenderState) NodePath::
- r_get_partial_state(NodePathComponent *comp, int n) const {
- if (n == 0 || comp == (NodePathComponent *)NULL) {
- return RenderState::make_empty();
- } else {
- CPT(RenderState) state = comp->get_node()->get_state();
- return r_get_partial_state(comp->get_next(), n - 1)->compose(state);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_net_transform
- // Access: Private
- // Description: Recursively determines the net transform to the
- // indicated component node from the root of the graph.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- r_get_net_transform(NodePathComponent *comp) const {
- if (comp == (NodePathComponent *)NULL) {
- return TransformState::make_identity();
- } else {
- CPT(TransformState) net_transform = r_get_net_transform(comp->get_next());
- CPT(TransformState) transform = comp->get_node()->get_transform();
- CPT(RenderEffects) effects = comp->get_node()->get_effects();
- if (effects->has_adjust_transform()) {
- effects->adjust_transform(net_transform, transform);
- }
-
- return net_transform->compose(transform);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_partial_transform
- // Access: Private
- // Description: Recursively determines the net transform to the
- // indicated component node from the nth node above it.
- // If n exceeds the length of the path, this returns the
- // net transform from the root of the graph.
- //
- // If any node in the path had a net_transform effect
- // applied, returns NULL--in this case the partial
- // transform cannot be easily determined.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- r_get_partial_transform(NodePathComponent *comp, int n) const {
- if (n == 0 || comp == (NodePathComponent *)NULL) {
- return TransformState::make_identity();
- } else {
- if (comp->get_node()->get_effects()->has_adjust_transform()) {
- return NULL;
- }
- CPT(TransformState) transform = comp->get_node()->get_transform();
- CPT(TransformState) partial = r_get_partial_transform(comp->get_next(), n - 1);
- if (partial == (const TransformState *)NULL) {
- return NULL;
- }
- return partial->compose(transform);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_net_prev_transform
- // Access: Private
- // Description: Recursively determines the net "previous" transform
- // to the indicated component node from the root of the
- // graph.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- r_get_net_prev_transform(NodePathComponent *comp) const {
- if (comp == (NodePathComponent *)NULL) {
- return TransformState::make_identity();
- } else {
- CPT(TransformState) transform = comp->get_node()->get_prev_transform();
- return r_get_net_prev_transform(comp->get_next())->compose(transform);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_get_partial_prev_transform
- // Access: Private
- // Description: Recursively determines the net "previous" transform
- // to the indicated component node from the nth node
- // above it. If n exceeds the length of the path, this
- // returns the net previous transform from the root of
- // the graph.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- r_get_partial_prev_transform(NodePathComponent *comp, int n) const {
- if (n == 0 || comp == (NodePathComponent *)NULL) {
- return TransformState::make_identity();
- } else {
- CPT(TransformState) transform = comp->get_node()->get_prev_transform();
- return r_get_partial_prev_transform(comp->get_next(), n - 1)->compose(transform);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_matches
- // Access: Private
- // Description: Finds up to max_matches matches against the given
- // path string from this node and deeper. The
- // max_matches count indicates the maximum number of
- // matches to return, or -1 not to limit the number
- // returned.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- find_matches(NodePathCollection &result, const string &path,
- int max_matches) const {
- if (is_empty()) {
- pgraph_cat.warning()
- << "Attempt to extend an empty NodePath by '" << path
- << "'.\n";
- return;
- }
- FindApproxPath approx_path;
- if (approx_path.add_string(path)) {
- find_matches(result, approx_path, max_matches);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_matches
- // Access: Private
- // Description: Finds up to max_matches matches against the given
- // approx_path from this node and deeper. The
- // max_matches count indicates the maximum number of
- // matches to return, or -1 not to limit the number
- // returned.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- find_matches(NodePathCollection &result, FindApproxPath &approx_path,
- int max_matches) const {
- if (is_empty()) {
- pgraph_cat.warning()
- << "Attempt to extend an empty NodePath by: " << approx_path << ".\n";
- return;
- }
- // We start with just one entry on the level.
- FindApproxLevelEntry *level =
- new FindApproxLevelEntry(WorkingNodePath(*this), approx_path);
- nassertv(level->_node_path.is_valid());
- find_matches(result, level, max_matches);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::find_matches
- // Access: Private
- // Description: The fundamental implementation of find_matches(),
- // given a starting level (a linked list of
- // FindApproxLevelEntry objects).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- find_matches(NodePathCollection &result, FindApproxLevelEntry *level,
- int max_matches) const {
-
- int num_levels_remaining = _max_search_depth;
- FindApproxLevelEntry *deleted_entries = NULL;
- while (num_levels_remaining > 0 && level != NULL) {
- if (pgraph_cat.is_spam()) {
- pgraph_cat.spam()
- << "find_matches pass: " << result << ", "
- << max_matches << ", " << num_levels_remaining << "\n";
- level->write_level(pgraph_cat.spam(false), 4);
- }
- num_levels_remaining--;
- FindApproxLevelEntry *next_level = NULL;
- // For each node in the current level, build up the set of possible
- // matches in the next level.
- FindApproxLevelEntry *entry = level;
- while (entry != (FindApproxLevelEntry *)NULL) {
- if (entry->consider_node(result, next_level, max_matches, 0)) {
- // If we found the requisite number of matches, we can stop.
- // Delete all remaining entries and return immediately.
- while (entry != (FindApproxLevelEntry *)NULL) {
- FindApproxLevelEntry *next = entry->_next;
- delete entry;
- entry = next;
- }
- while (next_level != (FindApproxLevelEntry *)NULL) {
- FindApproxLevelEntry *next = next_level->_next;
- delete next_level;
- next_level = next;
- }
- while (deleted_entries != (FindApproxLevelEntry *)NULL) {
- FindApproxLevelEntry *next = deleted_entries->_next;
- delete deleted_entries;
- deleted_entries = next;
- }
- return;
- }
- // Move the entry to the delete chain so we can delete it before
- // we return from this method. (We can't delete it immediately,
- // because there might be WorkingNodePaths in the next_level
- // that reference the WorkingNodePath object within the entry.)
- FindApproxLevelEntry *next = entry->_next;
- entry->_next = deleted_entries;
- deleted_entries = entry;
- entry = next;
- }
-
- // Make sure the remaining entries from this level are added to
- // the delete chain.
- while (entry != (FindApproxLevelEntry *)NULL) {
- FindApproxLevelEntry *next = entry->_next;
- entry->_next = deleted_entries;
- deleted_entries = entry;
- entry = next;
- }
- level = next_level;
- }
- // Now it's safe to delete all entries on the delete chain.
- while (deleted_entries != (FindApproxLevelEntry *)NULL) {
- FindApproxLevelEntry *next = deleted_entries->_next;
- delete deleted_entries;
- deleted_entries = next;
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_adjust_all_priorities
- // Access: Private
- // Description: The recursive implementation of
- // adjust_all_priorities(). This walks through the
- // subgraph defined by the indicated node and below.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_adjust_all_priorities(PandaNode *node, int adjustment) {
- node->set_state(node->get_state()->adjust_all_priorities(adjustment));
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- gnode->set_geom_state(i, gnode->get_geom_state(i)->adjust_all_priorities(adjustment));
- }
- }
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- r_adjust_all_priorities(cr.get_child(i), adjustment);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_force_recompute_bounds
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_force_recompute_bounds(PandaNode *node) {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- const Geom *geom = gnode->get_geom(i);
- // It's ok to cast away the const modifier on this Geom pointer,
- // since marking the bounding volume stale doesn't really change
- // the Geom in any substantial way.
- ((Geom *)geom)->mark_bound_stale();
- }
- }
- node->mark_bound_stale();
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- r_force_recompute_bounds(cr.get_child(i));
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_set_collide_mask
- // Access: Private
- // Description: Recursively applies the indicated collide mask to the
- // nodes at and below this node.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_set_collide_mask(PandaNode *node,
- CollideMask and_mask, CollideMask or_mask,
- TypeHandle node_type) {
- if (node->is_of_type(node_type)) {
- CollideMask into_collide_mask = node->get_into_collide_mask();
- into_collide_mask = (into_collide_mask & and_mask) | or_mask;
- node->set_into_collide_mask(into_collide_mask);
- }
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- r_set_collide_mask(cr.get_child(i), and_mask, or_mask, node_type);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_texture
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- Texture * NodePath::
- r_find_texture(PandaNode *node, const RenderState *state,
- const GlobPattern &glob) const {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_R(gnode, node, NULL);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state =
- state->compose(gnode->get_geom_state(i));
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- for (int i = 0; i < ta->get_num_on_stages(); i++) {
- Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
- if (texture != (Texture *)NULL) {
- if (glob.matches(texture->get_name())) {
- return texture;
- }
- }
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- CPT(RenderState) next_state = state->compose(child->get_state());
- Texture *result = r_find_texture(child, next_state, glob);
- if (result != (Texture *)NULL) {
- return result;
- }
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_all_textures
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_find_all_textures(PandaNode *node, const RenderState *state,
- NodePath::Textures &textures) const {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state =
- state->compose(gnode->get_geom_state(i));
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- for (int i = 0; i < ta->get_num_on_stages(); i++) {
- Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
- if (texture != (Texture *)NULL) {
- textures.insert(texture);
- }
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- CPT(RenderState) next_state = state->compose(child->get_state());
- r_find_all_textures(child, next_state, textures);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_texture
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- Texture * NodePath::
- r_find_texture(PandaNode *node, TextureStage *stage) const {
- // Look for a TextureAttrib on the node.
- const RenderAttrib *attrib =
- node->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- if (ta->has_on_stage(stage)) {
- return ta->get_on_texture(stage);
- }
- }
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_R(gnode, node, NULL);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state = gnode->get_geom_state(i);
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- if (ta->has_on_stage(stage)) {
- return ta->get_on_texture(stage);
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- Texture *result = r_find_texture(child, stage);
- if (result != (Texture *)NULL) {
- return result;
- }
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_all_textures
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_find_all_textures(PandaNode *node, TextureStage *stage,
- NodePath::Textures &textures) const {
- // Look for a TextureAttrib on the node.
- const RenderAttrib *attrib =
- node->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- if (ta->has_on_stage(stage)) {
- textures.insert(ta->get_on_texture(stage));
- }
- }
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state = gnode->get_geom_state(i);
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- if (ta->has_on_stage(stage)) {
- textures.insert(ta->get_on_texture(stage));
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- r_find_all_textures(child, stage, textures);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_texture_stage
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- TextureStage * NodePath::
- r_find_texture_stage(PandaNode *node, const RenderState *state,
- const GlobPattern &glob) const {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_R(gnode, node, NULL);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state =
- state->compose(gnode->get_geom_state(i));
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- for (int i = 0; i < ta->get_num_on_stages(); i++) {
- TextureStage *texture_stage = ta->get_on_stage(i);
- if (texture_stage != (TextureStage *)NULL) {
- if (glob.matches(texture_stage->get_name())) {
- return texture_stage;
- }
- }
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- CPT(RenderState) next_state = state->compose(child->get_state());
- TextureStage *result = r_find_texture_stage(child, next_state, glob);
- if (result != (TextureStage *)NULL) {
- return result;
- }
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_all_texture_stages
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_find_all_texture_stages(PandaNode *node, const RenderState *state,
- NodePath::TextureStages &texture_stages) const {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state =
- state->compose(gnode->get_geom_state(i));
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- for (int i = 0; i < ta->get_num_on_stages(); i++) {
- TextureStage *texture_stage = ta->get_on_stage(i);
- if (texture_stage != (TextureStage *)NULL) {
- texture_stages.insert(texture_stage);
- }
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- CPT(RenderState) next_state = state->compose(child->get_state());
- r_find_all_texture_stages(child, next_state, texture_stages);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_unify_texture_stages
- // Access: Private
- // Description:
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_unify_texture_stages(PandaNode *node, TextureStage *stage) {
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- node->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- CPT(RenderAttrib) new_attrib = ta->unify_texture_stages(stage);
- if (new_attrib != ta) {
- node->set_attrib(new_attrib);
- }
- }
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) state = gnode->get_geom_state(i);
- // Look for a TextureAttrib on the state.
- const RenderAttrib *attrib =
- state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- CPT(RenderAttrib) new_attrib = ta->unify_texture_stages(stage);
- if (new_attrib != ta) {
- CPT(RenderState) new_state = state->add_attrib(new_attrib);
- gnode->set_geom_state(i, new_state);
- }
- }
- }
- }
- // Now consider children.
- PandaNode::Children cr = node->get_children();
- int num_children = cr.get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = cr.get_child(i);
- r_unify_texture_stages(child, stage);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_prepare_scene
- // Access: Private
- // Description: The recursive implementation of prepare_scene.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_prepare_scene(PandaNode *node, const RenderState *state,
- PreparedGraphicsObjects *prepared_objects) {
- if (node->is_geom_node()) {
- GeomNode *gnode;
- DCAST_INTO_V(gnode, node);
- /*
- Not implemented yet in pgraph. Maybe we don't need this anyway.
- if (retained_mode) {
- gnode->prepare(gsg);
- }
- */
- int num_geoms = gnode->get_num_geoms();
- for (int i = 0; i < num_geoms; i++) {
- CPT(RenderState) geom_state = state->compose(gnode->get_geom_state(i));
- const RenderAttrib *attrib =
- geom_state->get_attrib(TextureAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta;
- DCAST_INTO_V(ta, attrib);
- Texture *texture = ta->get_texture();
- if (texture != (Texture *)NULL) {
- texture->prepare(prepared_objects);
- }
- }
- }
- }
- int num_children = node->get_num_children();
- for (int i = 0; i < num_children; i++) {
- PandaNode *child = node->get_child(i);
- CPT(RenderState) child_state = state->compose(child->get_state());
- r_prepare_scene(child, child_state, prepared_objects);
- }
- }
|