RayVsModel && RayVsAABB tests added and working. Also adjusted RayVsModel,RayVsAABB with deltas when values are very close to each other (floatingprecision problems)

This commit is contained in:
verysecrethero
2015-12-15 11:07:09 +01:00
parent 948f6d5de7
commit 8e431c8edd
2 changed files with 225 additions and 148 deletions
+10 -3
View File
@@ -6,6 +6,7 @@
namespace Collision namespace Collision
{ {
//note: this one hasnt been delta adjusted like RayVsAABB has
bool RayAABBIntr(const Ray& ray, const AABB& box) bool RayAABBIntr(const Ray& ray, const AABB& box)
{ {
glm::vec3 w = 75.0f * ray.Direction; glm::vec3 w = 75.0f * ray.Direction;
@@ -52,7 +53,10 @@ bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6)); float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6)); float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
if (tmax < 0 || tmin > tmax) //if (tmax < 0 || tmin > tmax)
//if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly
//greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax
if (tmax < 0 || tmin>(tmax + 0.0001f))
return false; return false;
outDistance = (tmin > 0) ? tmin : tmax; outDistance = (tmin > 0) ? tmin : tmax;
@@ -93,7 +97,8 @@ bool RayVsModel(const Ray& ray,
DetInv = 1.0f / DetInv; DetInv = 1.0f / DetInv;
float u = glm::dot(m, DxE2) * DetInv; float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction, MxE1) * DetInv; float v = glm::dot(ray.Direction, MxE1) * DetInv;
if (u < 0 || v < 0 || 1 < u + v) { //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
continue; continue;
} }
//Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit.
@@ -131,8 +136,10 @@ bool RayVsModel(const Ray& ray,
} }
float u = glm::dot(m, DxE2) * DetInv; float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction, MxE1) * DetInv; float v = glm::dot(ray.Direction, MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
//If u and v are positive, u+v <= 1, dist is positive, and less than closest. //If u and v are positive, u+v <= 1, dist is positive, and less than closest.
if (0 <= u && 0 <= v && u + v <= 1 && 0 <= dist) { if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) {
outDistance = dist; outDistance = dist;
outUCoord = u; outUCoord = u;
outVCoord = v; outVCoord = v;
+78 -8
View File
@@ -96,13 +96,12 @@ BOOST_AUTO_TEST_CASE(collisionTest2)
BOOST_AUTO_TEST_CASE(rayVsModelTest) BOOST_AUTO_TEST_CASE(rayVsModelTest)
{ {
//simple test //simple box test
Ray ray; Ray ray;
ray.Origin = glm::vec3(-50, 0, 0); ray.Origin = glm::vec3(-50, 0, 0);
//ray.Direction = glm::vec3(-1, 0, 0);
ray.Direction = glm::normalize(glm::vec3(1, 0, 0)); ray.Direction = glm::normalize(glm::vec3(1, 0, 0));
//inte model, det kräver renderar grejs tydligen //using a rawmodel here, else we have to init the renderingsystem
ResourceManager::RegisterType<RawModel>("RawModel"); ResourceManager::RegisterType<RawModel>("RawModel");
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitBox.obj"); auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitBox.obj");
BOOST_CHECK(unitBox != nullptr); BOOST_CHECK(unitBox != nullptr);
@@ -115,19 +114,24 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest)
BOOST_AUTO_TEST_CASE(rayVsModelTest2) BOOST_AUTO_TEST_CASE(rayVsModelTest2)
{ {
//advanced test, based on ray vs AABB //advanced test, this will check so rayVSAABB and rayVsModel(with boxmodel) gives the same result (hit/miss)
srand(7676762); //testing with different seeds
// srand(7676762);
// srand(7676462);
// srand(7462);
srand(72);
Ray ray; Ray ray;
AABB someAABB; AABB someAABB;
glm::vec3 minPos; glm::vec3 minPos;
glm::vec3 maxPos; glm::vec3 maxPos;
bool z; bool z;
int test = 0; int test = 0;
//min/max is the same as the rawmodels boundaries ofcourse
minPos = glm::vec3(-0.5f, -0.5f, -0.5f); minPos = glm::vec3(-0.5f, -0.5f, -0.5f);
maxPos = glm::vec3(0.5f, 0.5f, 0.5f); maxPos = glm::vec3(0.5f, 0.5f, 0.5f);
someAABB = AABB(minPos, maxPos); someAABB = AABB(minPos, maxPos);
//using a rawmodel here, else we have to init the renderingsystem
ResourceManager::RegisterType<RawModel>("RawModel"); ResourceManager::RegisterType<RawModel>("RawModel");
//auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitBox.obj");
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitCube.obj"); auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitCube.obj");
BOOST_CHECK(unitBox != nullptr); BOOST_CHECK(unitBox != nullptr);
@@ -142,6 +146,9 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
ray.Origin /= 100; ray.Origin /= 100;
ray.Origin = glm::vec3(-2, 0, 0); ray.Origin = glm::vec3(-2, 0, 0);
ray.Direction /= 100; ray.Direction /= 100;
//if we normalize the ray.direction when its 0,0,0 then we get nan,nan,nan - thus we have this check to prevent that
if (ray.Direction.x < 0.0001f && ray.Direction.y < 0.0001f && ray.Direction.z < 0.0001f)
continue;
ray.Direction = glm::normalize(ray.Direction); ray.Direction = glm::normalize(ray.Direction);
z = Collision::RayVsAABB(ray, someAABB); z = Collision::RayVsAABB(ray, someAABB);
@@ -149,7 +156,7 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
//hit //hit
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
if (!hit) { if (!hit) {
hit = hit; //if rayvsaabb hit but rayvvmodel didnt hit, we get to here
glm::vec3 outtttttttt; glm::vec3 outtttttttt;
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt);
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
@@ -159,13 +166,21 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
} }
BOOST_CHECK(hit); BOOST_CHECK(hit);
} }
////breakpoint test
//if (!z) {
// z = z;
//}
// //
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
////breakpoint test
//if (!hit) {
// hit = hit;
//}
if (hit) { if (hit) {
//hit //hit
z = Collision::RayVsAABB(ray, someAABB); z = Collision::RayVsAABB(ray, someAABB);
if (!z) { if (!z) {
z = z; //if rayvsmodel hit but rayvsaabb didnt hit then we get to here
z = Collision::RayVsAABB(ray, someAABB); z = Collision::RayVsAABB(ray, someAABB);
glm::vec3 outtttttttt; glm::vec3 outtttttttt;
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt);
@@ -180,7 +195,62 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
} }
} }
BOOST_AUTO_TEST_CASE(rayVsModelTest3)
{
//simple test
Ray ray;
ray.Origin = glm::vec3(-50, 0, 0);
//ray.Direction = glm::vec3(-1, 0, 0);
ray.Direction = glm::normalize(glm::vec3(1, 0, 0));
//using a rawmodel here, else we have to init the renderingsystem
ResourceManager::RegisterType<RawModel>("RawModel");
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitSphere.obj");
BOOST_CHECK(unitBox != nullptr);
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(hit);
ray.Direction = glm::normalize(glm::vec3(-1, 0, 0));
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(!hit);
}
BOOST_AUTO_TEST_CASE(rayVsModelTest4)
{
//simple test
Ray ray;
ray.Origin = glm::vec3(-50, 0, 0);
//ray.Direction = glm::vec3(-1, 0, 0);
ray.Direction = glm::normalize(glm::vec3(1, 0, 0));
//using a rawmodel here, else we have to init the renderingsystem
ResourceManager::RegisterType<RawModel>("RawModel");
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitCylinder.obj");
BOOST_CHECK(unitBox != nullptr);
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(hit);
ray.Direction = glm::normalize(glm::vec3(-1, 0, 0));
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(!hit);
}
BOOST_AUTO_TEST_CASE(rayVsModelTest5)
{
//simple test
Ray ray;
ray.Origin = glm::vec3(-50, 0, 0);
//ray.Direction = glm::vec3(-1, 0, 0);
ray.Direction = glm::normalize(glm::vec3(1, 0, 0));
//using a rawmodel here, else we have to init the renderingsystem
ResourceManager::RegisterType<RawModel>("RawModel");
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitRaptor.obj");
BOOST_CHECK(unitBox != nullptr);
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(hit);
ray.Direction = glm::normalize(glm::vec3(-1, 0, 0));
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
BOOST_CHECK(!hit);
}
BOOST_AUTO_TEST_CASE(octTest) BOOST_AUTO_TEST_CASE(octTest)
{ {
glm::vec3 mini = glm::vec3(-1, -1, -1); glm::vec3 mini = glm::vec3(-1, -1, -1);