Panda3D
Loading...
Searching...
No Matches
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
37class 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 */
54class EXPCL_PANDA_PGRAPH TransformState final : public NodeCachedReferenceCount {
55protected:
57
58public:
59 TransformState(const TransformState &copy) = delete;
60 virtual ~TransformState();
61 ALLOC_DELETED_CHAIN(TransformState);
62
63 TransformState &operator = (const TransformState &copy) = delete;
64
65PUBLISHED:
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#ifdef CPPPARSER
136 // Force interrogate to make a copy as a temporary solution for #1625.
137 LPoint3 get_pos() const;
138 LVecBase3 get_hpr() const;
139 LQuaternion get_quat() const;
140 LQuaternion get_norm_quat() const;
141 LVecBase3 get_scale() const;
142 PN_stdfloat get_uniform_scale() const;
143 LVecBase3 get_shear() const;
144 LMatrix4 get_mat() const;
145#else
146 INLINE const LPoint3 &get_pos() const;
147 INLINE const LVecBase3 &get_hpr() const;
148 INLINE const LQuaternion &get_quat() const;
149 INLINE const LQuaternion &get_norm_quat() const;
150 INLINE const LVecBase3 &get_scale() const;
151 INLINE PN_stdfloat get_uniform_scale() const;
152 INLINE const LVecBase3 &get_shear() const;
153 INLINE const LMatrix4 &get_mat() const;
154#endif
155
156 INLINE LVecBase2 get_pos2d() const;
157 INLINE PN_stdfloat get_rotate2d() const;
158 INLINE LVecBase2 get_scale2d() const;
159 INLINE PN_stdfloat get_shear2d() const;
160 INLINE LMatrix3 get_mat3() const;
161
162 MAKE_PROPERTY(pos, get_pos);
163 MAKE_PROPERTY(hpr, get_hpr);
164 MAKE_PROPERTY(quat, get_quat);
165 MAKE_PROPERTY(norm_quat, get_norm_quat);
166 MAKE_PROPERTY(scale, get_scale);
167 MAKE_PROPERTY(shear, get_shear);
168 MAKE_PROPERTY(mat, get_mat);
169
170 CPT(TransformState) set_pos(const LVecBase3 &pos) const;
171 CPT(TransformState) set_hpr(const LVecBase3 &hpr) const;
172 CPT(TransformState) set_quat(const LQuaternion &quat) const;
173 CPT(TransformState) set_scale(const LVecBase3 &scale) const;
174 CPT(TransformState) set_shear(const LVecBase3 &shear) const;
175
176 CPT(TransformState) set_pos2d(const LVecBase2 &pos) const;
177 CPT(TransformState) set_rotate2d(PN_stdfloat rotate) const;
178 CPT(TransformState) set_scale2d(const LVecBase2 &scale) const;
179 CPT(TransformState) set_shear2d(PN_stdfloat shear) const;
180
181 CPT(TransformState) compose(const TransformState *other) const;
182 CPT(TransformState) invert_compose(const TransformState *other) const;
183
184 INLINE CPT(TransformState) get_inverse() const;
185 INLINE CPT(TransformState) get_unique() const;
186
187 INLINE int get_geom_rendering(int geom_rendering) const;
188
189 virtual bool unref() const;
190
191 INLINE void cache_ref() const;
192 INLINE bool cache_unref() const;
193 INLINE void node_ref() const;
194 INLINE bool node_unref() const;
195
196 INLINE size_t get_composition_cache_num_entries() const;
197 INLINE size_t get_invert_composition_cache_num_entries() const;
198
199 INLINE size_t get_composition_cache_size() const;
200 INLINE const TransformState *get_composition_cache_source(size_t n) const;
201 INLINE const TransformState *get_composition_cache_result(size_t n) const;
202 INLINE size_t get_invert_composition_cache_size() const;
203 INLINE const TransformState *get_invert_composition_cache_source(size_t n) const;
204 INLINE const TransformState *get_invert_composition_cache_result(size_t n) const;
205 bool validate_composition_cache() const;
206 EXTENSION(PyObject *get_composition_cache() const);
207 EXTENSION(PyObject *get_invert_composition_cache() const);
208
209 void output(std::ostream &out) const;
210 void write(std::ostream &out, int indent_level) const;
211 void write_composition_cache(std::ostream &out, int indent_level) const;
212
213 static int get_num_states();
214 static int get_num_unused_states();
215 static int clear_cache();
216 static int garbage_collect();
217 static void list_cycles(std::ostream &out);
218 static void list_states(std::ostream &out);
219 static bool validate_states();
220 EXTENSION(static PyObject *get_states());
221 EXTENSION(static PyObject *get_unused_states());
222
223public:
224 static void init_states();
225
226 INLINE static void flush_level();
227
228 INLINE void cache_ref_only() const;
229
230protected:
231 INLINE void cache_unref_only() const;
232
233private:
234 INLINE bool do_cache_unref() const;
235 INLINE bool do_node_unref() const;
236
237 class CompositionCycleDescEntry {
238 public:
239 INLINE CompositionCycleDescEntry(const TransformState *obj,
240 const TransformState *result,
241 bool inverted);
242
243 const TransformState *_obj;
244 const TransformState *_result;
245 bool _inverted;
246 };
247 typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
248
249 static CPT(TransformState) return_new(TransformState *state);
250 static CPT(TransformState) return_unique(TransformState *state);
251
252 CPT(TransformState) do_compose(const TransformState *other) const;
253 CPT(TransformState) do_invert_compose(const TransformState *other) const;
254 void detect_and_break_cycles();
255 static bool r_detect_cycles(const TransformState *start_state,
256 const TransformState *current_state,
257 int length, UpdateSeq this_seq,
258 CompositionCycleDesc *cycle_desc);
259 static bool r_detect_reverse_cycles(const TransformState *start_state,
260 const TransformState *current_state,
261 int length, UpdateSeq this_seq,
262 CompositionCycleDesc *cycle_desc);
263
264 void release_new();
265 void remove_cache_pointers();
266
267private:
268 // This mutex protects _states. It also protects any modification to the
269 // cache, which is encoded in _composition_cache and
270 // _invert_composition_cache.
271 static LightReMutex *_states_lock;
273 static States *_states;
274 static CPT(TransformState) _identity_state;
275 static CPT(TransformState) _invalid_state;
276
277 // This iterator records the entry corresponding to this TransformState
278 // object in the above global set. We keep the index around so we can
279 // remove it when the TransformState destructs.
280 int _saved_entry;
281
282 // This data structure manages the job of caching the composition of two
283 // TransformStates. It's complicated because we have to be sure to remove
284 // the entry if *either* of the input TransformStates destructs. To
285 // implement this, we always record Composition entries in pairs, one in
286 // each of the two involved TransformState objects.
287
288 // The first element of the map is the object we compose with. This is not
289 // reference counted within this map; instead we store a companion pointer
290 // in the other object, and remove the references explicitly when either
291 // object destructs.
292 class Composition {
293 public:
294 INLINE Composition();
295 INLINE Composition(const Composition &copy);
296
297 // _result is reference counted if and only if it is not the same pointer
298 // as this.
299 const TransformState *_result;
300 };
301
302 typedef SimpleHashMap<const TransformState *, Composition, pointer_hash> CompositionCache;
303 mutable CompositionCache _composition_cache;
304 mutable CompositionCache _invert_composition_cache;
305
306 // This is used to mark nodes as we visit them to detect cycles.
307 UpdateSeq _cycle_detect;
308 static UpdateSeq _last_cycle_detect;
309
310 // This keeps track of our current position through the garbage collection
311 // cycle.
312 static size_t _garbage_index;
313
314 static bool _uniquify_matrix;
315
316 static PStatCollector _cache_update_pcollector;
317 static PStatCollector _garbage_collect_pcollector;
318 static PStatCollector _transform_compose_pcollector;
319 static PStatCollector _transform_invert_pcollector;
320 static PStatCollector _transform_calc_pcollector;
321 static PStatCollector _transform_break_cycles_pcollector;
322 static PStatCollector _transform_new_pcollector;
323 static PStatCollector _transform_validate_pcollector;
324 static PStatCollector _transform_hash_pcollector;
325
326 static PStatCollector _node_counter;
327 static PStatCollector _cache_counter;
328
329private:
330 // This is the actual data within the TransformState.
331 INLINE void check_hash() const;
332 INLINE void check_singular() const;
333 INLINE void check_components() const;
334 INLINE void check_hpr() const;
335 INLINE void check_quat() const;
336 INLINE void check_norm_quat() const;
337 INLINE void check_mat() const;
338 INLINE void calc_hash();
339 void do_calc_hash();
340 void calc_singular();
341 INLINE void calc_components();
342 void do_calc_components();
343 INLINE void calc_hpr();
344 void do_calc_hpr();
345 void calc_quat();
346 void calc_norm_quat();
347 INLINE void calc_mat();
348 void do_calc_mat();
349
350 INLINE void check_uniform_scale();
351 INLINE void check_uniform_scale2d();
352
353 INLINE void set_destructing();
354 INLINE bool is_destructing() const;
355
356 INLINE void consider_update_pstats(int old_referenced_bits) const;
357 static void update_pstats(int old_referenced_bits, int new_referenced_bits);
358
359 enum Flags {
360 F_is_identity = 0x00000001,
361 F_is_singular = 0x00000002,
362 F_singular_known = 0x00000004, // set if we know F_is_singular
363 F_components_given = 0x00000008,
364 F_components_known = 0x00000010, // set if we know F_has_components
365 F_has_components = 0x00000020,
366 F_mat_known = 0x00000040, // set if _mat is defined
367 F_is_invalid = 0x00000080,
368 F_quat_given = 0x00000100,
369 F_quat_known = 0x00000200, // set if _quat is defined
370 F_hpr_given = 0x00000400,
371 F_hpr_known = 0x00000800, // set if _hpr is defined
372 F_uniform_scale = 0x00001000,
373 F_identity_scale = 0x00002000,
374 F_has_nonzero_shear = 0x00004000,
375 F_is_destructing = 0x00008000,
376 F_is_2d = 0x00010000,
377 F_hash_known = 0x00020000,
378 F_norm_quat_known = 0x00040000,
379 };
380 LPoint3 _pos;
381 LVecBase3 _hpr, _scale, _shear;
382 LQuaternion _quat, _norm_quat;
383 LMatrix4 _mat;
384 LMatrix4 *_inv_mat;
385 size_t _hash;
386
387 unsigned int _flags;
388
389 // This mutex protects _flags, and all of the above computed values.
390 LightMutex _lock;
391
392 static CacheStats _cache_stats;
393
394public:
395 static void register_with_read_factory();
396 virtual void write_datagram(BamWriter *manager, Datagram &dg);
397 static PT(TypedWritableReferenceCount) change_this(TypedWritableReferenceCount *old_ptr, BamReader *manager);
398
399protected:
400 static TypedWritable *make_from_bam(const FactoryParams &params);
401 void fillin(DatagramIterator &scan, BamReader *manager);
402
403public:
404 static TypeHandle get_class_type() {
405 return _type_handle;
406 }
407 static void init_type() {
408 NodeCachedReferenceCount::init_type();
409 register_type(_type_handle, "TransformState",
410 NodeCachedReferenceCount::get_class_type());
411 }
412 virtual TypeHandle get_type() const {
413 return get_class_type();
414 }
415 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
416
417private:
418 static TypeHandle _type_handle;
419
420 friend class Extension<TransformState>;
421};
422
423// We can safely redefine this as a no-op.
424template<>
425INLINE void PointerToBase<TransformState>::update_type(To *ptr) {}
426
427INLINE std::ostream &operator << (std::ostream &out, const TransformState &state) {
428 state.output(out);
429 return out;
430}
431
432#include "transformState.I"
433
434#endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A lightweight reentrant mutex.
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.
virtual bool unref() const
Explicitly decrements the reference count.
This template class implements an unordered map of keys to data, implemented as a hashtable.
Indicates a coordinate-system transform on vertices.
static int clear_cache()
Empties the cache of composed TransformStates.
static int get_num_unused_states()
Returns the total number of TransformState objects that have been allocated but have no references ou...
bool is_invalid() const
Returns true if the transform represents an invalid matrix, for instance the result of inverting a si...
PN_stdfloat get_rotate2d() const
Returns the rotation component of the 2-d transform as an angle in degrees clockwise about the origin...
static void list_states(std::ostream &out)
Lists all of the TransformStates in the cache to the output stream, one per line.
bool validate_composition_cache() const
Returns true if the composition cache and invert composition cache for this particular TransformState...
get_quat
Returns the rotation component of the transform as a quaternion.
static int get_num_states()
Returns the total number of unique TransformState objects allocated in the world.
static void list_cycles(std::ostream &out)
Detects all of the reference-count cycles in the cache and reports them to standard output.
bool has_mat() const
Returns true if the transform can be described as a matrix.
bool has_scale() const
Returns true if the transform's scale component can be extracted out separately.
size_t get_hash() const
Returns a suitable hash value for phash_map.
static int garbage_collect()
Performs a garbage-collection cycle.
bool components_given() const
Returns true if the transform was specified componentwise, or false if it was specified with a genera...
bool hpr_given() const
Returns true if the rotation was specified via a trio of Euler angles, false otherwise.
get_shear
Returns the shear component of the transform.
static bool validate_states()
Ensures that the cache is still stored in sorted order, and that none of the cache elements have been...
bool has_quat() const
Returns true if the transform's rotation component can be extracted out separately and described as a...
bool has_uniform_scale() const
Returns true if the scale is uniform across all three axes (and therefore can be expressed as a singl...
bool has_shear() const
Returns true if the transform's shear component can be extracted out separately.
LVecBase2 get_scale2d() const
Returns the scale component of the 2-d transform.
bool has_pos() const
Returns true if the transform's pos component can be extracted out separately.
get_norm_quat
Returns the rotation component of the transform as a quaternion.
bool has_identity_scale() const
Returns true if the scale is uniform 1.0, or false if the scale has some real value.
int compare_to(const TransformState &other) const
Provides an arbitrary ordering among all unique TransformStates, so we can store the essentially diff...
static void init_states()
Make sure the global _states map is allocated.
get_scale
Returns the scale component of the transform.
get_hpr
Returns the rotation component of the transform as a trio of Euler angles.
LMatrix3 get_mat3() const
Returns the 3x3 matrix that describes the 2-d transform.
bool has_components() const
Returns true if the transform can be described by separate pos, hpr, and scale components.
bool has_hpr() const
Returns true if the transform's rotation component can be extracted out separately and described as a...
LVecBase2 get_pos2d() const
Returns the pos component of the 2-d transform.
bool has_nonzero_shear() const
Returns true if the shear component is non-zero, false if it is zero or if the matrix cannot be decom...
bool is_2d() const
Returns true if the transform has been constructed entirely using the 2-d transform operations,...
get_mat
Returns the matrix that describes the transform.
PN_stdfloat get_uniform_scale() const
Returns the scale component of the transform, as a single number.
bool is_singular() const
Returns true if the transform represents a singular transform (that is, it has a zero scale,...
bool is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.
void write_composition_cache(std::ostream &out, int indent_level) const
Writes a brief description of the composition cache and invert composition cache to the indicated ost...
get_pos
Returns the pos component of the transform.
PN_stdfloat get_shear2d() const
Returns the shear component of the 2-d transform.
bool quat_given() const
Returns true if the rotation was specified via a quaternion, false otherwise.
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...
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 a sequence number that increments monotonically.
Definition updateSeq.h:37
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(),...
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.