optimize TransformState inverse operation a bit more
This commit is contained in:
parent
ddff6234ba
commit
597e892b98
|
|
@ -90,8 +90,11 @@ INLINE CullTraverserData::
|
|||
INLINE bool CullTraverserData::
|
||||
is_in_view(PandaNode *node) {
|
||||
if (_view_frustum == (GeometricBoundingVolume *)NULL) {
|
||||
// If we don't have a frustum, we're always in.
|
||||
// If the transform is valid, but we don't have a frustum, it's
|
||||
// always in.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, compare the bounding volume to the frustum.
|
||||
return is_in_view_impl(node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,11 @@ r_traverse(PandaNode *node, const CullTraverserData &data) {
|
|||
// optimization, we should tag nodes with these properties as
|
||||
// being "fancy", and skip this processing for non-fancy nodes.
|
||||
|
||||
if (node->get_transform()->is_invalid()) {
|
||||
// If the transform is invalid, forget it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (next_data.is_in_view(node)) {
|
||||
next_data.apply_transform_and_state(node);
|
||||
|
||||
|
|
@ -265,6 +270,11 @@ r_get_decals(PandaNode *node, const CullTraverserData &data,
|
|||
CullableObject *decals) {
|
||||
CullTraverserData next_data(data);
|
||||
|
||||
if (node->get_transform()->is_invalid()) {
|
||||
// If the transform is invalid, forget it.
|
||||
return decals;
|
||||
}
|
||||
|
||||
if (next_data.is_in_view(node)) {
|
||||
next_data.apply_transform_and_state(node);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ TransformState() {
|
|||
_saved_entry = _states.end();
|
||||
_self_compose = (TransformState *)NULL;
|
||||
_flags = F_is_identity | F_singular_known;
|
||||
_inv_mat = (LMatrix4f *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -70,6 +71,11 @@ operator = (const TransformState &) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
TransformState::
|
||||
~TransformState() {
|
||||
// Free the inverse matrix computation, if it has been stored.
|
||||
if (_inv_mat != (LMatrix4f *)NULL) {
|
||||
delete _inv_mat;
|
||||
}
|
||||
|
||||
// Remove the deleted TransformState object from the global pool.
|
||||
if (_saved_entry != _states.end()) {
|
||||
_states.erase(_saved_entry);
|
||||
|
|
@ -584,19 +590,22 @@ do_invert_compose(const TransformState *other) const {
|
|||
nassertr((_flags & F_is_invalid) == 0, this);
|
||||
nassertr((other->_flags & F_is_invalid) == 0, other);
|
||||
|
||||
if (is_singular()) {
|
||||
return make_invalid();
|
||||
}
|
||||
|
||||
// We should do this operation componentwise if both transforms were
|
||||
// given componentwise.
|
||||
|
||||
// Perhaps we should cache the result of the inverse matrix
|
||||
// operation separately, as a further optimization.
|
||||
// Now that is_singular() has returned true, we can assume that
|
||||
// _inv_mat has been allocated and filled in.
|
||||
nassertr(_inv_mat != (LMatrix4f *)NULL, make_invalid());
|
||||
|
||||
LMatrix4f new_mat;
|
||||
bool invertible = new_mat.invert_from(get_mat());
|
||||
if (!invertible) {
|
||||
return make_invalid();
|
||||
if (other->is_identity()) {
|
||||
return make_mat(*_inv_mat);
|
||||
} else {
|
||||
return make_mat(other->get_mat() * (*_inv_mat));
|
||||
}
|
||||
new_mat = other->get_mat() * new_mat;
|
||||
return make_mat(new_mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -608,19 +617,21 @@ do_invert_compose(const TransformState *other) const {
|
|||
void TransformState::
|
||||
calc_singular() {
|
||||
nassertv((_flags & F_is_invalid) == 0);
|
||||
bool singular = false;
|
||||
|
||||
if (has_components()) {
|
||||
// The matrix is singular if any component of its scale is 0.
|
||||
singular = (_scale[0] == 0.0f || _scale[1] == 0.0f || _scale[2] == 0.0f);
|
||||
} else {
|
||||
// The matrix is singular if its determinant is zero.
|
||||
const LMatrix4f &mat = get_mat();
|
||||
singular = (mat.get_upper_3().determinant() == 0.0f);
|
||||
}
|
||||
// We determine if a matrix is singular by attempting to invert it
|
||||
// (and we save the result of this invert operation for a subsequent
|
||||
// do_invert_compose() call, which is almost certain to be made if
|
||||
// someone is asking whether we're singular).
|
||||
|
||||
if (singular) {
|
||||
// This should be NULL if no one has called calc_singular() yet.
|
||||
nassertv(_inv_mat == (LMatrix4f *)NULL);
|
||||
_inv_mat = new LMatrix4f;
|
||||
bool inverted = _inv_mat->invert_from(get_mat());
|
||||
|
||||
if (!inverted) {
|
||||
_flags |= F_is_singular;
|
||||
delete _inv_mat;
|
||||
_inv_mat = (LMatrix4f *)NULL;
|
||||
}
|
||||
_flags |= F_singular_known;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ private:
|
|||
};
|
||||
LVecBase3f _pos, _hpr, _scale;
|
||||
LMatrix4f _mat;
|
||||
LMatrix4f *_inv_mat;
|
||||
|
||||
short _flags;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue