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