Panda3D
|
00001 // Filename: pandaNode.h 00002 // Created by: drose (20Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef PANDANODE_H 00016 #define PANDANODE_H 00017 00018 #include "pandabase.h" 00019 00020 #include "cycleData.h" 00021 #include "cycleDataReader.h" 00022 #include "cycleDataWriter.h" 00023 #include "cycleDataLockedStageReader.h" 00024 #include "cycleDataStageReader.h" 00025 #include "cycleDataStageWriter.h" 00026 #include "pipelineCycler.h" 00027 #include "renderState.h" 00028 #include "renderEffects.h" 00029 #include "transformState.h" 00030 #include "drawMask.h" 00031 #include "typedWritable.h" 00032 #include "collideMask.h" 00033 #include "namable.h" 00034 #include "referenceCount.h" 00035 #include "luse.h" 00036 #include "ordered_vector.h" 00037 #include "pointerTo.h" 00038 #include "nodePointerTo.h" 00039 #include "pointerToArray.h" 00040 #include "pnotify.h" 00041 #include "updateSeq.h" 00042 #include "deletedChain.h" 00043 #include "pandaNodeChain.h" 00044 #include "pStatCollector.h" 00045 #include "copyOnWriteObject.h" 00046 #include "copyOnWritePointer.h" 00047 #include "lightReMutex.h" 00048 00049 #ifdef HAVE_PYTHON 00050 00051 #undef _POSIX_C_SOURCE 00052 #include <Python.h> 00053 00054 #endif // HAVE_PYTHON 00055 00056 class NodePathComponent; 00057 class CullTraverser; 00058 class CullTraverserData; 00059 class Light; 00060 class FactoryParams; 00061 class AccumulatedAttribs; 00062 class GeomTransformer; 00063 class GraphicsStateGuardianBase; 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Class : PandaNode 00067 // Description : A basic node of the scene graph or data graph. This 00068 // is the base class of all specialized nodes, and also 00069 // serves as a generic node with no special properties. 00070 //////////////////////////////////////////////////////////////////// 00071 class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritable, public Namable, 00072 public LinkedListNode, 00073 virtual public ReferenceCount { 00074 PUBLISHED: 00075 PandaNode(const string &name); 00076 virtual ~PandaNode(); 00077 //published so that characters can be combined. 00078 virtual PandaNode *combine_with(PandaNode *other); 00079 00080 protected: 00081 PandaNode(const PandaNode ©); 00082 private: 00083 void operator = (const PandaNode ©); 00084 00085 public: 00086 virtual ReferenceCount *as_reference_count(); 00087 virtual PandaNode *dupe_for_flatten() const; 00088 00089 virtual bool safe_to_flatten() const; 00090 virtual bool safe_to_transform() const; 00091 virtual bool safe_to_modify_transform() const; 00092 virtual bool safe_to_combine() const; 00093 virtual bool safe_to_combine_children() const; 00094 virtual bool safe_to_flatten_below() const; 00095 virtual bool preserve_name() const; 00096 virtual int get_unsafe_to_apply_attribs() const; 00097 virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, 00098 int attrib_types, 00099 GeomTransformer &transformer); 00100 virtual void xform(const LMatrix4 &mat); 00101 00102 virtual CPT(TransformState) 00103 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, 00104 bool &found_any, 00105 const TransformState *transform, 00106 Thread *current_thread = Thread::get_current_thread()) const; 00107 00108 virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); 00109 virtual bool has_selective_visibility() const; 00110 virtual int get_first_visible_child() const; 00111 virtual int get_next_visible_child(int n) const; 00112 virtual bool has_single_child_visibility() const; 00113 virtual int get_visible_child() const; 00114 virtual bool is_renderable() const; 00115 virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data); 00116 00117 PUBLISHED: 00118 virtual PandaNode *make_copy() const; 00119 PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const; 00120 00121 #ifdef HAVE_PYTHON 00122 PT(PandaNode) __copy__() const; 00123 PyObject *__deepcopy__(PyObject *self, PyObject *memo) const; 00124 #endif 00125 00126 INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const; 00127 INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const; 00128 INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const; 00129 00130 INLINE int get_num_children(Thread *current_thread = Thread::get_current_thread()) const; 00131 INLINE PandaNode *get_child(int n, Thread *current_thread = Thread::get_current_thread()) const; 00132 INLINE int get_child_sort(int n, Thread *current_thread = Thread::get_current_thread()) const; 00133 INLINE int find_child(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const; 00134 00135 int count_num_descendants() const; 00136 00137 void add_child(PandaNode *child_node, int sort = 0, 00138 Thread *current_thread = Thread::get_current_thread()); 00139 void remove_child(int child_index, Thread *current_thread = Thread::get_current_thread()); 00140 bool remove_child(PandaNode *child_node, Thread *current_thread = Thread::get_current_thread()); 00141 bool replace_child(PandaNode *orig_child, PandaNode *new_child, 00142 Thread *current_thread = Thread::get_current_thread()); 00143 00144 INLINE bool stash_child(PandaNode *child_node, 00145 Thread *current_thread = Thread::get_current_thread()); 00146 void stash_child(int child_index, 00147 Thread *current_thread = Thread::get_current_thread()); 00148 INLINE bool unstash_child(PandaNode *child_node, 00149 Thread *current_thread = Thread::get_current_thread()); 00150 void unstash_child(int stashed_index, 00151 Thread *current_thread = Thread::get_current_thread()); 00152 00153 INLINE int get_num_stashed(Thread *current_thread = Thread::get_current_thread()) const; 00154 INLINE PandaNode *get_stashed(int n, Thread *current_thread = Thread::get_current_thread()) const; 00155 INLINE int get_stashed_sort(int n, Thread *current_thread = Thread::get_current_thread()) const; 00156 INLINE int find_stashed(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const; 00157 00158 void add_stashed(PandaNode *child_node, int sort = 0, Thread *current_thread = Thread::get_current_thread()); 00159 void remove_stashed(int child_index, Thread *current_thread = Thread::get_current_thread()); 00160 00161 void remove_all_children(Thread *current_thread = Thread::get_current_thread()); 00162 void steal_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread()); 00163 void copy_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread()); 00164 00165 void set_attrib(const RenderAttrib *attrib, int override = 0); 00166 INLINE const RenderAttrib *get_attrib(TypeHandle type) const; 00167 INLINE const RenderAttrib *get_attrib(int slot) const; 00168 INLINE bool has_attrib(TypeHandle type) const; 00169 INLINE bool has_attrib(int slot) const; 00170 INLINE void clear_attrib(TypeHandle type); 00171 void clear_attrib(int slot); 00172 00173 void set_effect(const RenderEffect *effect); 00174 INLINE const RenderEffect *get_effect(TypeHandle type) const; 00175 INLINE bool has_effect(TypeHandle type) const; 00176 void clear_effect(TypeHandle type); 00177 00178 void set_state(const RenderState *state, Thread *current_thread = Thread::get_current_thread()); 00179 INLINE const RenderState *get_state(Thread *current_thread = Thread::get_current_thread()) const; 00180 INLINE void clear_state(Thread *current_thread = Thread::get_current_thread()); 00181 00182 void set_effects(const RenderEffects *effects, Thread *current_thread = Thread::get_current_thread()); 00183 INLINE const RenderEffects *get_effects(Thread *current_thread = Thread::get_current_thread()) const; 00184 INLINE void clear_effects(Thread *current_thread = Thread::get_current_thread()); 00185 00186 void set_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread()); 00187 INLINE const TransformState *get_transform(Thread *current_thread = Thread::get_current_thread()) const; 00188 INLINE void clear_transform(Thread *current_thread = Thread::get_current_thread()); 00189 00190 void set_prev_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread()); 00191 INLINE const TransformState *get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const; 00192 void reset_prev_transform(Thread *current_thread = Thread::get_current_thread()); 00193 INLINE bool has_dirty_prev_transform() const; 00194 static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread()); 00195 00196 void set_tag(const string &key, const string &value, 00197 Thread *current_thread = Thread::get_current_thread()); 00198 INLINE string get_tag(const string &key, 00199 Thread *current_thread = Thread::get_current_thread()) const; 00200 INLINE bool has_tag(const string &key, 00201 Thread *current_thread = Thread::get_current_thread()) const; 00202 void clear_tag(const string &key, 00203 Thread *current_thread = Thread::get_current_thread()); 00204 00205 #ifdef HAVE_PYTHON 00206 void set_python_tag(const string &key, PyObject *value); 00207 PyObject *get_python_tag(const string &key) const; 00208 bool has_python_tag(const string &key) const; 00209 void clear_python_tag(const string &key); 00210 #endif // HAVE_PYTHON 00211 00212 INLINE bool has_tags() const; 00213 void copy_tags(PandaNode *other); 00214 void list_tags(ostream &out, const string &separator = "\n") const; 00215 00216 int compare_tags(const PandaNode *other) const; 00217 00218 void copy_all_properties(PandaNode *other); 00219 void replace_node(PandaNode *other); 00220 00221 enum UnexpectedChange { 00222 UC_parents = 0x001, 00223 UC_children = 0x002, 00224 UC_transform = 0x004, 00225 UC_state = 0x008, 00226 UC_draw_mask = 0x010, 00227 }; 00228 void set_unexpected_change(unsigned int flags); 00229 unsigned int get_unexpected_change(unsigned int flags) const; 00230 void clear_unexpected_change(unsigned int flags); 00231 00232 INLINE static DrawMask get_overall_bit(); 00233 INLINE static DrawMask get_all_camera_mask(); 00234 INLINE bool is_overall_hidden() const; 00235 INLINE void set_overall_hidden(bool overall_hidden); 00236 00237 void adjust_draw_mask(DrawMask show_mask, 00238 DrawMask hide_mask, 00239 DrawMask clear_mask); 00240 INLINE DrawMask get_draw_control_mask() const; 00241 INLINE DrawMask get_draw_show_mask() const; 00242 00243 DrawMask get_net_draw_control_mask() const; 00244 DrawMask get_net_draw_show_mask() const; 00245 00246 void set_into_collide_mask(CollideMask mask); 00247 INLINE CollideMask get_into_collide_mask() const; 00248 virtual CollideMask get_legal_collide_mask() const; 00249 00250 CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const; 00251 CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const; 00252 00253 void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state); 00254 00255 bool is_scene_root() const; 00256 bool is_under_scene_root() const; 00257 00258 virtual void output(ostream &out) const; 00259 virtual void write(ostream &out, int indent_level) const; 00260 00261 INLINE void ls(ostream &out, int indent_level) const; 00262 00263 // A node has three bounding volumes: an "external" bounding volume 00264 // that represents the node and all of its children, an "internal" 00265 // bounding volume which represents only the node itself (and is 00266 // usually empty, unless a specific node type sets it otherwise), 00267 // and a "user" bounding volume which is specified by the user. 00268 00269 // We define set_bounds() and get_bounds() functions so that 00270 // set_bounds() sets the user bounding volume, while get_bounds() 00271 // returns the external bounding volume. Although it might seem 00272 // strange and confusing to do this, this is actually the natural 00273 // way the user thinks about nodes and bounding volumes. 00274 void set_bounds_type(BoundingVolume::BoundsType bounds_type); 00275 BoundingVolume::BoundsType get_bounds_type() const; 00276 00277 void set_bounds(const BoundingVolume *volume); 00278 void set_bound(const BoundingVolume *volume); 00279 INLINE void clear_bounds(); 00280 CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const; 00281 CPT(BoundingVolume) get_bounds(UpdateSeq &seq, Thread *current_thread = Thread::get_current_thread()) const; 00282 int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const; 00283 INLINE CPT(BoundingVolume) get_internal_bounds(Thread *current_thread = Thread::get_current_thread()) const; 00284 INLINE int get_internal_vertices(Thread *current_thread = Thread::get_current_thread()) const; 00285 00286 void mark_bounds_stale(Thread *current_thread = Thread::get_current_thread()) const; 00287 void mark_internal_bounds_stale(Thread *current_thread = Thread::get_current_thread()); 00288 INLINE bool is_bounds_stale() const; 00289 00290 INLINE void set_final(bool flag); 00291 INLINE bool is_final(Thread *current_thread = Thread::get_current_thread()) const; 00292 00293 virtual bool is_geom_node() const; 00294 virtual bool is_lod_node() const; 00295 virtual bool is_collision_node() const; 00296 virtual Light *as_light(); 00297 virtual bool is_ambient_light() const; 00298 00299 enum FancyBits { 00300 FB_transform = 0x0001, 00301 FB_state = 0x0002, 00302 FB_effects = 0x0004, 00303 FB_tag = 0x0010, 00304 FB_draw_mask = 0x0020, 00305 FB_cull_callback = 0x0040, 00306 }; 00307 INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const; 00308 00309 00310 PUBLISHED: 00311 static PT(PandaNode) decode_from_bam_stream(const string &data, BamReader *reader = NULL); 00312 00313 protected: 00314 class BoundsData; 00315 00316 INLINE CPT(BoundingVolume) get_user_bounds(int pipeline_stage, Thread *current_thread) const; 00317 CPT(BoundingVolume) get_internal_bounds(int pipeline_stage, Thread *current_thread) const; 00318 int get_internal_vertices(int pipeline_stage, Thread *current_thread) const; 00319 void set_internal_bounds(const BoundingVolume *volume); 00320 00321 INLINE void mark_bounds_stale(int pipeline_stage, Thread *current_thread) const; 00322 void force_bounds_stale(Thread *current_thread = Thread::get_current_thread()); 00323 void force_bounds_stale(int pipeline_stage, Thread *current_thread); 00324 INLINE void mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread); 00325 00326 virtual void r_mark_geom_bounds_stale(Thread *current_thread); 00327 00328 virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, 00329 int &internal_vertices, 00330 int pipeline_stage, 00331 Thread *current_thread) const; 00332 virtual void parents_changed(); 00333 virtual void children_changed(); 00334 virtual void transform_changed(); 00335 virtual void state_changed(); 00336 virtual void draw_mask_changed(); 00337 00338 typedef pmap<PandaNode *, PandaNode *> InstanceMap; 00339 virtual PT(PandaNode) r_copy_subgraph(InstanceMap &inst_map, 00340 Thread *current_thread) const; 00341 virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map, 00342 Thread *current_thread); 00343 00344 void set_cull_callback(); 00345 void disable_cull_callback(); 00346 public: 00347 virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, 00348 const RenderState *node_state, 00349 GeomTransformer &transformer, 00350 Thread *current_thread); 00351 00352 protected: 00353 // This is a base class of CData, defined below. It contains just 00354 // the protected (not private) part of CData that will be needed by 00355 // derived classes to implement compute_internal_bounds(). 00356 class EXPCL_PANDA_PGRAPH BoundsData : public CycleData { 00357 protected: 00358 INLINE BoundsData(); 00359 INLINE BoundsData(const BoundsData ©); 00360 INLINE void copy_bounds(const BoundsData ©); 00361 00362 public: 00363 // This is the "internal" bounding volume, which is normally 00364 // empty, but which a particular PandaNode subclass may define to 00365 // be any arbitrary volume, by calling set_internal_bounds() or by 00366 // overriding compute_internal_bounds(). 00367 CPT(BoundingVolume) _internal_bounds; 00368 int _internal_vertices; 00369 UpdateSeq _internal_bounds_mark; // incremented on mark_stale 00370 UpdateSeq _internal_bounds_computed; // set to above when computing 00371 }; 00372 00373 private: 00374 class CData; 00375 00376 INLINE int do_find_parent(PandaNode *node, const CData *cdata) const; 00377 bool stage_remove_child(PandaNode *child_node, int pipeline_stage, 00378 Thread *current_thread); 00379 bool stage_replace_child(PandaNode *orig_child, PandaNode *new_child, 00380 int pipeline_stage, Thread *current_thread); 00381 00382 void quick_add_new_child(PandaNode *child_node, int sort, 00383 Thread *current_thread); 00384 00385 INLINE bool verify_child_no_cycles(PandaNode *child_node); 00386 void report_cycle(PandaNode *node); 00387 bool find_node_above(PandaNode *node); 00388 00389 // parent-child manipulation for NodePath support. Don't try to 00390 // call these directly. 00391 static PT(NodePathComponent) attach(NodePathComponent *parent, 00392 PandaNode *child, int sort, 00393 int pipeline_stage, Thread *current_thread); 00394 static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread); 00395 static void detach_one_stage(NodePathComponent *child, int pipeline_stage, Thread *current_thread); 00396 static bool reparent(NodePathComponent *new_parent, 00397 NodePathComponent *child, int sort, bool as_stashed, 00398 int pipeline_stage, Thread *current_thread); 00399 static bool reparent_one_stage(NodePathComponent *new_parent, 00400 NodePathComponent *child, int sort, 00401 bool as_stashed, int pipeline_stage, Thread *current_thread); 00402 static PT(NodePathComponent) get_component(NodePathComponent *parent, 00403 PandaNode *child, 00404 int pipeline_stage, Thread *current_thread); 00405 static PT(NodePathComponent) get_top_component(PandaNode *child, bool force, 00406 int pipeline_stage, Thread *current_thread); 00407 PT(NodePathComponent) get_generic_component(bool accept_ambiguity, 00408 int pipeline_stage, Thread *current_thread); 00409 PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity, 00410 bool &ambiguity_detected, 00411 int pipeline_stage, Thread *current_thread); 00412 void delete_component(NodePathComponent *component); 00413 static void sever_connection(PandaNode *parent_node, PandaNode *child_node, 00414 int pipeline_stage, Thread *current_thread); 00415 static void new_connection(PandaNode *parent_node, PandaNode *child_node, 00416 int pipeline_stage, Thread *current_thread); 00417 void fix_path_lengths(int pipeline_stage, Thread *current_thread); 00418 void r_list_descendants(ostream &out, int indent_level) const; 00419 00420 INLINE void do_set_dirty_prev_transform(); 00421 INLINE void do_clear_dirty_prev_transform(); 00422 00423 public: 00424 // This must be declared public so that VC6 will allow the nested 00425 // CData class to access it. 00426 class EXPCL_PANDA_PGRAPH DownConnection { 00427 public: 00428 INLINE DownConnection(PandaNode *child, int sort); 00429 INLINE bool operator < (const DownConnection &other) const; 00430 INLINE PandaNode *get_child() const; 00431 INLINE void set_child(PandaNode *child); 00432 INLINE int get_sort() const; 00433 00434 private: 00435 // Child pointers are reference counted. That way, holding a 00436 // pointer to the root of a subgraph keeps the entire subgraph 00437 // around. 00438 PT(PandaNode) _child; 00439 int _sort; 00440 }; 00441 00442 private: 00443 typedef ov_multiset<DownConnection> DownList; 00444 typedef CopyOnWriteObj1< DownList, TypeHandle > Down; 00445 00446 // Store a pointer to the down_list during the bam read pass. 00447 class EXPCL_PANDA_PGRAPH BamReaderAuxDataDown : public BamReaderAuxData { 00448 public: 00449 INLINE BamReaderAuxDataDown(); 00450 Down _down_list; 00451 public: 00452 virtual TypeHandle get_type() const { 00453 return get_class_type(); 00454 } 00455 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00456 static TypeHandle get_class_type() { 00457 return _type_handle; 00458 } 00459 00460 public: 00461 static void init_type() { 00462 BamReaderAuxData::init_type(); 00463 register_type(_type_handle, "BamReaderAuxDataDown", 00464 BamReaderAuxData::get_class_type()); 00465 } 00466 00467 private: 00468 static TypeHandle _type_handle; 00469 }; 00470 00471 class EXPCL_PANDA_PGRAPH UpConnection { 00472 public: 00473 INLINE UpConnection(PandaNode *child); 00474 INLINE bool operator < (const UpConnection &other) const; 00475 INLINE PandaNode *get_parent() const; 00476 00477 private: 00478 // Parent pointers are not reference counted. That way, parents and 00479 // children do not circularly reference each other. 00480 PandaNode *_parent; 00481 }; 00482 typedef ov_set<UpConnection> UpList; 00483 typedef CopyOnWriteObj1< UpList, TypeHandle > Up; 00484 00485 // We also maintain a set of NodePathComponents in the node. This 00486 // represents the set of instances of this node that we have 00487 // requested a NodePath for. We don't keep reference counts; when 00488 // each NodePathComponent destructs, it removes itself from this 00489 // set. 00490 typedef phash_set<NodePathComponent *, pointer_hash> Paths; 00491 00492 // We don't cycle the set of Paths, since these are across all 00493 // threads. A NodePathComponent, once created, is always associated 00494 // with the same node. We do, however, protect the Paths under a mutex. 00495 Paths _paths; 00496 LightReMutex _paths_lock; 00497 00498 bool _dirty_prev_transform; 00499 static PandaNodeChain _dirty_prev_transforms; 00500 00501 // This is used to maintain a table of keyed data on each node, for 00502 // the user's purposes. 00503 typedef phash_map<string, string, string_hash> TagData; 00504 #ifdef HAVE_PYTHON 00505 typedef phash_map<string, PyObject *, string_hash> PythonTagData; 00506 #endif // HAVE_PYTHON 00507 00508 #ifndef NDEBUG 00509 unsigned int _unexpected_change_flags; 00510 #endif // !NDEBUG 00511 00512 // This is the data that must be cycled between pipeline stages. 00513 00514 class EXPCL_PANDA_PGRAPH CData : public BoundsData { 00515 public: 00516 CData(); 00517 CData(const CData ©); 00518 virtual ~CData(); 00519 ALLOC_DELETED_CHAIN(CData); 00520 00521 virtual CycleData *make_copy() const; 00522 virtual void write_datagram(BamWriter *manager, Datagram &dg) const; 00523 void update_bam_nested(BamWriter *manager) const; 00524 virtual int complete_pointers(TypedWritable **plist, BamReader *manager); 00525 virtual void fillin(DatagramIterator &scan, BamReader *manager); 00526 virtual TypeHandle get_parent_type() const { 00527 return PandaNode::get_class_type(); 00528 } 00529 00530 public: 00531 // This section contains the lightweight parts of the node that 00532 // are likely to change fairly often: transform and state. 00533 00534 NCPT(RenderState) _state; 00535 NCPT(TransformState) _transform; 00536 NCPT(TransformState) _prev_transform; 00537 00538 public: 00539 // This section contains the heavierweight parts of the node that 00540 // are less likely to change as often: tags, collide mask. 00541 00542 INLINE void set_fancy_bit(int bits, bool value); 00543 00544 #ifdef HAVE_PYTHON 00545 void inc_py_refs(); 00546 void dec_py_refs(); 00547 #endif 00548 00549 CPT(RenderEffects) _effects; 00550 00551 TagData _tag_data; 00552 #ifdef HAVE_PYTHON 00553 PythonTagData _python_tag_data; 00554 #endif // HAVE_PYTHON 00555 00556 // These two together determine the per-camera visibility of this 00557 // node. See adjust_draw_mask() for details. 00558 DrawMask _draw_control_mask, _draw_show_mask; 00559 00560 // This is the mask that indicates which CollisionNodes may detect 00561 // a collision with this particular node. By default it is zero 00562 // for an ordinary PandaNode, and all bits on for a CollisionNode 00563 // or GeomNode. 00564 CollideMask _into_collide_mask; 00565 00566 // The requested bounding volume type. 00567 BoundingVolume::BoundsType _bounds_type; 00568 00569 // This is the user bounding volume, which is only specified by a 00570 // user. It defaults to NULL, which means an empty volume. 00571 CPT(BoundingVolume) _user_bounds; 00572 00573 // See BoundsData, above, for _internal_bounds. 00574 00575 // This is true if the external bounds of this node should be 00576 // deemed "final". See set_final(). 00577 bool _final_bounds; 00578 00579 // This bitmask is maintained automatically by the internal 00580 // PandaNode code; it contains a 1 for each "fancy" attribute that 00581 // is set on the node. See enum FancyBits, above. 00582 int _fancy_bits; 00583 00584 public: 00585 // This section contains the data that is accumulated upward from 00586 // the node's children: that is, the external bounding volume, and 00587 // conceptually similar things like the net_collide_mask, etc. 00588 // None of the data in this object is preserved in a bam file. 00589 00590 // This is the union of all into_collide_mask bits for any nodes 00591 // at and below this level. 00592 CollideMask _net_collide_mask; 00593 00594 // These are similar, for the draw mask. 00595 DrawMask _net_draw_control_mask, _net_draw_show_mask; 00596 00597 // This is a ClipPlaneAttrib that represents the union of all clip 00598 // planes that have been turned *off* at and below this level. 00599 // TODO: fix the circular reference counts involved here. 00600 CPT(RenderAttrib) _off_clip_planes; 00601 00602 // The number of vertices rendered by this node and all child 00603 // nodes. 00604 int _nested_vertices; 00605 00606 // This is the bounding volume around the _user_bounds, the 00607 // _internal_bounds, and all of the children's external bounding 00608 // volumes. 00609 CPT(BoundingVolume) _external_bounds; 00610 00611 // When _last_update != _next_update, this cache is stale. 00612 UpdateSeq _last_update, _next_update; 00613 00614 public: 00615 // This section stores the links to other nodes above and below 00616 // this node in the graph. 00617 00618 void write_up_list(const Up &up_list, 00619 BamWriter *manager, Datagram &dg) const; 00620 void write_down_list(const Down &down_list, 00621 BamWriter *manager, Datagram &dg) const; 00622 void update_up_list(const Up &up_list, BamWriter *manager) const; 00623 void update_down_list(const Down &down_list, BamWriter *manager) const; 00624 int complete_up_list(Up &up_list, const string &tag, 00625 TypedWritable **p_list, BamReader *manager); 00626 int complete_down_list(Down &down_list, const string &tag, 00627 TypedWritable **p_list, BamReader *manager); 00628 void fillin_up_list(Up &up_list, const string &tag, 00629 DatagramIterator &scan, BamReader *manager); 00630 void fillin_down_list(Down &down_list, const string &tag, 00631 DatagramIterator &scan, BamReader *manager); 00632 00633 INLINE CPT(Down) get_down() const; 00634 INLINE PT(Down) modify_down(); 00635 INLINE CPT(Down) get_stashed() const; 00636 INLINE PT(Down) modify_stashed(); 00637 INLINE CPT(Up) get_up() const; 00638 INLINE PT(Up) modify_up(); 00639 00640 private: 00641 // We store the child lists by reference, so we can copy them 00642 // quickly. We perform copy-on-write when necessary. 00643 COWPT(Down) _down; 00644 COWPT(Down) _stashed; 00645 COWPT(Up) _up; 00646 00647 public: 00648 static TypeHandle get_class_type() { 00649 return _type_handle; 00650 } 00651 static void init_type() { 00652 register_type(_type_handle, "PandaNode::CData"); 00653 } 00654 00655 private: 00656 static TypeHandle _type_handle; 00657 }; 00658 00659 PipelineCycler<CData> _cycler; 00660 typedef CycleDataReader<CData> CDReader; 00661 typedef CycleDataWriter<CData> CDWriter; 00662 typedef CycleDataLockedStageReader<CData> CDLockedStageReader; 00663 typedef CycleDataStageReader<CData> CDStageReader; 00664 typedef CycleDataStageWriter<CData> CDStageWriter; 00665 00666 int do_find_child(PandaNode *node, const Down *down) const; 00667 CDStageWriter update_bounds(int pipeline_stage, CDLockedStageReader &cdata); 00668 00669 static DrawMask _overall_bit; 00670 00671 static PStatCollector _reset_prev_pcollector; 00672 static PStatCollector _update_bounds_pcollector; 00673 00674 public: 00675 // This class is returned from get_children(). Use it to walk 00676 // through the list of children. This is faster, and safer, than 00677 // walking through the children one at a time via 00678 // get_num_children()/get_child(), since the list of children is 00679 // saved out ahead of time, rather than having to reacquire the lock 00680 // with each iteration, or to keep the lock held for the entire 00681 // pass. 00682 class EXPCL_PANDA_PGRAPH Children { 00683 public: 00684 INLINE Children(); 00685 INLINE Children(const CData *cdata); 00686 INLINE Children(const Children ©); 00687 INLINE void operator = (const Children ©); 00688 00689 INLINE int get_num_children() const; 00690 INLINE PandaNode *get_child(int n) const; 00691 INLINE int get_child_sort(int n) const; 00692 00693 private: 00694 CPT(Down) _down; 00695 }; 00696 00697 // Similarly for stashed children. 00698 class EXPCL_PANDA_PGRAPH Stashed { 00699 public: 00700 INLINE Stashed(); 00701 INLINE Stashed(const CData *cdata); 00702 INLINE Stashed(const Stashed ©); 00703 INLINE void operator = (const Stashed ©); 00704 00705 INLINE int get_num_stashed() const; 00706 INLINE PandaNode *get_stashed(int n) const; 00707 INLINE int get_stashed_sort(int n) const; 00708 00709 private: 00710 CPT(Down) _stashed; 00711 }; 00712 00713 // This class is returned from get_parents(). 00714 class EXPCL_PANDA_PGRAPH Parents { 00715 public: 00716 INLINE Parents(); 00717 INLINE Parents(const CData *cdata); 00718 INLINE Parents(const Parents ©); 00719 INLINE void operator = (const Parents ©); 00720 00721 INLINE int get_num_parents() const; 00722 INLINE PandaNode *get_parent(int n) const; 00723 00724 private: 00725 CPT(Up) _up; 00726 }; 00727 00728 INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const; 00729 INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const; 00730 INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const; 00731 00732 typedef bool SceneRootFunc(const PandaNode *); 00733 static void set_scene_root_func(SceneRootFunc *func); 00734 00735 private: 00736 static SceneRootFunc *_scene_root_func; 00737 00738 public: 00739 static void register_with_read_factory(); 00740 virtual void write_datagram(BamWriter *manager, Datagram &dg); 00741 virtual void update_bam_nested(BamWriter *manager); 00742 void write_recorder(BamWriter *manager, Datagram &dg); 00743 00744 protected: 00745 static TypedWritable *make_from_bam(const FactoryParams ¶ms); 00746 void fillin(DatagramIterator &scan, BamReader *manager); 00747 void fillin_recorder(DatagramIterator &scan, BamReader *manager); 00748 00749 public: 00750 static TypeHandle get_class_type() { 00751 return _type_handle; 00752 } 00753 static void init_type() { 00754 TypedWritable::init_type(); 00755 ReferenceCount::init_type(); 00756 Namable::init_type(); 00757 register_type(_type_handle, "PandaNode", 00758 TypedWritable::get_class_type(), 00759 ReferenceCount::get_class_type(), 00760 Namable::get_class_type()); 00761 CData::init_type(); 00762 Down::init_type(); 00763 Up::init_type(); 00764 BamReaderAuxDataDown::init_type(); 00765 } 00766 virtual TypeHandle get_type() const { 00767 return get_class_type(); 00768 } 00769 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00770 00771 private: 00772 static TypeHandle _type_handle; 00773 00774 #ifndef DO_PIPELINING 00775 friend class PandaNode::Children; 00776 friend class PandaNode::Stashed; 00777 #endif 00778 friend class NodePath; 00779 friend class NodePathComponent; 00780 friend class WorkingNodePath; 00781 friend class PandaNodePipelineReader; 00782 friend class EggLoader; 00783 }; 00784 00785 //////////////////////////////////////////////////////////////////// 00786 // Class : PandaNodePipelineReader 00787 // Description : Encapsulates the data from a PandaNode, 00788 // pre-fetched for one stage of the pipeline. 00789 //////////////////////////////////////////////////////////////////// 00790 class EXPCL_PANDA_PGRAPH PandaNodePipelineReader { 00791 public: 00792 INLINE PandaNodePipelineReader(const PandaNode *object, Thread *current_thread); 00793 INLINE PandaNodePipelineReader(const PandaNodePipelineReader ©); 00794 INLINE void operator = (const PandaNodePipelineReader ©); 00795 00796 public: 00797 INLINE ~PandaNodePipelineReader(); 00798 ALLOC_DELETED_CHAIN(PandaNodePipelineReader); 00799 00800 INLINE const PandaNode *get_object() const; 00801 INLINE Thread *get_current_thread() const; 00802 00803 INLINE void release(); 00804 00805 void check_bounds() const; 00806 00807 INLINE void compose_draw_mask(DrawMask &running_draw_mask) const; 00808 INLINE bool compare_draw_mask(DrawMask running_draw_mask, 00809 DrawMask camera_mask) const; 00810 00811 INLINE int get_num_parents() const; 00812 INLINE PandaNode *get_parent(int n) const; 00813 INLINE int find_parent(PandaNode *node) const; 00814 00815 INLINE int get_num_children() const; 00816 INLINE PandaNode *get_child(int n) const; 00817 INLINE int get_child_sort(int n) const; 00818 INLINE int find_child(PandaNode *node) const; 00819 00820 INLINE int get_num_stashed() const; 00821 INLINE PandaNode *get_stashed(int n) const; 00822 INLINE int get_stashed_sort(int n) const; 00823 INLINE int find_stashed(PandaNode *node) const; 00824 00825 INLINE const RenderState *get_state() const; 00826 INLINE const RenderEffects *get_effects() const; 00827 INLINE const TransformState *get_transform() const; 00828 INLINE const TransformState *get_prev_transform() const; 00829 00830 INLINE string get_tag(const string &key) const; 00831 INLINE bool has_tag(const string &key) const; 00832 00833 INLINE CollideMask get_net_collide_mask() const; 00834 INLINE CPT(RenderAttrib) get_off_clip_planes() const; 00835 INLINE CPT(BoundingVolume) get_bounds() const; 00836 INLINE int get_nested_vertices() const; 00837 INLINE bool is_final() const; 00838 INLINE int get_fancy_bits() const; 00839 00840 INLINE PandaNode::Children get_children() const; 00841 INLINE PandaNode::Stashed get_stashed() const; 00842 INLINE PandaNode::Parents get_parents() const; 00843 00844 private: 00845 const PandaNode *_object; 00846 Thread *_current_thread; 00847 00848 const PandaNode::CData *_cdata; 00849 00850 public: 00851 static TypeHandle get_class_type() { 00852 return _type_handle; 00853 } 00854 static void init_type() { 00855 register_type(_type_handle, "PandaNodePipelineReader"); 00856 } 00857 00858 private: 00859 static TypeHandle _type_handle; 00860 00861 }; 00862 00863 INLINE ostream &operator << (ostream &out, const PandaNode &node) { 00864 node.output(out); 00865 return out; 00866 } 00867 00868 #include "pandaNode.I" 00869 00870 #endif 00871