historical/toontown-classic.git/panda/include/transformState.I

1014 lines
28 KiB
Text
Raw Normal View History

2024-01-16 11:20:27 -06:00
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file transformState.I
* @author drose
* @date 2002-02-25
*/
/**
* Opposite of operator ==.
*/
INLINE bool TransformState::
operator != (const TransformState &other) const {
return !(operator == (other));
}
/**
* Provides an arbitrary ordering among all unique TransformStates, so we can
* store the essentially different ones in a big set and throw away the rest.
*
* Note that if this returns 0, it doesn't necessarily imply that operator ==
* returns true; it uses a very slightly different comparison threshold.
*/
INLINE int TransformState::
compare_to(const TransformState &other) const {
return compare_to(other, _uniquify_matrix);
}
/**
* Returns a suitable hash value for phash_map.
*/
INLINE size_t TransformState::
get_hash() const {
check_hash();
return _hash;
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos(const LVecBase3 &pos) {
return make_pos_hpr_scale(pos,
LVecBase3(0.0f, 0.0f, 0.0f),
LVecBase3(1.0f, 1.0f, 1.0f));
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_hpr(const LVecBase3 &hpr) {
return make_pos_hpr_scale(LVecBase3(0.0f, 0.0f, 0.0f),
hpr,
LVecBase3(1.0f, 1.0f, 1.0f));
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_quat(const LQuaternion &quat) {
return make_pos_quat_scale(LVecBase3(0.0f, 0.0f, 0.0f),
quat,
LVecBase3(1.0f, 1.0f, 1.0f));
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos_hpr(const LVecBase3 &pos, const LVecBase3 &hpr) {
return make_pos_hpr_scale(pos, hpr,
LVecBase3(1.0, 1.0f, 1.0f));
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_scale(PN_stdfloat scale) {
// We actually map this 3-d uniform make_scale() to the 2-d version--might
// as well call it a 2-d scale.
return make_scale2d(scale);
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_scale(const LVecBase3 &scale) {
return make_pos_hpr_scale(LVecBase3(0.0f, 0.0f, 0.0f),
LVecBase3(0.0f, 0.0f, 0.0f),
scale);
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_shear(const LVecBase3 &shear) {
return make_pos_hpr_scale_shear(LVecBase3(0.0f, 0.0f, 0.0f),
LVecBase3(0.0f, 0.0f, 0.0f),
LVecBase3(1.0f, 1.0f, 1.0f),
shear);
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos_hpr_scale(const LVecBase3 &pos, const LVecBase3 &hpr,
const LVecBase3 &scale) {
return make_pos_hpr_scale_shear(pos, hpr, scale, LVecBase3::zero());
}
/**
* Makes a new TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos_quat_scale(const LVecBase3 &pos, const LQuaternion &quat,
const LVecBase3 &scale) {
return make_pos_quat_scale_shear(pos, quat, scale, LVecBase3::zero());
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos2d(const LVecBase2 &pos) {
return make_pos_rotate_scale2d(pos, 0.0f, LVecBase2(1.0f, 1.0f));
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_rotate2d(PN_stdfloat rotate) {
return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), rotate,
LVecBase2(1.0f, 1.0f));
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos_rotate2d(const LVecBase2 &pos, PN_stdfloat rotate) {
return make_pos_rotate_scale2d(pos, rotate,
LVecBase2(1.0, 1.0f));
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_scale2d(PN_stdfloat scale) {
return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), 0.0f,
LVecBase2(scale, scale));
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_scale2d(const LVecBase2 &scale) {
return make_pos_rotate_scale2d(LVecBase2(0.0f, 0.0f), 0.0f, scale);
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_shear2d(PN_stdfloat shear) {
return make_pos_rotate_scale_shear2d(LVecBase2(0.0f, 0.0f), 0.0f,
LVecBase2(1.0f, 1.0f), shear);
}
/**
* Makes a new 2-d TransformState with the specified components.
*/
INLINE CPT(TransformState) TransformState::
make_pos_rotate_scale2d(const LVecBase2 &pos, PN_stdfloat rotate,
const LVecBase2 &scale) {
return make_pos_rotate_scale_shear2d(pos, rotate, scale, 0.0f);
}
/**
* Returns true if the transform represents the identity matrix, false
* otherwise.
*/
INLINE bool TransformState::
is_identity() const {
return ((_flags & F_is_identity) != 0);
}
/**
* Returns true if the transform represents an invalid matrix, for instance
* the result of inverting a singular matrix, or false if the transform is
* valid.
*/
INLINE bool TransformState::
is_invalid() const {
return ((_flags & F_is_invalid) != 0);
}
/**
* Returns true if the transform represents a singular transform (that is, it
* has a zero scale, and it cannot be inverted), or false otherwise.
*/
INLINE bool TransformState::
is_singular() const {
check_singular();
return ((_flags & F_is_singular) != 0);
}
/**
* Returns true if the transform has been constructed entirely using the 2-d
* transform operations, e.g. make_pos2d(), and therefore operates strictly
* in two-dimensional space on X and Y only.
*/
INLINE bool TransformState::
is_2d() const {
return ((_flags & F_is_2d) != 0);
}
/**
* Returns true if the transform can be described by separate pos, hpr, and
* scale components. Most transforms we use in everyday life can be so
* described, but some kinds of transforms (for instance, those involving a
* skew) cannot.
*
* This is not related to whether the transform was originally described
* componentwise. Even a transform that was constructed with a 4x4 may return
* true here if the matrix is a simple affine matrix with no skew.
*
* If this returns true, you may safely call get_hpr() and get_scale() to
* retrieve the components. (You may always safely call get_pos() whether
* this returns true or false.)
*/
INLINE bool TransformState::
has_components() const {
check_components();
return ((_flags & F_has_components) != 0);
}
/**
* Returns true if the transform was specified componentwise, or false if it
* was specified with a general 4x4 matrix. If this is true, the components
* returned by get_pos() and get_scale() will be exactly those that were set;
* otherwise, these functions will return computed values. If this is true,
* the rotation may have been set either with a hpr trio or with a quaternion;
* hpr_given() or quat_given() can resolve the difference.
*/
INLINE bool TransformState::
components_given() const {
return ((_flags & F_components_given) != 0);
}
/**
* Returns true if the rotation was specified via a trio of Euler angles,
* false otherwise. If this is true, get_hpr() will be exactly as set;
* otherwise, it will return a computed value.
*/
INLINE bool TransformState::
hpr_given() const {
return ((_flags & F_hpr_given) != 0);
}
/**
* Returns true if the rotation was specified via a quaternion, false
* otherwise. If this is true, get_quat() will be exactly as set; otherwise,
* it will return a computed value.
*/
INLINE bool TransformState::
quat_given() const {
return ((_flags & F_quat_given) != 0);
}
/**
* Returns true if the transform's pos component can be extracted out
* separately. This is generally always true, unless the transform is invalid
* (i.e. is_invalid() returns true).
*/
INLINE bool TransformState::
has_pos() const {
return !is_invalid();
}
/**
* Returns true if the transform's rotation component can be extracted out
* separately and described as a set of Euler angles. This is generally true
* only when has_components() is true.
*/
INLINE bool TransformState::
has_hpr() const {
return has_components();
}
/**
* Returns true if the transform's rotation component can be extracted out
* separately and described as a quaternion. This is generally true only when
* has_components() is true.
*/
INLINE bool TransformState::
has_quat() const {
return has_components();
}
/**
* Returns true if the transform's scale component can be extracted out
* separately. This is generally true only when has_components() is true.
*/
INLINE bool TransformState::
has_scale() const {
return has_components();
}
/**
* Returns true if the scale is uniform 1.0, or false if the scale has some
* real value.
*/
INLINE bool TransformState::
has_identity_scale() const {
check_components();
return (_flags & F_identity_scale) != 0;
}
/**
* Returns true if the scale is uniform across all three axes (and therefore
* can be expressed as a single number), or false if the transform has a
* different scale in different dimensions.
*/
INLINE bool TransformState::
has_uniform_scale() const {
check_components();
return (_flags & F_uniform_scale) != 0;
}
/**
* Returns true if the transform's shear component can be extracted out
* separately. This is generally true only when has_components() is true.
*/
INLINE bool TransformState::
has_shear() const {
return has_components();
}
/**
* Returns true if the shear component is non-zero, false if it is zero or if
* the matrix cannot be decomposed.
*/
INLINE bool TransformState::
has_nonzero_shear() const {
check_components();
return (_flags & F_has_nonzero_shear) != 0;
}
/**
* Returns true if the transform can be described as a matrix. This is
* generally always true, unless is_invalid() is true.
*/
INLINE bool TransformState::
has_mat() const {
return !is_invalid();
}
/**
* Returns the pos component of the transform. It is an error to call this if
* has_pos() returned false.
*/
INLINE const LPoint3 &TransformState::
get_pos() const {
check_components();
nassertr(has_pos(), _pos);
return _pos;
}
/**
* Returns the rotation component of the transform as a trio of Euler angles.
* It is an error to call this if has_components() returned false.
*/
INLINE const LVecBase3 &TransformState::
get_hpr() const {
check_hpr();
nassertr(!is_invalid(), _hpr);
return _hpr;
}
/**
* Returns the rotation component of the transform as a quaternion. The
* return value will be normalized if a normalized quaternion was given to the
* constructor (or if the quaternion was computed implicitly); it will be non-
* normalized if a non-normalized quaternion was given to the constructor.
* See also get_norm_quat().
*
* It is an error to call this if has_components() returned false.
*/
INLINE const LQuaternion &TransformState::
get_quat() const {
check_quat();
nassertr(!is_invalid(), _quat);
return _quat;
}
/**
* Returns the rotation component of the transform as a quaternion. Unlike
* the result of get_quat(), the return value of this method is guaranteed to
* be normalized. It is an error to call this if has_components() returned
* false.
*/
INLINE const LQuaternion &TransformState::
get_norm_quat() const {
check_norm_quat();
nassertr(!is_invalid(), _norm_quat);
return _norm_quat;
}
/**
* Returns the scale component of the transform. It is an error to call this
* if has_components() returned false.
*/
INLINE const LVecBase3 &TransformState::
get_scale() const {
check_components();
nassertr(!is_invalid(), _scale);
return _scale;
}
/**
* Returns the scale component of the transform, as a single number. It is an
* error to call this if has_uniform_scale() returned false.
*/
INLINE PN_stdfloat TransformState::
get_uniform_scale() const {
check_components();
nassertr(has_uniform_scale(), _scale[0]);
return _scale[0];
}
/**
* Returns the shear component of the transform. It is an error to call this
* if has_components() returned false.
*/
INLINE const LVecBase3 &TransformState::
get_shear() const {
check_components();
nassertr(!is_invalid(), _shear);
return _shear;
}
/**
* Returns the matrix that describes the transform.
*/
INLINE const LMatrix4 &TransformState::
get_mat() const {
nassertr(has_mat(), LMatrix4::ident_mat());
check_mat();
return _mat;
}
/**
* Returns the pos component of the 2-d transform. It is an error to call
* this if has_pos() or is_2d() returned false.
*/
INLINE LVecBase2 TransformState::
get_pos2d() const {
check_components();
nassertr(has_pos() && is_2d(), LVecBase2::zero());
return LVecBase2(_pos[0], _pos[1]);
}
/**
* Returns the rotation component of the 2-d transform as an angle in degrees
* clockwise about the origin. It is an error to call this if
* has_components() or is_2d() returned false.
*/
INLINE PN_stdfloat TransformState::
get_rotate2d() const {
check_hpr();
nassertr(!is_invalid() && is_2d(), 0);
switch (get_default_coordinate_system()) {
default:
case CS_zup_right:
return _hpr[0];
case CS_zup_left:
return -_hpr[0];
case CS_yup_right:
return -_hpr[2];
case CS_yup_left:
return _hpr[2];
}
}
/**
* Returns the scale component of the 2-d transform. It is an error to call
* this if has_components() or is_2d() returned false.
*/
INLINE LVecBase2 TransformState::
get_scale2d() const {
check_components();
nassertr(!is_invalid() && is_2d(), LVecBase2::zero());
return LVecBase2(_scale[0], _scale[1]);
}
/**
* Returns the shear component of the 2-d transform. It is an error to call
* this if has_components() or is_2d() returned false.
*/
INLINE PN_stdfloat TransformState::
get_shear2d() const {
check_components();
nassertr(!is_invalid() && is_2d(), 0.0f);
return _shear[0];
}
/**
* Returns the 3x3 matrix that describes the 2-d transform. It is an error to
* call this if is_2d() returned false.
*/
INLINE LMatrix3 TransformState::
get_mat3() const {
nassertr(has_mat() && is_2d(), LMatrix3::ident_mat());
check_mat();
return LMatrix3(_mat(0, 0), _mat(0, 1), _mat(0, 3),
_mat(1, 0), _mat(1, 1), _mat(1, 3),
_mat(3, 0), _mat(3, 1), _mat(3, 3));
}
/**
* Returns the inverse of this transform. If you are going to immediately
* compose this result with another TransformState, it is faster to do it in
* one operation with invert_compose().
*/
INLINE CPT(TransformState) TransformState::
get_inverse() const {
return invert_compose(TransformState::make_identity());
}
/**
* Returns the pointer to the unique TransformState in the cache that is
* equivalent to this one. This may be the same pointer as this object, or it
* may be a different pointer; but it will be an equivalent object, and it
* will be a shared pointer. This may be called from time to time to improve
* cache benefits.
*/
INLINE CPT(TransformState) TransformState::
get_unique() const {
return return_unique((TransformState *)this);
}
/**
* Returns the union of the Geom::GeomRendering bits that will be required
* once this TransformState is applied to a geom which includes the indicated
* geom_rendering bits. The RenderState's get_geom_rendering() should already
* have been applied.
*/
INLINE int TransformState::
get_geom_rendering(int geom_rendering) const {
if ((geom_rendering & GeomEnums::GR_point_perspective) != 0) {
if (!has_identity_scale()) {
geom_rendering |= GeomEnums::GR_point_scale;
}
}
return geom_rendering;
}
/**
* Overrides this method to update PStats appropriately.
*/
INLINE void TransformState::
cache_ref() const {
#ifdef DO_PSTATS
int old_referenced_bits = get_referenced_bits();
NodeCachedReferenceCount::cache_ref();
consider_update_pstats(old_referenced_bits);
#else // DO_PSTATS
NodeCachedReferenceCount::cache_ref();
#endif // DO_PSTATS
}
/**
* Overrides this method to update PStats appropriately.
*/
INLINE bool TransformState::
cache_unref() const {
#ifdef DO_PSTATS
int old_referenced_bits = get_referenced_bits();
bool result = do_cache_unref();
consider_update_pstats(old_referenced_bits);
return result;
#else // DO_PSTATS
return do_cache_unref();
#endif // DO_PSTATS
}
/**
* Overrides this method to update PStats appropriately.
*/
INLINE void TransformState::
node_ref() const {
#ifdef DO_PSTATS
int old_referenced_bits = get_referenced_bits();
NodeCachedReferenceCount::node_ref();
consider_update_pstats(old_referenced_bits);
#else // DO_PSTATS
NodeCachedReferenceCount::node_ref();
#endif // DO_PSTATS
}
/**
* Overrides this method to update PStats appropriately.
*/
INLINE bool TransformState::
node_unref() const {
#ifdef DO_PSTATS
int old_referenced_bits = get_referenced_bits();
bool result = do_node_unref();
consider_update_pstats(old_referenced_bits);
return result;
#else // DO_PSTATS
return do_node_unref();
#endif // DO_PSTATS
}
/**
* Returns the number of entries in the composition cache for this
* TransformState. This is the number of other TransformStates whose
* composition with this one has been cached. This number is not useful for
* any practical reason other than performance analysis.
*/
INLINE size_t TransformState::
get_composition_cache_num_entries() const {
LightReMutexHolder holder(*_states_lock);
return _composition_cache.get_num_entries();
}
/**
* Returns the number of entries in the invert_composition cache for this
* TransformState. This is similar to the composition cache, but it records
* cache entries for the invert_compose() operation. See
* get_composition_cache_num_entries().
*/
INLINE size_t TransformState::
get_invert_composition_cache_num_entries() const {
LightReMutexHolder holder(*_states_lock);
return _invert_composition_cache.get_num_entries();
}
/**
* Returns the number of slots in the composition cache for this
* TransformState. You may use this as an upper bound when walking through
* all of the composition cache results via get_composition_cache_source() or
* result().
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE size_t TransformState::
get_composition_cache_size() const {
LightReMutexHolder holder(*_states_lock);
return _composition_cache.get_num_entries();
}
/**
* Returns the source TransformState of the nth element in the composition
* cache. Returns NULL if there doesn't happen to be an entry in the nth
* element. See get_composition_cache_result().
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE const TransformState *TransformState::
get_composition_cache_source(size_t n) const {
LightReMutexHolder holder(*_states_lock);
return _composition_cache.get_key(n);
}
/**
* Returns the result TransformState of the nth element in the composition
* cache. Returns NULL if there doesn't happen to be an entry in the nth
* element.
*
* In general, a->compose(a->get_composition_cache_source(n)) ==
* a->get_composition_cache_result(n).
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE const TransformState *TransformState::
get_composition_cache_result(size_t n) const {
LightReMutexHolder holder(*_states_lock);
return _composition_cache.get_data(n)._result;
}
/**
* Returns the number of slots in the composition cache for this
* TransformState. You may use this as an upper bound when walking through
* all of the composition cache results via
* get_invert_composition_cache_source() or result().
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE size_t TransformState::
get_invert_composition_cache_size() const {
LightReMutexHolder holder(*_states_lock);
return _invert_composition_cache.get_num_entries();
}
/**
* Returns the source TransformState of the nth element in the invert
* composition cache. Returns NULL if there doesn't happen to be an entry in
* the nth element. See get_invert_composition_cache_result().
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE const TransformState *TransformState::
get_invert_composition_cache_source(size_t n) const {
LightReMutexHolder holder(*_states_lock);
return _invert_composition_cache.get_key(n);
}
/**
* Returns the result TransformState of the nth element in the invert
* composition cache. Returns NULL if there doesn't happen to be an entry in
* the nth element.
*
* In general, a->invert_compose(a->get_invert_composition_cache_source(n)) ==
* a->get_invert_composition_cache_result(n).
*
* This has no practical value other than for examining the cache for
* performance analysis.
*/
INLINE const TransformState *TransformState::
get_invert_composition_cache_result(size_t n) const {
LightReMutexHolder holder(*_states_lock);
return _invert_composition_cache.get_data(n)._result;
}
/**
* Flushes the PStatCollectors used during traversal.
*/
INLINE void TransformState::
flush_level() {
_node_counter.flush_level();
_cache_counter.flush_level();
}
/**
* Reimplements NodeReferenceCount::node_unref(). We do this because we have
* a non-virtual unref() method.
*/
INLINE bool TransformState::
do_node_unref() const {
node_unref_only();
return unref();
}
/**
* Reimplements CachedTypedWritableReferenceCount::cache_unref(). We do this
* because we have a non-virtual unref() method.
*/
INLINE bool TransformState::
do_cache_unref() const {
cache_unref_only();
return unref();
}
/**
* Ensures that we know the hash value.
*/
INLINE void TransformState::
check_hash() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_hash_known) == 0) {
((TransformState *)this)->calc_hash();
}
}
/**
* Ensures that we know whether the matrix is singular.
*/
INLINE void TransformState::
check_singular() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_singular_known) == 0) {
((TransformState *)this)->calc_singular();
}
}
/**
* Ensures that we know the components of the transform (or that we know they
* cannot be derived).
*/
INLINE void TransformState::
check_components() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_components_known) == 0) {
((TransformState *)this)->calc_components();
}
}
/**
* Ensures that we know the hpr of the transform (or that we know they cannot
* be derived).
*/
INLINE void TransformState::
check_hpr() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_hpr_known) == 0) {
((TransformState *)this)->calc_hpr();
}
}
/**
* Ensures that we know the quat of the transform (or that we know they cannot
* be derived).
*/
INLINE void TransformState::
check_quat() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_quat_known) == 0) {
((TransformState *)this)->calc_quat();
}
}
/**
* Ensures that we know the normalized quat of the transform (or that we know
* they cannot be derived).
*/
INLINE void TransformState::
check_norm_quat() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_norm_quat_known) == 0) {
((TransformState *)this)->calc_norm_quat();
}
}
/**
* Ensures that we know the overall matrix.
*/
INLINE void TransformState::
check_mat() const {
// This pretends to be a const function, even though it's not, because it
// only updates a transparent cache value.
if ((_flags & F_mat_known) == 0) {
((TransformState *)this)->calc_mat();
}
}
/**
* Computes the hash value.
*/
INLINE void TransformState::
calc_hash() {
LightMutexHolder holder(_lock);
do_calc_hash();
}
/**
* Derives the components from the matrix, if possible.
*/
INLINE void TransformState::
calc_components() {
LightMutexHolder holder(_lock);
do_calc_components();
}
/**
* Derives the hpr, from the matrix if necessary, or from the quat.
*/
INLINE void TransformState::
calc_hpr() {
LightMutexHolder holder(_lock);
do_calc_hpr();
}
/**
* Computes the matrix from the components.
*/
INLINE void TransformState::
calc_mat() {
LightMutexHolder holder(_lock);
do_calc_mat();
}
/**
* Should be called immediately after _scale (and F_has_components) is set,
* this checks for a identity and/or uniform scale (as well as a non-zero
* shear) and sets the bit appropriately.
*
* It does not matter whether the lock is or is not held before calling this
* method.
*/
INLINE void TransformState::
check_uniform_scale() {
if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) &&
IS_NEARLY_EQUAL(_scale[0], _scale[2])) {
_flags |= F_uniform_scale;
if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
_flags |= F_identity_scale;
}
}
if (!_shear.almost_equal(LVecBase3::zero())) {
_flags |= F_has_nonzero_shear;
}
}
/**
* Should be called immediately after _scale (and F_has_components) is set,
* for a known 2-d scale, this checks for a identity and/or uniform scale (as
* well as a non-zero shear) and sets the bit appropriately.
*
* It does not matter whether the lock is or is not held before calling this
* method.
*/
INLINE void TransformState::
check_uniform_scale2d() {
if (IS_NEARLY_EQUAL(_scale[0], _scale[1])) {
_scale[2] = _scale[0];
_flags |= F_uniform_scale;
if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) {
_flags |= F_identity_scale;
}
}
if (!_shear.almost_equal(LVecBase3::zero())) {
_flags |= F_has_nonzero_shear;
}
}
/**
* This function should only be called from the destructor; it indicates that
* this TransformState object is beginning destruction. It is only used as a
* sanity check, and is only meaningful when NDEBUG is not defined.
*/
INLINE void TransformState::
set_destructing() {
#ifndef NDEBUG
_flags |= F_is_destructing;
#endif
}
/**
* Returns true if the TransformState object is currently within its
* destructor (i.e. set_destructing() has been called). This is only used as
* a sanity check, and is only meaningful when NDEBUG is not defined.
*/
INLINE bool TransformState::
is_destructing() const {
#ifndef NDEBUG
return (_flags & F_is_destructing) != 0;
#else
return false;
#endif
}
/**
* Calls update_pstats() if the state of the referenced bits has changed from
* the indicated value.
*/
INLINE void TransformState::
consider_update_pstats(int old_referenced_bits) const {
#ifdef DO_PSTATS
int new_referenced_bits = get_referenced_bits();
if (old_referenced_bits != new_referenced_bits) {
update_pstats(old_referenced_bits, new_referenced_bits);
}
#endif // DO_PSTATS
}
/**
*
*/
INLINE TransformState::Composition::
Composition() {
}
/**
*
*/
INLINE TransformState::Composition::
Composition(const TransformState::Composition &copy) :
_result(copy._result)
{
}
/**
*
*/
INLINE TransformState::CompositionCycleDescEntry::
CompositionCycleDescEntry(const TransformState *obj,
const TransformState *result,
bool inverted) :
_obj(obj),
_result(result),
_inverted(inverted)
{
}