Made Ray into a class with checks so the direction will always be normalized.
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
#ifndef Collision_h__
|
#ifndef Collision_h__
|
||||||
#define Collision_h__
|
#define Collision_h__
|
||||||
|
|
||||||
|
//NOTE: Collision.h needs to be #included before <GLFW/glfw3.h>,
|
||||||
|
//because Collision #includes "RawModel.h", which has "Texture.h", which has "OpenGL.h" which must be #included first
|
||||||
|
//or you will get "fatal error C1189: #error: gl.h included before glew.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Core/Ray.h"
|
#include "Core/Ray.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "Core/AABB.h"
|
#include "Core/AABB.h"
|
||||||
|
|
||||||
struct Ray;
|
class Ray;
|
||||||
|
|
||||||
class OctTree
|
class OctTree
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,11 +2,30 @@
|
|||||||
#define Ray_h__
|
#define Ray_h__
|
||||||
|
|
||||||
#include "../GLM.h"
|
#include "../GLM.h"
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
struct Ray
|
class Ray
|
||||||
{
|
{
|
||||||
glm::vec3 Origin;
|
public:
|
||||||
glm::vec3 Direction;
|
Ray(const glm::vec3& origin, const glm::vec3& dir)
|
||||||
|
: m_Origin(origin)
|
||||||
|
, m_Direction(glm::normalize(dir))
|
||||||
|
{
|
||||||
|
IF_DEBUG_IS(true) {
|
||||||
|
if (glm::any(glm::isnan(m_Direction))) {
|
||||||
|
LOG_WARNING("Ray Direction was set to the zero-vector, expect unknown side effects and/or crashes.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const glm::vec3& Origin() const { return m_Origin; }
|
||||||
|
const glm::vec3& Direction() const { return m_Direction; }
|
||||||
|
//Sets the ray origin at parameter.
|
||||||
|
void SetOrigin(const glm::vec3& origin) { m_Origin = origin; }
|
||||||
|
//Normalizes the parameter and sets direction to it.
|
||||||
|
void SetDirection(const glm::vec3& direction) { m_Direction = glm::normalize(direction); }
|
||||||
|
private:
|
||||||
|
glm::vec3 m_Origin;
|
||||||
|
glm::vec3 m_Direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Ray_h__
|
#endif // Ray_h__
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ namespace Collision
|
|||||||
//note: this one hasnt been delta adjusted like RayVsAABB has
|
//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();
|
||||||
glm::vec3 v = glm::abs(w);
|
glm::vec3 v = glm::abs(w);
|
||||||
glm::vec3 c = ray.Origin - box.Center() + w;
|
glm::vec3 c = ray.Origin() - box.Center() + w;
|
||||||
glm::vec3 half = box.HalfSize();
|
glm::vec3 half = box.HalfSize();
|
||||||
|
|
||||||
if (abs(c.x) > v.x + half.x) {
|
if (abs(c.x) > v.x + half.x) {
|
||||||
@@ -43,14 +43,15 @@ namespace Collision
|
|||||||
|
|
||||||
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
|
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
|
||||||
{
|
{
|
||||||
glm::vec3 invdir = 1.0f / ray.Direction;
|
glm::vec3 invdir = 1.0f / ray.Direction();
|
||||||
|
glm::vec3 origin = ray.Origin();
|
||||||
|
|
||||||
float t1 = (box.MinCorner().x - ray.Origin.x)*invdir.x;
|
float t1 = (box.MinCorner().x - origin.x)*invdir.x;
|
||||||
float t2 = (box.MaxCorner().x - ray.Origin.x)*invdir.x;
|
float t2 = (box.MaxCorner().x - origin.x)*invdir.x;
|
||||||
float t3 = (box.MinCorner().y - ray.Origin.y)*invdir.y;
|
float t3 = (box.MinCorner().y - origin.y)*invdir.y;
|
||||||
float t4 = (box.MaxCorner().y - ray.Origin.y)*invdir.y;
|
float t4 = (box.MaxCorner().y - origin.y)*invdir.y;
|
||||||
float t5 = (box.MinCorner().z - ray.Origin.z)*invdir.z;
|
float t5 = (box.MinCorner().z - origin.z)*invdir.z;
|
||||||
float t6 = (box.MaxCorner().z - ray.Origin.z)*invdir.z;
|
float t6 = (box.MaxCorner().z - origin.z)*invdir.z;
|
||||||
|
|
||||||
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));
|
||||||
@@ -123,16 +124,16 @@ namespace Collision
|
|||||||
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
||||||
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
||||||
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
||||||
glm::vec3 m = ray.Origin - v0;
|
glm::vec3 m = ray.Origin() - v0;
|
||||||
glm::vec3 MxE1 = glm::cross(m, e1);
|
glm::vec3 MxE1 = glm::cross(m, e1);
|
||||||
glm::vec3 DxE2 = glm::cross(ray.Direction, e2);
|
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);
|
||||||
float DetInv = glm::dot(e1, DxE2);
|
float DetInv = glm::dot(e1, DxE2);
|
||||||
if (std::abs(DetInv) < FLT_EPSILON) {
|
if (std::abs(DetInv) < FLT_EPSILON) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
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;
|
||||||
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
|
//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) {
|
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
|
||||||
continue;
|
continue;
|
||||||
@@ -158,9 +159,9 @@ namespace Collision
|
|||||||
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
||||||
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
||||||
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
||||||
glm::vec3 m = ray.Origin - v0;
|
glm::vec3 m = ray.Origin() - v0;
|
||||||
glm::vec3 MxE1 = glm::cross(m, e1);
|
glm::vec3 MxE1 = glm::cross(m, e1);
|
||||||
glm::vec3 DxE2 = glm::cross(ray.Direction, e2);//pVec
|
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec
|
||||||
float DetInv = glm::dot(e1, DxE2);
|
float DetInv = glm::dot(e1, DxE2);
|
||||||
if (std::abs(DetInv) < FLT_EPSILON) {
|
if (std::abs(DetInv) < FLT_EPSILON) {
|
||||||
continue;
|
continue;
|
||||||
@@ -171,7 +172,7 @@ namespace Collision
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
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
|
//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.
|
||||||
@@ -194,7 +195,7 @@ namespace Collision
|
|||||||
float v;
|
float v;
|
||||||
float dist;
|
float dist;
|
||||||
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
|
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
|
||||||
outHitPosition = ray.Origin + dist * ray.Direction;
|
outHitPosition = ray.Origin() + dist * ray.Direction();
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ bool OctTree::OctChild::RayCollides(const Ray& ray, Output& data) const
|
|||||||
std::vector<ChildInfo> childInfos;
|
std::vector<ChildInfo> childInfos;
|
||||||
childInfos.reserve(8);
|
childInfos.reserve(8);
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
childInfos.push_back({ i, glm::distance(ray.Origin, m_Children[i]->m_Box.Center()) });
|
childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Center()) });
|
||||||
}
|
}
|
||||||
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
||||||
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
||||||
|
|||||||
+19
-34
@@ -26,16 +26,14 @@ using boost::unit_test_framework::test_case;
|
|||||||
|
|
||||||
void RayTest(std::string fileName) {
|
void RayTest(std::string fileName) {
|
||||||
//simple box test
|
//simple box test
|
||||||
Ray ray;
|
Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0));
|
||||||
ray.Origin = glm::vec3(-50, 0, 0);
|
|
||||||
ray.Direction = glm::normalize(glm::vec3(1, 0, 0));
|
|
||||||
//using a rawmodel here, else we have to init the renderingsystem
|
//using a rawmodel here, else we have to init the renderingsystem
|
||||||
ResourceManager::RegisterType<RawModel>("RawModel");
|
ResourceManager::RegisterType<RawModel>("RawModel");
|
||||||
auto unitBox = ResourceManager::Load<RawModel>(fileName);
|
auto unitBox = ResourceManager::Load<RawModel>(fileName);
|
||||||
BOOST_CHECK(unitBox != nullptr);
|
BOOST_REQUIRE(unitBox != nullptr);
|
||||||
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
|
bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
|
||||||
BOOST_CHECK(hit);
|
BOOST_CHECK(hit);
|
||||||
ray.Direction = glm::normalize(glm::vec3(-1, 0, 0));
|
ray.SetDirection(glm::vec3(-1, 0, 0));
|
||||||
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
|
hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices);
|
||||||
BOOST_CHECK(!hit);
|
BOOST_CHECK(!hit);
|
||||||
}
|
}
|
||||||
@@ -49,7 +47,6 @@ BOOST_AUTO_TEST_CASE(collisionTest)
|
|||||||
|
|
||||||
//fixed seed
|
//fixed seed
|
||||||
srand(2);
|
srand(2);
|
||||||
Ray ray;
|
|
||||||
AABB someAABB;
|
AABB someAABB;
|
||||||
glm::vec3 minPos;
|
glm::vec3 minPos;
|
||||||
glm::vec3 maxPos;
|
glm::vec3 maxPos;
|
||||||
@@ -57,12 +54,10 @@ BOOST_AUTO_TEST_CASE(collisionTest)
|
|||||||
int test = 0;
|
int test = 0;
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
ray.Origin.x = rand() % 100;
|
Ray ray(
|
||||||
ray.Origin.y = rand() % 100;
|
glm::vec3(rand() % 100, rand() % 100, rand() % 100),
|
||||||
ray.Origin.z = rand() % 100;
|
glm::vec3(rand() % 100, rand() % 100, rand() % 100)
|
||||||
ray.Direction.x = rand() % 100;
|
);
|
||||||
ray.Direction.y = rand() % 100;
|
|
||||||
ray.Direction.z = rand() % 100;
|
|
||||||
minPos.x = rand() % 100;
|
minPos.x = rand() % 100;
|
||||||
minPos.y = rand() % 100;
|
minPos.y = rand() % 100;
|
||||||
minPos.z = rand() % 100;
|
minPos.z = rand() % 100;
|
||||||
@@ -83,7 +78,6 @@ BOOST_AUTO_TEST_CASE(collisionTest2)
|
|||||||
{
|
{
|
||||||
//fixed seed
|
//fixed seed
|
||||||
srand(2);
|
srand(2);
|
||||||
Ray ray;
|
|
||||||
AABB someAABB;
|
AABB someAABB;
|
||||||
glm::vec3 minPos;
|
glm::vec3 minPos;
|
||||||
glm::vec3 maxPos;
|
glm::vec3 maxPos;
|
||||||
@@ -91,12 +85,10 @@ BOOST_AUTO_TEST_CASE(collisionTest2)
|
|||||||
int test = 0;
|
int test = 0;
|
||||||
for (size_t i = 0; i < 1000000; i++)
|
for (size_t i = 0; i < 1000000; i++)
|
||||||
{
|
{
|
||||||
ray.Origin.x = rand() % 100;
|
Ray ray(
|
||||||
ray.Origin.y = rand() % 100;
|
glm::vec3(rand() % 100, rand() % 100, rand() % 100),
|
||||||
ray.Origin.z = rand() % 100;
|
glm::vec3(rand() % 100, rand() % 100, rand() % 100)
|
||||||
ray.Direction.x = rand() % 100;
|
);
|
||||||
ray.Direction.y = rand() % 100;
|
|
||||||
ray.Direction.z = rand() % 100;
|
|
||||||
minPos.x = rand() % 100;
|
minPos.x = rand() % 100;
|
||||||
minPos.y = rand() % 100;
|
minPos.y = rand() % 100;
|
||||||
minPos.z = rand() % 100;
|
minPos.z = rand() % 100;
|
||||||
@@ -114,7 +106,7 @@ BOOST_AUTO_TEST_CASE(collisionTest2)
|
|||||||
BOOST_AUTO_TEST_CASE(rayVsModelTest)
|
BOOST_AUTO_TEST_CASE(rayVsModelTest)
|
||||||
{
|
{
|
||||||
//simple box test
|
//simple box test
|
||||||
RayTest("Models/Core/UnitBox.obj");
|
RayTest("Models/Core/UnitCube.obj");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
||||||
@@ -125,7 +117,6 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
|||||||
// srand(7676462);
|
// srand(7676462);
|
||||||
// srand(7462);
|
// srand(7462);
|
||||||
srand(72);
|
srand(72);
|
||||||
Ray ray;
|
|
||||||
AABB someAABB;
|
AABB someAABB;
|
||||||
glm::vec3 minPos;
|
glm::vec3 minPos;
|
||||||
glm::vec3 maxPos;
|
glm::vec3 maxPos;
|
||||||
@@ -142,19 +133,13 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
|||||||
|
|
||||||
for (size_t i = 0; i < 1000000; i++)
|
for (size_t i = 0; i < 1000000; i++)
|
||||||
{
|
{
|
||||||
ray.Origin.x = rand() % 100;
|
Ray ray(
|
||||||
ray.Origin.y = rand() % 100;
|
glm::vec3(-2, 0, 0),
|
||||||
ray.Origin.z = rand() % 100;
|
glm::vec3(rand() % 100, rand() % 100, rand() % 100)
|
||||||
ray.Direction.x = rand() % 100;
|
);
|
||||||
ray.Direction.y = rand() % 100;
|
|
||||||
ray.Direction.z = rand() % 100;
|
|
||||||
ray.Origin /= 100;
|
|
||||||
ray.Origin = glm::vec3(-2, 0, 0);
|
|
||||||
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 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)
|
if (glm::any(glm::isnan(ray.Direction())))
|
||||||
continue;
|
continue;
|
||||||
ray.Direction = glm::normalize(ray.Direction);
|
|
||||||
|
|
||||||
z = Collision::RayVsAABB(ray, someAABB);
|
z = Collision::RayVsAABB(ray, someAABB);
|
||||||
if (z) {
|
if (z) {
|
||||||
@@ -224,10 +209,10 @@ BOOST_AUTO_TEST_CASE(octTest)
|
|||||||
tree.AddDynamicObject(AABB(mini, -0.9f*maxi));
|
tree.AddDynamicObject(AABB(mini, -0.9f*maxi));
|
||||||
OctTree::Output data;
|
OctTree::Output data;
|
||||||
glm::vec3 origin = 3.0f * mini;
|
glm::vec3 origin = 3.0f * mini;
|
||||||
bool rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data);
|
bool rayIntersected = tree.RayCollides(Ray(origin , mini - origin), data);
|
||||||
BOOST_CHECK(rayIntersected);
|
BOOST_CHECK(rayIntersected);
|
||||||
tree.ClearDynamicObjects();
|
tree.ClearDynamicObjects();
|
||||||
rayIntersected = tree.RayCollides({ origin , glm::normalize(mini - origin) }, data);
|
rayIntersected = tree.RayCollides(Ray(origin, mini - origin), data);
|
||||||
BOOST_CHECK(!rayIntersected);
|
BOOST_CHECK(!rayIntersected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const
|
|||||||
std::vector<ChildInfo> childInfos;
|
std::vector<ChildInfo> childInfos;
|
||||||
childInfos.reserve(8);
|
childInfos.reserve(8);
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
childInfos.push_back({ i, glm::distance(ray.Origin, m_Children[i]->m_Box.Center()) });
|
childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Center()) });
|
||||||
}
|
}
|
||||||
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
||||||
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "Core/AABB.h"
|
#include "Core/AABB.h"
|
||||||
|
|
||||||
struct Ray;
|
class Ray;
|
||||||
class World;
|
class World;
|
||||||
class Camera;
|
class Camera;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user