add parabola test, performance optimization

This commit is contained in:
SamGondelman 2018-07-03 15:14:43 -07:00
parent 90091d11e4
commit bfcf4f7865
4 changed files with 162 additions and 46 deletions

View file

@ -310,31 +310,66 @@ bool AABox::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& v
for (int i = 0; i < 3; i++) {
a = 0.5f * acceleration[i];
b = velocity[i];
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
if (origin[i] < _corner[i]) {
// If we're below _corner, we only need to check the min face
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
}
}
}
}
{ // max
c = origin[i] - (_corner[i] + _scale[i]);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
} else if (origin[i] > _corner[i] + _scale[i]) {
// If we're above _corner + _scale, we only need to check the max face
{ // max
c = origin[i] - (_corner[i] + _scale[i]);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
}
}
}
} else {
// If we're inside on this axis, we could hit either face depending on our velocity and acceleration, so we need to check both
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
}
}
}
{ // max
c = origin[i] - (_corner[i] + _scale[i]);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
}
}
}
}

View file

@ -306,31 +306,66 @@ bool AACube::findParabolaIntersection(const glm::vec3& origin, const glm::vec3&
for (int i = 0; i < 3; i++) {
a = 0.5f * acceleration[i];
b = velocity[i];
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
if (origin[i] < _corner[i]) {
// If we're below _corner, we only need to check the min face
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
}
}
}
}
{ // max
c = origin[i] - (_corner[i] + _scale);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
} else if (origin[i] > _corner[i] + _scale) {
// If we're above _corner + _scale, we only need to check the max face
{ // max
c = origin[i] - (_corner[i] + _scale);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
}
}
}
} else {
// If we're inside on this axis, we could hit either face depending on our velocity and acceleration, so we need to check both
{ // min
c = origin[i] - _corner[i];
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i);
minNormal = glm::vec3(0.0f);
minNormal[i] = -1.0f;
}
}
}
{ // max
c = origin[i] - (_corner[i] + _scale);
possibleDistances = { FLT_MAX, FLT_MAX };
if (computeRealQuadraticRoots(a, b, c, possibleDistances)) {
bool hit = false;
checkPossibleParabolicIntersection(possibleDistances.first, i, minDistance, origin, velocity, acceleration, hit);
checkPossibleParabolicIntersection(possibleDistances.second, i, minDistance, origin, velocity, acceleration, hit);
if (hit) {
minFace = BoxFace(2 * i + 1);
minNormal = glm::vec3(0.0f);
minNormal[i] = 1.0f;
}
}
}
}

View file

@ -152,3 +152,47 @@ void AACubeTests::touchesSphere() {
}
}
void AACubeTests::rayVsParabolaPerformance() {
// Test performance of findRayIntersection vs. findParabolaIntersection
// 100000 cubes with scale 500 in the +x +y +z quadrant
const int NUM_CUBES = 100000;
const float MAX_POS = 1000.0f;
const float MAX_SCALE = 500.0f;
int numRayHits = 0;
int numParabolaHits = 0;
std::vector<AACube> cubes;
cubes.reserve(NUM_CUBES);
for (int i = 0; i < NUM_CUBES; i++) {
cubes.emplace_back(glm::vec3(randFloatInRange(0.0f, MAX_POS), randFloatInRange(0.0f, MAX_POS), randFloatInRange(0.0f, MAX_POS)), MAX_SCALE);
}
glm::vec3 origin(0.0f);
glm::vec3 direction = glm::normalize(glm::vec3(1.0f));
float distance;
BoxFace face;
glm::vec3 normal;
auto start = std::chrono::high_resolution_clock::now();
for (auto& cube : cubes) {
if (cube.findRayIntersection(origin, direction, distance, face, normal)) {
numRayHits++;
}
}
auto rayTime = std::chrono::high_resolution_clock::now() - start;
start = std::chrono::high_resolution_clock::now();
direction = 10.0f * direction;
glm::vec3 acceleration = glm::vec3(-0.0001f, -0.0001f, -0.0001f);
for (auto& cube : cubes) {
if (cube.findParabolaIntersection(origin, direction, acceleration, distance, face, normal)) {
numParabolaHits++;
}
}
auto parabolaTime = std::chrono::high_resolution_clock::now() - start;
qDebug() << "Ray vs. Parabola perfomance: rayHit%:" << numRayHits / ((float)NUM_CUBES) * 100.0f << ", rayTime:" << rayTime.count() <<
", parabolaHit%:" << numParabolaHits / ((float)NUM_CUBES) * 100.0f << ", parabolaTime:" << parabolaTime.count() << ", parabolaTime/rayTime: " << (float)parabolaTime.count()/(float)rayTime.count();
}
void AACubeTests::cleanupTestCase() {
}

View file

@ -23,6 +23,8 @@ private slots:
void ctorsAndSetters();
void containsPoint();
void touchesSphere();
void rayVsParabolaPerformance();
void cleanupTestCase();
};
#endif // hifi_AACubeTests_h