mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:37:17 +02:00
ShapeColliderTests now uses QtTest
This commit is contained in:
parent
01c85e0a2c
commit
c2b7f70d2b
7 changed files with 1062 additions and 799 deletions
|
@ -73,6 +73,32 @@ inline QString QTest_generateCompareFailureMessage (const char * failMessage, co
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Why does qt have to make things so complicated...?
|
||||||
|
inline QString makeMessageFromStream (std::function<void(QTextStream &)> writeMessage) {
|
||||||
|
QString msg;
|
||||||
|
QTextStream stream(&msg);
|
||||||
|
writeMessage(stream);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void QTest_failWithCustomMessage (std::function<void(QTextStream &stream)> writeMessage, int line, const char *file)
|
||||||
|
{
|
||||||
|
QTest::qFail(qPrintable(makeMessageFromStream(writeMessage)), file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QFAIL_WITH_MESSAGE(...) \
|
||||||
|
do { \
|
||||||
|
QTest_failWithCustomMessage([&](QTextStream& stream) { stream << __VA_ARGS__; }, __LINE__, __FILE__); \
|
||||||
|
return; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
inline void foo () {
|
||||||
|
int thing = 2;
|
||||||
|
QFAIL_WITH_MESSAGE("Message " << thing << ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Generates a QCOMPARE style failure message with custom arguments.
|
// Generates a QCOMPARE style failure message with custom arguments.
|
||||||
// This is expected to be wrapped in a macro (see QFUZZY_COMPARE), and it must
|
// This is expected to be wrapped in a macro (see QFUZZY_COMPARE), and it must
|
||||||
// actually return on failure (unless other functionality is desired).
|
// actually return on failure (unless other functionality is desired).
|
||||||
|
@ -100,7 +126,9 @@ template <typename T, typename V>
|
||||||
inline auto QTest_fuzzyCompare(const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, int line, const char * file, const V & epsilon) -> decltype(fuzzyCompare(actual, expected))
|
inline auto QTest_fuzzyCompare(const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, int line, const char * file, const V & epsilon) -> decltype(fuzzyCompare(actual, expected))
|
||||||
{
|
{
|
||||||
if (fuzzyCompare(actual, expected) > epsilon) {
|
if (fuzzyCompare(actual, expected) > epsilon) {
|
||||||
QTest::qFail(qPrintable(QTest_generateCompareFailureMessage("Compared values are not the same (fuzzy compare)", actual, expected, actual_expr, expected_expr,
|
QTest::qFail(qPrintable(QTest_generateCompareFailureMessage(
|
||||||
|
"Compared values are not the same (fuzzy compare)",
|
||||||
|
actual, expected, actual_expr, expected_expr,
|
||||||
[&] (QTextStream & stream) -> QTextStream & {
|
[&] (QTextStream & stream) -> QTextStream & {
|
||||||
return stream << "Err tolerance: " << fuzzyCompare((actual), (expected)) << " > " << epsilon;
|
return stream << "Err tolerance: " << fuzzyCompare((actual), (expected)) << " > " << epsilon;
|
||||||
})), file, line);
|
})), file, line);
|
||||||
|
@ -115,4 +143,24 @@ do { \
|
||||||
return; \
|
return; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define QCOMPARE_WITH_FUNCTION(actual, expected, testFunc) \
|
||||||
|
do { \
|
||||||
|
if (!testFunc(actual, expected)) { \
|
||||||
|
QTest_failWithMessage("Compared values are not the same", actual, expected, #actual, #expected, __LINE__, __FILE__); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define QCOMPARE_WITH_LAMBDA(actual, expected, testClosure) \
|
||||||
|
do { \
|
||||||
|
if (!testClosure()) \
|
||||||
|
QTest_failWithMessage("Compared values are not the same", actual, expected, #actual, #expected, __LINE__, __FILE__); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ void BulletUtilTests::fromBulletToGLM() {
|
||||||
glm::quat gQ = bulletToGLM(bQ);
|
glm::quat gQ = bulletToGLM(bQ);
|
||||||
QCOMPARE(gQ.x, bQ.getX());
|
QCOMPARE(gQ.x, bQ.getX());
|
||||||
QCOMPARE(gQ.y, bQ.getY());
|
QCOMPARE(gQ.y, bQ.getY());
|
||||||
QCOMPARE(gQ.z, bQ.getZ() + 10);
|
QCOMPARE(gQ.z, bQ.getZ());
|
||||||
QCOMPARE(gQ.w, bQ.getW());
|
QCOMPARE(gQ.w, bQ.getW());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,11 +66,11 @@ void BulletUtilTests::fromGLMToBullet() {
|
||||||
QCOMPARE(gQ.w, bQ.getW());
|
QCOMPARE(gQ.w, bQ.getW());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletUtilTests::fooTest () {
|
//void BulletUtilTests::fooTest () {
|
||||||
|
//
|
||||||
glm::vec3 a { 1, 0, 3 };
|
// glm::vec3 a { 1, 0, 3 };
|
||||||
glm::vec3 b { 2, 0, 5 };
|
// glm::vec3 b { 2, 0, 5 };
|
||||||
|
//
|
||||||
// QCOMPARE(10, 22);
|
//// QCOMPARE(10, 22);
|
||||||
QFUZZY_COMPARE(a, b, 1.0f);
|
// QFUZZY_COMPARE(a, b, 1.0f);
|
||||||
}
|
//}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class BulletUtilTests : public QObject {
|
||||||
private slots:
|
private slots:
|
||||||
void fromBulletToGLM();
|
void fromBulletToGLM();
|
||||||
void fromGLMToBullet();
|
void fromGLMToBullet();
|
||||||
void fooTest ();
|
// void fooTest ();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define comparison + printing functions for the data types we need
|
// Define comparison + printing functions for the data types we need
|
||||||
|
|
|
@ -86,7 +86,7 @@ void MeshMassPropertiesTests::testParallelAxisTheorem() {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Try commenting this out to see what happens when the test fails
|
// Try commenting this out to see what happens when the test fails
|
||||||
twoSmallBoxesInertia[0][2] += 10;
|
// twoSmallBoxesInertia[0][2] += 10;
|
||||||
|
|
||||||
// This now does the same as the above (using the maxDiff fuzzyCompare impl for two btMatrices)
|
// This now does the same as the above (using the maxDiff fuzzyCompare impl for two btMatrices)
|
||||||
QFUZZY_COMPARE(bitBoxInertia, twoSmallBoxesInertia, acceptableAbsoluteError);
|
QFUZZY_COMPARE(bitBoxInertia, twoSmallBoxesInertia, acceptableAbsoluteError);
|
||||||
|
@ -101,10 +101,7 @@ void MeshMassPropertiesTests::testParallelAxisTheorem() {
|
||||||
void MeshMassPropertiesTests::testTetrahedron(){
|
void MeshMassPropertiesTests::testTetrahedron(){
|
||||||
// given the four vertices of a tetrahedron verify the analytic formula for inertia
|
// given the four vertices of a tetrahedron verify the analytic formula for inertia
|
||||||
// agrees with expected results
|
// agrees with expected results
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
|
||||||
std::cout << "\n" << __FUNCTION__ << std::endl;
|
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
|
||||||
|
|
||||||
// these numbers from the Tonon paper:
|
// these numbers from the Tonon paper:
|
||||||
btVector3 points[4];
|
btVector3 points[4];
|
||||||
points[0] = btVector3(8.33220f, -11.86875f, 0.93355f);
|
points[0] = btVector3(8.33220f, -11.86875f, 0.93355f);
|
||||||
|
@ -142,37 +139,59 @@ void MeshMassPropertiesTests::testTetrahedron(){
|
||||||
}
|
}
|
||||||
btMatrix3x3 inertia;
|
btMatrix3x3 inertia;
|
||||||
computeTetrahedronInertia(volume, points, inertia);
|
computeTetrahedronInertia(volume, points, inertia);
|
||||||
|
|
||||||
// verify
|
// if error = (volume - expectedVolume) / expectedVolume
|
||||||
for (int i = 0; i < 3; ++i) {
|
// then fabsf(error) > acceptableRelativeError == fabsf(volume - expectedVolume) > err
|
||||||
for (int j = 0; j < 3; ++j) {
|
// where err = acceptableRelativeError * expectedVolume
|
||||||
error = (inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
QFUZZY_COMPARE(volume, expectedVolume, acceptableRelativeError * volume);
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
|
||||||
<< error << std::endl;
|
// pseudo-hack -- error value is calculated per-element, so QFUZZY_COMPARE will not work.
|
||||||
|
// QCOMPARE_WITH_FUNCTION and QCOMPARE_WITH_LAMBDA lets you get around this by writing
|
||||||
|
// a custom function to do the actual comparison; printing, etc is done automatically.
|
||||||
|
auto testFunc = [&inertia, &expectedInertia] () {
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
auto error = (inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
|
if (fabsf(error) > acceptableRelativeError)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
|
};
|
||||||
|
QCOMPARE_WITH_LAMBDA(inertia, expectedInertia, testFunc);
|
||||||
|
|
||||||
|
QCOMPARE_WITH_RELATIVE_ERROR(inertia, expectedInertia, acceptableRelativeError);
|
||||||
|
// // verify
|
||||||
|
// for (int i = 0; i < 3; ++i) {
|
||||||
|
// for (int j = 0; j < 3; ++j) {
|
||||||
|
// error = (inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "expected volume = " << expectedVolume << std::endl;
|
// std::cout << "expected volume = " << expectedVolume << std::endl;
|
||||||
std::cout << "measured volume = " << volume << std::endl;
|
// std::cout << "measured volume = " << volume << std::endl;
|
||||||
printMatrix("expected inertia", expectedInertia);
|
// printMatrix("expected inertia", expectedInertia);
|
||||||
printMatrix("computed inertia", inertia);
|
// printMatrix("computed inertia", inertia);
|
||||||
|
//
|
||||||
// when building VERBOSE you might be instrested in the results from the brute force method:
|
// // when building VERBOSE you might be instrested in the results from the brute force method:
|
||||||
btMatrix3x3 bruteInertia;
|
// btMatrix3x3 bruteInertia;
|
||||||
computeTetrahedronInertiaByBruteForce(points, bruteInertia);
|
// computeTetrahedronInertiaByBruteForce(points, bruteInertia);
|
||||||
printMatrix("brute inertia", bruteInertia);
|
// printMatrix("brute inertia", bruteInertia);
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshMassPropertiesTests::testOpenTetrahedonMesh() {
|
void MeshMassPropertiesTests::testOpenTetrahedonMesh() {
|
||||||
// given the simplest possible mesh (open, with one triangle)
|
// given the simplest possible mesh (open, with one triangle)
|
||||||
// verify MeshMassProperties computes the right nubers
|
// verify MeshMassProperties computes the right nubers
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "\n" << __FUNCTION__ << std::endl;
|
// std::cout << "\n" << __FUNCTION__ << std::endl;
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
|
|
||||||
// these numbers from the Tonon paper:
|
// these numbers from the Tonon paper:
|
||||||
VectorOfPoints points;
|
VectorOfPoints points;
|
||||||
|
@ -208,27 +227,37 @@ void MeshMassPropertiesTests::testOpenTetrahedonMesh() {
|
||||||
MeshMassProperties mesh(shiftedPoints, triangles);
|
MeshMassProperties mesh(shiftedPoints, triangles);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
btScalar error = (mesh._volume - expectedVolume) / expectedVolume;
|
// (expected - actual) / expected > e ==> expected - actual > e * expected
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
QFUZZY_COMPARE(mesh._volume, expectedVolume, acceptableRelativeError * expectedVolume);
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
|
||||||
<< error << std::endl;
|
|
||||||
}
|
|
||||||
|
// btScalar error = (mesh._volume - expectedVolume) / expectedVolume;
|
||||||
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
||||||
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
|
||||||
if (fabsf(error) > acceptableAbsoluteError) {
|
QFUZZY_COMPARE(mesh._centerOfMass, expectedCenterOfMass, acceptableAbsoluteError);
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
|
||||||
<< error << std::endl;
|
// error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
||||||
}
|
// if (fabsf(error) > acceptableAbsoluteError) {
|
||||||
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
||||||
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
QCOMPARE_WITH_RELATIVE_ERROR(mesh._inertia, expectedInertia, acceptableRelativeError);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
// for (int i = 0; i < 3; ++i) {
|
||||||
for (int j = 0; j < 3; ++j) {
|
// for (int j = 0; j < 3; ++j) {
|
||||||
error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
// error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
<< error << std::endl;
|
// << error << std::endl;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "expected volume = " << expectedVolume << std::endl;
|
std::cout << "expected volume = " << expectedVolume << std::endl;
|
||||||
|
@ -277,36 +306,40 @@ void MeshMassPropertiesTests::testClosedTetrahedronMesh() {
|
||||||
MeshMassProperties mesh(points, triangles);
|
MeshMassProperties mesh(points, triangles);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
btScalar error;
|
QFUZZY_COMPARE(mesh._volume, expectedVolume, acceptableRelativeError);
|
||||||
error = (mesh._volume - expectedVolume) / expectedVolume;
|
// btScalar error;
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
// error = (mesh._volume - expectedVolume) / expectedVolume;
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
<< error << std::endl;
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
||||||
}
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
|
||||||
if (fabsf(error) > acceptableAbsoluteError) {
|
QFUZZY_COMPARE(mesh._centerOfMass, expectedCenterOfMass, acceptableAbsoluteError);
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
// error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
||||||
<< error << std::endl;
|
// if (fabsf(error) > acceptableAbsoluteError) {
|
||||||
}
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
||||||
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
QCOMPARE_WITH_RELATIVE_ERROR(mesh._inertia, expectedInertia, acceptableRelativeError);
|
||||||
for (int j = 0; j < 3; ++j) {
|
// for (int i = 0; i < 3; ++i) {
|
||||||
error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
// for (int j = 0; j < 3; ++j) {
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
// error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
<< error << std::endl;
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
}
|
// << error << std::endl;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "(a) tetrahedron as mesh" << std::endl;
|
// std::cout << "(a) tetrahedron as mesh" << std::endl;
|
||||||
std::cout << "expected volume = " << expectedVolume << std::endl;
|
// std::cout << "expected volume = " << expectedVolume << std::endl;
|
||||||
std::cout << "measured volume = " << mesh._volume << std::endl;
|
// std::cout << "measured volume = " << mesh._volume << std::endl;
|
||||||
printMatrix("expected inertia", expectedInertia);
|
// printMatrix("expected inertia", expectedInertia);
|
||||||
printMatrix("computed inertia", mesh._inertia);
|
// printMatrix("computed inertia", mesh._inertia);
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
|
|
||||||
// test again, but this time shift the points so that the origin is definitely OUTSIDE the mesh
|
// test again, but this time shift the points so that the origin is definitely OUTSIDE the mesh
|
||||||
btVector3 shift = points[0] + expectedCenterOfMass;
|
btVector3 shift = points[0] + expectedCenterOfMass;
|
||||||
|
@ -319,42 +352,45 @@ void MeshMassPropertiesTests::testClosedTetrahedronMesh() {
|
||||||
mesh.computeMassProperties(points, triangles);
|
mesh.computeMassProperties(points, triangles);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
error = (mesh._volume - expectedVolume) / expectedVolume;
|
// QFUZZY_COMPARE(mesh._volume, expectedVolume, acceptableRelativeError * expectedVolume);
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
//// error = (mesh._volume - expectedVolume) / expectedVolume;
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
//// if (fabsf(error) > acceptableRelativeError) {
|
||||||
<< error << std::endl;
|
//// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
||||||
}
|
//// << error << std::endl;
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
// QFUZZY_COMPARE(mesh._centerOfMass, expectedCenterOfMass, acceptableAbsoluteError);
|
||||||
|
//// error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
||||||
|
//// if (fabsf(error) > acceptableAbsoluteError) {
|
||||||
|
//// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
||||||
|
//// << error << std::endl;
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
// QCOMPARE_WITH_RELATIVE_ERROR(mesh._inertia, expectedInertia, acceptableRelativeError);
|
||||||
|
//// for (int i = 0; i < 3; ++i) {
|
||||||
|
//// for (int j = 0; j < 3; ++j) {
|
||||||
|
//// error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
|
//// if (fabsf(error) > acceptableRelativeError) {
|
||||||
|
//// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
|
//// << error << std::endl;
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
|
||||||
error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
if (fabsf(error) > acceptableAbsoluteError) {
|
// std::cout << "(b) shifted tetrahedron as mesh" << std::endl;
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
// std::cout << "expected volume = " << expectedVolume << std::endl;
|
||||||
<< error << std::endl;
|
// std::cout << "measured volume = " << mesh._volume << std::endl;
|
||||||
}
|
// printMatrix("expected inertia", expectedInertia);
|
||||||
|
// printMatrix("computed inertia", mesh._inertia);
|
||||||
for (int i = 0; i < 3; ++i) {
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
for (int j = 0; j < 3; ++j) {
|
|
||||||
error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
|
||||||
<< error << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
|
||||||
std::cout << "(b) shifted tetrahedron as mesh" << std::endl;
|
|
||||||
std::cout << "expected volume = " << expectedVolume << std::endl;
|
|
||||||
std::cout << "measured volume = " << mesh._volume << std::endl;
|
|
||||||
printMatrix("expected inertia", expectedInertia);
|
|
||||||
printMatrix("computed inertia", mesh._inertia);
|
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshMassPropertiesTests::testBoxAsMesh() {
|
void MeshMassPropertiesTests::testBoxAsMesh() {
|
||||||
// verify that a mesh box produces the same mass properties as the analytic box.
|
// verify that a mesh box produces the same mass properties as the analytic box.
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "\n" << __FUNCTION__ << std::endl;
|
// std::cout << "\n" << __FUNCTION__ << std::endl;
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
|
|
||||||
|
|
||||||
// build a box:
|
// build a box:
|
||||||
|
@ -411,58 +447,56 @@ void MeshMassPropertiesTests::testBoxAsMesh() {
|
||||||
MeshMassProperties mesh(points, triangles);
|
MeshMassProperties mesh(points, triangles);
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
btScalar error;
|
|
||||||
error = (mesh._volume - expectedVolume) / expectedVolume;
|
QFUZZY_COMPARE(mesh._volume, expectedVolume, acceptableRelativeError * expectedVolume);
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
// btScalar error;
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
// error = (mesh._volume - expectedVolume) / expectedVolume;
|
||||||
<< error << std::endl;
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
}
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : volume of tetrahedron off by = "
|
||||||
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
QFUZZY_COMPARE(mesh._centerOfMass, expectedCenterOfMass, acceptableAbsoluteError);
|
||||||
if (fabsf(error) > acceptableAbsoluteError) {
|
// error = (mesh._centerOfMass - expectedCenterOfMass).length();
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
// if (fabsf(error) > acceptableAbsoluteError) {
|
||||||
<< error << std::endl;
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : centerOfMass of tetrahedron off by = "
|
||||||
}
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
for (int j = 0; j < 3; ++j) {
|
// do this twice to avoid divide-by-zero?
|
||||||
if (expectedInertia [i][j] == btScalar(0.0f)) {
|
QFUZZY_COMPARE(mesh._inertia, expectedInertia, acceptableAbsoluteError);
|
||||||
error = mesh._inertia[i][j] - expectedInertia[i][j];
|
QCOMPARE_WITH_RELATIVE_ERROR(mesh._inertia, expectedInertia, acceptableRelativeError);
|
||||||
if (fabsf(error) > acceptableAbsoluteError) {
|
// for (int i = 0; i < 3; ++i) {
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
// for (int j = 0; j < 3; ++j) {
|
||||||
<< error << " absolute"<< std::endl;
|
// if (expectedInertia [i][j] == btScalar(0.0f)) {
|
||||||
}
|
// error = mesh._inertia[i][j] - expectedInertia[i][j];
|
||||||
} else {
|
// if (fabsf(error) > acceptableAbsoluteError) {
|
||||||
error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
if (fabsf(error) > acceptableRelativeError) {
|
// << error << " absolute"<< std::endl;
|
||||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
// }
|
||||||
<< error << std::endl;
|
// } else {
|
||||||
}
|
// error = (mesh._inertia[i][j] - expectedInertia[i][j]) / expectedInertia[i][j];
|
||||||
}
|
// if (fabsf(error) > acceptableRelativeError) {
|
||||||
}
|
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : inertia[" << i << "][" << j << "] off by "
|
||||||
}
|
// << error << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#ifdef VERBOSE_UNIT_TESTS
|
//#ifdef VERBOSE_UNIT_TESTS
|
||||||
std::cout << "expected volume = " << expectedVolume << std::endl;
|
// std::cout << "expected volume = " << expectedVolume << std::endl;
|
||||||
std::cout << "measured volume = " << mesh._volume << std::endl;
|
// std::cout << "measured volume = " << mesh._volume << std::endl;
|
||||||
std::cout << "expected center of mass = < "
|
// std::cout << "expected center of mass = < "
|
||||||
<< expectedCenterOfMass[0] << ", "
|
// << expectedCenterOfMass[0] << ", "
|
||||||
<< expectedCenterOfMass[1] << ", "
|
// << expectedCenterOfMass[1] << ", "
|
||||||
<< expectedCenterOfMass[2] << "> " << std::endl;
|
// << expectedCenterOfMass[2] << "> " << std::endl;
|
||||||
std::cout << "computed center of mass = < "
|
// std::cout << "computed center of mass = < "
|
||||||
<< mesh._centerOfMass[0] << ", "
|
// << mesh._centerOfMass[0] << ", "
|
||||||
<< mesh._centerOfMass[1] << ", "
|
// << mesh._centerOfMass[1] << ", "
|
||||||
<< mesh._centerOfMass[2] << "> " << std::endl;
|
// << mesh._centerOfMass[2] << "> " << std::endl;
|
||||||
printMatrix("expected inertia", expectedInertia);
|
// printMatrix("expected inertia", expectedInertia);
|
||||||
printMatrix("computed inertia", mesh._inertia);
|
// printMatrix("computed inertia", mesh._inertia);
|
||||||
#endif // VERBOSE_UNIT_TESTS
|
//#endif // VERBOSE_UNIT_TESTS
|
||||||
}
|
}
|
||||||
|
|
||||||
//void MeshMassPropertiesTests::runAllTests() {
|
|
||||||
// testParallelAxisTheorem();
|
|
||||||
// testTetrahedron();
|
|
||||||
// testOpenTetrahedonMesh();
|
|
||||||
// testClosedTetrahedronMesh();
|
|
||||||
// testBoxAsMesh();
|
|
||||||
// //testWithCube();
|
|
||||||
//}
|
|
||||||
|
|
|
@ -32,17 +32,17 @@ private slots:
|
||||||
|
|
||||||
// Define comparison + printing functions for the data types we need
|
// Define comparison + printing functions for the data types we need
|
||||||
|
|
||||||
inline float fuzzyCompare (const glm::vec3 & a, const glm::vec3 & b) {
|
inline float fuzzyCompare(const glm::vec3 & a, const glm::vec3 & b) {
|
||||||
return glm::distance(a, b);
|
return glm::distance(a, b);
|
||||||
}
|
}
|
||||||
inline QTextStream & operator << (QTextStream & stream, const glm::vec3 & v) {
|
inline QTextStream & operator << (QTextStream & stream, const glm::vec3 & v) {
|
||||||
return stream << "glm::vec3 { " << v.x << ", " << v.y << ", " << v.z << " }";
|
return stream << "glm::vec3 { " << v.x << ", " << v.y << ", " << v.z << " }";
|
||||||
}
|
}
|
||||||
inline btScalar fuzzyCompare (const btScalar & a, const btScalar & b) {
|
inline btScalar fuzzyCompare(const btScalar & a, const btScalar & b) {
|
||||||
return fabs(a - b);
|
return fabs(a - b);
|
||||||
}
|
}
|
||||||
// uh... how do we compare matrices?
|
|
||||||
// Guess we'll just do this element-wise for the time being
|
// Matrices are compared element-wise -- if the error value for any element > epsilon, then fail
|
||||||
inline btScalar fuzzyCompare (const btMatrix3x3 & a, const btMatrix3x3 & b) {
|
inline btScalar fuzzyCompare (const btMatrix3x3 & a, const btMatrix3x3 & b) {
|
||||||
btScalar totalDiff = 0;
|
btScalar totalDiff = 0;
|
||||||
btScalar maxDiff = 0;
|
btScalar maxDiff = 0;
|
||||||
|
@ -56,6 +56,7 @@ inline btScalar fuzzyCompare (const btMatrix3x3 & a, const btMatrix3x3 & b) {
|
||||||
// return totalDiff;
|
// return totalDiff;
|
||||||
return maxDiff;
|
return maxDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QTextStream & operator << (QTextStream & stream, const btMatrix3x3 & matrix) {
|
inline QTextStream & operator << (QTextStream & stream, const btMatrix3x3 & matrix) {
|
||||||
stream << "[\n\t\t";
|
stream << "[\n\t\t";
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
@ -68,7 +69,32 @@ inline QTextStream & operator << (QTextStream & stream, const btMatrix3x3 & matr
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline btScalar fuzzyCompare(const btVector3 & a, const btVector3 & b)
|
||||||
|
{
|
||||||
|
return (a - b).length();
|
||||||
|
}
|
||||||
|
inline QTextStream & operator << (QTextStream & stream, const btVector3 & v) {
|
||||||
|
return stream << "btVector3 { " << v.x() << ", " << v.y() << ", " << v.z() << " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produces a relative error test for btMatrix3x3 usable with QCOMPARE_WITH_LAMBDA
|
||||||
|
inline auto errorTest (const btMatrix3x3 & actual, const btMatrix3x3 & expected, const btScalar acceptableRelativeError)
|
||||||
|
-> std::function<bool ()>
|
||||||
|
{
|
||||||
|
return [&actual, &expected, acceptableRelativeError] () {
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
auto err = (actual[i][j] - expected[i][j]) / expected[i][j];
|
||||||
|
if (fabsf(err) > acceptableRelativeError)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QCOMPARE_WITH_RELATIVE_ERROR(actual, expected, relativeError) \
|
||||||
|
QCOMPARE_WITH_LAMBDA(actual, expected, errorTest(actual, expected, relativeError))
|
||||||
|
|
||||||
|
|
||||||
// These hook into this (and must be defined first...)
|
// These hook into this (and must be defined first...)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,8 @@ class ShapeColliderTests : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void initTestCase();
|
||||||
|
|
||||||
void sphereMissesSphere();
|
void sphereMissesSphere();
|
||||||
void sphereTouchesSphere();
|
void sphereTouchesSphere();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue