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
19 #include "nodeCachedReferenceCount.h"
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
36 class GraphicsStateGuardianBase;
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:
56 TransformState();
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;
260 typedef SimpleHashMap<const TransformState *, std::nullptr_t, indirect_equals_hash<const TransformState *> > States;
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
290 typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
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
cacheStats.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
CacheStats
This is used to track the utilization of the TransformState and RenderState caches,...
Definition: cacheStats.h:25
CachedTypedWritableReferenceCount::cache_ref
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
Definition: cachedTypedWritableReferenceCount.I:119
CachedTypedWritableReferenceCount::cache_unref
bool cache_unref() const
Explicitly decrements the cache reference count and the normal reference count simultaneously.
Definition: cachedTypedWritableReferenceCount.I:136
CachedTypedWritableReferenceCount::cache_ref_only
void cache_ref_only() const
Decrements the cache reference count without affecting the normal reference count.
Definition: cachedTypedWritableReferenceCount.I:168
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Extension
The default class template does not define any methods.
Definition: extension.h:34
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
LightMutex
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:41
LightReMutex
A lightweight reentrant mutex.
Definition: lightReMutex.h:32
NodeCachedReferenceCount
This class further specializes CachedTypedWritableReferenceCount to also add a node_ref_count,...
Definition: nodeCachedReferenceCount.h:49
NodeCachedReferenceCount::node_unref
bool node_unref() const
Explicitly decrements the node reference count and the normal reference count simultaneously.
Definition: nodeCachedReferenceCount.I:140
NodeCachedReferenceCount::node_ref
void node_ref() const
Explicitly increments the reference count.
Definition: nodeCachedReferenceCount.I:123
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
PointerToBase
This is the base class for PointerTo and ConstPointerTo.
Definition: pointerToBase.h:29
SimpleHashMap
This template class implements an unordered map of keys to data, implemented as a hashtable.
Definition: simpleHashMap.h:81
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
TransformState::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
TransformState::unref
virtual bool unref() const
Explicitly decrements the reference count.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedWritableReferenceCount
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
Definition: typedWritableReferenceCount.h:31
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
TypedWritable::fillin
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...
Definition: typedWritable.cxx:103
UpdateSeq
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
compare_to
An STL function object class, this is intended to be used on any ordered collection of class objects ...
Definition: stl_compares.h:73
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
deletedChain.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
extension.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomEnums.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightMutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightReMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightReMutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
luse.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
nodeCachedReferenceCount.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatCollector.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pointerTo.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
register_type
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
simpleHashMap.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TransformState
STTransform::operator CPT() TransformState() const
This is used internally to convert an STTransform into a TransformState pointer.
Definition: stTransform.I:98
transformState.I
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
updateSeq.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.