From c67f7a14a1dd010d4315aafd1b744442aa02ed03 Mon Sep 17 00:00:00 2001 From: Uwila Date: Mon, 30 Mar 2020 23:44:00 +0200 Subject: [PATCH 1/5] Add ray-triangle intersection check --- Makefile.am | 9 ++++-- docs/source/api.rst | 1 + docs/source/ray.rst | 31 +++++++++++++++++++ include/cglm/call.h | 1 + include/cglm/call/ray.h | 22 ++++++++++++++ include/cglm/cglm.h | 1 + include/cglm/ray.h | 66 ++++++++++++++++++++++++++++++++++++++++ src/ray.c | 8 +++++ win/cglm.vcxproj | 3 ++ win/cglm.vcxproj.filters | 9 ++++++ 10 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 docs/source/ray.rst create mode 100644 include/cglm/call/ray.h create mode 100644 include/cglm/ray.h create mode 100644 src/ray.c 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/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..0bfefe0 --- /dev/null +++ b/include/cglm/call/ray.h @@ -0,0 +1,22 @@ +/* + * 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..c2433cb --- /dev/null +++ b/include/cglm/ray.h @@ -0,0 +1,66 @@ +/* + * 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) { + const float epsilon = 0.000001; + vec3 edge1, edge2, p, t, q; + float det, inv_det, u, v; + + 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.0 / det; + + glm_vec3_sub(origin, v0, t); + + u = inv_det * glm_vec3_dot(t, p); + + if (u < 0.0 || u > 1.0) + return 0; + + glm_vec3_cross(t, edge1, q); + + v = inv_det * glm_vec3_dot(direction, q); + + if (v < 0.0 || u + v > 1.0) + return 0; + + *d = inv_det * glm_vec3_dot(edge2, q); + return *d > epsilon; +} + +#endif diff --git a/src/ray.c b/src/ray.c new file mode 100644 index 0000000..4ce0c58 --- /dev/null +++ b/src/ray.c @@ -0,0 +1,8 @@ +#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/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 From 99076be6bb8c8d3e5d2bb44835ed252f4a832091 Mon Sep 17 00:00:00 2001 From: Uwila Date: Fri, 3 Apr 2020 12:56:50 +0200 Subject: [PATCH 2/5] Improve code style in ray.h - 2 spaces instead of 4, for indentation - Newline after return - Check if pointer is null --- include/cglm/ray.h | 49 +++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/include/cglm/ray.h b/include/cglm/ray.h index c2433cb..eac5140 100644 --- a/include/cglm/ray.h +++ b/include/cglm/ray.h @@ -30,37 +30,46 @@ CGLM_INLINE bool glm_ray_triangle(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d) { - const float epsilon = 0.000001; - vec3 edge1, edge2, p, t, q; - float det, inv_det, u, v; + vec3 edge1, edge2, p, t, q; + float det, inv_det, u, v, dist; + const float epsilon = 0.000001; - glm_vec3_sub(v1, v0, edge1); - glm_vec3_sub(v2, v0, edge2); + glm_vec3_sub(v1, v0, edge1); + glm_vec3_sub(v2, v0, edge2); - glm_vec3_cross(direction, edge2, p); + glm_vec3_cross(direction, edge2, p); - det = glm_vec3_dot(edge1, p); + det = glm_vec3_dot(edge1, p); - if (det > -epsilon && det < epsilon) - return 0; - inv_det = 1.0 / det; + if (det > -epsilon && det < epsilon) + return 0; - glm_vec3_sub(origin, v0, t); + inv_det = 1.0 / det; - u = inv_det * glm_vec3_dot(t, p); + glm_vec3_sub(origin, v0, t); - if (u < 0.0 || u > 1.0) - return 0; + u = inv_det * glm_vec3_dot(t, p); - glm_vec3_cross(t, edge1, q); + if (u < 0.0 || u > 1.0) + return 0; - v = inv_det * glm_vec3_dot(direction, q); + glm_vec3_cross(t, edge1, q); - if (v < 0.0 || u + v > 1.0) - return 0; + v = inv_det * glm_vec3_dot(direction, q); - *d = inv_det * glm_vec3_dot(edge2, q); - return *d > epsilon; + if (v < 0.0 || u + v > 1.0) + return 0; + + dist = inv_det * glm_vec3_dot(edge2, q); + if (dist > epsilon) { + if (d != NULL) { + *d = dist; + } + + return 1; + } + + return 0; } #endif From 7bf38a3062540f80369c593e1e7647627055e06a Mon Sep 17 00:00:00 2001 From: Uwila Date: Fri, 3 Apr 2020 13:10:38 +0200 Subject: [PATCH 3/5] Update credits with ray-triangle intersection algorithm --- CREDITS | 6 ++++++ 1 file changed, 6 insertions(+) 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 From 339adab783b8470f137f03b4ea0465986374e7a9 Mon Sep 17 00:00:00 2001 From: Uwila Date: Fri, 3 Apr 2020 17:56:53 +0200 Subject: [PATCH 4/5] Align variables in ray code --- include/cglm/call/ray.h | 7 ++++++- include/cglm/ray.h | 14 ++++++++++++-- src/ray.c | 7 ++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/cglm/call/ray.h b/include/cglm/call/ray.h index 0bfefe0..1fff055 100644 --- a/include/cglm/call/ray.h +++ b/include/cglm/call/ray.h @@ -14,7 +14,12 @@ extern "C" { CGLM_EXPORT bool -glmc_ray_triangle(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d); +glmc_ray_triangle(vec3 origin, + vec3 direction, + vec3 v0, + vec3 v1, + vec3 v2, + float *d); #ifdef __cplusplus } diff --git a/include/cglm/ray.h b/include/cglm/ray.h index eac5140..ec434a1 100644 --- a/include/cglm/ray.h +++ b/include/cglm/ray.h @@ -7,7 +7,12 @@ /* Functions: - CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d); + CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin, + vec3 direction, + vec3 v0, + vec3 v1, + vec3 v2, + float *d); */ #ifndef cglm_ray_h @@ -29,7 +34,12 @@ CGLM_INLINE bool -glm_ray_triangle(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d) { +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.000001; diff --git a/src/ray.c b/src/ray.c index 4ce0c58..973c059 100644 --- a/src/ray.c +++ b/src/ray.c @@ -3,6 +3,11 @@ CGLM_EXPORT bool -glmc_ray_triangle(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, float *d) { +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); } From c1331a1dd4911f950bbfa8a4259e6a1e07b0704f Mon Sep 17 00:00:00 2001 From: Uwila Date: Fri, 3 Apr 2020 18:00:49 +0200 Subject: [PATCH 5/5] Improve ray.h style --- include/cglm/ray.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/include/cglm/ray.h b/include/cglm/ray.h index ec434a1..f29bbde 100644 --- a/include/cglm/ray.h +++ b/include/cglm/ray.h @@ -42,7 +42,7 @@ glm_ray_triangle(vec3 origin, float *d) { vec3 edge1, edge2, p, t, q; float det, inv_det, u, v, dist; - const float epsilon = 0.000001; + const float epsilon = 0.000001f; glm_vec3_sub(v1, v0, edge1); glm_vec3_sub(v2, v0, edge2); @@ -54,32 +54,28 @@ glm_ray_triangle(vec3 origin, if (det > -epsilon && det < epsilon) return 0; - inv_det = 1.0 / det; + inv_det = 1.0f / det; glm_vec3_sub(origin, v0, t); u = inv_det * glm_vec3_dot(t, p); - if (u < 0.0 || u > 1.0) + 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.0 || u + v > 1.0) + if (v < 0.0f || u + v > 1.0f) return 0; dist = inv_det * glm_vec3_dot(edge2, q); - if (dist > epsilon) { - if (d != NULL) { + + if (d) *d = dist; - } - return 1; - } - - return 0; + return dist > epsilon; } #endif