| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932 |
- // Filename: nodePath.cxx
- // Created by: drose (25Feb02)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) 2001, 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://www.panda3d.org/license.txt .
- //
- // To contact the maintainers of this program write to
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "nodePath.h"
- #include "nodePathCollection.h"
- #include "findApproxPath.h"
- #include "findApproxLevelEntry.h"
- #include "findApproxLevel.h"
- #include "config_pgraph.h"
- #include "colorAttrib.h"
- #include "colorScaleAttrib.h"
- #include "cullBinAttrib.h"
- #include "textureAttrib.h"
- #include "materialAttrib.h"
- #include "fogAttrib.h"
- #include "renderModeAttrib.h"
- #include "cullFaceAttrib.h"
- #include "alphaTestAttrib.h"
- #include "depthTestAttrib.h"
- #include "depthWriteAttrib.h"
- #include "billboardEffect.h"
- #include "compassEffect.h"
- #include "showBoundsEffect.h"
- #include "transparencyAttrib.h"
- #include "materialPool.h"
- #include "look_at.h"
- #include "plist.h"
- #include "boundingSphere.h"
- #include "geomNode.h"
- #include "sceneGraphReducer.h"
- #include "textureCollection.h"
- #include "globPattern.h"
- #include "config_gobj.h"
- #include "bamFile.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.
- ////////////////////////////////////////////////////////////////////
- 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_node
- // Access: Published
- // Description: Returns the top node of the path, or NULL if the path
- // is empty. This requires iterating through the path.
- ////////////////////////////////////////////////////////////////////
- PandaNode *NodePath::
- get_top_node() const {
- if (is_empty()) {
- return (PandaNode *)NULL;
- }
- NodePathComponent *comp = _head;
- while (!comp->is_top_node()) {
- comp = comp->get_next();
- nassertr(comp != (NodePathComponent *)NULL, NULL);
- }
- return comp->get_node();
- }
- ////////////////////////////////////////////////////////////////////
- // 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.
- ////////////////////////////////////////////////////////////////////
- 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.
- ////////////////////////////////////////////////////////////////////
- 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. If there are no other
- // instances to the node, this becomes a singleton
- // NodePath; otherwise, this NodePath becomes the same
- // as another arbitrary instance.
- //
- // 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 from the render state of this node to 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 (is_empty()) {
- return other.get_net_state();
- }
- if (other.is_empty()) {
- return 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 a_state->invert_compose(b_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 has the indicated value when seen relative to
- // 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.
- NodePath parent = get_parent();
- CPT(RenderState) rel_state = parent.get_state(other);
- 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) {
- 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 = r_get_partial_transform(_head, a_count);
- CPT(TransformState) b_transform = r_get_partial_transform(other._head, b_count);
- 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_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_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::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_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_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.
- ////////////////////////////////////////////////////////////////////
- const LMatrix4f &NodePath::
- get_mat(const NodePath &other) const {
- CPT(TransformState) transform = get_transform(other);
- // We can safely assume the transform won't go away when the
- // function returns, since its reference count is also held in the
- // cache. This assumption allows us to return a reference to the
- // matrix, instead of having to return a matrix on the stack.
- nassertr(transform->get_ref_count() > 1, LMatrix4f::ident_mat());
- 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) {
- LPoint3f rel_point = LPoint3f(point) * other.get_mat(*this);
- 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) {
- LVector3f rel_vector = LVector3f(vec) * other.get_mat(*this);
- 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());
- NodePath parent = get_parent();
- LPoint3f rel_point = point * other.get_mat(parent);
- 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());
- NodePath parent = get_parent();
- LPoint3f rel_point = point * other.get_mat(parent);
- 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());
- node()->set_attrib(ColorScaleAttrib::make(scale), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_alpha_scale
- // Access: Published
- // Description: Sets the alpha scale component of the transform
- // without 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) {
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- const LVecBase4f &sc = csa->get_scale();
- set_color_scale(sc[0], sc[1], sc[2], scale, priority);
- } else {
- set_color_scale(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 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) {
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
- const LVecBase4f &sc = csa->get_scale();
- set_color_scale(scale, scale, scale, sc[3], priority);
- } else {
- set_color_scale(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 the bottom node, or all 1's (identity) if
- // no scale has been applied.
- ////////////////////////////////////////////////////////////////////
- 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_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: Sets the geometry at this level and below to render
- // using the indicated texture.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture(Texture *tex, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(TextureAttrib::make(tex), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_texture_off
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using no texture. This is normally the default, but
- // it may be useful to use this to contradict
- // set_texture() at a higher node level (or, with a
- // priority, to override a set_texture() at a lower
- // level).
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_texture_off(int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(TextureAttrib::make_off(), 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::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 {
- 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->is_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_texture_off
- // Access: Published
- // Description: Returns true if a texture 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(ColorAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const TextureAttrib *ta = DCAST(TextureAttrib, attrib);
- return ta->is_off();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_texture
- // Access: Published
- // Description: Returns the 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::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_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::set_material
- // Access: Published
- // Description: Sets the geometry at this level and below to render
- // using the indicated material.
- //
- // This operation copies the given material pointer. If
- // the material structure is changed later, it must be
- // reapplied via another call to set_material().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- set_material(Material *mat, int priority) {
- nassertv_always(!is_empty());
- nassertv(mat != NULL);
- // We create a temporary Material pointer, a copy of the one we are
- // given, to allow the user to monkey with the material and set it
- // again later, with the desired effect. If we stored the user's
- // pointer directly, it would be bad if the user later modified the
- // values within the Material.
- PT(Material) temp = new Material(*mat);
- const Material *mp = MaterialPool::get_material(temp);
- node()->set_attrib(MaterialAttrib::make(mp), 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::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_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::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;
- }
- #if 0
- // programmers prolly wont need alpha-test control
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::set_alpha_test
- // Access: Published
- // Description: Specifically sets or disables the testing of the
- // alpha 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_alpha_test(RenderAttrib::PandaCompareFunc alpha_test_mode,float reference_alpha, int priority) {
- nassertv_always(!is_empty());
- node()->set_attrib(AlphaTestAttrib::make(alpha_test_mode,reference_alpha), priority);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::clear_alpha_test
- // Access: Published
- // Description: Completely removes any alpha-test adjustment that
- // may have been set on this node via set_alpha_test().
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- clear_alpha_test() {
- nassertv_always(!is_empty());
- node()->clear_attrib(AlphaTestAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::has_alpha_test
- // Access: Published
- // Description: Returns true if a alpha-test adjustment has been
- // explicitly set on this particular node via
- // set_alpha_test(). If this returns true, then
- // get_alpha_test() may be called to determine which has
- // been set.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- has_alpha_test() const {
- nassertr_always(!is_empty(), false);
- return node()->has_attrib(AlphaTestAttrib::get_class_type());
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::get_alpha_test
- // Access: Published
- // Description: Returns true if alpha-test rendering has been
- // specifically set on this node via set_alpha_test(), or
- // false if alpha-test rendering has been specifically
- // disabled, or if nothing has been specifically set. See
- // also has_alpha_test().
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- get_alpha_test() const {
- nassertr_always(!is_empty(), false);
- const RenderAttrib *attrib =
- node()->get_attrib(AlphaTestAttrib::get_class_type());
- if (attrib != (const RenderAttrib *)NULL) {
- const AlphaTestAttrib *dta = DCAST(AlphaTestAttrib, attrib);
- return (dta->get_mode() != AlphaTestAttrib::M_none);
- }
- return false;
- }
- #endif
- ////////////////////////////////////////////////////////////////////
- // 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());
- NodePath parent = get_parent();
- LMatrix4f rel_mat = camera.get_mat(parent);
- 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());
- NodePath parent = get_parent();
- LMatrix4f rel_mat = camera.get_mat(parent);
- 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());
- NodePath parent = get_parent();
- LMatrix4f rel_mat = camera.get_mat(parent);
- 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(bool transparency, int priority) {
- nassertv_always(!is_empty());
- TransparencyAttrib::Mode mode =
- transparency ?
- TransparencyAttrib::M_alpha :
- TransparencyAttrib::M_none;
- 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 true if transparent rendering has been
- // specifically set on this node via set_transparency(), or
- // false 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.
- ////////////////////////////////////////////////////////////////////
- bool NodePath::
- get_transparency() const {
- nassertr_always(!is_empty(), false);
- 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() != TransparencyAttrib::M_none);
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // 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::compare_to
- // Access: Published
- // Description: Returns a number less than zero if this NodePath
- // sorts before the other one, greater than zero if it
- // sorts after, or zero if they are equivalent.
- //
- // Two NodePaths are considered equivalent if they
- // consist of exactly the same list of nodes in the same
- // order. Otherwise, they are different; different
- // NodePaths will be ranked in a consistent but
- // undefined ordering; the ordering is useful only for
- // placing the NodePaths in a sorted container like an
- // STL set.
- ////////////////////////////////////////////////////////////////////
- int NodePath::
- compare_to(const NodePath &other) const {
- // Nowadays, the NodePathComponents at the head are pointerwise
- // equivalent if and only if the NodePaths are equivalent. So we
- // only have to compare pointers.
- if (_head != other._head) {
- return _head < other._head ? -1 : 1;
- }
- return 0;
- }
- ////////////////////////////////////////////////////////////////////
- // 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.
- //
- // If force_retained_mode is true, retained mode is set
- // on the geometry encountered, regardless of the
- // setting of the retained-mode Config variable.
- // Otherwise, retained mode is set only if the
- // retained-mode Config variable is true.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- prepare_scene(GraphicsStateGuardianBase *gsg, bool force_retained_mode) {
- nassertv_always(!is_empty());
- CPT(RenderState) net_state = get_net_state();
- r_prepare_scene(node(), net_state, gsg,
- retained_mode || force_retained_mode);
- }
- ////////////////////////////////////////////////////////////////////
- // 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());
- }
- ////////////////////////////////////////////////////////////////////
- // 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::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(), false);
- 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(), true);
- 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);
- }
- ////////////////////////////////////////////////////////////////////
- // 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) transform = comp->get_node()->get_transform();
- return r_get_net_transform(comp->get_next())->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.
- ////////////////////////////////////////////////////////////////////
- CPT(TransformState) NodePath::
- r_get_partial_transform(NodePathComponent *comp, int n) const {
- if (n == 0 || comp == (NodePathComponent *)NULL) {
- return TransformState::make_identity();
- } else {
- CPT(TransformState) transform = comp->get_node()->get_transform();
- return r_get_partial_transform(comp->get_next(), n - 1)->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;
- }
- FindApproxLevelEntry start(WorkingNodePath(*this), approx_path);
- nassertv(start._node_path.is_valid());
- FindApproxLevel level;
- level.add_entry(start);
- r_find_matches(result, level, max_matches, _max_search_depth);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: NodePath::r_find_matches
- // Access: Private
- // Description: The recursive implementation of find_matches.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_find_matches(NodePathCollection &result,
- const FindApproxLevel &level,
- int max_matches, int num_levels_remaining) const {
- // Go on to the next level. If we exceeded the requested maximum
- // depth, stop.
- if (num_levels_remaining <= 0) {
- return;
- }
- num_levels_remaining--;
- FindApproxLevel next_level;
- bool okflag = true;
- // For each node in the current level, build up the set of possible
- // matches in the next level.
- FindApproxLevel::Vec::const_iterator li;
- for (li = level._v.begin(); li != level._v.end() && okflag; ++li) {
- const FindApproxLevelEntry &entry = (*li);
- if (entry.is_solution(0)) {
- // Does this entry already represent a solution?
- result.add_path(entry._node_path.get_node_path());
- } else {
- entry.consider_node(result, next_level, max_matches, 0);
- }
- if (max_matches > 0 && result.get_num_paths() >= max_matches) {
- // Really, we just want to return here. But returning from
- // within the conditional within the for loop seems to sometimes
- // cause a compiler fault in GCC. We'll use a semaphore
- // variable instead.
- okflag = false;
- }
- }
- // Now recurse on the next level.
- if (okflag) {
- r_find_matches(result, next_level, max_matches, num_levels_remaining);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // 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++) {
- gnode->get_geom(i)->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_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);
- Texture *texture = ta->get_texture();
- 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);
- Texture *texture = ta->get_texture();
- 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_prepare_scene
- // Access: Private
- // Description: The recursive implementation of prepare_scene.
- ////////////////////////////////////////////////////////////////////
- void NodePath::
- r_prepare_scene(PandaNode *node, const RenderState *state,
- GraphicsStateGuardianBase *gsg, bool do_retained_mode) {
- 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 (do_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(gsg);
- }
- }
- }
- }
- 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, gsg, do_retained_mode);
- }
- }
|