diff --git a/CREDITS b/CREDITS
index a159edf..ef9b2e4 100644
--- a/CREDITS
+++ b/CREDITS
@@ -65,3 +65,9 @@ https://forums.khronos.org/showthread.php/10651-Animation-TCB-Spline-Interpolati
12. vec2 cross product
http://allenchou.net/2013/07/cross-product-of-2d-vectors/
+13. Ray triangle intersect
+Möller–Trumbore ray-triangle intersection algorithm, from "Fast, Minimum Storage Ray/Triangle Intersection"
+Authors:
+ Thomas Möller (tompa@clarus.se)
+ Ben Trumbore (wbt@graphics.cornell.edu)
+Link to paper: http://webserver2.tecgraf.puc-rio.br/~mgattass/cg/trbRR/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index 46b90b5..f6b4a21 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -63,7 +63,8 @@ cglm_HEADERS = include/cglm/version.h \
include/cglm/ease.h \
include/cglm/curve.h \
include/cglm/bezier.h \
- include/cglm/applesimd.h
+ include/cglm/applesimd.h \
+ include/cglm/ray.h
cglm_calldir=$(includedir)/cglm/call
cglm_call_HEADERS = include/cglm/call/mat4.h \
@@ -84,7 +85,8 @@ cglm_call_HEADERS = include/cglm/call/mat4.h \
include/cglm/call/sphere.h \
include/cglm/call/ease.h \
include/cglm/call/curve.h \
- include/cglm/call/bezier.h
+ include/cglm/call/bezier.h \
+ include/cglm/call/ray.h
cglm_simddir=$(includedir)/cglm/simd
cglm_simd_HEADERS = include/cglm/simd/intrin.h \
@@ -147,7 +149,8 @@ libcglm_la_SOURCES=\
src/sphere.c \
src/ease.c \
src/curve.c \
- src/bezier.c
+ src/bezier.c \
+ src/ray.c
test_tests_SOURCES=\
test/runner.c \
diff --git a/README.md b/README.md
index 8a6e634..222bc1d 100644
--- a/README.md
+++ b/README.md
@@ -314,7 +314,7 @@ You can pass matrices the same way to other APIs e.g. Vulkan, DX...
## Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
-
+
## Backers
diff --git a/docs/source/api.rst b/docs/source/api.rst
index b157716..717b61c 100644
--- a/docs/source/api.rst
+++ b/docs/source/api.rst
@@ -52,3 +52,4 @@ Follow the :doc:`build` documentation for this
curve
bezier
version
+ ray
diff --git a/docs/source/ray.rst b/docs/source/ray.rst
new file mode 100644
index 0000000..c5faf33
--- /dev/null
+++ b/docs/source/ray.rst
@@ -0,0 +1,31 @@
+.. default-domain:: C
+
+ray
+====
+
+Header: cglm/ray.h
+
+This is for collision-checks used by ray-tracers and the like.
+
+Table of contents (click to go):
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Functions:
+
+1. :c:func:`glm_ray_triangle`
+
+Functions documentation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. c:function:: bool glm_ray_triangle(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d)
+
+ Möller–Trumbore ray-triangle intersection algorithm
+
+ Parameters:
+ | *[in]* **origin** origin of ray
+ | *[in]* **direction** direction of ray
+ | *[in]* **v0** first vertex of triangle
+ | *[in]* **v1** second vertex of triangle
+ | *[in]* **v2** third vertex of triangle
+ | *[in, out]* **d** float pointer to save distance to intersection
+ | *[out]* **intersection** whether there is intersection
diff --git a/include/cglm/call.h b/include/cglm/call.h
index 87ecea5..b51b731 100644
--- a/include/cglm/call.h
+++ b/include/cglm/call.h
@@ -31,6 +31,7 @@ extern "C" {
#include "call/ease.h"
#include "call/curve.h"
#include "call/bezier.h"
+#include "call/ray.h"
#ifdef __cplusplus
}
diff --git a/include/cglm/call/ray.h b/include/cglm/call/ray.h
new file mode 100644
index 0000000..1fff055
--- /dev/null
+++ b/include/cglm/call/ray.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_ray_h
+#define cglmc_ray_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "../cglm.h"
+
+CGLM_EXPORT
+bool
+glmc_ray_triangle(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_ray_h */
diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h
index cbd2952..afc7f99 100644
--- a/include/cglm/cglm.h
+++ b/include/cglm/cglm.h
@@ -30,5 +30,6 @@
#include "ease.h"
#include "curve.h"
#include "bezier.h"
+#include "ray.h"
#endif /* cglm_h */
diff --git a/include/cglm/ray.h b/include/cglm/ray.h
new file mode 100644
index 0000000..f29bbde
--- /dev/null
+++ b/include/cglm/ray.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+/*
+ Functions:
+ CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d);
+*/
+
+#ifndef cglm_ray_h
+#define cglm_ray_h
+
+#include "vec3.h"
+
+/*!
+ * @brief Möller–Trumbore ray-triangle intersection algorithm
+ *
+ * @param[in] origin origin of ray
+ * @param[in] direction direction of ray
+ * @param[in] v0 first vertex of triangle
+ * @param[in] v1 second vertex of triangle
+ * @param[in] v2 third vertex of triangle
+ * @param[in, out] d distance to intersection
+ * @param[out] intersection whether there is intersection
+ */
+
+CGLM_INLINE
+bool
+glm_ray_triangle(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d) {
+ vec3 edge1, edge2, p, t, q;
+ float det, inv_det, u, v, dist;
+ const float epsilon = 0.000001f;
+
+ glm_vec3_sub(v1, v0, edge1);
+ glm_vec3_sub(v2, v0, edge2);
+
+ glm_vec3_cross(direction, edge2, p);
+
+ det = glm_vec3_dot(edge1, p);
+
+ if (det > -epsilon && det < epsilon)
+ return 0;
+
+ inv_det = 1.0f / det;
+
+ glm_vec3_sub(origin, v0, t);
+
+ u = inv_det * glm_vec3_dot(t, p);
+
+ if (u < 0.0f || u > 1.0f)
+ return 0;
+
+ glm_vec3_cross(t, edge1, q);
+
+ v = inv_det * glm_vec3_dot(direction, q);
+
+ if (v < 0.0f || u + v > 1.0f)
+ return 0;
+
+ dist = inv_det * glm_vec3_dot(edge2, q);
+
+ if (d)
+ *d = dist;
+
+ return dist > epsilon;
+}
+
+#endif
diff --git a/src/ray.c b/src/ray.c
new file mode 100644
index 0000000..973c059
--- /dev/null
+++ b/src/ray.c
@@ -0,0 +1,13 @@
+#include "../include/cglm/cglm.h"
+#include "../include/cglm/call.h"
+
+CGLM_EXPORT
+bool
+glmc_ray_triangle(vec3 origin,
+ vec3 direction,
+ vec3 v0,
+ vec3 v1,
+ vec3 v2,
+ float *d) {
+ return glm_ray_triangle(origin, direction, v0, v1, v2, d);
+}
diff --git a/test/src/test_ray.h b/test/src/test_ray.h
new file mode 100644
index 0000000..c1b0281
--- /dev/null
+++ b/test/src/test_ray.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#include "test_common.h"
+
+TEST_IMPL(GLM_PREFIX, ray_triangle) {
+ /* Check whether a simple hit is recognized with the right distance */
+ vec3 origin = { 0.0f, 0.0f, 0.0f};
+ vec3 direction = { 1.0f, 0.0f, 0.0f};
+ vec3 opposite = {-1.0f, 0.0f, 0.0f};
+ vec3 v0 = { 5.0f, -1.0f, 1.0f};
+ vec3 v1 = { 5.0f, -1.0f, -1.0f};
+ vec3 v2 = { 5.0f, 1.0f, 0.0f};
+ float d;
+ bool hit;
+
+ hit = GLM(ray_triangle)(origin, direction, v0, v1, v2, &d);
+ ASSERT(hit);
+ ASSERT(fabsf(d - 5.0f) <= 0.0000009);
+
+ /* Check whether a simple miss works */
+ hit = GLM(ray_triangle)(origin, opposite, v0, v1, v2, &d);
+ ASSERT(!hit);
+
+ /* Check that we can disregard distance and pass NULL pointer instead */
+ hit = GLM(ray_triangle)(origin, direction, v0, v1, v2, NULL);
+ ASSERT(hit);
+
+ TEST_SUCCESS
+}
diff --git a/test/src/tests.c b/test/src/tests.c
index 669b33c..ea9f902 100644
--- a/test/src/tests.c
+++ b/test/src/tests.c
@@ -23,6 +23,7 @@
#include "test_plane.h"
#include "test_affine.h"
#include "test_affine_mat.h"
+#include "test_ray.h"
#undef GLM
#undef GLM_PREFIX
@@ -44,6 +45,7 @@
#include "test_plane.h"
#include "test_affine.h"
#include "test_affine_mat.h"
+#include "test_ray.h"
#undef GLM
#undef GLM_PREFIX
diff --git a/test/tests.h b/test/tests.h
index 4c9a552..1ed75d8 100644
--- a/test/tests.h
+++ b/test/tests.h
@@ -218,6 +218,10 @@ TEST_DECLARE(clamp)
/* euler */
TEST_DECLARE(euler)
+/* ray */
+TEST_DECLARE(glm_ray_triangle)
+TEST_DECLARE(glmc_ray_triangle)
+
/* quat */
TEST_DECLARE(MACRO_GLM_QUAT_IDENTITY_INIT)
TEST_DECLARE(MACRO_GLM_QUAT_IDENTITY)
@@ -905,6 +909,10 @@ TEST_LIST {
/* euler */
TEST_ENTRY(euler)
+ /* ray */
+ TEST_ENTRY(glm_ray_triangle)
+ TEST_ENTRY(glmc_ray_triangle)
+
/* quat */
TEST_ENTRY(MACRO_GLM_QUAT_IDENTITY_INIT)
TEST_ENTRY(MACRO_GLM_QUAT_IDENTITY)
diff --git a/win/cglm-test.vcxproj b/win/cglm-test.vcxproj
index 1c0916d..6599103 100644
--- a/win/cglm-test.vcxproj
+++ b/win/cglm-test.vcxproj
@@ -42,6 +42,7 @@
+
diff --git a/win/cglm-test.vcxproj.filters b/win/cglm-test.vcxproj.filters
index c81dc11..b8f7326 100644
--- a/win/cglm-test.vcxproj.filters
+++ b/win/cglm-test.vcxproj.filters
@@ -79,5 +79,8 @@
src
+
+ src
+
\ No newline at end of file
diff --git a/win/cglm.vcxproj b/win/cglm.vcxproj
index e1a0e4d..a95f21e 100644
--- a/win/cglm.vcxproj
+++ b/win/cglm.vcxproj
@@ -34,6 +34,7 @@
+
@@ -61,6 +62,7 @@
+
@@ -80,6 +82,7 @@
+
diff --git a/win/cglm.vcxproj.filters b/win/cglm.vcxproj.filters
index a2f1432..fe23bd6 100644
--- a/win/cglm.vcxproj.filters
+++ b/win/cglm.vcxproj.filters
@@ -92,6 +92,9 @@
src
+
+ src
+
@@ -124,6 +127,9 @@
include\cglm\call
+
+ include\cglm\call
+
include\cglm\simd\avx
@@ -241,6 +247,9 @@
include\cglm
+
+ include\cglm
+
include\cglm\simd