Panda3D
 All Classes Functions Variables Enumerations
pandaNode.h
1 // Filename: pandaNode.h
2 // Created by: drose (20Feb02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef PANDANODE_H
16 #define PANDANODE_H
17 
18 #include "pandabase.h"
19 
20 #include "cycleData.h"
21 #include "cycleDataReader.h"
22 #include "cycleDataWriter.h"
23 #include "cycleDataLockedStageReader.h"
24 #include "cycleDataStageReader.h"
25 #include "cycleDataStageWriter.h"
26 #include "pipelineCycler.h"
27 #include "renderState.h"
28 #include "renderEffects.h"
29 #include "transformState.h"
30 #include "drawMask.h"
31 #include "typedWritable.h"
32 #include "collideMask.h"
33 #include "namable.h"
34 #include "referenceCount.h"
35 #include "luse.h"
36 #include "ordered_vector.h"
37 #include "pointerTo.h"
38 #include "nodePointerTo.h"
39 #include "pointerToArray.h"
40 #include "pnotify.h"
41 #include "updateSeq.h"
42 #include "deletedChain.h"
43 #include "pandaNodeChain.h"
44 #include "pStatCollector.h"
45 #include "copyOnWriteObject.h"
46 #include "copyOnWritePointer.h"
47 #include "lightReMutex.h"
48 #include "extension.h"
49 
50 #ifdef HAVE_PYTHON
51 
52 #undef _POSIX_C_SOURCE
53 #include <Python.h>
54 
55 #endif // HAVE_PYTHON
56 
57 class NodePathComponent;
58 class CullTraverser;
59 class CullTraverserData;
60 class Light;
61 class FactoryParams;
62 class AccumulatedAttribs;
63 class GeomTransformer;
65 
66 ////////////////////////////////////////////////////////////////////
67 // Class : PandaNode
68 // Description : A basic node of the scene graph or data graph. This
69 // is the base class of all specialized nodes, and also
70 // serves as a generic node with no special properties.
71 ////////////////////////////////////////////////////////////////////
72 class EXPCL_PANDA_PGRAPH PandaNode : public TypedWritableReferenceCount,
73  public Namable, public LinkedListNode {
74 PUBLISHED:
75  PandaNode(const string &name);
76  virtual ~PandaNode();
77  //published so that characters can be combined.
78  virtual PandaNode *combine_with(PandaNode *other);
79 
80 protected:
81  PandaNode(const PandaNode &copy);
82 private:
83  void operator = (const PandaNode &copy);
84 
85 public:
86  virtual PandaNode *dupe_for_flatten() const;
87 
88  virtual bool safe_to_flatten() const;
89  virtual bool safe_to_transform() const;
90  virtual bool safe_to_modify_transform() const;
91  virtual bool safe_to_combine() const;
92  virtual bool safe_to_combine_children() const;
93  virtual bool safe_to_flatten_below() const;
94  virtual bool preserve_name() const;
95  virtual int get_unsafe_to_apply_attribs() const;
96  virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
97  int attrib_types,
98  GeomTransformer &transformer);
99  virtual void xform(const LMatrix4 &mat);
100 
101  virtual CPT(TransformState)
102  calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
103  bool &found_any,
104  const TransformState *transform,
105  Thread *current_thread = Thread::get_current_thread()) const;
106 
107  virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
108  virtual bool has_selective_visibility() const;
109  virtual int get_first_visible_child() const;
110  virtual int get_next_visible_child(int n) const;
111  virtual bool has_single_child_visibility() const;
112  virtual int get_visible_child() const;
113  virtual bool is_renderable() const;
114  virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data);
115 
116 PUBLISHED:
117  virtual PandaNode *make_copy() const;
118  PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
119 
120  EXTENSION(PT(PandaNode) __copy__() const);
121  EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
122 
123  INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
124  INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
125  INLINE int find_parent(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
126  MAKE_SEQ(get_parents, get_num_parents, get_parent);
127 
128  INLINE int get_num_children(Thread *current_thread = Thread::get_current_thread()) const;
129  INLINE PandaNode *get_child(int n, Thread *current_thread = Thread::get_current_thread()) const;
130  INLINE int get_child_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
131  INLINE int find_child(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
132  MAKE_SEQ(get_children, get_num_children, get_child);
133 
134  int count_num_descendants() const;
135 
136  void add_child(PandaNode *child_node, int sort = 0,
137  Thread *current_thread = Thread::get_current_thread());
138  void remove_child(int child_index, Thread *current_thread = Thread::get_current_thread());
139  bool remove_child(PandaNode *child_node, Thread *current_thread = Thread::get_current_thread());
140  bool replace_child(PandaNode *orig_child, PandaNode *new_child,
141  Thread *current_thread = Thread::get_current_thread());
142 
143  INLINE bool stash_child(PandaNode *child_node,
144  Thread *current_thread = Thread::get_current_thread());
145  void stash_child(int child_index,
146  Thread *current_thread = Thread::get_current_thread());
147  INLINE bool unstash_child(PandaNode *child_node,
148  Thread *current_thread = Thread::get_current_thread());
149  void unstash_child(int stashed_index,
150  Thread *current_thread = Thread::get_current_thread());
151 
152  INLINE int get_num_stashed(Thread *current_thread = Thread::get_current_thread()) const;
153  INLINE PandaNode *get_stashed(int n, Thread *current_thread = Thread::get_current_thread()) const;
154  INLINE int get_stashed_sort(int n, Thread *current_thread = Thread::get_current_thread()) const;
155  INLINE int find_stashed(PandaNode *node, Thread *current_thread = Thread::get_current_thread()) const;
156  MAKE_SEQ(get_stashed, get_num_stashed, get_stashed);
157 
158  void add_stashed(PandaNode *child_node, int sort = 0, Thread *current_thread = Thread::get_current_thread());
159  void remove_stashed(int child_index, Thread *current_thread = Thread::get_current_thread());
160 
161  void remove_all_children(Thread *current_thread = Thread::get_current_thread());
162  void steal_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
163  void copy_children(PandaNode *other, Thread *current_thread = Thread::get_current_thread());
164 
165  void set_attrib(const RenderAttrib *attrib, int override = 0);
166  INLINE CPT(RenderAttrib) get_attrib(TypeHandle type) const;
167  INLINE CPT(RenderAttrib) get_attrib(int slot) const;
168  INLINE bool has_attrib(TypeHandle type) const;
169  INLINE bool has_attrib(int slot) const;
170  INLINE void clear_attrib(TypeHandle type);
171  void clear_attrib(int slot);
172 
173  void set_effect(const RenderEffect *effect);
174  INLINE CPT(RenderEffect) get_effect(TypeHandle type) const;
175  INLINE bool has_effect(TypeHandle type) const;
176  void clear_effect(TypeHandle type);
177 
178  void set_state(const RenderState *state, Thread *current_thread = Thread::get_current_thread());
179  INLINE CPT(RenderState) get_state(Thread *current_thread = Thread::get_current_thread()) const;
180  INLINE void clear_state(Thread *current_thread = Thread::get_current_thread());
181 
182  void set_effects(const RenderEffects *effects, Thread *current_thread = Thread::get_current_thread());
183  INLINE CPT(RenderEffects) get_effects(Thread *current_thread = Thread::get_current_thread()) const;
184  INLINE void clear_effects(Thread *current_thread = Thread::get_current_thread());
185 
186  void set_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
187  INLINE CPT(TransformState) get_transform(Thread *current_thread = Thread::get_current_thread()) const;
188  INLINE void clear_transform(Thread *current_thread = Thread::get_current_thread());
189 
190  void set_prev_transform(const TransformState *transform, Thread *current_thread = Thread::get_current_thread());
191  INLINE CPT(TransformState) get_prev_transform(Thread *current_thread = Thread::get_current_thread()) const;
192  void reset_prev_transform(Thread *current_thread = Thread::get_current_thread());
193  INLINE bool has_dirty_prev_transform() const;
194  static void reset_all_prev_transform(Thread *current_thread = Thread::get_current_thread());
195 
196  void set_tag(const string &key, const string &value,
197  Thread *current_thread = Thread::get_current_thread());
198  INLINE string get_tag(const string &key,
199  Thread *current_thread = Thread::get_current_thread()) const;
200  INLINE bool has_tag(const string &key,
201  Thread *current_thread = Thread::get_current_thread()) const;
202  void clear_tag(const string &key,
203  Thread *current_thread = Thread::get_current_thread());
204  void get_tag_keys(vector_string &keys) const;
205 
206  EXTENSION(PyObject *get_tag_keys() const);
207 
208  EXTENSION(void set_python_tag(const string &key, PyObject *value));
209  EXTENSION(PyObject *get_python_tag(const string &key) const);
210  EXTENSION(bool has_python_tag(const string &key) const);
211  EXTENSION(void clear_python_tag(const string &key));
212  EXTENSION(void get_python_tag_keys(vector_string &keys) const);
213  EXTENSION(PyObject *get_python_tag_keys() const);
214 
215  INLINE bool has_tags() const;
216  void copy_tags(PandaNode *other);
217  void list_tags(ostream &out, const string &separator = "\n") const;
218 
219  int compare_tags(const PandaNode *other) const;
220 
221  void copy_all_properties(PandaNode *other);
222  void replace_node(PandaNode *other);
223 
224  enum UnexpectedChange {
225  UC_parents = 0x001,
226  UC_children = 0x002,
227  UC_transform = 0x004,
228  UC_state = 0x008,
229  UC_draw_mask = 0x010,
230  };
231  void set_unexpected_change(unsigned int flags);
232  unsigned int get_unexpected_change(unsigned int flags) const;
233  void clear_unexpected_change(unsigned int flags);
234 
235  INLINE static DrawMask get_overall_bit();
236  INLINE static DrawMask get_all_camera_mask();
237  INLINE bool is_overall_hidden() const;
238  INLINE void set_overall_hidden(bool overall_hidden);
239 
240  void adjust_draw_mask(DrawMask show_mask,
241  DrawMask hide_mask,
242  DrawMask clear_mask);
243  INLINE DrawMask get_draw_control_mask() const;
244  INLINE DrawMask get_draw_show_mask() const;
245 
246  DrawMask get_net_draw_control_mask() const;
247  DrawMask get_net_draw_show_mask() const;
248 
249  void set_into_collide_mask(CollideMask mask);
250  INLINE CollideMask get_into_collide_mask() const;
251  virtual CollideMask get_legal_collide_mask() const;
252 
253  CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const;
254  CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const;
255 
256  void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state);
257 
258  bool is_scene_root() const;
259  bool is_under_scene_root() const;
260 
261  virtual void output(ostream &out) const;
262  virtual void write(ostream &out, int indent_level) const;
263 
264  INLINE void ls(ostream &out, int indent_level) const;
265 
266  // A node has three bounding volumes: an "external" bounding volume
267  // that represents the node and all of its children, an "internal"
268  // bounding volume which represents only the node itself (and is
269  // usually empty, unless a specific node type sets it otherwise),
270  // and a "user" bounding volume which is specified by the user.
271 
272  // We define set_bounds() and get_bounds() functions so that
273  // set_bounds() sets the user bounding volume, while get_bounds()
274  // returns the external bounding volume. Although it might seem
275  // strange and confusing to do this, this is actually the natural
276  // way the user thinks about nodes and bounding volumes.
277  void set_bounds_type(BoundingVolume::BoundsType bounds_type);
278  BoundingVolume::BoundsType get_bounds_type() const;
279 
280  void set_bounds(const BoundingVolume *volume);
281  void set_bound(const BoundingVolume *volume);
282  INLINE void clear_bounds();
283  CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const;
284  CPT(BoundingVolume) get_bounds(UpdateSeq &seq, Thread *current_thread = Thread::get_current_thread()) const;
285  int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const;
286  INLINE CPT(BoundingVolume) get_internal_bounds(Thread *current_thread = Thread::get_current_thread()) const;
287  INLINE int get_internal_vertices(Thread *current_thread = Thread::get_current_thread()) const;
288 
289  void mark_bounds_stale(Thread *current_thread = Thread::get_current_thread()) const;
290  void mark_internal_bounds_stale(Thread *current_thread = Thread::get_current_thread());
291  INLINE bool is_bounds_stale() const;
292 
293  INLINE void set_final(bool flag);
294  INLINE bool is_final(Thread *current_thread = Thread::get_current_thread()) const;
295 
296  virtual bool is_geom_node() const;
297  virtual bool is_lod_node() const;
298  virtual bool is_collision_node() const;
299  virtual Light *as_light();
300  virtual bool is_ambient_light() const;
301 
302  enum FancyBits {
303  FB_transform = 0x0001,
304  FB_state = 0x0002,
305  FB_effects = 0x0004,
306  FB_tag = 0x0010,
307  FB_draw_mask = 0x0020,
308  FB_cull_callback = 0x0040,
309  };
310  INLINE int get_fancy_bits(Thread *current_thread = Thread::get_current_thread()) const;
311 
312 
313 PUBLISHED:
314  static PT(PandaNode) decode_from_bam_stream(const string &data, BamReader *reader = NULL);
315 
316 protected:
317  class BoundsData;
318 
319  INLINE CPT(BoundingVolume) get_user_bounds(int pipeline_stage, Thread *current_thread) const;
320  CPT(BoundingVolume) get_internal_bounds(int pipeline_stage, Thread *current_thread) const;
321  int get_internal_vertices(int pipeline_stage, Thread *current_thread) const;
322  void set_internal_bounds(const BoundingVolume *volume);
323 
324  INLINE void mark_bounds_stale(int pipeline_stage, Thread *current_thread) const;
325  void force_bounds_stale(Thread *current_thread = Thread::get_current_thread());
326  void force_bounds_stale(int pipeline_stage, Thread *current_thread);
327  INLINE void mark_internal_bounds_stale(int pipeline_stage, Thread *current_thread);
328 
329  virtual void r_mark_geom_bounds_stale(Thread *current_thread);
330 
331  virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
332  int &internal_vertices,
333  int pipeline_stage,
334  Thread *current_thread) const;
335  virtual void parents_changed();
336  virtual void children_changed();
337  virtual void transform_changed();
338  virtual void state_changed();
339  virtual void draw_mask_changed();
340 
342  virtual PT(PandaNode) r_copy_subgraph(InstanceMap &inst_map,
343  Thread *current_thread) const;
344  virtual void r_copy_children(const PandaNode *from, InstanceMap &inst_map,
345  Thread *current_thread);
346 
347  void set_cull_callback();
348  void disable_cull_callback();
349 public:
350  virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg,
351  const RenderState *node_state,
352  GeomTransformer &transformer,
353  Thread *current_thread);
354 
355 protected:
356  // This is a base class of CData, defined below. It contains just
357  // the protected (not private) part of CData that will be needed by
358  // derived classes to implement compute_internal_bounds().
359  class EXPCL_PANDA_PGRAPH BoundsData : public CycleData {
360  protected:
361  INLINE BoundsData();
362  INLINE BoundsData(const BoundsData &copy);
363  INLINE void copy_bounds(const BoundsData &copy);
364 
365  public:
366  // This is the "internal" bounding volume, which is normally
367  // empty, but which a particular PandaNode subclass may define to
368  // be any arbitrary volume, by calling set_internal_bounds() or by
369  // overriding compute_internal_bounds().
370  CPT(BoundingVolume) _internal_bounds;
371  int _internal_vertices;
372  UpdateSeq _internal_bounds_mark; // incremented on mark_stale
373  UpdateSeq _internal_bounds_computed; // set to above when computing
374  };
375 
376 private:
377  class CData;
378 
379  INLINE int do_find_parent(PandaNode *node, const CData *cdata) const;
380  bool stage_remove_child(PandaNode *child_node, int pipeline_stage,
381  Thread *current_thread);
382  bool stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
383  int pipeline_stage, Thread *current_thread);
384 
385  void quick_add_new_child(PandaNode *child_node, int sort,
386  Thread *current_thread);
387 
388  INLINE bool verify_child_no_cycles(PandaNode *child_node);
389  void report_cycle(PandaNode *node);
390  bool find_node_above(PandaNode *node);
391 
392  // parent-child manipulation for NodePath support. Don't try to
393  // call these directly.
394  static PT(NodePathComponent) attach(NodePathComponent *parent,
395  PandaNode *child, int sort,
396  int pipeline_stage, Thread *current_thread);
397  static void detach(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
398  static void detach_one_stage(NodePathComponent *child, int pipeline_stage, Thread *current_thread);
399  static bool reparent(NodePathComponent *new_parent,
400  NodePathComponent *child, int sort, bool as_stashed,
401  int pipeline_stage, Thread *current_thread);
402  static bool reparent_one_stage(NodePathComponent *new_parent,
403  NodePathComponent *child, int sort,
404  bool as_stashed, int pipeline_stage, Thread *current_thread);
405  static PT(NodePathComponent) get_component(NodePathComponent *parent,
406  PandaNode *child,
407  int pipeline_stage, Thread *current_thread);
408  static PT(NodePathComponent) get_top_component(PandaNode *child, bool force,
409  int pipeline_stage, Thread *current_thread);
410  PT(NodePathComponent) get_generic_component(bool accept_ambiguity,
411  int pipeline_stage, Thread *current_thread);
412  PT(NodePathComponent) r_get_generic_component(bool accept_ambiguity,
413  bool &ambiguity_detected,
414  int pipeline_stage, Thread *current_thread);
415  void delete_component(NodePathComponent *component);
416  static void sever_connection(PandaNode *parent_node, PandaNode *child_node,
417  int pipeline_stage, Thread *current_thread);
418  static void new_connection(PandaNode *parent_node, PandaNode *child_node,
419  int pipeline_stage, Thread *current_thread);
420  void fix_path_lengths(int pipeline_stage, Thread *current_thread);
421  void r_list_descendants(ostream &out, int indent_level) const;
422 
423  INLINE void do_set_dirty_prev_transform();
424  INLINE void do_clear_dirty_prev_transform();
425 
426 public:
427  // This must be declared public so that VC6 will allow the nested
428  // CData class to access it.
429  class EXPCL_PANDA_PGRAPH DownConnection {
430  public:
431  INLINE DownConnection(PandaNode *child, int sort);
432  INLINE bool operator < (const DownConnection &other) const;
433  INLINE PandaNode *get_child() const;
434  INLINE void set_child(PandaNode *child);
435  INLINE int get_sort() const;
436 
437  private:
438  // Child pointers are reference counted. That way, holding a
439  // pointer to the root of a subgraph keeps the entire subgraph
440  // around.
441  PT(PandaNode) _child;
442  int _sort;
443  };
444 
445 private:
448 
449  // Store a pointer to the down_list during the bam read pass.
450  class EXPCL_PANDA_PGRAPH BamReaderAuxDataDown : public BamReaderAuxData {
451  public:
452  INLINE BamReaderAuxDataDown();
453  Down _down_list;
454  public:
455  virtual TypeHandle get_type() const {
456  return get_class_type();
457  }
458  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
459  static TypeHandle get_class_type() {
460  return _type_handle;
461  }
462 
463  public:
464  static void init_type() {
465  BamReaderAuxData::init_type();
466  register_type(_type_handle, "BamReaderAuxDataDown",
467  BamReaderAuxData::get_class_type());
468  }
469 
470  private:
471  static TypeHandle _type_handle;
472  };
473 
474  class EXPCL_PANDA_PGRAPH UpConnection {
475  public:
476  INLINE UpConnection(PandaNode *child);
477  INLINE bool operator < (const UpConnection &other) const;
478  INLINE PandaNode *get_parent() const;
479 
480  private:
481  // Parent pointers are not reference counted. That way, parents and
482  // children do not circularly reference each other.
483  PandaNode *_parent;
484  };
485  typedef ov_set<UpConnection> UpList;
487 
488  // We also maintain a set of NodePathComponents in the node. This
489  // represents the set of instances of this node that we have
490  // requested a NodePath for. We don't keep reference counts; when
491  // each NodePathComponent destructs, it removes itself from this
492  // set.
493  typedef phash_set<NodePathComponent *, pointer_hash> Paths;
494 
495  // We don't cycle the set of Paths, since these are across all
496  // threads. A NodePathComponent, once created, is always associated
497  // with the same node. We do, however, protect the Paths under a mutex.
498  Paths _paths;
499  LightReMutex _paths_lock;
500 
501  bool _dirty_prev_transform;
502  static PandaNodeChain _dirty_prev_transforms;
503 
504  // This is used to maintain a table of keyed data on each node, for
505  // the user's purposes.
506  typedef phash_map<string, string, string_hash> TagData;
507 #ifdef HAVE_PYTHON
508  typedef phash_map<string, PyObject *, string_hash> PythonTagData;
509 #endif // HAVE_PYTHON
510 
511 #ifndef NDEBUG
512  unsigned int _unexpected_change_flags;
513 #endif // !NDEBUG
514 
515  // This is the data that must be cycled between pipeline stages.
516 
517  class EXPCL_PANDA_PGRAPH CData : public BoundsData {
518  public:
519  CData();
520  CData(const CData &copy);
521  virtual ~CData();
522  ALLOC_DELETED_CHAIN(CData);
523 
524  virtual CycleData *make_copy() const;
525  virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
526  void update_bam_nested(BamWriter *manager) const;
527  virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
528  virtual void fillin(DatagramIterator &scan, BamReader *manager);
529  virtual TypeHandle get_parent_type() const {
530  return PandaNode::get_class_type();
531  }
532 
533  public:
534  // This section contains the lightweight parts of the node that
535  // are likely to change fairly often: transform and state.
536 
537  NCPT(RenderState) _state;
538  NCPT(TransformState) _transform;
539  NCPT(TransformState) _prev_transform;
540 
541  public:
542  // This section contains the heavierweight parts of the node that
543  // are less likely to change as often: tags, collide mask.
544 
545  INLINE void set_fancy_bit(int bits, bool value);
546 
547 #ifdef HAVE_PYTHON
548  void inc_py_refs();
549  void dec_py_refs();
550 #endif
551 
552  CPT(RenderEffects) _effects;
553 
554  TagData _tag_data;
555 #ifdef HAVE_PYTHON
556  PythonTagData _python_tag_data;
557 #endif // HAVE_PYTHON
558 
559  // These two together determine the per-camera visibility of this
560  // node. See adjust_draw_mask() for details.
561  DrawMask _draw_control_mask, _draw_show_mask;
562 
563  // This is the mask that indicates which CollisionNodes may detect
564  // a collision with this particular node. By default it is zero
565  // for an ordinary PandaNode, and all bits on for a CollisionNode
566  // or GeomNode.
567  CollideMask _into_collide_mask;
568 
569  // The requested bounding volume type.
570  BoundingVolume::BoundsType _bounds_type;
571 
572  // This is the user bounding volume, which is only specified by a
573  // user. It defaults to NULL, which means an empty volume.
574  CPT(BoundingVolume) _user_bounds;
575 
576  // See BoundsData, above, for _internal_bounds.
577 
578  // This is true if the external bounds of this node should be
579  // deemed "final". See set_final().
580  bool _final_bounds;
581 
582  // This bitmask is maintained automatically by the internal
583  // PandaNode code; it contains a 1 for each "fancy" attribute that
584  // is set on the node. See enum FancyBits, above.
585  int _fancy_bits;
586 
587  public:
588  // This section contains the data that is accumulated upward from
589  // the node's children: that is, the external bounding volume, and
590  // conceptually similar things like the net_collide_mask, etc.
591  // None of the data in this object is preserved in a bam file.
592 
593  // This is the union of all into_collide_mask bits for any nodes
594  // at and below this level.
595  CollideMask _net_collide_mask;
596 
597  // These are similar, for the draw mask.
598  DrawMask _net_draw_control_mask, _net_draw_show_mask;
599 
600  // This is a ClipPlaneAttrib that represents the union of all clip
601  // planes that have been turned *off* at and below this level.
602  // TODO: fix the circular reference counts involved here.
603  CPT(RenderAttrib) _off_clip_planes;
604 
605  // The number of vertices rendered by this node and all child
606  // nodes.
607  int _nested_vertices;
608 
609  // This is the bounding volume around the _user_bounds, the
610  // _internal_bounds, and all of the children's external bounding
611  // volumes.
612  CPT(BoundingVolume) _external_bounds;
613 
614  // When _last_update != _next_update, this cache is stale.
615  UpdateSeq _last_update, _next_update;
616 
617  // We don't always update the bounding volume and number of
618  // nested vertices. This indicates the last time they were changed.
619  // It is never higher than _last_update.
620  UpdateSeq _last_bounds_update;
621 
622  public:
623  // This section stores the links to other nodes above and below
624  // this node in the graph.
625 
626  void write_up_list(const Up &up_list,
627  BamWriter *manager, Datagram &dg) const;
628  void write_down_list(const Down &down_list,
629  BamWriter *manager, Datagram &dg) const;
630  void update_up_list(const Up &up_list, BamWriter *manager) const;
631  void update_down_list(const Down &down_list, BamWriter *manager) const;
632  int complete_up_list(Up &up_list, const string &tag,
633  TypedWritable **p_list, BamReader *manager);
634  int complete_down_list(Down &down_list, const string &tag,
635  TypedWritable **p_list, BamReader *manager);
636  void fillin_up_list(Up &up_list, const string &tag,
637  DatagramIterator &scan, BamReader *manager);
638  void fillin_down_list(Down &down_list, const string &tag,
639  DatagramIterator &scan, BamReader *manager);
640 
641  INLINE CPT(Down) get_down() const;
642  INLINE PT(Down) modify_down();
643  INLINE CPT(Down) get_stashed() const;
644  INLINE PT(Down) modify_stashed();
645  INLINE CPT(Up) get_up() const;
646  INLINE PT(Up) modify_up();
647 
648  private:
649  // We store the child lists by reference, so we can copy them
650  // quickly. We perform copy-on-write when necessary.
651  COWPT(Down) _down;
652  COWPT(Down) _stashed;
653  COWPT(Up) _up;
654 
655  public:
656  static TypeHandle get_class_type() {
657  return _type_handle;
658  }
659  static void init_type() {
660  register_type(_type_handle, "PandaNode::CData");
661  }
662 
663  private:
664  static TypeHandle _type_handle;
665  };
666 
667  PipelineCycler<CData> _cycler;
668  typedef CycleDataReader<CData> CDReader;
669  typedef CycleDataWriter<CData> CDWriter;
670  typedef CycleDataLockedStageReader<CData> CDLockedStageReader;
671  typedef CycleDataStageReader<CData> CDStageReader;
672  typedef CycleDataStageWriter<CData> CDStageWriter;
673 
674  int do_find_child(PandaNode *node, const Down *down) const;
675  CDStageWriter update_cached(bool update_bounds, int pipeline_stage,
676  CDLockedStageReader &cdata);
677 
678  static DrawMask _overall_bit;
679 
680  static PStatCollector _reset_prev_pcollector;
681  static PStatCollector _update_bounds_pcollector;
682 
683 public:
684  // This class is returned from get_children(). Use it to walk
685  // through the list of children. This is faster, and safer, than
686  // walking through the children one at a time via
687  // get_num_children()/get_child(), since the list of children is
688  // saved out ahead of time, rather than having to reacquire the lock
689  // with each iteration, or to keep the lock held for the entire
690  // pass.
691  class EXPCL_PANDA_PGRAPH Children {
692  public:
693  INLINE Children();
694  INLINE Children(const CData *cdata);
695  INLINE Children(const Children &copy);
696  INLINE void operator = (const Children &copy);
697 
698 #ifdef USE_MOVE_SEMANTICS
699  INLINE Children(Children &&from) NOEXCEPT;
700  INLINE void operator = (Children &&from) NOEXCEPT;
701 #endif
702 
703  INLINE int get_num_children() const;
704  INLINE PandaNode *get_child(int n) const;
705  INLINE int get_child_sort(int n) const;
706 
707  private:
708  CPT(Down) _down;
709  };
710 
711  // Similarly for stashed children.
712  class EXPCL_PANDA_PGRAPH Stashed {
713  public:
714  INLINE Stashed();
715  INLINE Stashed(const CData *cdata);
716  INLINE Stashed(const Stashed &copy);
717  INLINE void operator = (const Stashed &copy);
718 
719 #ifdef USE_MOVE_SEMANTICS
720  INLINE Stashed(Stashed &&from) NOEXCEPT;
721  INLINE void operator = (Stashed &&from) NOEXCEPT;
722 #endif
723 
724  INLINE int get_num_stashed() const;
725  INLINE PandaNode *get_stashed(int n) const;
726  INLINE int get_stashed_sort(int n) const;
727 
728  private:
729  CPT(Down) _stashed;
730  };
731 
732  // This class is returned from get_parents().
733  class EXPCL_PANDA_PGRAPH Parents {
734  public:
735  INLINE Parents();
736  INLINE Parents(const CData *cdata);
737  INLINE Parents(const Parents &copy);
738  INLINE void operator = (const Parents &copy);
739 
740 #ifdef USE_MOVE_SEMANTICS
741  INLINE Parents(Parents &&from) NOEXCEPT;
742  INLINE void operator = (Parents &&from) NOEXCEPT;
743 #endif
744 
745  INLINE int get_num_parents() const;
746  INLINE PandaNode *get_parent(int n) const;
747 
748  private:
749  CPT(Up) _up;
750  };
751 
752  INLINE Children get_children(Thread *current_thread = Thread::get_current_thread()) const;
753  INLINE Stashed get_stashed(Thread *current_thread = Thread::get_current_thread()) const;
754  INLINE Parents get_parents(Thread *current_thread = Thread::get_current_thread()) const;
755 
756  typedef bool SceneRootFunc(const PandaNode *);
757  static void set_scene_root_func(SceneRootFunc *func);
758 
759 private:
760  static SceneRootFunc *_scene_root_func;
761 
762 public:
763  static void register_with_read_factory();
764  virtual void write_datagram(BamWriter *manager, Datagram &dg);
765  virtual void update_bam_nested(BamWriter *manager);
766  void write_recorder(BamWriter *manager, Datagram &dg);
767 
768 protected:
769  static TypedWritable *make_from_bam(const FactoryParams &params);
770  void fillin(DatagramIterator &scan, BamReader *manager);
771  void fillin_recorder(DatagramIterator &scan, BamReader *manager);
772 
773 public:
774  static TypeHandle get_class_type() {
775  return _type_handle;
776  }
777  static void init_type() {
778  TypedWritable::init_type();
779  ReferenceCount::init_type();
780  Namable::init_type();
781  register_type(_type_handle, "PandaNode",
782  TypedWritable::get_class_type(),
783  ReferenceCount::get_class_type(),
784  Namable::get_class_type());
785  CData::init_type();
786  Down::init_type();
787  Up::init_type();
788  BamReaderAuxDataDown::init_type();
789  }
790  virtual TypeHandle get_type() const {
791  return get_class_type();
792  }
793  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
794 
795 private:
796  static TypeHandle _type_handle;
797 
798 #ifndef DO_PIPELINING
799  friend class PandaNode::Children;
800  friend class PandaNode::Stashed;
801 #endif
802  friend class NodePath;
803  friend class NodePathComponent;
804  friend class WorkingNodePath;
805  friend class PandaNodePipelineReader;
806  friend class EggLoader;
807  friend class Extension<PandaNode>;
808 };
809 
810 ////////////////////////////////////////////////////////////////////
811 // Class : PandaNodePipelineReader
812 // Description : Encapsulates the data from a PandaNode,
813 // pre-fetched for one stage of the pipeline.
814 ////////////////////////////////////////////////////////////////////
815 class EXPCL_PANDA_PGRAPH PandaNodePipelineReader {
816 public:
817  INLINE PandaNodePipelineReader(const PandaNode *object, Thread *current_thread);
818  INLINE PandaNodePipelineReader(const PandaNodePipelineReader &copy);
819  INLINE void operator = (const PandaNodePipelineReader &copy);
820 
821 public:
822  INLINE ~PandaNodePipelineReader();
823  ALLOC_DELETED_CHAIN(PandaNodePipelineReader);
824 
825  INLINE const PandaNode *get_node() const;
826  INLINE Thread *get_current_thread() const;
827 
828  INLINE void release();
829 
830  void check_cached(bool update_bounds) const;
831 
832  INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
833  INLINE bool compare_draw_mask(DrawMask running_draw_mask,
834  DrawMask camera_mask) const;
835 
836  INLINE int get_num_parents() const;
837  INLINE PandaNode *get_parent(int n) const;
838  INLINE int find_parent(PandaNode *node) const;
839 
840  INLINE int get_num_children() const;
841  INLINE PandaNode *get_child(int n) const;
842  INLINE int get_child_sort(int n) const;
843  INLINE int find_child(PandaNode *node) const;
844 
845  INLINE int get_num_stashed() const;
846  INLINE PandaNode *get_stashed(int n) const;
847  INLINE int get_stashed_sort(int n) const;
848  INLINE int find_stashed(PandaNode *node) const;
849 
850  INLINE const RenderState *get_state() const;
851  INLINE const RenderEffects *get_effects() const;
852  INLINE const TransformState *get_transform() const;
853  INLINE const TransformState *get_prev_transform() const;
854 
855  INLINE string get_tag(const string &key) const;
856  INLINE bool has_tag(const string &key) const;
857 
858  INLINE CollideMask get_net_collide_mask() const;
859  INLINE CPT(RenderAttrib) get_off_clip_planes() const;
860  INLINE CPT(BoundingVolume) get_bounds() const;
861  INLINE int get_nested_vertices() const;
862  INLINE bool is_final() const;
863  INLINE int get_fancy_bits() const;
864 
865  INLINE PandaNode::Children get_children() const;
866  INLINE PandaNode::Stashed get_stashed() const;
867  INLINE PandaNode::Parents get_parents() const;
868 
869 private:
870  const PandaNode *_node;
871  Thread *_current_thread;
872 
873  const PandaNode::CData *_cdata;
874 
875 public:
876  static TypeHandle get_class_type() {
877  return _type_handle;
878  }
879  static void init_type() {
880  register_type(_type_handle, "PandaNodePipelineReader");
881  }
882 
883 private:
884  static TypeHandle _type_handle;
885 
886 };
887 
888 INLINE ostream &operator << (ostream &out, const PandaNode &node) {
889  node.output(out);
890  return out;
891 }
892 
893 #include "pandaNode.I"
894 
895 #endif
896 
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
The abstract interface to all kinds of lights.
Definition: light.h:42
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:60
Stores auxiliary data that may be piggybacked on the BamReader during each object&#39;s read pass...
Definition: bamReader.h:64
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
A lightweight reentrant mutex.
Definition: lightReMutex.h:34
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:56
This is our own Panda specialization on the default STL list.
Definition: plist.h:38
This is a class designed to support low-overhead traversals of the complete scene graph...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
This just stores the pointers to implement a doubly-linked list of some kind of object.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
A base class for all things which can have a name.
Definition: namable.h:29
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
A specialization of ordered_vector that emulates a standard STL set: many copies of each element are ...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
The default class template does not define any methods.
Definition: extension.h:39
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
void output(ostream &out) const
Outputs the Namable.
Definition: namable.I:97
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A thread; that is, a lightweight process.
Definition: thread.h:51
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Definition: pandaNode.h:815
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
Definition: renderEffects.h:46
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
Definition: cullTraverser.h:48
This class maintains a linked list of PandaNodes.
Converts an egg data structure, possibly read from an egg file but not necessarily, into a scene graph suitable for rendering.
Definition: eggLoader.h:70
This is one component of a NodePath.
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...