Panda3D
transformState.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file transformState.h
10  * @author drose
11  * @date 2002-02-25
12  */
13 
14 #ifndef TRANSFORMSTATE_H
15 #define TRANSFORMSTATE_H
16 
17 #include "pandabase.h"
18 
20 #include "pointerTo.h"
21 #include "luse.h"
22 #include "event.h"
23 #include "updateSeq.h"
24 #include "pStatCollector.h"
25 #include "geomEnums.h"
26 #include "lightReMutex.h"
27 #include "lightReMutexHolder.h"
28 #include "lightMutex.h"
29 #include "lightMutexHolder.h"
30 #include "config_pgraph.h"
31 #include "deletedChain.h"
32 #include "simpleHashMap.h"
33 #include "cacheStats.h"
34 #include "extension.h"
35 
37 class FactoryParams;
38 
39 /**
40  * Indicates a coordinate-system transform on vertices. TransformStates are
41  * the primary means for storing transformations on the scene graph.
42  *
43  * Transforms may be specified in one of two ways: componentwise, with a pos-
44  * hpr-scale, or with an arbitrary transform matrix. If you specify a
45  * transform componentwise, it will remember its original components.
46  *
47  * TransformState objects are managed very much like RenderState objects.
48  * They are immutable and reference-counted automatically.
49  *
50  * You should not attempt to create or modify a TransformState object
51  * directly. Instead, call one of the make() functions to create one for you.
52  * And instead of modifying a TransformState object, create a new one.
53  */
54 class EXPCL_PANDA_PGRAPH TransformState final : public NodeCachedReferenceCount {
55 protected:
57 
58 public:
59  TransformState(const TransformState &copy) = delete;
60  virtual ~TransformState();
61  ALLOC_DELETED_CHAIN(TransformState);
62 
63  TransformState &operator = (const TransformState &copy) = delete;
64 
65 PUBLISHED:
66  INLINE bool operator != (const TransformState &other) const;
67  INLINE int compare_to(const TransformState &other) const;
68  int compare_to(const TransformState &other, bool uniquify_matrix) const;
69  bool operator == (const TransformState &other) const;
70  INLINE size_t get_hash() const;
71 
72  static CPT(TransformState) make_identity();
73  static CPT(TransformState) make_invalid();
74  INLINE static CPT(TransformState) make_pos(const LVecBase3 &pos);
75  INLINE static CPT(TransformState) make_hpr(const LVecBase3 &hpr);
76  INLINE static CPT(TransformState) make_quat(const LQuaternion &quat);
77  INLINE static CPT(TransformState) make_pos_hpr(const LVecBase3 &pos,
78  const LVecBase3 &hpr);
79  INLINE static CPT(TransformState) make_scale(PN_stdfloat scale);
80  INLINE static CPT(TransformState) make_scale(const LVecBase3 &scale);
81  INLINE static CPT(TransformState) make_shear(const LVecBase3 &shear);
82  INLINE static CPT(TransformState) make_pos_hpr_scale(const LVecBase3 &pos,
83  const LVecBase3 &hpr,
84  const LVecBase3 &scale);
85  INLINE static CPT(TransformState) make_pos_quat_scale(const LVecBase3 &pos,
86  const LQuaternion &quat,
87  const LVecBase3 &scale);
88  static CPT(TransformState) make_pos_hpr_scale_shear(const LVecBase3 &pos,
89  const LVecBase3 &hpr,
90  const LVecBase3 &scale,
91  const LVecBase3 &shear);
92  static CPT(TransformState) make_pos_quat_scale_shear(const LVecBase3 &pos,
93  const LQuaternion &quat,
94  const LVecBase3 &scale,
95  const LVecBase3 &shear);
96  static CPT(TransformState) make_mat(const LMatrix4 &mat);
97 
98 
99  INLINE static CPT(TransformState) make_pos2d(const LVecBase2 &pos);
100  INLINE static CPT(TransformState) make_rotate2d(PN_stdfloat rotate);
101  INLINE static CPT(TransformState) make_pos_rotate2d(const LVecBase2 &pos,
102  PN_stdfloat rotate);
103  INLINE static CPT(TransformState) make_scale2d(PN_stdfloat scale);
104  INLINE static CPT(TransformState) make_scale2d(const LVecBase2 &scale);
105  INLINE static CPT(TransformState) make_shear2d(PN_stdfloat shear);
106  INLINE static CPT(TransformState) make_pos_rotate_scale2d(const LVecBase2 &pos,
107  PN_stdfloat rotate,
108  const LVecBase2 &scale);
109  static CPT(TransformState) make_pos_rotate_scale_shear2d(const LVecBase2 &pos,
110  PN_stdfloat rotate,
111  const LVecBase2 &scale,
112  PN_stdfloat shear);
113  static CPT(TransformState) make_mat3(const LMatrix3 &mat);
114 
115 
116  INLINE bool is_identity() const;
117  INLINE bool is_invalid() const;
118  INLINE bool is_singular() const;
119  INLINE bool is_2d() const;
120 
121  INLINE bool has_components() const;
122  INLINE bool components_given() const;
123  INLINE bool hpr_given() const;
124  INLINE bool quat_given() const;
125  INLINE bool has_pos() const;
126  INLINE bool has_hpr() const;
127  INLINE bool has_quat() const;
128  INLINE bool has_scale() const;
129  INLINE bool has_identity_scale() const;
130  INLINE bool has_uniform_scale() const;
131  INLINE bool has_shear() const;
132  INLINE bool has_nonzero_shear() const;
133  INLINE bool has_mat() const;
134 
135  INLINE const LPoint3 &get_pos() const;
136  INLINE const LVecBase3 &get_hpr() const;
137  INLINE const LQuaternion &get_quat() const;
138  INLINE const LQuaternion &get_norm_quat() const;
139  INLINE const LVecBase3 &get_scale() const;
140  INLINE PN_stdfloat get_uniform_scale() const;
141  INLINE const LVecBase3 &get_shear() const;
142  INLINE const LMatrix4 &get_mat() const;
143 
144  INLINE LVecBase2 get_pos2d() const;
145  INLINE PN_stdfloat get_rotate2d() const;
146  INLINE LVecBase2 get_scale2d() const;
147  INLINE PN_stdfloat get_shear2d() const;
148  INLINE LMatrix3 get_mat3() const;
149 
150  MAKE_PROPERTY(pos, get_pos);
151  MAKE_PROPERTY(hpr, get_hpr);
152  MAKE_PROPERTY(quat, get_quat);
153  MAKE_PROPERTY(norm_quat, get_norm_quat);
154  MAKE_PROPERTY(scale, get_scale);
155  MAKE_PROPERTY(shear, get_shear);
156  MAKE_PROPERTY(mat, get_mat);
157 
158  CPT(TransformState) set_pos(const LVecBase3 &pos) const;
159  CPT(TransformState) set_hpr(const LVecBase3 &hpr) const;
160  CPT(TransformState) set_quat(const LQuaternion &quat) const;
161  CPT(TransformState) set_scale(const LVecBase3 &scale) const;
162  CPT(TransformState) set_shear(const LVecBase3 &shear) const;
163 
164  CPT(TransformState) set_pos2d(const LVecBase2 &pos) const;
165  CPT(TransformState) set_rotate2d(PN_stdfloat rotate) const;
166  CPT(TransformState) set_scale2d(const LVecBase2 &scale) const;
167  CPT(TransformState) set_shear2d(PN_stdfloat shear) const;
168 
169  CPT(TransformState) compose(const TransformState *other) const;
170  CPT(TransformState) invert_compose(const TransformState *other) const;
171 
172  INLINE CPT(TransformState) get_inverse() const;
173  INLINE CPT(TransformState) get_unique() const;
174 
175  INLINE int get_geom_rendering(int geom_rendering) const;
176 
177  virtual bool unref() const;
178 
179  INLINE void cache_ref() const;
180  INLINE bool cache_unref() const;
181  INLINE void node_ref() const;
182  INLINE bool node_unref() const;
183 
184  INLINE size_t get_composition_cache_num_entries() const;
185  INLINE size_t get_invert_composition_cache_num_entries() const;
186 
187  INLINE size_t get_composition_cache_size() const;
188  INLINE const TransformState *get_composition_cache_source(size_t n) const;
189  INLINE const TransformState *get_composition_cache_result(size_t n) const;
190  INLINE size_t get_invert_composition_cache_size() const;
191  INLINE const TransformState *get_invert_composition_cache_source(size_t n) const;
192  INLINE const TransformState *get_invert_composition_cache_result(size_t n) const;
193  bool validate_composition_cache() const;
194  EXTENSION(PyObject *get_composition_cache() const);
195  EXTENSION(PyObject *get_invert_composition_cache() const);
196 
197  void output(std::ostream &out) const;
198  void write(std::ostream &out, int indent_level) const;
199  void write_composition_cache(std::ostream &out, int indent_level) const;
200 
201  static int get_num_states();
202  static int get_num_unused_states();
203  static int clear_cache();
204  static int garbage_collect();
205  static void list_cycles(std::ostream &out);
206  static void list_states(std::ostream &out);
207  static bool validate_states();
208  EXTENSION(static PyObject *get_states());
209  EXTENSION(static PyObject *get_unused_states());
210 
211 public:
212  static void init_states();
213 
214  INLINE static void flush_level();
215 
216 private:
217  INLINE bool do_cache_unref() const;
218  INLINE bool do_node_unref() const;
219 
220  class CompositionCycleDescEntry {
221  public:
222  INLINE CompositionCycleDescEntry(const TransformState *obj,
223  const TransformState *result,
224  bool inverted);
225 
226  const TransformState *_obj;
227  const TransformState *_result;
228  bool _inverted;
229  };
230  typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
231 
232  static CPT(TransformState) return_new(TransformState *state);
233  static CPT(TransformState) return_unique(TransformState *state);
234 
235  CPT(TransformState) do_compose(const TransformState *other) const;
236  CPT(TransformState) do_invert_compose(const TransformState *other) const;
237  void detect_and_break_cycles();
238  static bool r_detect_cycles(const TransformState *start_state,
239  const TransformState *current_state,
240  int length, UpdateSeq this_seq,
241  CompositionCycleDesc *cycle_desc);
242  static bool r_detect_reverse_cycles(const TransformState *start_state,
243  const TransformState *current_state,
244  int length, UpdateSeq this_seq,
245  CompositionCycleDesc *cycle_desc);
246 
247  void release_new();
248  void remove_cache_pointers();
249 
250 private:
251  // This mutex protects _states. It also protects any modification to the
252  // cache, which is encoded in _composition_cache and
253  // _invert_composition_cache.
254  static LightReMutex *_states_lock;
256  static States *_states;
257  static CPT(TransformState) _identity_state;
258  static CPT(TransformState) _invalid_state;
259 
260  // This iterator records the entry corresponding to this TransformState
261  // object in the above global set. We keep the index around so we can
262  // remove it when the TransformState destructs.
263  int _saved_entry;
264 
265  // This data structure manages the job of caching the composition of two
266  // TransformStates. It's complicated because we have to be sure to remove
267  // the entry if *either* of the input TransformStates destructs. To
268  // implement this, we always record Composition entries in pairs, one in
269  // each of the two involved TransformState objects.
270 
271  // The first element of the map is the object we compose with. This is not
272  // reference counted within this map; instead we store a companion pointer
273  // in the other object, and remove the references explicitly when either
274  // object destructs.
275  class Composition {
276  public:
277  INLINE Composition();
278  INLINE Composition(const Composition &copy);
279 
280  // _result is reference counted if and only if it is not the same pointer
281  // as this.
282  const TransformState *_result;
283  };
284 
286  mutable CompositionCache _composition_cache;
287  mutable CompositionCache _invert_composition_cache;
288 
289  // This is used to mark nodes as we visit them to detect cycles.
290  UpdateSeq _cycle_detect;
291  static UpdateSeq _last_cycle_detect;
292 
293  // This keeps track of our current position through the garbage collection
294  // cycle.
295  static size_t _garbage_index;
296 
297  static bool _uniquify_matrix;
298 
299  static PStatCollector _cache_update_pcollector;
300  static PStatCollector _garbage_collect_pcollector;
301  static PStatCollector _transform_compose_pcollector;
302  static PStatCollector _transform_invert_pcollector;
303  static PStatCollector _transform_calc_pcollector;
304  static PStatCollector _transform_break_cycles_pcollector;
305  static PStatCollector _transform_new_pcollector;
306  static PStatCollector _transform_validate_pcollector;
307  static PStatCollector _transform_hash_pcollector;
308 
309  static PStatCollector _node_counter;
310  static PStatCollector _cache_counter;
311 
312 private:
313  // This is the actual data within the TransformState.
314  INLINE void check_hash() const;
315  INLINE void check_singular() const;
316  INLINE void check_components() const;
317  INLINE void check_hpr() const;
318  INLINE void check_quat() const;
319  INLINE void check_norm_quat() const;
320  INLINE void check_mat() const;
321  INLINE void calc_hash();
322  void do_calc_hash();
323  void calc_singular();
324  INLINE void calc_components();
325  void do_calc_components();
326  INLINE void calc_hpr();
327  void do_calc_hpr();
328  void calc_quat();
329  void calc_norm_quat();
330  INLINE void calc_mat();
331  void do_calc_mat();
332 
333  INLINE void check_uniform_scale();
334  INLINE void check_uniform_scale2d();
335 
336  INLINE void set_destructing();
337  INLINE bool is_destructing() const;
338 
339  INLINE void consider_update_pstats(int old_referenced_bits) const;
340  static void update_pstats(int old_referenced_bits, int new_referenced_bits);
341 
342  enum Flags {
343  F_is_identity = 0x00000001,
344  F_is_singular = 0x00000002,
345  F_singular_known = 0x00000004, // set if we know F_is_singular
346  F_components_given = 0x00000008,
347  F_components_known = 0x00000010, // set if we know F_has_components
348  F_has_components = 0x00000020,
349  F_mat_known = 0x00000040, // set if _mat is defined
350  F_is_invalid = 0x00000080,
351  F_quat_given = 0x00000100,
352  F_quat_known = 0x00000200, // set if _quat is defined
353  F_hpr_given = 0x00000400,
354  F_hpr_known = 0x00000800, // set if _hpr is defined
355  F_uniform_scale = 0x00001000,
356  F_identity_scale = 0x00002000,
357  F_has_nonzero_shear = 0x00004000,
358  F_is_destructing = 0x00008000,
359  F_is_2d = 0x00010000,
360  F_hash_known = 0x00020000,
361  F_norm_quat_known = 0x00040000,
362  };
363  LPoint3 _pos;
364  LVecBase3 _hpr, _scale, _shear;
365  LQuaternion _quat, _norm_quat;
366  LMatrix4 _mat;
367  LMatrix4 *_inv_mat;
368  size_t _hash;
369 
370  unsigned int _flags;
371 
372  // This mutex protects _flags, and all of the above computed values.
373  LightMutex _lock;
374 
375  static CacheStats _cache_stats;
376 
377 public:
378  static void register_with_read_factory();
379  virtual void write_datagram(BamWriter *manager, Datagram &dg);
380  static PT(TypedWritableReferenceCount) change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager);
381 
382 protected:
383  static TypedWritable *make_from_bam(const FactoryParams &params);
384  void fillin(DatagramIterator &scan, BamReader *manager);
385 
386 public:
387  static TypeHandle get_class_type() {
388  return _type_handle;
389  }
390  static void init_type() {
391  NodeCachedReferenceCount::init_type();
392  register_type(_type_handle, "TransformState",
393  NodeCachedReferenceCount::get_class_type());
394  }
395  virtual TypeHandle get_type() const {
396  return get_class_type();
397  }
398  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
399 
400 private:
401  static TypeHandle _type_handle;
402 
403  friend class Extension<TransformState>;
404 };
405 
406 // We can safely redefine this as a no-op.
407 template<>
408 INLINE void PointerToBase<TransformState>::update_type(To *ptr) {}
409 
410 INLINE std::ostream &operator << (std::ostream &out, const TransformState &state) {
411  state.output(out);
412  return out;
413 }
414 
415 #include "transformState.I"
416 
417 #endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Indicates a coordinate-system transform on vertices.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class further specializes CachedTypedWritableReferenceCount to also add a node_ref_count,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight reentrant mutex.
Definition: lightReMutex.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void node_ref() const
Explicitly increments the reference count.
This template class implements an unordered map of keys to data, implemented as a hashtable.
Definition: simpleHashMap.h:81
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
A lightweight class that represents a single element that may be timed and/or counted via stats.
bool cache_unref() const
Explicitly decrements the cache reference count and the normal reference count simultaneously.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The default class template does not define any methods.
Definition: extension.h:34
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An STL function object class, this is intended to be used on any ordered collection of class objects ...
Definition: stl_compares.h:73
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is used to track the utilization of the TransformState and RenderState caches,...
Definition: cacheStats.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A class to retrieve the individual data elements previously stored in a Datagram.
STTransform::operator CPT() TransformState() const
This is used internally to convert an STTransform into a TransformState pointer.
Definition: stTransform.I:98
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
virtual bool unref() const
Explicitly decrements the reference count.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.