Panda3D
Loading...
Searching...
No Matches
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 */
18operator != (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 */
30compare_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 */
37INLINE size_t TransformState::
38get_hash() const {
39 check_hash();
40 return _hash;
41}
42
43/**
44 * Makes a new TransformState with the specified components.
45 */
46INLINE CPT(TransformState) TransformState::
47make_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 */
56INLINE CPT(TransformState) TransformState::
57make_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 */
66INLINE CPT(TransformState) TransformState::
67make_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 */
76INLINE CPT(TransformState) TransformState::
77make_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 */
85INLINE CPT(TransformState) TransformState::
86make_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 */
95INLINE CPT(TransformState) TransformState::
96make_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 */
105INLINE CPT(TransformState) TransformState::
106make_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 */
116INLINE CPT(TransformState) TransformState::
117make_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 */
125INLINE CPT(TransformState) TransformState::
126make_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 */
134INLINE CPT(TransformState) TransformState::
135make_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 */
142INLINE CPT(TransformState) TransformState::
143make_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 */
151INLINE CPT(TransformState) TransformState::
152make_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 */
160INLINE CPT(TransformState) TransformState::
161make_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 */
169INLINE CPT(TransformState) TransformState::
170make_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 */
177INLINE CPT(TransformState) TransformState::
178make_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 */
186INLINE CPT(TransformState) TransformState::
187make_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 */
197is_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 */
207is_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 */
216is_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 */
227is_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 */
246has_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 */
260components_given() const {
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 */
270hpr_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 */
280quat_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 */
290has_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 */
300has_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 */
310has_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 */
319has_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 */
328has_identity_scale() const {
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 */
339has_uniform_scale() const {
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 */
349has_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 */
358has_nonzero_shear() const {
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 */
368has_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 */
376INLINE const LPoint3 &TransformState::
377get_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 */
387INLINE const LVecBase3 &TransformState::
388get_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 */
403INLINE const LQuaternion &TransformState::
404get_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 */
416INLINE const LQuaternion &TransformState::
417get_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 */
427INLINE const LVecBase3 &TransformState::
428get_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 */
438INLINE PN_stdfloat TransformState::
439get_uniform_scale() const {
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 */
449INLINE const LVecBase3 &TransformState::
450get_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 */
459INLINE const LMatrix4 &TransformState::
460get_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 */
470INLINE LVecBase2 TransformState::
471get_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 */
482INLINE PN_stdfloat TransformState::
483get_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 */
503INLINE LVecBase2 TransformState::
504get_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 */
514INLINE PN_stdfloat TransformState::
515get_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 */
525INLINE LMatrix3 TransformState::
526get_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 */
539INLINE CPT(TransformState) TransformState::
540get_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 */
551INLINE CPT(TransformState) TransformState::
552get_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 */
562INLINE int TransformState::
563get_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 */
576INLINE void TransformState::
577cache_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 */
590INLINE bool TransformState::
591cache_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 */
605INLINE void TransformState::
606node_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 */
619INLINE bool TransformState::
620node_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 */
637INLINE size_t TransformState::
638get_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 */
649INLINE size_t TransformState::
650get_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 */
664INLINE size_t TransformState::
665get_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 */
678INLINE const TransformState *TransformState::
679get_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 */
695INLINE const TransformState *TransformState::
696get_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 */
710INLINE size_t TransformState::
711get_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 */
724INLINE const TransformState *TransformState::
725get_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 */
741INLINE const TransformState *TransformState::
742get_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 */
750INLINE void TransformState::
751flush_level() {
752 _node_counter.flush_level();
753 _cache_counter.flush_level();
754}
755
756/**
757 * Overrides this method to update PStats appropriately.
758 */
760cache_ref_only() const {
761#ifdef DO_PSTATS
762 int old_referenced_bits = get_referenced_bits();
764 consider_update_pstats(old_referenced_bits);
765#else // DO_PSTATS
767#endif // DO_PSTATS
768}
769
770/**
771 * Overrides this method to update PStats appropriately.
772 */
773INLINE void TransformState::
774cache_unref_only() const {
775#ifdef DO_PSTATS
776 int old_referenced_bits = get_referenced_bits();
777 NodeCachedReferenceCount::cache_unref_only();
778 consider_update_pstats(old_referenced_bits);
779#else // DO_PSTATS
780 NodeCachedReferenceCount::cache_unref_only();
781#endif // DO_PSTATS
782}
783
784/**
785 * Reimplements NodeReferenceCount::node_unref(). We do this because we have
786 * a non-virtual unref() method.
787 */
788INLINE bool TransformState::
789do_node_unref() const {
790 node_unref_only();
791 return unref();
792}
793
794/**
795 * Reimplements CachedTypedWritableReferenceCount::cache_unref(). We do this
796 * because we have a non-virtual unref() method.
797 */
798INLINE bool TransformState::
799do_cache_unref() const {
800 NodeCachedReferenceCount::cache_unref_only();
801 return unref();
802}
803
804/**
805 * Ensures that we know the hash value.
806 */
807INLINE void TransformState::
808check_hash() const {
809 // This pretends to be a const function, even though it's not, because it
810 // only updates a transparent cache value.
811 if ((_flags & F_hash_known) == 0) {
812 ((TransformState *)this)->calc_hash();
813 }
814}
815
816/**
817 * Ensures that we know whether the matrix is singular.
818 */
819INLINE void TransformState::
820check_singular() const {
821 // This pretends to be a const function, even though it's not, because it
822 // only updates a transparent cache value.
823 if ((_flags & F_singular_known) == 0) {
824 ((TransformState *)this)->calc_singular();
825 }
826}
827
828/**
829 * Ensures that we know the components of the transform (or that we know they
830 * cannot be derived).
831 */
832INLINE void TransformState::
833check_components() const {
834 // This pretends to be a const function, even though it's not, because it
835 // only updates a transparent cache value.
836 if ((_flags & F_components_known) == 0) {
837 ((TransformState *)this)->calc_components();
838 }
839}
840
841/**
842 * Ensures that we know the hpr of the transform (or that we know they cannot
843 * be derived).
844 */
845INLINE void TransformState::
846check_hpr() const {
847 // This pretends to be a const function, even though it's not, because it
848 // only updates a transparent cache value.
849 if ((_flags & F_hpr_known) == 0) {
850 ((TransformState *)this)->calc_hpr();
851 }
852}
853
854/**
855 * Ensures that we know the quat of the transform (or that we know they cannot
856 * be derived).
857 */
858INLINE void TransformState::
859check_quat() const {
860 // This pretends to be a const function, even though it's not, because it
861 // only updates a transparent cache value.
862 if ((_flags & F_quat_known) == 0) {
863 ((TransformState *)this)->calc_quat();
864 }
865}
866
867/**
868 * Ensures that we know the normalized quat of the transform (or that we know
869 * they cannot be derived).
870 */
871INLINE void TransformState::
872check_norm_quat() const {
873 // This pretends to be a const function, even though it's not, because it
874 // only updates a transparent cache value.
875 if ((_flags & F_norm_quat_known) == 0) {
876 ((TransformState *)this)->calc_norm_quat();
877 }
878}
879
880/**
881 * Ensures that we know the overall matrix.
882 */
883INLINE void TransformState::
884check_mat() const {
885 // This pretends to be a const function, even though it's not, because it
886 // only updates a transparent cache value.
887 if ((_flags & F_mat_known) == 0) {
888 ((TransformState *)this)->calc_mat();
889 }
890}
891
892/**
893 * Computes the hash value.
894 */
895INLINE void TransformState::
896calc_hash() {
897 LightMutexHolder holder(_lock);
898 do_calc_hash();
899}
900
901/**
902 * Derives the components from the matrix, if possible.
903 */
904INLINE void TransformState::
905calc_components() {
906 LightMutexHolder holder(_lock);
907 do_calc_components();
908}
909
910/**
911 * Derives the hpr, from the matrix if necessary, or from the quat.
912 */
913INLINE void TransformState::
914calc_hpr() {
915 LightMutexHolder holder(_lock);
916 do_calc_hpr();
917}
918
919/**
920 * Computes the matrix from the components.
921 */
922INLINE void TransformState::
923calc_mat() {
924 LightMutexHolder holder(_lock);
925 do_calc_mat();
926}
927
928/**
929 * Should be called immediately after _scale (and F_has_components) is set,
930 * this checks for a identity and/or uniform scale (as well as a non-zero
931 * shear) and sets the bit appropriately.
932 *
933 * It does not matter whether the lock is or is not held before calling this
934 * method.
935 */
936INLINE void TransformState::
937check_uniform_scale() {
938 if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) &&
939 IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
940 _flags |= F_uniform_scale;
941 if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
942 _flags |= F_identity_scale;
943 }
944 }
945
946 if (!_shear.almost_equal(LVecBase3::zero())) {
947 _flags |= F_has_nonzero_shear;
948 }
949}
950
951/**
952 * Should be called immediately after _scale (and F_has_components) is set,
953 * for a known 2-d scale, this checks for a identity and/or uniform scale (as
954 * well as a non-zero shear) and sets the bit appropriately.
955 *
956 * It does not matter whether the lock is or is not held before calling this
957 * method.
958 */
959INLINE void TransformState::
960check_uniform_scale2d() {
961 if (IS_NEARLY_EQUAL(_scale[0], _scale[1])) {
962 _scale[2] = _scale[0];
963 _flags |= F_uniform_scale;
964 if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
965 _flags |= F_identity_scale;
966 }
967 }
968
969 if (!_shear.almost_equal(LVecBase3::zero())) {
970 _flags |= F_has_nonzero_shear;
971 }
972}
973
974/**
975 * This function should only be called from the destructor; it indicates that
976 * this TransformState object is beginning destruction. It is only used as a
977 * sanity check, and is only meaningful when NDEBUG is not defined.
978 */
979INLINE void TransformState::
980set_destructing() {
981#ifndef NDEBUG
982 _flags |= F_is_destructing;
983#endif
984}
985
986/**
987 * Returns true if the TransformState object is currently within its
988 * destructor (i.e. set_destructing() has been called). This is only used as
989 * a sanity check, and is only meaningful when NDEBUG is not defined.
990 */
991INLINE bool TransformState::
992is_destructing() const {
993#ifndef NDEBUG
994 return (_flags & F_is_destructing) != 0;
995#else
996 return false;
997#endif
998}
999
1000/**
1001 * Calls update_pstats() if the state of the referenced bits has changed from
1002 * the indicated value.
1003 */
1004INLINE void TransformState::
1005consider_update_pstats(int old_referenced_bits) const {
1006#ifdef DO_PSTATS
1007 int new_referenced_bits = get_referenced_bits();
1008 if (old_referenced_bits != new_referenced_bits) {
1009 update_pstats(old_referenced_bits, new_referenced_bits);
1010 }
1011#endif // DO_PSTATS
1012}
1013
1014/**
1015 *
1016 */
1017INLINE TransformState::Composition::
1018Composition() {
1019}
1020
1021/**
1022 *
1023 */
1024INLINE TransformState::Composition::
1025Composition(const TransformState::Composition &copy) :
1026 _result(copy._result)
1027{
1028}
1029
1030/**
1031 *
1032 */
1033INLINE TransformState::CompositionCycleDescEntry::
1034CompositionCycleDescEntry(const TransformState *obj,
1035 const TransformState *result,
1036 bool inverted) :
1037 _obj(obj),
1038 _result(result),
1039 _inverted(inverted)
1040{
1041}
void cache_ref() const
Explicitly increments 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.
Similar to MutexHolder, but for a light mutex.
Similar to MutexHolder, but for a light reentrant mutex.
void node_ref() const
Explicitly increments the reference count.
int get_referenced_bits() const
Returns the union of the values defined in the Referenced enum that represents the various things tha...
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
size_t get_num_entries() const
Returns the number of active entries in the table.
Indicates a coordinate-system transform on vertices.
bool is_invalid() const
Returns true if the transform represents an invalid matrix, for instance the result of inverting a si...
bool operator==(const TransformState &other) const
Tests equivalence between two transform states.
PN_stdfloat get_rotate2d() const
Returns the rotation component of the 2-d transform as an angle in degrees clockwise about the origin...
get_quat
Returns the rotation component of the transform as a quaternion.
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.
bool components_given() const
Returns true if the transform was specified componentwise, or false if it was specified with a genera...
virtual bool unref() const
Explicitly decrements the reference count.
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.
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...
bool operator!=(const TransformState &other) const
Opposite of operator ==.
void cache_ref_only() const
Overrides this method to update PStats appropriately.
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.
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.