mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Added a custom test macro, QFUZZY_COMPARE (compares two values with an explicit error tolerance), and the infrastructure for defining more.
Reworked physics test files, but they're a WIP.
This commit is contained in:
parent
d75f3b1398
commit
16dd5e0590
9 changed files with 274 additions and 330 deletions
108
tests/QTestExtensions.hpp
Normal file
108
tests/QTestExtensions.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// QTestExtensions.hpp
|
||||
// tests/
|
||||
//
|
||||
// Created by Seiji Emery on 6/20/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#ifndef hifi_QTestExtensions_hpp
|
||||
#define hifi_QTestExtensions_hpp
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <functional>
|
||||
|
||||
// Adds some additional functionality to QtTest (eg. explicitely defined fuzzy comparison
|
||||
// of float and custom data types), and some extension mechanisms to provide other new
|
||||
// functionality as needed.
|
||||
|
||||
|
||||
// Generic function that reimplements the debugging output of a QCOMPARE failure via QFAIL.
|
||||
// Use this to implement your own QCOMPARE-ish macros (see QEXPLICIT_FUZZY_COMPARE for
|
||||
// more info).
|
||||
template <typename T>
|
||||
void QTest_failWithMessage (const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, int line, const char * file)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Generic function that reimplements the debugging output of a QCOMPARE failure via QFAIL.
|
||||
// Use this to implement your own QCOMPARE-ish macros (see QEXPLICIT_FUZZY_COMPARE for
|
||||
// more info).
|
||||
// This version provides a callback to write additional messages.
|
||||
// If the messages span more than one line, wrap them with '\n\t' to get proper indentation.
|
||||
template <typename T>
|
||||
inline QString QTest_generateCompareFailureMessage (const char * failMessage, const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, std::function<QTextStream & (QTextStream &)> writeAdditionalMessages)
|
||||
{
|
||||
QString s1 = actual_expr, s2 = expected_expr;
|
||||
int pad1_ = qMax(s2.length() - s1.length(), 0);
|
||||
int pad2_ = qMax(s1.length() - s2.length(), 0);
|
||||
|
||||
QString pad1 = QString(")").rightJustified(pad1_, ' ');
|
||||
QString pad2 = QString(")").rightJustified(pad2_, ' ');
|
||||
|
||||
QString msg;
|
||||
QTextStream stream (&msg);
|
||||
stream << failMessage << "\n\t"
|
||||
"Actual: (" << actual_expr << pad1 << ": " << actual << "\n\t"
|
||||
"Expected: (" << expected_expr << pad2 << ": " << expected << "\n\t";
|
||||
writeAdditionalMessages(stream);
|
||||
return msg;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QString QTest_generateCompareFailureMessage (const char * failMessage, const T & actual, const T & expected, const char * actual_expr, const char * expected_expr)
|
||||
{
|
||||
QString s1 = actual_expr, s2 = expected_expr;
|
||||
int pad1_ = qMax(s2.length() - s1.length(), 0);
|
||||
int pad2_ = qMax(s1.length() - s2.length(), 0);
|
||||
|
||||
QString pad1 = QString(")").rightJustified(pad1_, ' ');
|
||||
QString pad2 = QString(")").rightJustified(pad2_, ' ');
|
||||
|
||||
QString msg;
|
||||
QTextStream stream (&msg);
|
||||
stream << failMessage << "\n\t"
|
||||
"Actual: (" << actual_expr << pad1 << ": " << actual << "\n\t"
|
||||
"Expected: (" << expected_expr << pad2 << ": " << expected;
|
||||
return msg;
|
||||
}
|
||||
|
||||
template <typename T, typename V>
|
||||
inline bool QTest_fuzzyCompare(const T & actual, const T & expected, const char * actual_expr, const char * expected_expr, int line, const char * file, const V & 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,
|
||||
[&] (QTextStream & stream) -> QTextStream & {
|
||||
return stream << "Err tolerance: " << fuzzyCompare((actual), (expected)) << " > " << epsilon;
|
||||
})), file, line);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define QFUZZY_COMPARE(actual, expected, epsilon) \
|
||||
do { \
|
||||
if (!QTest_fuzzyCompare(actual, expected, #actual, #expected, __LINE__, __FILE__, epsilon)) \
|
||||
return; \
|
||||
} while(0)
|
||||
|
||||
// Note: this generates a message that looks something like the following:
|
||||
// FAIL! : BulletUtilTests::fooTest() Compared values are not the same (fuzzy compare)
|
||||
// Actual (foo * 3): glm::vec3 { 1, 0, 3 }
|
||||
// Expected (bar + baz): glm::vec3 { 2, 0, 5 }
|
||||
// Error Tolerance: 2.23607 > 1
|
||||
// Loc: [/Users/semery/hifi/tests/physics/src/BulletUtilTests.cpp(68)]
|
||||
//
|
||||
// The last line (and the FAIL! message up to "Compared values...") are generated automatically by
|
||||
// QFAIL. It is possible to generate these manually via __FILE__ and __LINE__, but QFAIL does this
|
||||
// already so there's no point in reimplementing it. However, since we are using QFAIL to generate
|
||||
// our line number for us, it's important that it's actually invoked on the same line as the thing
|
||||
// that calls it -- hence the elaborate macro(s) above (since the result is *technically* one line)
|
||||
//
|
||||
|
||||
#endif
|
|
@ -11,13 +11,13 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "PhysicsTestUtil.h"
|
||||
#include <BulletUtil.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "BulletUtilTests.h"
|
||||
|
||||
|
||||
|
||||
QTEST_MAIN(BulletUtilTests)
|
||||
|
||||
void BulletUtilTests::fromBulletToGLM() {
|
||||
|
@ -25,18 +25,8 @@ void BulletUtilTests::fromBulletToGLM() {
|
|||
glm::vec3 gV = bulletToGLM(bV);
|
||||
|
||||
QCOMPARE(gV.x, bV.getX());
|
||||
// if (gV.x != bV .getX()) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: x mismatch bullet.x = " << bV.getX() << " != glm.x = " << gV.x << std::endl;
|
||||
// }
|
||||
if (gV.y != bV.getY()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.y = " << bV.getY() << " != glm.y = " << gV.y << std::endl;
|
||||
}
|
||||
if (gV.z != bV.getZ()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.z = " << bV.getZ() << " != glm.z = " << gV.z << std::endl;
|
||||
}
|
||||
QCOMPARE(gV.y, bV.getY());
|
||||
QCOMPARE(gV.z, bV.getZ());
|
||||
|
||||
float angle = 0.317f * PI;
|
||||
btVector3 axis(1.23f, 2.34f, 3.45f);
|
||||
|
@ -44,39 +34,19 @@ void BulletUtilTests::fromBulletToGLM() {
|
|||
btQuaternion bQ(axis, angle);
|
||||
|
||||
glm::quat gQ = bulletToGLM(bQ);
|
||||
if (gQ.x != bQ.getX()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.x = " << bQ.getX() << " != glm.x = " << gQ.x << std::endl;
|
||||
}
|
||||
if (gQ.y != bQ.getY()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.y = " << bQ.getY() << " != glm.y = " << gQ.y << std::endl;
|
||||
}
|
||||
if (gQ.z != bQ.getZ()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.z = " << bQ.getZ() << " != glm.z = " << gQ.z << std::endl;
|
||||
}
|
||||
if (gQ.w != bQ.getW()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch bullet.w = " << bQ.getW() << " != glm.w = " << gQ.w << std::endl;
|
||||
}
|
||||
QCOMPARE(gQ.x, bQ.getX());
|
||||
QCOMPARE(gQ.y, bQ.getY());
|
||||
QCOMPARE(gQ.z, bQ.getZ() + 10);
|
||||
QCOMPARE(gQ.w, bQ.getW());
|
||||
}
|
||||
|
||||
void BulletUtilTests::fromGLMToBullet() {
|
||||
glm::vec3 gV(1.23f, 4.56f, 7.89f);
|
||||
btVector3 bV = glmToBullet(gV);
|
||||
if (gV.x != bV.getX()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.x = " << gV.x << " != bullet.x = " << bV.getX() << std::endl;
|
||||
}
|
||||
if (gV.y != bV.getY()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.y = " << gV.y << " != bullet.y = " << bV.getY() << std::endl;
|
||||
}
|
||||
if (gV.z != bV.getZ()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.z = " << gV.z << " != bullet.z = " << bV.getZ() << std::endl;
|
||||
}
|
||||
|
||||
QCOMPARE(gV.x, bV.getX());
|
||||
QCOMPARE(gV.y, bV.getY());
|
||||
QCOMPARE(gV.z, bV.getZ());
|
||||
|
||||
float angle = 0.317f * PI;
|
||||
btVector3 axis(1.23f, 2.34f, 3.45f);
|
||||
|
@ -84,25 +54,17 @@ void BulletUtilTests::fromGLMToBullet() {
|
|||
btQuaternion bQ(axis, angle);
|
||||
|
||||
glm::quat gQ = bulletToGLM(bQ);
|
||||
if (gQ.x != bQ.getX()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.x = " << gQ.x << " != bullet.x = " << bQ.getX() << std::endl;
|
||||
}
|
||||
if (gQ.y != bQ.getY()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.y = " << gQ.y << " != bullet.y = " << bQ.getY() << std::endl;
|
||||
}
|
||||
if (gQ.z != bQ.getZ()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.z = " << gQ.z << " != bullet.z = " << bQ.getZ() << std::endl;
|
||||
}
|
||||
if (gQ.w != bQ.getW()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: x mismatch glm.w = " << gQ.w << " != bullet.w = " << bQ.getW() << std::endl;
|
||||
}
|
||||
QCOMPARE(gQ.x, bQ.getX());
|
||||
QCOMPARE(gQ.y, bQ.getY());
|
||||
QCOMPARE(gQ.z, bQ.getZ());
|
||||
QCOMPARE(gQ.w, bQ.getW());
|
||||
}
|
||||
|
||||
//void BulletUtilTests::runAllTests() {
|
||||
// fromBulletToGLM();
|
||||
// fromGLMToBullet();
|
||||
//}
|
||||
void BulletUtilTests::fooTest () {
|
||||
|
||||
glm::vec3 a { 1, 0, 3 };
|
||||
glm::vec3 b { 2, 0, 5 };
|
||||
|
||||
// QCOMPARE(10, 22);
|
||||
QFUZZY_COMPARE(a, b, 1.0f);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class BulletUtilTests : public QObject {
|
|||
private slots:
|
||||
void fromBulletToGLM();
|
||||
void fromGLMToBullet();
|
||||
// void runAllTests();
|
||||
void fooTest ();
|
||||
};
|
||||
|
||||
#endif // hifi_BulletUtilTests_h
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
QTEST_MAIN(CollisionInfoTests)
|
||||
/*
|
||||
|
||||
static glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
static glm::vec3 xZxis(0.0f, 1.0f, 0.0f);
|
||||
static glm::vec3 xYxis(0.0f, 0.0f, 1.0f);
|
||||
|
@ -32,83 +31,82 @@ static glm::vec3 xYxis(0.0f, 0.0f, 1.0f);
|
|||
void CollisionInfoTests::rotateThenTranslate() {
|
||||
CollisionInfo collision;
|
||||
collision._penetration = xAxis;
|
||||
collision._contactPoint = yAxis;
|
||||
collision._addedVelocity = xAxis + yAxis + zAxis;
|
||||
collision._contactPoint = xYxis;
|
||||
collision._addedVelocity = xAxis + xYxis + xZxis;
|
||||
|
||||
glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis);
|
||||
float distance = 3.0f;
|
||||
glm::vec3 translation = distance * yAxis;
|
||||
glm::vec3 translation = distance * xYxis;
|
||||
|
||||
collision.rotateThenTranslate(rotation, translation);
|
||||
|
||||
float error = glm::distance(collision._penetration, yAxis);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._penetration = " << collision._penetration
|
||||
<< " but we expected " << yAxis
|
||||
<< std::endl;
|
||||
}
|
||||
QCOMPARE(collision._penetration, xYxis);
|
||||
// float error = glm::distance(collision._penetration, xYxis);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._penetration = " << collision._penetration
|
||||
// << " but we expected " << xYxis
|
||||
// << std::endl;
|
||||
// }
|
||||
|
||||
glm::vec3 expectedContactPoint = -xAxis + translation;
|
||||
error = glm::distance(collision._contactPoint, expectedContactPoint);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._contactPoint = " << collision._contactPoint
|
||||
<< " but we expected " << expectedContactPoint
|
||||
<< std::endl;
|
||||
}
|
||||
QCOMPARE(collision._contactPoint, expectedContactPoint);
|
||||
// error = glm::distance(collision._contactPoint, expectedContactPoint);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._contactPoint = " << collision._contactPoint
|
||||
// << " but we expected " << expectedContactPoint
|
||||
// << std::endl;
|
||||
// }
|
||||
|
||||
glm::vec3 expectedAddedVelocity = yAxis - xAxis + zAxis;
|
||||
error = glm::distance(collision._addedVelocity, expectedAddedVelocity);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._addedVelocity = " << collision._contactPoint
|
||||
<< " but we expected " << expectedAddedVelocity
|
||||
<< std::endl;
|
||||
}
|
||||
glm::vec3 expectedAddedVelocity = xYxis - xAxis + xZxis;
|
||||
QCOMPARE(collision._addedVelocity, expectedAddedVelocity);
|
||||
// error = glm::distance(collision._addedVelocity, expectedAddedVelocity);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._addedVelocity = " << collision._contactPoint
|
||||
// << " but we expected " << expectedAddedVelocity
|
||||
// << std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
void CollisionInfoTests::translateThenRotate() {
|
||||
CollisionInfo collision;
|
||||
collision._penetration = xAxis;
|
||||
collision._contactPoint = yAxis;
|
||||
collision._addedVelocity = xAxis + yAxis + zAxis;
|
||||
collision._contactPoint = xYxis;
|
||||
collision._addedVelocity = xAxis + xYxis + xZxis;
|
||||
|
||||
glm::quat rotation = glm::angleAxis( -PI_OVER_TWO, zAxis);
|
||||
float distance = 3.0f;
|
||||
glm::vec3 translation = distance * yAxis;
|
||||
glm::vec3 translation = distance * xYxis;
|
||||
|
||||
collision.translateThenRotate(translation, rotation);
|
||||
|
||||
float error = glm::distance(collision._penetration, -yAxis);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._penetration = " << collision._penetration
|
||||
<< " but we expected " << -yAxis
|
||||
<< std::endl;
|
||||
}
|
||||
QCOMPARE(collision._penetration, -xYxis);
|
||||
// float error = glm::distance(collision._penetration, -xYxis);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._penetration = " << collision._penetration
|
||||
// << " but we expected " << -yAxis
|
||||
// << std::endl;
|
||||
// }
|
||||
|
||||
glm::vec3 expectedContactPoint = (1.0f + distance) * xAxis;
|
||||
error = glm::distance(collision._contactPoint, expectedContactPoint);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._contactPoint = " << collision._contactPoint
|
||||
<< " but we expected " << expectedContactPoint
|
||||
<< std::endl;
|
||||
}
|
||||
QCOMPARE(collision._contactPoint, expectedContactPoint);
|
||||
// error = glm::distance(collision._contactPoint, expectedContactPoint);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._contactPoint = " << collision._contactPoint
|
||||
// << " but we expected " << expectedContactPoint
|
||||
// << std::endl;
|
||||
// }
|
||||
|
||||
glm::vec3 expectedAddedVelocity = - yAxis + xAxis + zAxis;
|
||||
error = glm::distance(collision._addedVelocity, expectedAddedVelocity);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: collision._addedVelocity = " << collision._contactPoint
|
||||
<< " but we expected " << expectedAddedVelocity
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
*/
|
||||
glm::vec3 expectedAddedVelocity = - xYxis + xAxis + xYxis;
|
||||
QCOMPARE(collision._addedVelocity, expectedAddedVelocity);
|
||||
// error = glm::distance(collision._addedVelocity, expectedAddedVelocity);
|
||||
// if (error > EPSILON) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__
|
||||
// << " ERROR: collision._addedVelocity = " << collision._contactPoint
|
||||
// << " but we expected " << expectedAddedVelocity
|
||||
// << std::endl;
|
||||
// }
|
||||
}*/
|
||||
|
||||
//void CollisionInfoTests::runAllTests() {
|
||||
// CollisionInfoTests::rotateThenTranslate();
|
||||
// CollisionInfoTests::translateThenRotate();
|
||||
//}
|
||||
|
|
|
@ -20,8 +20,6 @@ class CollisionInfoTests : public QObject {
|
|||
private slots:
|
||||
// void rotateThenTranslate();
|
||||
// void translateThenRotate();
|
||||
|
||||
// void runAllTests();
|
||||
};
|
||||
|
||||
#endif // hifi_CollisionInfoTests_h
|
||||
|
|
|
@ -9,13 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "PhysicsTestUtil.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <MeshMassProperties.h>
|
||||
|
||||
#include "MeshMassPropertiesTests.h"
|
||||
|
||||
//#define VERBOSE_UNIT_TESTS
|
||||
#define VERBOSE_UNIT_TESTS
|
||||
|
||||
const btScalar acceptableRelativeError(1.0e-5f);
|
||||
const btScalar acceptableAbsoluteError(1.0e-4f);
|
||||
|
@ -40,13 +41,13 @@ void pushTriangle(VectorOfIndices& indices, uint32_t a, uint32_t b, uint32_t c)
|
|||
}
|
||||
|
||||
void MeshMassPropertiesTests::testParallelAxisTheorem() {
|
||||
#ifdef EXPOSE_HELPER_FUNCTIONS_FOR_UNIT_TEST
|
||||
// verity we can compute the inertia tensor of a box in two different ways:
|
||||
//#ifdef EXPOSE_HELPER_FUNCTIONS_FOR_UNIT_TEST
|
||||
// verity we can compute the inertia tensor of a box in two different ways:
|
||||
// (a) as one box
|
||||
// (b) as a combination of two partial boxes.
|
||||
#ifdef VERBOSE_UNIT_TESTS
|
||||
std::cout << "\n" << __FUNCTION__ << std::endl;
|
||||
#endif // VERBOSE_UNIT_TESTS
|
||||
//#ifdef VERBOSE_UNIT_TESTS
|
||||
// std::cout << "\n" << __FUNCTION__ << std::endl;
|
||||
//#endif // VERBOSE_UNIT_TESTS
|
||||
|
||||
btScalar bigBoxX = 7.0f;
|
||||
btScalar bigBoxY = 9.0f;
|
||||
|
@ -76,11 +77,12 @@ void MeshMassPropertiesTests::testParallelAxisTheorem() {
|
|||
btScalar error;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
error = bitBoxInertia[i][j] - twoSmallBoxesInertia[i][j];
|
||||
if (fabsf(error) > acceptableAbsoluteError) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR : box inertia[" << i << "][" << j << "] off by = "
|
||||
<< error << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(bitBoxInertia[i][j], twoSmallBoxesInertia[i][j], acceptableAbsoluteError);
|
||||
// error = bitBoxInertia[i][j] - twoSmallBoxesInertia[i][j];
|
||||
// if (fabsf(error) > acceptableAbsoluteError) {
|
||||
// std::cout << __FILE__ << ":" << __LINE__ << " ERROR : box inertia[" << i << "][" << j << "] off by = "
|
||||
// << error << std::endl;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,7 @@ void MeshMassPropertiesTests::testParallelAxisTheorem() {
|
|||
printMatrix("expected inertia", bitBoxInertia);
|
||||
printMatrix("computed inertia", twoSmallBoxesInertia);
|
||||
#endif // VERBOSE_UNIT_TESTS
|
||||
#endif // EXPOSE_HELPER_FUNCTIONS_FOR_UNIT_TEST
|
||||
//#endif // EXPOSE_HELPER_FUNCTIONS_FOR_UNIT_TEST
|
||||
}
|
||||
|
||||
void MeshMassPropertiesTests::testTetrahedron(){
|
||||
|
|
|
@ -14,18 +14,39 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <BulletUtil.h>
|
||||
|
||||
#include <qtextstream.h>
|
||||
|
||||
#include <CollisionInfo.h>
|
||||
|
||||
const glm::vec3 origin(0.0f);
|
||||
const glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
const glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
const glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) {
|
||||
return s << "[penetration=" << c._penetration
|
||||
<< ", contactPoint=" << c._contactPoint
|
||||
<< ", addedVelocity=" << c._addedVelocity
|
||||
<< "]";
|
||||
// Implement these functions for whatever data types you need.
|
||||
//
|
||||
// fuzzyCompare takes two args of type T (the type you're comparing), and should
|
||||
// return an error / difference of type V (eg. if T is a vector, V is a scalar).
|
||||
// For vector types this is just the distance between a and b.
|
||||
//
|
||||
// stringify is just a toString() / repr() style function. For PoD types,
|
||||
// I'd recommend using the c++11 initialization syntax (type { constructor args... }),
|
||||
// since it's clear and unambiguous.
|
||||
//
|
||||
inline float fuzzyCompare (const glm::vec3 & a, const glm::vec3 & b) {
|
||||
return glm::distance(a, b);
|
||||
}
|
||||
inline QTextStream & operator << (QTextStream & stream, const glm::vec3 & v) {
|
||||
return stream << "glm::vec3 { " << v.x << ", " << v.y << ", " << v.z << " }";
|
||||
}
|
||||
|
||||
inline btScalar fuzzyCompare (btScalar a, btScalar b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
#include "../QTestExtensions.hpp"
|
||||
|
||||
|
||||
#endif // hifi_PhysicsTestUtil_h
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
|
||||
//#include <stdio.h>
|
||||
#include "PhysicsTestUtil.h"
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -27,10 +28,11 @@
|
|||
|
||||
#include "ShapeColliderTests.h"
|
||||
|
||||
const glm::vec3 origin(0.0f);
|
||||
static const glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
static const glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
static const glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
|
||||
|
||||
//const glm::vec3 origin(0.0f);
|
||||
//static const glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
//static const glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
//static const glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
|
||||
|
||||
QTEST_MAIN(ShapeColliderTests)
|
||||
|
||||
|
@ -47,37 +49,12 @@ void ShapeColliderTests::sphereMissesSphere() {
|
|||
SphereShape sphereB(radiusB, offsetDistance * offsetDirection);
|
||||
CollisionList collisions(16);
|
||||
|
||||
// collide A to B...
|
||||
{
|
||||
bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions);
|
||||
if (touching) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// collide B to A...
|
||||
{
|
||||
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
|
||||
if (touching) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// also test shapeShape
|
||||
{
|
||||
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
|
||||
if (touching) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphereA and sphereB should NOT touch" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (collisions.size() > 0) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: expected empty collision list but size is " << collisions.size() << std::endl;
|
||||
}
|
||||
// collide A to B and vice versa
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &sphereB, collisions), false);
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereB, &sphereA, collisions), false);
|
||||
|
||||
// Collision list should be empty
|
||||
QCOMPARE(collisions.size(), 0);
|
||||
}
|
||||
|
||||
void ShapeColliderTests::sphereTouchesSphere() {
|
||||
|
@ -98,74 +75,38 @@ void ShapeColliderTests::sphereTouchesSphere() {
|
|||
|
||||
// collide A to B...
|
||||
{
|
||||
bool touching = ShapeCollider::collideShapes(&sphereA, &sphereB, collisions);
|
||||
if (!touching) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphereA and sphereB should touch" << std::endl;
|
||||
} else {
|
||||
++numCollisions;
|
||||
}
|
||||
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &sphereB, collisions), true);
|
||||
++numCollisions;
|
||||
|
||||
// verify state of collisions
|
||||
if (numCollisions != collisions.size()) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: expected collisions size of " << numCollisions << " but actual size is " << collisions.size()
|
||||
<< std::endl;
|
||||
}
|
||||
QCOMPARE(collisions.size(), numCollisions);
|
||||
CollisionInfo* collision = collisions.getCollision(numCollisions - 1);
|
||||
if (!collision) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: null collision" << std::endl;
|
||||
return;
|
||||
}
|
||||
QVERIFY(collision != nullptr);
|
||||
|
||||
// penetration points from sphereA into sphereB
|
||||
float inaccuracy = glm::length(collision->_penetration - expectedPenetration);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad penetration: expected = " << expectedPenetration
|
||||
<< " actual = " << collision->_penetration << std::endl;
|
||||
}
|
||||
QCOMPARE(collision->_penetration, expectedPenetration);
|
||||
|
||||
// contactPoint is on surface of sphereA
|
||||
glm::vec3 AtoB = sphereB.getTranslation() - sphereA.getTranslation();
|
||||
glm::vec3 expectedContactPoint = sphereA.getTranslation() + radiusA * glm::normalize(AtoB);
|
||||
inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad contactPoint: expected = " << expectedContactPoint
|
||||
<< " actual = " << collision->_contactPoint << std::endl;
|
||||
}
|
||||
QCOMPARE(collision->_contactPoint, expectedContactPoint);
|
||||
|
||||
QFUZZY_COMPARE(collision->_contactPoint, expectedContactPoint, EPSILON);
|
||||
}
|
||||
|
||||
// collide B to A...
|
||||
{
|
||||
bool touching = ShapeCollider::collideShapes(&sphereB, &sphereA, collisions);
|
||||
if (!touching) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphereA and sphereB should touch" << std::endl;
|
||||
} else {
|
||||
++numCollisions;
|
||||
}
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &sphereB, collisions), true);
|
||||
++numCollisions;
|
||||
|
||||
// penetration points from sphereA into sphereB
|
||||
CollisionInfo* collision = collisions.getCollision(numCollisions - 1);
|
||||
float inaccuracy = glm::length(collision->_penetration + expectedPenetration);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad penetration: expected = " << expectedPenetration
|
||||
<< " actual = " << collision->_penetration << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_penetration, expectedPenetration, EPSILON);
|
||||
|
||||
// contactPoint is on surface of sphereA
|
||||
glm::vec3 BtoA = sphereA.getTranslation() - sphereB.getTranslation();
|
||||
glm::vec3 expectedContactPoint = sphereB.getTranslation() + radiusB * glm::normalize(BtoA);
|
||||
inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad contactPoint: expected = " << expectedContactPoint
|
||||
<< " actual = " << collision->_contactPoint << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_contactPoint, expectedContactPoint, EPSILON);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,25 +141,12 @@ void ShapeColliderTests::sphereMissesCapsule() {
|
|||
glm::vec3 localPosition = localStartPosition + ((float)i * delta) * yAxis;
|
||||
sphereA.setTranslation(rotation * localPosition + translation);
|
||||
|
||||
// sphereA agains capsuleB
|
||||
if (ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphere and capsule should NOT touch" << std::endl;
|
||||
}
|
||||
|
||||
// capsuleB against sphereA
|
||||
if (ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphere and capsule should NOT touch" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (collisions.size() > 0) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: expected empty collision list but size is " << collisions.size() << std::endl;
|
||||
// sphereA agains capsuleB and vice versa
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions), false);
|
||||
QCOMPARE(ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions), false);
|
||||
}
|
||||
|
||||
QCOMPARE(collisions.size(), 0);
|
||||
}
|
||||
|
||||
void ShapeColliderTests::sphereTouchesCapsule() {
|
||||
|
@ -239,42 +167,22 @@ void ShapeColliderTests::sphereTouchesCapsule() {
|
|||
|
||||
{ // sphereA collides with capsuleB's cylindrical wall
|
||||
sphereA.setTranslation(radialOffset * xAxis);
|
||||
|
||||
if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphere and capsule should touch" << std::endl;
|
||||
} else {
|
||||
++numCollisions;
|
||||
}
|
||||
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions), true);
|
||||
++numCollisions;
|
||||
|
||||
// penetration points from sphereA into capsuleB
|
||||
CollisionInfo* collision = collisions.getCollision(numCollisions - 1);
|
||||
glm::vec3 expectedPenetration = (radialOffset - totalRadius) * xAxis;
|
||||
float inaccuracy = glm::length(collision->_penetration - expectedPenetration);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad penetration: expected = " << expectedPenetration
|
||||
<< " actual = " << collision->_penetration << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_penetration, expectedPenetration, EPSILON);
|
||||
|
||||
// contactPoint is on surface of sphereA
|
||||
glm::vec3 expectedContactPoint = sphereA.getTranslation() - radiusA * xAxis;
|
||||
inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad contactPoint: expected = " << expectedContactPoint
|
||||
<< " actual = " << collision->_contactPoint << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_contactPoint, expectedContactPoint, EPSILON);
|
||||
|
||||
// capsuleB collides with sphereA
|
||||
if (!ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions))
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: capsule and sphere should touch" << std::endl;
|
||||
} else {
|
||||
++numCollisions;
|
||||
}
|
||||
QCOMPARE(ShapeCollider::collideShapes(&capsuleB, &sphereA, collisions), true);
|
||||
++numCollisions;
|
||||
|
||||
// penetration points from sphereA into capsuleB
|
||||
collision = collisions.getCollision(numCollisions - 1);
|
||||
|
@ -283,13 +191,8 @@ void ShapeColliderTests::sphereTouchesCapsule() {
|
|||
// the ShapeCollider swapped the order of the shapes
|
||||
expectedPenetration *= -1.0f;
|
||||
}
|
||||
inaccuracy = glm::length(collision->_penetration - expectedPenetration);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad penetration: expected = " << expectedPenetration
|
||||
<< " actual = " << collision->_penetration << std::endl;
|
||||
}
|
||||
|
||||
QFUZZY_COMPARE(collision->_penetration, expectedPenetration, EPSILON);
|
||||
|
||||
// contactPoint is on surface of capsuleB
|
||||
glm::vec3 BtoA = sphereA.getTranslation() - capsuleB.getTranslation();
|
||||
glm::vec3 closestApproach = capsuleB.getTranslation() + glm::dot(BtoA, yAxis) * yAxis;
|
||||
|
@ -299,37 +202,24 @@ void ShapeColliderTests::sphereTouchesCapsule() {
|
|||
closestApproach = sphereA.getTranslation() - glm::dot(BtoA, yAxis) * yAxis;
|
||||
expectedContactPoint = closestApproach - radiusB * glm::normalize(BtoA - closestApproach);
|
||||
}
|
||||
inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad contactPoint: expected = " << expectedContactPoint
|
||||
<< " actual = " << collision->_contactPoint << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_contactPoint, expectedContactPoint, EPSILON);
|
||||
}
|
||||
{ // sphereA hits end cap at axis
|
||||
glm::vec3 axialOffset = (halfHeightB + alpha * radiusA + beta * radiusB) * yAxis;
|
||||
sphereA.setTranslation(axialOffset);
|
||||
|
||||
if (!ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions))
|
||||
{
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: sphere and capsule should touch" << std::endl;
|
||||
} else {
|
||||
++numCollisions;
|
||||
}
|
||||
QCOMPARE(ShapeCollider::collideShapes(&sphereA, &capsuleB, collisions), true);
|
||||
++numCollisions;
|
||||
|
||||
// penetration points from sphereA into capsuleB
|
||||
CollisionInfo* collision = collisions.getCollision(numCollisions - 1);
|
||||
glm::vec3 expectedPenetration = - ((1.0f - alpha) * radiusA + (1.0f - beta) * radiusB) * yAxis;
|
||||
float inaccuracy = glm::length(collision->_penetration - expectedPenetration);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
<< " ERROR: bad penetration: expected = " << expectedPenetration
|
||||
<< " actual = " << collision->_penetration << std::endl;
|
||||
}
|
||||
QFUZZY_COMPARE(collision->_penetration, expectedPenetration, EPSILON);
|
||||
|
||||
// contactPoint is on surface of sphereA
|
||||
glm::vec3 expectedContactPoint = sphereA.getTranslation() - radiusA * yAxis;
|
||||
|
||||
|
||||
inaccuracy = glm::length(collision->_contactPoint - expectedContactPoint);
|
||||
if (fabsf(inaccuracy) > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
|
@ -2509,36 +2399,3 @@ void ShapeColliderTests::measureTimeOfCollisionDispatch() {
|
|||
*/
|
||||
}
|
||||
|
||||
//void ShapeColliderTests::runAllTests() {
|
||||
// ShapeCollider::initDispatchTable();
|
||||
//
|
||||
// //measureTimeOfCollisionDispatch();
|
||||
//
|
||||
// sphereMissesSphere();
|
||||
// sphereTouchesSphere();
|
||||
//
|
||||
// sphereMissesCapsule();
|
||||
// sphereTouchesCapsule();
|
||||
//
|
||||
// capsuleMissesCapsule();
|
||||
// capsuleTouchesCapsule();
|
||||
//
|
||||
// sphereMissesAACube();
|
||||
// sphereTouchesAACubeFaces();
|
||||
// sphereTouchesAACubeEdges();
|
||||
// sphereTouchesAACubeCorners();
|
||||
//
|
||||
// capsuleMissesAACube();
|
||||
// capsuleTouchesAACube();
|
||||
//
|
||||
// rayHitsSphere();
|
||||
// rayBarelyHitsSphere();
|
||||
// rayBarelyMissesSphere();
|
||||
// rayHitsCapsule();
|
||||
// rayMissesCapsule();
|
||||
// rayHitsPlane();
|
||||
// rayMissesPlane();
|
||||
//
|
||||
// rayHitsAACube();
|
||||
// rayMissesAACube();
|
||||
//}
|
||||
|
|
|
@ -46,8 +46,6 @@ private slots:
|
|||
void rayMissesAACube();
|
||||
|
||||
void measureTimeOfCollisionDispatch();
|
||||
|
||||
// void runAllTests();
|
||||
};
|
||||
|
||||
#endif // hifi_ShapeColliderTests_h
|
||||
|
|
Loading…
Reference in a new issue