383 lines
9.5 KiB
Text
383 lines
9.5 KiB
Text
/**
|
|
* 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 transformBlend.I
|
|
* @author drose
|
|
* @date 2005-03-24
|
|
*/
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend() {
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend(const VertexTransform *transform0, PN_stdfloat) {
|
|
add_transform(transform0, 1.0f);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
|
|
const VertexTransform *transform1, PN_stdfloat weight1) {
|
|
add_transform(transform0, weight0);
|
|
add_transform(transform1, weight1);
|
|
normalize_weights();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
|
|
const VertexTransform *transform1, PN_stdfloat weight1,
|
|
const VertexTransform *transform2, PN_stdfloat weight2) {
|
|
add_transform(transform0, weight0);
|
|
add_transform(transform1, weight1);
|
|
add_transform(transform2, weight2);
|
|
normalize_weights();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
|
|
const VertexTransform *transform1, PN_stdfloat weight1,
|
|
const VertexTransform *transform2, PN_stdfloat weight2,
|
|
const VertexTransform *transform3, PN_stdfloat weight3) {
|
|
add_transform(transform0, weight0);
|
|
add_transform(transform1, weight1);
|
|
add_transform(transform2, weight2);
|
|
add_transform(transform3, weight3);
|
|
normalize_weights();
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
TransformBlend(const TransformBlend ©) :
|
|
_entries(copy._entries)
|
|
{
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void TransformBlend::
|
|
operator = (const TransformBlend ©) {
|
|
_entries = copy._entries;
|
|
Thread *current_thread = Thread::get_current_thread();
|
|
clear_result(current_thread);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::
|
|
~TransformBlend() {
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE bool TransformBlend::
|
|
operator < (const TransformBlend &other) const {
|
|
return compare_to(other) < 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE bool TransformBlend::
|
|
operator == (const TransformBlend &other) const {
|
|
return compare_to(other) == 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE bool TransformBlend::
|
|
operator != (const TransformBlend &other) const {
|
|
return compare_to(other) != 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of transforms stored in the blend object.
|
|
*/
|
|
INLINE size_t TransformBlend::
|
|
get_num_transforms() const {
|
|
return _entries.size();
|
|
}
|
|
|
|
/**
|
|
* Returns the nth transform stored in the blend object.
|
|
*/
|
|
INLINE const VertexTransform *TransformBlend::
|
|
get_transform(size_t n) const {
|
|
nassertr(n < _entries.size(), nullptr);
|
|
return _entries[n]._transform;
|
|
}
|
|
|
|
/**
|
|
* Returns the weight associated with the nth transform stored in the blend
|
|
* object.
|
|
*/
|
|
INLINE PN_stdfloat TransformBlend::
|
|
get_weight(size_t n) const {
|
|
nassertr(n < _entries.size(), 0.0f);
|
|
return _entries[n]._weight;
|
|
}
|
|
|
|
/**
|
|
* Removes the nth transform stored in the blend object.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
remove_transform(size_t n) {
|
|
nassertv(n < _entries.size());
|
|
_entries.erase(_entries.begin() + n);
|
|
Thread *current_thread = Thread::get_current_thread();
|
|
clear_result(current_thread);
|
|
}
|
|
|
|
/**
|
|
* Replaces the nth transform stored in the blend object.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
set_transform(size_t n, const VertexTransform *transform) {
|
|
nassertv(n < _entries.size());
|
|
_entries[n]._transform = transform;
|
|
}
|
|
|
|
/**
|
|
* Replaces the weight associated with the nth transform stored in the blend
|
|
* object.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
set_weight(size_t n, PN_stdfloat weight) {
|
|
nassertv(n < _entries.size());
|
|
_entries[n]._weight = weight;
|
|
}
|
|
|
|
/**
|
|
* Recomputes the internal representation of the blend value, if necessary.
|
|
* You should call this before calling get_blend() or transform_point().
|
|
*/
|
|
INLINE void TransformBlend::
|
|
update_blend(Thread *current_thread) const {
|
|
CDLockedReader cdata(_cycler, current_thread);
|
|
if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
|
|
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
|
|
((TransformBlend *)this)->recompute_result(cdataw, current_thread);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the current value of the blend, based on the current value of all
|
|
* of the nested transform objects and their associated weights.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
get_blend(LMatrix4 &result, Thread *current_thread) const {
|
|
CDReader cdata(_cycler, current_thread);
|
|
result = cdata->_result;
|
|
}
|
|
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint4 &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * cdata->_result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint3 &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * cdata->_result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transforms the indicated vector by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_vector(LVector3 &vector, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
vector = vector * cdata->_result;
|
|
}
|
|
}
|
|
|
|
#ifndef STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint4d &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * LCAST(double, cdata->_result);
|
|
}
|
|
}
|
|
#else // STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint4f &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * LCAST(float, cdata->_result);
|
|
}
|
|
}
|
|
#endif // STDFLOAT_DOUBLE
|
|
|
|
#ifndef STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint3d &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * LCAST(double, cdata->_result);
|
|
}
|
|
}
|
|
#else // STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated point by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_point(LPoint3f &point, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
point = point * LCAST(float, cdata->_result);
|
|
}
|
|
}
|
|
#endif // STDFLOAT_DOUBLE
|
|
|
|
#ifndef STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated vector by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_vector(LVector3d &vector, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
vector = vector * LCAST(double, cdata->_result);
|
|
}
|
|
}
|
|
#else // STDFLOAT_DOUBLE
|
|
/**
|
|
* Transforms the indicated vector by the blend matrix.
|
|
*
|
|
* You should call update_blend() to ensure that the cache is up-to-date
|
|
* before calling this.
|
|
*/
|
|
INLINE void TransformBlend::
|
|
transform_vector(LVector3f &vector, Thread *current_thread) const {
|
|
if (!_entries.empty()) {
|
|
CDReader cdata(_cycler, current_thread);
|
|
vector = vector * LCAST(float, cdata->_result);
|
|
}
|
|
}
|
|
#endif // STDFLOAT_DOUBLE
|
|
|
|
/**
|
|
* Returns a counter which is guaranteed to increment at least as often as the
|
|
* result of get_blend() changes.
|
|
*/
|
|
INLINE UpdateSeq TransformBlend::
|
|
get_modified(Thread *current_thread) const {
|
|
CDLockedReader cdata(_cycler, current_thread);
|
|
if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
|
|
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
|
|
((TransformBlend *)this)->recompute_result(cdataw, current_thread);
|
|
return cdataw->_modified;
|
|
} else {
|
|
return cdata->_modified;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Provides an ordering of TransformEntries by the VertexTransform pointer
|
|
* only, so we can easily look up in the set to see if a particular transform
|
|
* exists.
|
|
*/
|
|
INLINE bool TransformBlend::TransformEntry::
|
|
operator < (const TransformBlend::TransformEntry &other) const {
|
|
return _transform < other._transform;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::CData::
|
|
CData() :
|
|
_result(LMatrix4::ident_mat())
|
|
{
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE TransformBlend::CData::
|
|
CData(const TransformBlend::CData ©) :
|
|
_result(copy._result),
|
|
_modified(copy._modified),
|
|
_global_modified(copy._global_modified)
|
|
{
|
|
}
|
|
|
|
INLINE std::ostream &
|
|
operator << (std::ostream &out, const TransformBlend &obj) {
|
|
obj.output(out);
|
|
return out;
|
|
}
|