mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
better fix for transitive principle
This commit is contained in:
parent
c27920c40f
commit
84cc0a8010
@ -139,7 +139,7 @@ fill(FLOATTYPE fill_value) {
|
||||
int FLOATNAME(LMatrix3)::
|
||||
compare_to(const FLOATNAME(LMatrix3) &other, FLOATTYPE threshold) const {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (!IS_THRESHOLD_EQUAL(_m.data[i], other._m.data[i], threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_m.data[i], other._m.data[i], threshold)) {
|
||||
return (_m.data[i] < other._m.data[i]) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
@ -129,17 +129,10 @@ convert_mat(CoordinateSystem from, CoordinateSystem to) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int FLOATNAME(LMatrix4)::
|
||||
compare_to(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const {
|
||||
FLOATTYPE scale = 1.0f / threshold;
|
||||
|
||||
// We compare values in reverse order, since the last row of the
|
||||
// matrix is most likely to be different between different matrices.
|
||||
for (int i = 15; i >= 0; i--) {
|
||||
// We scale both elements into the same range and truncate, rather
|
||||
// than comparing the absolute values of their differences with
|
||||
// IS_THRESHOLD_EQUAL. This prevents a slippery-slope effect
|
||||
// where a == b and b == c but a != c.
|
||||
if (cfloor(_m.data[i] * scale + 0.5) !=
|
||||
cfloor(other._m.data[i] * scale + 0.5)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_m.data[i], other._m.data[i], threshold)) {
|
||||
return (_m.data[i] < other._m.data[i]) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
@ -375,10 +375,10 @@ compare_to(const FLOATNAME(LVecBase2) &other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH int FLOATNAME(LVecBase2)::
|
||||
compare_to(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const {
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._0, other._v.v._0, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._0, other._v.v._0, threshold)) {
|
||||
return (_v.v._0 < other._v.v._0) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._1, other._v.v._1, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._1, other._v.v._1, threshold)) {
|
||||
return (_v.v._1 < other._v.v._1) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -422,13 +422,13 @@ compare_to(const FLOATNAME(LVecBase3) &other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH int FLOATNAME(LVecBase3)::
|
||||
compare_to(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const {
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._0, other._v.v._0, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._0, other._v.v._0, threshold)) {
|
||||
return (_v.v._0 < other._v.v._0) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._1, other._v.v._1, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._1, other._v.v._1, threshold)) {
|
||||
return (_v.v._1 < other._v.v._1) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._2, other._v.v._2, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._2, other._v.v._2, threshold)) {
|
||||
return (_v.v._2 < other._v.v._2) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -449,16 +449,16 @@ compare_to(const FLOATNAME(LVecBase4) &other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH int FLOATNAME(LVecBase4)::
|
||||
compare_to(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const {
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._0, other._v.v._0, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._0, other._v.v._0, threshold)) {
|
||||
return (_v.v._0 < other._v.v._0) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._1, other._v.v._1, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._1, other._v.v._1, threshold)) {
|
||||
return (_v.v._1 < other._v.v._1) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._2, other._v.v._2, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._2, other._v.v._2, threshold)) {
|
||||
return (_v.v._2 < other._v.v._2) ? -1 : 1;
|
||||
}
|
||||
if (!IS_THRESHOLD_EQUAL(_v.v._3, other._v.v._3, threshold)) {
|
||||
if (!IS_THRESHOLD_COMPEQ(_v.v._3, other._v.v._3, threshold)) {
|
||||
return (_v.v._3 < other._v.v._3) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -40,17 +40,17 @@ get_nearly_zero_value(float) {
|
||||
((value) < (threshold) && (value) > -(threshold))
|
||||
|
||||
// IS_THRESHOLD_EQUAL(value1, value2, threshold) returns true if the
|
||||
// two values are within threshold of each other. The transitive
|
||||
// principle is guaranteed: IS_THRESHOLD_EQUAL(a, b, t) &&
|
||||
// IS_THRESHOLD_EQUAL(b, c, t) implies IS_THRESHOLD_EQUAL(a, c, t).
|
||||
|
||||
// We could define this via IS_THRESHOLD_ZERO(a - b, t) that wouldn't
|
||||
// guarantee the transitive principle, stated above. So we need a
|
||||
// more complex definition that rounds these to the nearest multiples
|
||||
// of threshold before comparing them.
|
||||
// two values are within threshold of each other.
|
||||
#define IS_THRESHOLD_EQUAL(value1, value2, threshold) \
|
||||
(cfloor(value1 / threshold + 0.5f) == cfloor(value2 / threshold + 0.5f))
|
||||
(IS_THRESHOLD_ZERO((value1) - (value2), threshold))
|
||||
|
||||
// IS_THRESHOLD_COMPEQ(value1, value2, threshold) returns true if
|
||||
// the two values are equal within threshold tolerance. Unlike
|
||||
// IS_THRESHOLD_EQUAL, the transitive principle is guaranteed:
|
||||
// IS_THRESHOLD_COMPEQ(a, b, t) && IS_THRESHOLD_COMPEQ(b, c, t)
|
||||
// implies IS_THRESHOLD_COMPEQ(a, c, t).
|
||||
#define IS_THRESHOLD_COMPEQ(value1, value2, threshold) \
|
||||
(cfloor(value1 / threshold + 0.5f) == cfloor(value2 / threshold + 0.5f))
|
||||
|
||||
// NEARLY_ZERO(float) returns a number that is considered to be so
|
||||
// close to zero as not to matter for a float. NEARLY_ZERO(double)
|
||||
|
Loading…
x
Reference in New Issue
Block a user