Panda3D
transformState.I
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.I
10  * @author drose
11  * @date 2002-02-25
12  */
13 
14 /**
15  * Opposite of operator ==.
16  */
17 INLINE bool TransformState::
18 operator != (const TransformState &other) const {
19  return !(operator == (other));
20 }
21 
22 /**
23  * Provides an arbitrary ordering among all unique TransformStates, so we can
24  * store the essentially different ones in a big set and throw away the rest.
25  *
26  * Note that if this returns 0, it doesn't necessarily imply that operator ==
27  * returns true; it uses a very slightly different comparison threshold.
28  */
29 INLINE int TransformState::
30 compare_to(const TransformState &other) const {
31  return compare_to(other, _uniquify_matrix);
32 }
33 
34 /**
35  * Returns a suitable hash value for phash_map.
36  */
37 INLINE size_t TransformState::
38 get_hash() const {
39  check_hash();
40  return _hash;
41 }
42 
43 /**
44  * Makes a new TransformState with the specified components.
45  */
46 INLINE CPT(TransformState) TransformState::
47 make_pos(const LVecBase3 &pos) {
48  return make_pos_hpr_scale(pos,
49  LVecBase3(0.0f, 0.0f, 0.0f),
50  LVecBase3(1.0f, 1.0f, 1.0f));
51 }
52 
53 /**
54  * Makes a new TransformState with the specified components.
55  */
56 INLINE CPT(TransformState) TransformState::
57 make_hpr(const LVecBase3 &hpr) {
58  return make_pos_hpr_scale(LVecBase3(0.0f, 0.0f, 0.0f),
59  hpr,
60  LVecBase3(1.0f, 1.0f, 1.0f));
61 }
62 
63 /**
64  * Makes a new TransformState with the specified components.
65  */
66 INLINE CPT(TransformState) TransformState::
67 make_quat(const LQuaternion &quat) {
68  return make_pos_quat_scale(LVecBase3(0.0f, 0.0f, 0.0f),
69  quat,
70  LVecBase3(1.0f, 1.0f, 1.0f));
71 }
72 
73 /**
74  * Makes a new TransformState with the specified components.
75  */
76 INLINE CPT(TransformState) TransformState::
77 make_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
78  return make_pos_hpr_scale(pos, hpr,
79  LVecBase3(1.0, 1.0f, 1.0f));
80 }
81 
82 /**
83  * Makes a new TransformState with the specified components.
84  */
85 INLINE CPT(TransformState) TransformState::
86 make_scale(PN_stdfloat scale) {
87  // We actually map this 3-d uniform make_scale() to the 2-d version--might
88  // as well call it a 2-d scale.
89  return make_scale2d(scale);
90 }
91 
92 /**
93  * Makes a new TransformState with the specified components.
94  */
95 INLINE CPT(TransformState) TransformState::
96 make_scale(const LVecBase3 &scale) {
97  return make_pos_hpr_scale(LVecBase3(0.0f, 0.0f, 0.0f),
98  LVecBase3(0.0f, 0.0f, 0.0f),
99  scale);
100 }
101 
102 /**
103  * Makes a new TransformState with the specified components.
104  */
105 INLINE CPT(TransformState) TransformState::
106 make_shear(const LVecBase3 &shear) {
107  return make_pos_hpr_scale_shear(LVecBase3(0.0f, 0.0f, 0.0f),
108  LVecBase3(0.0f, 0.0f, 0.0f),
109  LVecBase3(1.0f, 1.0f, 1.0f),
110  shear);
111 }
112 
113 /**
114  * Makes a new TransformState with the specified components.
115  */
116 INLINE CPT(TransformState) TransformState::
117 make_pos_hpr_scale(const LVecBase3 &pos, const LVecBase3 &hpr,
118  const LVecBase3 &scale) {
119  return make_pos_hpr_scale_shear(pos, hpr, scale, LVecBase3::zero());
120 }
121 
122 /**
123  * Makes a new TransformState with the specified components.
124  */
125 INLINE CPT(TransformState) TransformState::
126 make_pos_quat_scale(const LVecBase3 &pos, const LQuaternion &quat,
127  const LVecBase3 &scale) {
128  return make_pos_quat_scale_shear(pos, quat, scale, LVecBase3::zero());
129 }
130 
131 /**
132  * Makes a new 2-d TransformState with the specified components.
133  */
134 INLINE CPT(TransformState) TransformState::
135 make_pos2d(const LVecBase2 &pos) {
136  return make_pos_rotate_scale2d(pos, 0.0f, LVecBase2(1.0f, 1.0f));
137 }
138 
139 /**
140  * Makes a new 2-d TransformState with the specified components.
141  */
142 INLINE CPT(TransformState) TransformState::
143 make_rotate2d(PN_stdfloat rotate) {
144  return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), rotate,
145  LVecBase2(1.0f, 1.0f));
146 }
147 
148 /**
149  * Makes a new 2-d TransformState with the specified components.
150  */
151 INLINE CPT(TransformState) TransformState::
152 make_pos_rotate2d(const LVecBase2 &pos, PN_stdfloat rotate) {
153  return make_pos_rotate_scale2d(pos, rotate,
154  LVecBase2(1.0, 1.0f));
155 }
156 
157 /**
158  * Makes a new 2-d TransformState with the specified components.
159  */
160 INLINE CPT(TransformState) TransformState::
161 make_scale2d(PN_stdfloat scale) {
162  return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), 0.0f,
163  LVecBase2(scale, scale));
164 }
165 
166 /**
167  * Makes a new 2-d TransformState with the specified components.
168  */
169 INLINE CPT(TransformState) TransformState::
170 make_scale2d(const LVecBase2 &scale) {
171  return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), 0.0f, scale);
172 }
173 
174 /**
175  * Makes a new 2-d TransformState with the specified components.
176  */
177 INLINE CPT(TransformState) TransformState::
178 make_shear2d(PN_stdfloat shear) {
179  return make_pos_rotate_scale_shear2d(LVecBase2(0.0f, 0.0f), 0.0f,
180  LVecBase2(1.0f, 1.0f), shear);
181 }
182 
183 /**
184  * Makes a new 2-d TransformState with the specified components.
185  */
186 INLINE CPT(TransformState) TransformState::
187 make_pos_rotate_scale2d(const LVecBase2 &pos, PN_stdfloat rotate,
188  const LVecBase2 &scale) {
189  return make_pos_rotate_scale_shear2d(pos, rotate, scale, 0.0f);
190 }
191 
192 /**
193  * Returns true if the transform represents the identity matrix, false
194  * otherwise.
195  */
196 INLINE bool TransformState::
197 is_identity() const {
198  return ((_flags & F_is_identity) != 0);
199 }
200 
201 /**
202  * Returns true if the transform represents an invalid matrix, for instance
203  * the result of inverting a singular matrix, or false if the transform is
204  * valid.
205  */
206 INLINE bool TransformState::
207 is_invalid() const {
208  return ((_flags & F_is_invalid) != 0);
209 }
210 
211 /**
212  * Returns true if the transform represents a singular transform (that is, it
213  * has a zero scale, and it cannot be inverted), or false otherwise.
214  */
215 INLINE bool TransformState::
216 is_singular() const {
217  check_singular();
218  return ((_flags & F_is_singular) != 0);
219 }
220 
221 /**
222  * Returns true if the transform has been constructed entirely using the 2-d
223  * transform operations, e.g. make_pos2d(), and therefore operates strictly
224  * in two-dimensional space on X and Y only.
225  */
226 INLINE bool TransformState::
227 is_2d() const {
228  return ((_flags & F_is_2d) != 0);
229 }
230 
231 /**
232  * Returns true if the transform can be described by separate pos, hpr, and
233  * scale components. Most transforms we use in everyday life can be so
234  * described, but some kinds of transforms (for instance, those involving a
235  * skew) cannot.
236  *
237  * This is not related to whether the transform was originally described
238  * componentwise. Even a transform that was constructed with a 4x4 may return
239  * true here if the matrix is a simple affine matrix with no skew.
240  *
241  * If this returns true, you may safely call get_hpr() and get_scale() to
242  * retrieve the components. (You may always safely call get_pos() whether
243  * this returns true or false.)
244  */
245 INLINE bool TransformState::
246 has_components() const {
247  check_components();
248  return ((_flags & F_has_components) != 0);
249 }
250 
251 /**
252  * Returns true if the transform was specified componentwise, or false if it
253  * was specified with a general 4x4 matrix. If this is true, the components
254  * returned by get_pos() and get_scale() will be exactly those that were set;
255  * otherwise, these functions will return computed values. If this is true,
256  * the rotation may have been set either with a hpr trio or with a quaternion;
257  * hpr_given() or quat_given() can resolve the difference.
258  */
259 INLINE bool TransformState::
261  return ((_flags & F_components_given) != 0);
262 }
263 
264 /**
265  * Returns true if the rotation was specified via a trio of Euler angles,
266  * false otherwise. If this is true, get_hpr() will be exactly as set;
267  * otherwise, it will return a computed value.
268  */
269 INLINE bool TransformState::
270 hpr_given() const {
271  return ((_flags & F_hpr_given) != 0);
272 }
273 
274 /**
275  * Returns true if the rotation was specified via a quaternion, false
276  * otherwise. If this is true, get_quat() will be exactly as set; otherwise,
277  * it will return a computed value.
278  */
279 INLINE bool TransformState::
280 quat_given() const {
281  return ((_flags & F_quat_given) != 0);
282 }
283 
284 /**
285  * Returns true if the transform's pos component can be extracted out
286  * separately. This is generally always true, unless the transform is invalid
287  * (i.e. is_invalid() returns true).
288  */
289 INLINE bool TransformState::
290 has_pos() const {
291  return !is_invalid();
292 }
293 
294 /**
295  * Returns true if the transform's rotation component can be extracted out
296  * separately and described as a set of Euler angles. This is generally true
297  * only when has_components() is true.
298  */
299 INLINE bool TransformState::
300 has_hpr() const {
301  return has_components();
302 }
303 
304 /**
305  * Returns true if the transform's rotation component can be extracted out
306  * separately and described as a quaternion. This is generally true only when
307  * has_components() is true.
308  */
309 INLINE bool TransformState::
310 has_quat() const {
311  return has_components();
312 }
313 
314 /**
315  * Returns true if the transform's scale component can be extracted out
316  * separately. This is generally true only when has_components() is true.
317  */
318 INLINE bool TransformState::
319 has_scale() const {
320  return has_components();
321 }
322 
323 /**
324  * Returns true if the scale is uniform 1.0, or false if the scale has some
325  * real value.
326  */
327 INLINE bool TransformState::
329  check_components();
330  return (_flags & F_identity_scale) != 0;
331 }
332 
333 /**
334  * Returns true if the scale is uniform across all three axes (and therefore
335  * can be expressed as a single number), or false if the transform has a
336  * different scale in different dimensions.
337  */
338 INLINE bool TransformState::
340  check_components();
341  return (_flags & F_uniform_scale) != 0;
342 }
343 
344 /**
345  * Returns true if the transform's shear component can be extracted out
346  * separately. This is generally true only when has_components() is true.
347  */
348 INLINE bool TransformState::
349 has_shear() const {
350  return has_components();
351 }
352 
353 /**
354  * Returns true if the shear component is non-zero, false if it is zero or if
355  * the matrix cannot be decomposed.
356  */
357 INLINE bool TransformState::
359  check_components();
360  return (_flags & F_has_nonzero_shear) != 0;
361 }
362 
363 /**
364  * Returns true if the transform can be described as a matrix. This is
365  * generally always true, unless is_invalid() is true.
366  */
367 INLINE bool TransformState::
368 has_mat() const {
369  return !is_invalid();
370 }
371 
372 /**
373  * Returns the pos component of the transform. It is an error to call this if
374  * has_pos() returned false.
375  */
376 INLINE const LPoint3 &TransformState::
377 get_pos() const {
378  check_components();
379  nassertr(has_pos(), _pos);
380  return _pos;
381 }
382 
383 /**
384  * Returns the rotation component of the transform as a trio of Euler angles.
385  * It is an error to call this if has_components() returned false.
386  */
387 INLINE const LVecBase3 &TransformState::
388 get_hpr() const {
389  check_hpr();
390  nassertr(!is_invalid(), _hpr);
391  return _hpr;
392 }
393 
394 /**
395  * Returns the rotation component of the transform as a quaternion. The
396  * return value will be normalized if a normalized quaternion was given to the
397  * constructor (or if the quaternion was computed implicitly); it will be non-
398  * normalized if a non-normalized quaternion was given to the constructor.
399  * See also get_norm_quat().
400  *
401  * It is an error to call this if has_components() returned false.
402  */
403 INLINE const LQuaternion &TransformState::
404 get_quat() const {
405  check_quat();
406  nassertr(!is_invalid(), _quat);
407  return _quat;
408 }
409 
410 /**
411  * Returns the rotation component of the transform as a quaternion. Unlike
412  * the result of get_quat(), the return value of this method is guaranteed to
413  * be normalized. It is an error to call this if has_components() returned
414  * false.
415  */
416 INLINE const LQuaternion &TransformState::
417 get_norm_quat() const {
418  check_norm_quat();
419  nassertr(!is_invalid(), _norm_quat);
420  return _norm_quat;
421 }
422 
423 /**
424  * Returns the scale component of the transform. It is an error to call this
425  * if has_components() returned false.
426  */
427 INLINE const LVecBase3 &TransformState::
428 get_scale() const {
429  check_components();
430  nassertr(!is_invalid(), _scale);
431  return _scale;
432 }
433 
434 /**
435  * Returns the scale component of the transform, as a single number. It is an
436  * error to call this if has_uniform_scale() returned false.
437  */
438 INLINE PN_stdfloat TransformState::
440  check_components();
441  nassertr(has_uniform_scale(), _scale[0]);
442  return _scale[0];
443 }
444 
445 /**
446  * Returns the shear component of the transform. It is an error to call this
447  * if has_components() returned false.
448  */
449 INLINE const LVecBase3 &TransformState::
450 get_shear() const {
451  check_components();
452  nassertr(!is_invalid(), _shear);
453  return _shear;
454 }
455 
456 /**
457  * Returns the matrix that describes the transform.
458  */
459 INLINE const LMatrix4 &TransformState::
460 get_mat() const {
461  nassertr(has_mat(), LMatrix4::ident_mat());
462  check_mat();
463  return _mat;
464 }
465 
466 /**
467  * Returns the pos component of the 2-d transform. It is an error to call
468  * this if has_pos() or is_2d() returned false.
469  */
470 INLINE LVecBase2 TransformState::
471 get_pos2d() const {
472  check_components();
473  nassertr(has_pos() && is_2d(), LVecBase2::zero());
474  return LVecBase2(_pos[0], _pos[1]);
475 }
476 
477 /**
478  * Returns the rotation component of the 2-d transform as an angle in degrees
479  * clockwise about the origin. It is an error to call this if
480  * has_components() or is_2d() returned false.
481  */
482 INLINE PN_stdfloat TransformState::
483 get_rotate2d() const {
484  check_hpr();
485  nassertr(!is_invalid() && is_2d(), 0);
486  switch (get_default_coordinate_system()) {
487  default:
488  case CS_zup_right:
489  return _hpr[0];
490  case CS_zup_left:
491  return -_hpr[0];
492  case CS_yup_right:
493  return -_hpr[2];
494  case CS_yup_left:
495  return _hpr[2];
496  }
497 }
498 
499 /**
500  * Returns the scale component of the 2-d transform. It is an error to call
501  * this if has_components() or is_2d() returned false.
502  */
503 INLINE LVecBase2 TransformState::
504 get_scale2d() const {
505  check_components();
506  nassertr(!is_invalid() && is_2d(), LVecBase2::zero());
507  return LVecBase2(_scale[0], _scale[1]);
508 }
509 
510 /**
511  * Returns the shear component of the 2-d transform. It is an error to call
512  * this if has_components() or is_2d() returned false.
513  */
514 INLINE PN_stdfloat TransformState::
515 get_shear2d() const {
516  check_components();
517  nassertr(!is_invalid() && is_2d(), 0.0f);
518  return _shear[0];
519 }
520 
521 /**
522  * Returns the 3x3 matrix that describes the 2-d transform. It is an error to
523  * call this if is_2d() returned false.
524  */
525 INLINE LMatrix3 TransformState::
526 get_mat3() const {
527  nassertr(has_mat() && is_2d(), LMatrix3::ident_mat());
528  check_mat();
529  return LMatrix3(_mat(0, 0), _mat(0, 1), _mat(0, 3),
530  _mat(1, 0), _mat(1, 1), _mat(1, 3),
531  _mat(3, 0), _mat(3, 1), _mat(3, 3));
532 }
533 
534 /**
535  * Returns the inverse of this transform. If you are going to immediately
536  * compose this result with another TransformState, it is faster to do it in
537  * one operation with invert_compose().
538  */
539 INLINE CPT(TransformState) TransformState::
540 get_inverse() const {
541  return invert_compose(TransformState::make_identity());
542 }
543 
544 /**
545  * Returns the pointer to the unique TransformState in the cache that is
546  * equivalent to this one. This may be the same pointer as this object, or it
547  * may be a different pointer; but it will be an equivalent object, and it
548  * will be a shared pointer. This may be called from time to time to improve
549  * cache benefits.
550  */
551 INLINE CPT(TransformState) TransformState::
552 get_unique() const {
553  return return_unique((TransformState *)this);
554 }
555 
556 /**
557  * Returns the union of the Geom::GeomRendering bits that will be required
558  * once this TransformState is applied to a geom which includes the indicated
559  * geom_rendering bits. The RenderState's get_geom_rendering() should already
560  * have been applied.
561  */
562 INLINE int TransformState::
563 get_geom_rendering(int geom_rendering) const {
564  if ((geom_rendering & GeomEnums::GR_point_perspective) != 0) {
565  if (!has_identity_scale()) {
566  geom_rendering |= GeomEnums::GR_point_scale;
567  }
568  }
569 
570  return geom_rendering;
571 }
572 
573 /**
574  * Overrides this method to update PStats appropriately.
575  */
576 INLINE void TransformState::
577 cache_ref() const {
578 #ifdef DO_PSTATS
579  int old_referenced_bits = get_referenced_bits();
581  consider_update_pstats(old_referenced_bits);
582 #else // DO_PSTATS
584 #endif // DO_PSTATS
585 }
586 
587 /**
588  * Overrides this method to update PStats appropriately.
589  */
590 INLINE bool TransformState::
591 cache_unref() const {
592 #ifdef DO_PSTATS
593  int old_referenced_bits = get_referenced_bits();
594  bool result = do_cache_unref();
595  consider_update_pstats(old_referenced_bits);
596  return result;
597 #else // DO_PSTATS
598  return do_cache_unref();
599 #endif // DO_PSTATS
600 }
601 
602 /**
603  * Overrides this method to update PStats appropriately.
604  */
605 INLINE void TransformState::
606 node_ref() const {
607 #ifdef DO_PSTATS
608  int old_referenced_bits = get_referenced_bits();
610  consider_update_pstats(old_referenced_bits);
611 #else // DO_PSTATS
613 #endif // DO_PSTATS
614 }
615 
616 /**
617  * Overrides this method to update PStats appropriately.
618  */
619 INLINE bool TransformState::
620 node_unref() const {
621 #ifdef DO_PSTATS
622  int old_referenced_bits = get_referenced_bits();
623  bool result = do_node_unref();
624  consider_update_pstats(old_referenced_bits);
625  return result;
626 #else // DO_PSTATS
627  return do_node_unref();
628 #endif // DO_PSTATS
629 }
630 
631 /**
632  * Returns the number of entries in the composition cache for this
633  * TransformState. This is the number of other TransformStates whose
634  * composition with this one has been cached. This number is not useful for
635  * any practical reason other than performance analysis.
636  */
637 INLINE size_t TransformState::
638 get_composition_cache_num_entries() const {
639  LightReMutexHolder holder(*_states_lock);
640  return _composition_cache.get_num_entries();
641 }
642 
643 /**
644  * Returns the number of entries in the invert_composition cache for this
645  * TransformState. This is similar to the composition cache, but it records
646  * cache entries for the invert_compose() operation. See
647  * get_composition_cache_num_entries().
648  */
649 INLINE size_t TransformState::
650 get_invert_composition_cache_num_entries() const {
651  LightReMutexHolder holder(*_states_lock);
652  return _invert_composition_cache.get_num_entries();
653 }
654 
655 /**
656  * Returns the number of slots in the composition cache for this
657  * TransformState. You may use this as an upper bound when walking through
658  * all of the composition cache results via get_composition_cache_source() or
659  * result().
660  *
661  * This has no practical value other than for examining the cache for
662  * performance analysis.
663  */
664 INLINE size_t TransformState::
665 get_composition_cache_size() const {
666  LightReMutexHolder holder(*_states_lock);
667  return _composition_cache.get_num_entries();
668 }
669 
670 /**
671  * Returns the source TransformState of the nth element in the composition
672  * cache. Returns NULL if there doesn't happen to be an entry in the nth
673  * element. See get_composition_cache_result().
674  *
675  * This has no practical value other than for examining the cache for
676  * performance analysis.
677  */
678 INLINE const TransformState *TransformState::
679 get_composition_cache_source(size_t n) const {
680  LightReMutexHolder holder(*_states_lock);
681  return _composition_cache.get_key(n);
682 }
683 
684 /**
685  * Returns the result TransformState of the nth element in the composition
686  * cache. Returns NULL if there doesn't happen to be an entry in the nth
687  * element.
688  *
689  * In general, a->compose(a->get_composition_cache_source(n)) ==
690  * a->get_composition_cache_result(n).
691  *
692  * This has no practical value other than for examining the cache for
693  * performance analysis.
694  */
695 INLINE const TransformState *TransformState::
696 get_composition_cache_result(size_t n) const {
697  LightReMutexHolder holder(*_states_lock);
698  return _composition_cache.get_data(n)._result;
699 }
700 
701 /**
702  * Returns the number of slots in the composition cache for this
703  * TransformState. You may use this as an upper bound when walking through
704  * all of the composition cache results via
705  * get_invert_composition_cache_source() or result().
706  *
707  * This has no practical value other than for examining the cache for
708  * performance analysis.
709  */
710 INLINE size_t TransformState::
711 get_invert_composition_cache_size() const {
712  LightReMutexHolder holder(*_states_lock);
713  return _invert_composition_cache.get_num_entries();
714 }
715 
716 /**
717  * Returns the source TransformState of the nth element in the invert
718  * composition cache. Returns NULL if there doesn't happen to be an entry in
719  * the nth element. See get_invert_composition_cache_result().
720  *
721  * This has no practical value other than for examining the cache for
722  * performance analysis.
723  */
724 INLINE const TransformState *TransformState::
725 get_invert_composition_cache_source(size_t n) const {
726  LightReMutexHolder holder(*_states_lock);
727  return _invert_composition_cache.get_key(n);
728 }
729 
730 /**
731  * Returns the result TransformState of the nth element in the invert
732  * composition cache. Returns NULL if there doesn't happen to be an entry in
733  * the nth element.
734  *
735  * In general, a->invert_compose(a->get_invert_composition_cache_source(n)) ==
736  * a->get_invert_composition_cache_result(n).
737  *
738  * This has no practical value other than for examining the cache for
739  * performance analysis.
740  */
741 INLINE const TransformState *TransformState::
742 get_invert_composition_cache_result(size_t n) const {
743  LightReMutexHolder holder(*_states_lock);
744  return _invert_composition_cache.get_data(n)._result;
745 }
746 
747 /**
748  * Flushes the PStatCollectors used during traversal.
749  */
750 INLINE void TransformState::
751 flush_level() {
752  _node_counter.flush_level();
753  _cache_counter.flush_level();
754 }
755 
756 /**
757  * Reimplements NodeReferenceCount::node_unref(). We do this because we have
758  * a non-virtual unref() method.
759  */
760 INLINE bool TransformState::
761 do_node_unref() const {
762  node_unref_only();
763  return unref();
764 }
765 
766 /**
767  * Reimplements CachedTypedWritableReferenceCount::cache_unref(). We do this
768  * because we have a non-virtual unref() method.
769  */
770 INLINE bool TransformState::
771 do_cache_unref() const {
772  cache_unref_only();
773  return unref();
774 }
775 
776 /**
777  * Ensures that we know the hash value.
778  */
779 INLINE void TransformState::
780 check_hash() const {
781  // This pretends to be a const function, even though it's not, because it
782  // only updates a transparent cache value.
783  if ((_flags & F_hash_known) == 0) {
784  ((TransformState *)this)->calc_hash();
785  }
786 }
787 
788 /**
789  * Ensures that we know whether the matrix is singular.
790  */
791 INLINE void TransformState::
792 check_singular() const {
793  // This pretends to be a const function, even though it's not, because it
794  // only updates a transparent cache value.
795  if ((_flags & F_singular_known) == 0) {
796  ((TransformState *)this)->calc_singular();
797  }
798 }
799 
800 /**
801  * Ensures that we know the components of the transform (or that we know they
802  * cannot be derived).
803  */
804 INLINE void TransformState::
805 check_components() const {
806  // This pretends to be a const function, even though it's not, because it
807  // only updates a transparent cache value.
808  if ((_flags & F_components_known) == 0) {
809  ((TransformState *)this)->calc_components();
810  }
811 }
812 
813 /**
814  * Ensures that we know the hpr of the transform (or that we know they cannot
815  * be derived).
816  */
817 INLINE void TransformState::
818 check_hpr() const {
819  // This pretends to be a const function, even though it's not, because it
820  // only updates a transparent cache value.
821  if ((_flags & F_hpr_known) == 0) {
822  ((TransformState *)this)->calc_hpr();
823  }
824 }
825 
826 /**
827  * Ensures that we know the quat of the transform (or that we know they cannot
828  * be derived).
829  */
830 INLINE void TransformState::
831 check_quat() const {
832  // This pretends to be a const function, even though it's not, because it
833  // only updates a transparent cache value.
834  if ((_flags & F_quat_known) == 0) {
835  ((TransformState *)this)->calc_quat();
836  }
837 }
838 
839 /**
840  * Ensures that we know the normalized quat of the transform (or that we know
841  * they cannot be derived).
842  */
843 INLINE void TransformState::
844 check_norm_quat() const {
845  // This pretends to be a const function, even though it's not, because it
846  // only updates a transparent cache value.
847  if ((_flags & F_norm_quat_known) == 0) {
848  ((TransformState *)this)->calc_norm_quat();
849  }
850 }
851 
852 /**
853  * Ensures that we know the overall matrix.
854  */
855 INLINE void TransformState::
856 check_mat() const {
857  // This pretends to be a const function, even though it's not, because it
858  // only updates a transparent cache value.
859  if ((_flags & F_mat_known) == 0) {
860  ((TransformState *)this)->calc_mat();
861  }
862 }
863 
864 /**
865  * Computes the hash value.
866  */
867 INLINE void TransformState::
868 calc_hash() {
869  LightMutexHolder holder(_lock);
870  do_calc_hash();
871 }
872 
873 /**
874  * Derives the components from the matrix, if possible.
875  */
876 INLINE void TransformState::
877 calc_components() {
878  LightMutexHolder holder(_lock);
879  do_calc_components();
880 }
881 
882 /**
883  * Derives the hpr, from the matrix if necessary, or from the quat.
884  */
885 INLINE void TransformState::
886 calc_hpr() {
887  LightMutexHolder holder(_lock);
888  do_calc_hpr();
889 }
890 
891 /**
892  * Computes the matrix from the components.
893  */
894 INLINE void TransformState::
895 calc_mat() {
896  LightMutexHolder holder(_lock);
897  do_calc_mat();
898 }
899 
900 /**
901  * Should be called immediately after _scale (and F_has_components) is set,
902  * this checks for a identity and/or uniform scale (as well as a non-zero
903  * shear) and sets the bit appropriately.
904  *
905  * It does not matter whether the lock is or is not held before calling this
906  * method.
907  */
908 INLINE void TransformState::
909 check_uniform_scale() {
910  if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) &&
911  IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
912  _flags |= F_uniform_scale;
913  if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
914  _flags |= F_identity_scale;
915  }
916  }
917 
918  if (!_shear.almost_equal(LVecBase3::zero())) {
919  _flags |= F_has_nonzero_shear;
920  }
921 }
922 
923 /**
924  * Should be called immediately after _scale (and F_has_components) is set,
925  * for a known 2-d scale, this checks for a identity and/or uniform scale (as
926  * well as a non-zero shear) and sets the bit appropriately.
927  *
928  * It does not matter whether the lock is or is not held before calling this
929  * method.
930  */
931 INLINE void TransformState::
932 check_uniform_scale2d() {
933  if (IS_NEARLY_EQUAL(_scale[0], _scale[1])) {
934  _scale[2] = _scale[0];
935  _flags |= F_uniform_scale;
936  if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
937  _flags |= F_identity_scale;
938  }
939  }
940 
941  if (!_shear.almost_equal(LVecBase3::zero())) {
942  _flags |= F_has_nonzero_shear;
943  }
944 }
945 
946 /**
947  * This function should only be called from the destructor; it indicates that
948  * this TransformState object is beginning destruction. It is only used as a
949  * sanity check, and is only meaningful when NDEBUG is not defined.
950  */
951 INLINE void TransformState::
952 set_destructing() {
953 #ifndef NDEBUG
954  _flags |= F_is_destructing;
955 #endif
956 }
957 
958 /**
959  * Returns true if the TransformState object is currently within its
960  * destructor (i.e. set_destructing() has been called). This is only used as
961  * a sanity check, and is only meaningful when NDEBUG is not defined.
962  */
963 INLINE bool TransformState::
964 is_destructing() const {
965 #ifndef NDEBUG
966  return (_flags & F_is_destructing) != 0;
967 #else
968  return false;
969 #endif
970 }
971 
972 /**
973  * Calls update_pstats() if the state of the referenced bits has changed from
974  * the indicated value.
975  */
976 INLINE void TransformState::
977 consider_update_pstats(int old_referenced_bits) const {
978 #ifdef DO_PSTATS
979  int new_referenced_bits = get_referenced_bits();
980  if (old_referenced_bits != new_referenced_bits) {
981  update_pstats(old_referenced_bits, new_referenced_bits);
982  }
983 #endif // DO_PSTATS
984 }
985 
986 /**
987  *
988  */
989 INLINE TransformState::Composition::
990 Composition() {
991 }
992 
993 /**
994  *
995  */
996 INLINE TransformState::Composition::
997 Composition(const TransformState::Composition &copy) :
998  _result(copy._result)
999 {
1000 }
1001 
1002 /**
1003  *
1004  */
1005 INLINE TransformState::CompositionCycleDescEntry::
1006 CompositionCycleDescEntry(const TransformState *obj,
1007  const TransformState *result,
1008  bool inverted) :
1009  _obj(obj),
1010  _result(result),
1011  _inverted(inverted)
1012 {
1013 }
bool has_mat() const
Returns true if the transform can be described as a matrix.
Indicates a coordinate-system transform on vertices.
bool has_components() const
Returns true if the transform can be described by separate pos, hpr, and scale components.
bool hpr_given() const
Returns true if the rotation was specified via a trio of Euler angles, false otherwise.
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...
LMatrix3 get_mat3() const
Returns the 3x3 matrix that describes the 2-d transform.
LVecBase2 get_scale2d() const
Returns the scale component of the 2-d transform.
bool is_2d() const
Returns true if the transform has been constructed entirely using the 2-d transform operations,...
bool has_shear() const
Returns true if the transform's shear component can be extracted out separately.
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
void node_ref() const
Explicitly increments the reference count.
bool operator==(const TransformState &other) const
Tests equivalence between two transform states.
LVecBase2 get_pos2d() const
Returns the pos component of the 2-d transform.
bool has_quat() const
Returns true if the transform's rotation component can be extracted out separately and described as a...
bool components_given() const
Returns true if the transform was specified componentwise, or false if it was specified with a genera...
bool has_scale() const
Returns true if the transform's scale component can be extracted out separately.
size_t get_num_entries() const
Returns the number of active entries in the table.
size_t get_hash() const
Returns a suitable hash value for phash_map.
Similar to MutexHolder, but for a light mutex.
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
bool has_hpr() const
Returns true if the transform's rotation component can be extracted out separately and described as a...
void cache_ref() const
Explicitly increments the cache reference count and the normal reference count simultaneously.
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,...
Similar to MutexHolder, but for a light reentrant mutex.
virtual bool unref() const
Explicitly decrements the reference count.
bool is_invalid() const
Returns true if the transform represents an invalid matrix, for instance the result of inverting a si...
bool has_pos() const
Returns true if the transform's pos component can be extracted out separately.
PN_stdfloat get_rotate2d() const
Returns the rotation component of the 2-d transform as an angle in degrees clockwise about the origin...
bool has_identity_scale() const
Returns true if the scale is uniform 1.0, or false if the scale has some real value.
PN_stdfloat get_shear2d() const
Returns the shear component of the 2-d transform.
CPT(TransformState) TransformState
Makes a new TransformState with the specified components.
bool operator !=(const TransformState &other) const
Opposite of operator ==.
bool quat_given() const
Returns true if the rotation was specified via a quaternion, false otherwise.
int compare_to(const TransformState &other) const
Provides an arbitrary ordering among all unique TransformStates, so we can store the essentially diff...
int get_referenced_bits() const
Returns the union of the values defined in the Referenced enum that represents the various things tha...
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 is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.