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  INLINE void cache_ref_only() const;
217 
218 protected:
219  INLINE void cache_unref_only() const;
220 
221 private:
222  INLINE bool do_cache_unref() const;
223  INLINE bool do_node_unref() const;
224 
225  class CompositionCycleDescEntry {
226  public:
227  INLINE CompositionCycleDescEntry(const TransformState *obj,
228  const TransformState *result,
229  bool inverted);
230 
231  const TransformState *_obj;
232  const TransformState *_result;
233  bool _inverted;
234  };
235  typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
236 
237  static CPT(TransformState) return_new(TransformState *state);
238  static CPT(TransformState) return_unique(TransformState *state);
239 
240  CPT(TransformState) do_compose(const TransformState *other) const;
241  CPT(TransformState) do_invert_compose(const TransformState *other) const;
242  void detect_and_break_cycles();
243  static bool r_detect_cycles(const TransformState *start_state,
244  const TransformState *current_state,
245  int length, UpdateSeq this_seq,
246  CompositionCycleDesc *cycle_desc);
247  static bool r_detect_reverse_cycles(const TransformState *start_state,
248  const TransformState *current_state,
249  int length, UpdateSeq this_seq,
250  CompositionCycleDesc *cycle_desc);
251 
252  void release_new();
253  void remove_cache_pointers();
254 
255 private:
256  // This mutex protects _states. It also protects any modification to the
257  // cache, which is encoded in _composition_cache and
258  // _invert_composition_cache.
259  static LightReMutex *_states_lock;
261  static States *_states;
262  static CPT(TransformState) _identity_state;
263  static CPT(TransformState) _invalid_state;
264 
265  // This iterator records the entry corresponding to this TransformState
266  // object in the above global set. We keep the index around so we can
267  // remove it when the TransformState destructs.
268  int _saved_entry;
269 
270  // This data structure manages the job of caching the composition of two
271  // TransformStates. It's complicated because we have to be sure to remove
272  // the entry if *either* of the input TransformStates destructs. To
273  // implement this, we always record Composition entries in pairs, one in
274  // each of the two involved TransformState objects.
275 
276  // The first element of the map is the object we compose with. This is not
277  // reference counted within this map; instead we store a companion pointer
278  // in the other object, and remove the references explicitly when either
279  // object destructs.
280  class Composition {
281  public:
282  INLINE Composition();
283  INLINE Composition(const Composition &copy);
284 
285  // _result is reference counted if and only if it is not the same pointer
286  // as this.
287  const TransformState *_result;
288  };
289 
291  mutable CompositionCache _composition_cache;
292  mutable CompositionCache _invert_composition_cache;
293 
294  // This is used to mark nodes as we visit them to detect cycles.
295  UpdateSeq _cycle_detect;
296  static UpdateSeq _last_cycle_detect;
297 
298  // This keeps track of our current position through the garbage collection
299  // cycle.
300  static size_t _garbage_index;
301 
302  static bool _uniquify_matrix;
303 
304  static PStatCollector _cache_update_pcollector;
305  static PStatCollector _garbage_collect_pcollector;
306  static PStatCollector _transform_compose_pcollector;
307  static PStatCollector _transform_invert_pcollector;
308  static PStatCollector _transform_calc_pcollector;
309  static PStatCollector _transform_break_cycles_pcollector;
310  static PStatCollector _transform_new_pcollector;
311  static PStatCollector _transform_validate_pcollector;
312  static PStatCollector _transform_hash_pcollector;
313 
314  static PStatCollector _node_counter;
315  static PStatCollector _cache_counter;
316 
317 private:
318  // This is the actual data within the TransformState.
319  INLINE void check_hash() const;
320  INLINE void check_singular() const;
321  INLINE void check_components() const;
322  INLINE void check_hpr() const;
323  INLINE void check_quat() const;
324  INLINE void check_norm_quat() const;
325  INLINE void check_mat() const;
326  INLINE void calc_hash();
327  void do_calc_hash();
328  void calc_singular();
329  INLINE void calc_components();
330  void do_calc_components();
331  INLINE void calc_hpr();
332  void do_calc_hpr();
333  void calc_quat();
334  void calc_norm_quat();
335  INLINE void calc_mat();
336  void do_calc_mat();
337 
338  INLINE void check_uniform_scale();
339  INLINE void check_uniform_scale2d();
340 
341  INLINE void set_destructing();
342  INLINE bool is_destructing() const;
343 
344  INLINE void consider_update_pstats(int old_referenced_bits) const;
345  static void update_pstats(int old_referenced_bits, int new_referenced_bits);
346 
347  enum Flags {
348  F_is_identity = 0x00000001,
349  F_is_singular = 0x00000002,
350  F_singular_known = 0x00000004, // set if we know F_is_singular
351  F_components_given = 0x00000008,
352  F_components_known = 0x00000010, // set if we know F_has_components
353  F_has_components = 0x00000020,
354  F_mat_known = 0x00000040, // set if _mat is defined
355  F_is_invalid = 0x00000080,
356  F_quat_given = 0x00000100,
357  F_quat_known = 0x00000200, // set if _quat is defined
358  F_hpr_given = 0x00000400,
359  F_hpr_known = 0x00000800, // set if _hpr is defined
360  F_uniform_scale = 0x00001000,
361  F_identity_scale = 0x00002000,
362  F_has_nonzero_shear = 0x00004000,
363  F_is_destructing = 0x00008000,
364  F_is_2d = 0x00010000,
365  F_hash_known = 0x00020000,
366  F_norm_quat_known = 0x00040000,
367  };
368  LPoint3 _pos;
369  LVecBase3 _hpr, _scale, _shear;
370  LQuaternion _quat, _norm_quat;
371  LMatrix4 _mat;
372  LMatrix4 *_inv_mat;
373  size_t _hash;
374 
375  unsigned int _flags;
376 
377  // This mutex protects _flags, and all of the above computed values.
378  LightMutex _lock;
379 
380  static CacheStats _cache_stats;
381 
382 public:
383  static void register_with_read_factory();
384  virtual void write_datagram(BamWriter *manager, Datagram &dg);
385  static PT(TypedWritableReferenceCount) change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager);
386 
387 protected:
388  static TypedWritable *make_from_bam(const FactoryParams &params);
389  void fillin(DatagramIterator &scan, BamReader *manager);
390 
391 public:
392  static TypeHandle get_class_type() {
393  return _type_handle;
394  }
395  static void init_type() {
396  NodeCachedReferenceCount::init_type();
397  register_type(_type_handle, "TransformState",
398  NodeCachedReferenceCount::get_class_type());
399  }
400  virtual TypeHandle get_type() const {
401  return get_class_type();
402  }
403  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
404 
405 private:
406  static TypeHandle _type_handle;
407 
408  friend class Extension<TransformState>;
409 };
410 
411 // We can safely redefine this as a no-op.
412 template<>
413 INLINE void PointerToBase<TransformState>::update_type(To *ptr) {}
414 
415 INLINE std::ostream &operator << (std::ostream &out, const TransformState &state) {
416  state.output(out);
417  return out;
418 }
419 
420 #include "transformState.I"
421 
422 #endif
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
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
This is used to track the utilization of the TransformState and RenderState caches,...
Definition: cacheStats.h:25
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
bool cache_unref() const
Explicitly decrements the cache reference count and the normal reference count simultaneously.
void cache_ref_only() const
Decrements the cache reference count without affecting the normal reference count.
A class to retrieve the individual data elements previously stored in a Datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
The default class template does not define any methods.
Definition: extension.h:34
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:41
A lightweight reentrant mutex.
Definition: lightReMutex.h:32
This class further specializes CachedTypedWritableReferenceCount to also add a node_ref_count,...
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
void node_ref() const
Explicitly increments the reference count.
A lightweight class that represents a single element that may be timed and/or counted via stats.
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
This template class implements an unordered map of keys to data, implemented as a hashtable.
Definition: simpleHashMap.h:81
Indicates a coordinate-system transform on vertices.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual bool unref() const
Explicitly decrements the reference count.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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...
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
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 our own Panda specialization on the default STL vector.
Definition: pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
STTransform::operator CPT() TransformState() const
This is used internally to convert an STTransform into a TransformState pointer.
Definition: stTransform.I:98
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.