Fixed intersectRayTriangle #6

This commit is contained in:
Christophe Riccio 2016-11-25 00:33:45 +01:00
parent 07d826e185
commit 58c5e0ef4d
4 changed files with 96 additions and 14 deletions

View File

@ -44,12 +44,13 @@ namespace glm
typename genType::value_type & intersectionDistance);
//! Compute the intersection of a ray and a triangle.
/// Based om Tomas Möller implementation http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/
//! From GLM_GTX_intersect extension.
template <typename genType>
template <typename T, precision P>
GLM_FUNC_DECL bool intersectRayTriangle(
genType const & orig, genType const & dir,
genType const & vert0, genType const & vert1, genType const & vert2,
genType & baryPosition);
tvec3<T, P> const& orig, tvec3<T, P> const& dir,
tvec3<T, P> const& v0, tvec3<T, P> const& v1, tvec3<T, P> const& v2,
tvec3<T, P>& baryPosition, T& distance);
//! Compute the intersection of a line and a triangle.
//! From GLM_GTX_intersect extension.

View File

@ -23,21 +23,75 @@ namespace glm
return false;
}
template <typename genType>
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool intersectRayTriangle
(
genType const & orig, genType const & dir,
genType const & v0, genType const & v1, genType const & v2,
genType & baryPosition
tvec3<T, P> const& orig, tvec3<T, P> const& dir,
tvec3<T, P> const& vert0, tvec3<T, P> const& vert1, tvec3<T, P> const& vert2,
tvec2<T, P>& baryPosition, T& distance
)
{
genType e1 = v1 - v0;
genType e2 = v2 - v0;
// find vectors for two edges sharing vert0
tvec3<T, P> const edge1 = vert1 - vert0;
tvec3<T, P> const edge2 = vert2 - vert0;
genType p = glm::cross(dir, e2);
// begin calculating determinant - also used to calculate U parameter
tvec3<T, P> const p = glm::cross(dir, edge2);
typename genType::value_type a = glm::dot(e1, p);
// if determinant is near zero, ray lies in plane of triangle
T const det = glm::dot(edge1, p);
tvec3<T, P> qvec;
if(det > std::numeric_limits<T>::epsilon())
{
// calculate distance from vert0 to ray origin
tvec3<T, P> const tvec = orig - vert0;
// calculate U parameter and test bounds
baryPosition.x = glm::dot(tvec, p);
if(baryPosition.x < static_cast<T>(0) || baryPosition.x > det)
return false;
// prepare to test V parameter
qvec = glm::cross(tvec, edge1);
// calculate V parameter and test bounds
baryPosition.y = glm::dot(dir, qvec);
if((baryPosition.y < static_cast<T>(0)) || ((baryPosition.x + baryPosition.y) > det))
return false;
}
else if(det < -std::numeric_limits<T>::epsilon())
{
// calculate distance from vert0 to ray origin
tvec3<T, P> const tvec = orig - vert0;
// calculate U parameter and test bounds
baryPosition.x = glm::dot(tvec, p);
if((baryPosition.x > static_cast<T>(0)) || (baryPosition.x < det))
return false;
// prepare to test V parameter
qvec = glm::cross(tvec, edge1);
// calculate V parameter and test bounds
baryPosition.y = glm::dot(dir, qvec);
if((baryPosition.y > static_cast<T>(0)) || (baryPosition.x + baryPosition.y < det))
return false;
}
else
return false; // ray is parallel to the plane of the triangle
T inv_det = static_cast<T>(1) / det;
// calculate distance, ray intersects triangle
distance = glm::dot(edge2, qvec) * inv_det;
baryPosition *= inv_det;
return true;
}
/*
typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
if(a < Epsilon && a > -Epsilon)
return false;
@ -62,6 +116,7 @@ namespace glm
return baryPosition.z >= typename genType::value_type(0.0f);
}
*/
template <typename genType>
GLM_FUNC_QUALIFIER bool intersectLineTriangle

View File

@ -72,6 +72,7 @@ glm::mat4 camera(float Translate, glm::vec2 const & Rotate)
#### Fixes:
- Removed doxygen references to GTC_half_float which was removed in 0.9.4
- Fixed glm::decompose #448
- Fixed intersectRayTriangle #6
#### Deprecation:
- Removed GLM_GTX_simd_vec4 extension

View File

@ -1,9 +1,34 @@
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/epsilon.hpp>
#include <glm/gtx/intersect.hpp>
int main()
int test_intersectRayTriangle()
{
int Error(0);
int Error = 0;
glm::vec3 const Orig(0, 0, 2);
glm::vec3 const Dir(0, 0, -1);
glm::vec3 const Vert0(0, 0, 0);
glm::vec3 const Vert1(-1, -1, 0);
glm::vec3 const Vert2(1, -1, 0);
glm::vec2 BaryPosition(0);
float Distance = 0;
bool const Result = glm::intersectRayTriangle(Orig, Dir, Vert0, Vert1, Vert2, BaryPosition, Distance);
Error += glm::all(glm::epsilonEqual(BaryPosition, glm::vec2(0), std::numeric_limits<float>::epsilon())) ? 0 : 1;
Error += glm::abs(Distance - 2.f) <= std::numeric_limits<float>::epsilon() ? 0 : 1;
Error += Result ? 0 : 1;
return Error;
}
int main()
{
int Error = 0;
Error += test_intersectRayTriangle();
return Error;
}